watsonx Assistant が実行したElasticsearch検索APIリクエストをcurlコマンドで実行する

watsonx Assistant は、Elasticsearch 検索統合の機能を備えています。
今回デバッグのため、Assistant が Elasticsearch に送信しているリクエストをLinuxマシンからcurlコマンドで実行する機会がありました。その記録です。

Assistant が Elasticsearch に送信しているリクエストは、Preview で Inspectをクリックすることにより開く `Inspector` のAdvancedタブから確認できます。
＊ Inspectは `Conversational Search（会話型検索）` を `On` にした場合のみ表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164968/447160eb-8a81-5d61-6ef6-03083821e78f.png)

KNN 高密度ベクトル検索の例ですが、他の検索でも必要な更新は同様ではないかと思います。
次のように置き換えています。
- Elasticsearch URL: elastic.url
- index名: index

## オリジナルのリクエスト

Assistant の Inspector からコピーした `Request CURL`:
```
curl -X POST -H 'content-type: application/json' -H 'content-type: application/json' -H 'accept: application/json' -d '"{\"knn\":{\"k\":10,\"field\":\"passages.dense.text_embedding.predicted_value\",\"inner_hits\":{\"_source\":{\"excludes\":[\"passages.dense\"]}},\"num_candidates\":100,\"query_vector_builder\":{\"text_embedding\":{\"model_id\":\".multilingual-e5-small_linux-x86_64\",\"model_text\":\"IBM CloudのSLAクレジットとは?\"}}},\"_source\":false}"' 'https://elastic.url/index/_search'
```
このまま実行すると、次のエラーが発生しました。
```
curl: (51) SSL: no alternative certificate subject name matches target host name 'elastic.url'
```

エラーを回避して、正常に検索結果を得られるようリクエストを更新していきます。

## リクエスト更新 #1

- 整形し、SSL/TLS 証明書の検証を無視するため `-k` フラグを追加
```
$ curl -X POST \
-k \
-H 'content-type: application/json' \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-d '"{\"knn\":{\"k\":10,\"field\":\"passages.dense.text_embedding.predicted_value\",\"inner_hits\":{\"_source\":{\"excludes\":[\"passages.dense\"]}},\"num_candidates\":100,\"query_vector_builder\":{\"text_embedding\":{\"model_id\":\".multilingual-e5-small_linux-x86_64\",\"model_text\":\"IBM CloudのSLAクレジットとは?\"}}},\"_source\":false}"' 'https://elastic.url/index/_search'
```
これを実行すると、次のエラーが発生しました。
```
<html><h1>Error 404</h1><br/>Page Not Found</html>
```

## リクエスト更新 #2

- ElasticsearchのURLにポート番号が入っていなかったため追加 (port)
- `-u` オプションでauthentication情報を追加
- 重複していた `-H 'content-type: application/json'` を１つ削除 
```
$ curl -X POST \
-k \
-u 'user:password' \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-d '"{\"knn\":{\"k\":10,\"field\":\"passages.dense.text_embedding.predicted_value\",\"inner_hits\":{\"_source\":{\"excludes\":[\"passages.dense\"]}},\"num_candidates\":100,\"query_vector_builder\":{\"text_embedding\":{\"model_id\":\".multilingual-e5-small_linux-x86_64\",\"model_text\":\"IBM CloudのSLAクレジットとは?\"}}},\"_source\":false}"' 'https://elastic.url:port/index/_search'
```

これを実行すると、次のエラーが発生しました。
```
{"error":{"root_cause":[{"type":"parsing_exception","reason":"Expected [START_OBJECT] but found [VALUE_STRING]","line":1,"col":1}],"type":"parsing_exception","reason":"Expected [START_OBJECT] but found [VALUE_STRING]","line":1,"col":1},"status":400}
```

## リクエスト更新 #3 （最終）


- `-d` オプションの `'"` を `'` に変更し、その{}内のエスケープ文字(\\)を削除
```
$ curl -X POST \
-k \
-u 'user:password' \
-H 'content-type: application/json' \
-H 'accept: application/json' \
-d '{"knn":{"k":10,"field":"passages.dense.text_embedding.predicted_value","inner_hits":{"_source":{"excludes":["passages.dense"]}},"num_candidates":100,"query_vector_builder":{"text_embedding":{"model_id":".multilingual-e5-small_linux-x86_64","model_text":"IBM CloudのSLAクレジットとは?"}}},"_source":false}' 'https://elastic.url:port/index/_search'
```

これで、正常に実行できるようになりました。

## 検証環境
- watsonx Assistant Plus
- Elasticsearch 8.15.0

## 参考

https://cloud.ibm.com/docs/watson-assistant?topic=watson-assistant-search-elasticsearch-add