text-davinci-003 から Chat Completion API へ移行するテスト

Azure OpenAI Service で 7/6 から急に text-davinci-003 が新規デプロイできなくなった（既存でお使いの方は2024年7月5日まで使える）ため下記のコードが**~~新規デプロイしようとすると動かなくなってます~~ gpt-35-turbo を使うように変更されました。** [アナウンス](https://techcommunity.microsoft.com/t5/ai-cognitive-services-blog/announcing-updates-to-azure-openai-service-models/ba-p/3866757)によると後継の Chat Completion API を使う gpt-35-turbo-instruct へ移行とのことですがまだそのモデルが登場していません。

https://qiita.com/nohanaga/items/803c09b5a3a4e2d1776f

なので回避策を考えます。これは gpt-35-turbo-instruct が登場してもおそらく使えるはず。上記コードでは、Azure Cognitive Search の検索ワードを text-davinci-003 に生成させていましたが、これを gpt-35-turbo へ置き換えます。

# text-davinci-003 を gpt-35-turbo へ
API を ChatCompletion に変更し、ひとまず `max_tokens` を `100`、`temperature` を `0.0` に設定します。
```python
completion = openai.ChatCompletion.create(
    deployment_id=self.chatgpt_deployment,
    messages=messages,
    temperature=0.0,
    max_tokens=100, 
    n=1,
    stop=["\n"]
)
```

## System message
```yaml
このアシスタントは、ユーザーの会話や新しい質問に基づいて質問文を検索クエリに変換します。
検索クエリは必ずスペースで区切ってください。

Example:###
Question:徳川家康ってなにした人  
Search query: 徳川家康 人物 歴史

Question:徳川家康の武功を教えてください
Search query: 徳川家康 人物 武功 業績

Question:源範頼の墓所はどこにありますか？
Search query: 源範頼 墓所 墓
###
```

Few-shot で例を与え、テストします。

## User message
```
Question:源範頼の簡単な情報と、彼のゆかりの地にあるいいカフェを教えて  
Search query:
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/2e0894de-1724-727b-4122-439bccef033d.png" alt="image.png" width="600"/>

やるやん
でも同義語はうまく生成できていないみたいですね…　このワードが Azure Cognitive Search 側で言語アナライザによる解析を受けます。

このレベルだったらそもそも ChatGPT 使って検索ワードを生成させる必要ないのでは？（ｦｲ

# ユーザーからの質問を直で Azure Cognitive Search に投げる
Azure Cognitive Search は全文検索エンジンですから、標準で日本語のアナライザーが使えます。検索クエリの生成を GPT-3 でさせずに、ユーザーの生の質問の解析を言語アナライザーに搭載されたトークナイザーにやらせてしまうとどうなるでしょうか。（Score を見るに on your data はそのような仕組みでは？）

```json
{
  "text":"源範頼の簡単な情報と、彼のゆかりの地にあるいいカフェを教えて",
  "analyzer": "ja.lucene"
}   
```

```
源範頼 簡単 情報 彼 ゆかり 地 いい カフェ 教える
```

…、まぁそうなるよな…

```json
{
  "text":"源実朝の和歌にはどのような特徴があったのでしょうか？",
  "analyzer": "ja.lucene"
}   
```

```
源実朝　和歌　どの　特徴
```

いいですね

```json
{
  "text":"十三人の合議制はどのような役割を果たしていたのでしょうか？",
  "analyzer": "ja.lucene"
}   
```

```
十 三 人 合議 制 どの 役割 果たす
```

これはちょっと微妙です…が OR 検索すれば欲しいドキュメントは得られそうですね。
めちゃくちゃ長い質問をされたときエライことになりそうですが。

# 同義語を生成させる
ChatGPT による検索クエリ生成では同義語が生成されていないので、こちらを生成させるように System message に以下を追加します。

```yaml
**IMPORTANT**
検索クエリは、一般的な全文検索でヒットできるように、質問の意図に対して最低でも 3 つの同義語を生成し、
スペースで区切って追加する必要があります。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/23430935-4b8c-b8fb-dce1-9ba0d83fdb0e.png)
若干増えましたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/b03e1afc-65aa-d0ba-e56f-daa84f83ed80.png)

Cool😎

# ベクトル検索
Azure Cognitive Search にはベクトル検索機能がありますので、**検索クエリ生成アプローチを使わなくとも質問者の意図を考慮した検索も可能**ですのでこちらも検討します。すでに [Tudor Golubenco](https://xata.io/blog/keyword-vs-semantic-search-chatgpt) さんがベクトル検索とキーワード検索を比較した記事を書いています。

# ハイブリッド検索
ベクトル検索を使いつつキーワードのマッチも組み合わせることで、ベクトル検索では精度が出なかった場合のリカバリー策を講じることが可能です。

# セマンティック検索
Azure Cognitive Search のセマンティック検索を十分に使うためには検索アルゴリズム側に意図を伝えなければなりませんので、前処理で質問文から意図を削除してしまうと機能が十分に働かない可能性があります。

# おわりに
全文検索エンジンにおいて、適合率と再現率はトレードオフの関係ですから、どちらを重視するかを考える必要があります。このアーキテクチャにおいては多少検索ノイズが混じっていたとしても、トークン制限の中で検索結果を多く提供し、ChatGPT の質問応答能力によってカバーするというアプローチも考えられます。