はじめに
Azure OpenAI on your data は ChatGPT や GPT-4 といった LLM に独自のデータを追加できるサービスです。
前回の記事では、Azure OpenAI Studio の ChatGPT プレイグラウンドから動作を確認しました。
今回は本サービスの REST API の動作を確認します。
Completions extensions API のリクエスト
Completions API の拡張となる下記 Completions extensions API を使用します。
上記 MS Learn のドキュメントに記載がありますが、少しわかりづらい箇所がありますので、説明を補足したものを下記に記載します。
{}で囲んだ箇所に説明を記載しています。
curl -i -X POST {Azure OpenAIのエンドポイント(ドメイン名まで)}/openai/deployments/{デプロイ名}/extensions/chat/completions?api-version=2023-06-01-preview \
-H "Content-Type: application/json" \
-H "api-key: {Azure OpenAIのAPIキー}" \
-H "chatgpt_url: {Azure OpenAIのCompletion APIのURL(api-versionのクエリまで)}" \
-H "chatgpt_key: {Azure OpenAIのAPIキー}" \
-d \
'
{
"dataSources": [
{
"type": "AzureCognitiveSearch",
"parameters": {
"endpoint": "{Cognitive Searchのエンドポイント(ドメイン名まで)}",
"key": "{Cognitive Searchの管理者キー}",
"indexName": "{Cognitive Searchのデータ格納先としたインデックス}"
}
}
],
"messages": [
{通常のCompletion APIと同様、roleとcontentからなるmessage}
]
}
'
例:
curl --location 'https://xxx.openai.azure.com/openai/deployments/gpt-35-turbo/extensions/chat/completions?api-version=2023-06-01-preview' \
--header 'api-key: xxx' \
--header 'chatgpt_url: https://xxx.openai.azure.com/openai/deployments/gpt-35-turbo/chat/completions?api-version=2023-03-15-preview' \
--header 'chatgpt_key: xxx' \
--header 'Content-Type: application/json' \
--data '{
"dataSources": [
{
"type": "AzureCognitiveSearch",
"parameters": {
"endpoint": "https://xxx.search.windows.net",
"key": "xxx",
"indexName": "sample"
}
}
],
"messages": [
{
"role": "system",
"content": "You are an AI assistant that helps people find information. You retrieve Japanese documents, and you should read them carefully in Japanese and answer in Japanese."
},
{
"role": "user",
"content": "オフィスの入退室はどうすればいいですか。"
}
]
}'
わかりづらいと感じるのはヘッダの部分で、api-key と chatgpt_key は同じ値を指定することになります。
また、chatgpt_url は、エンドポイントのドメイン名だけでなく、Completion API の URL を最後まで指定する必要があります。
ChatGPT プレイグラウンドのコードの表示で「エンドポイント」として表示される URL をそのまま指定すればいいだけなのですが、URL のクエリで「api-version=2023-06-01-preview」を指定する一方で、chatgpt_url に「api-version=2023-03-15-preview」の値を指定するのはおかしいのでは?と考えた私は、最初ドメイン名のみ指定していたため、HTTP 500 応答が返ってくる結果となっていました。
API として見た場合、chatgpt_url、chatgpt_key あたりは冗長な気がしますので、今後変更されるかもしれません。
また、リクエストボディの key は管理者キーを指定する必要があります。Cognitive Search にはクエリキーというものもありますが、こちらを指定すると HTTP 500 応答が返ってきます。
Completions extensions API のレスポンス
前回と記事同様、ChatGPT プレイグラウンドで架空のオフィスに関する FAQ データをアップロードして Cognitive Search にインデックスを作成し、FAQ データにある質問を messages に含めて REST API を送信すると、下記のようなレスポンスが返ってきました。
{
"id": "xxx",
"model": "gpt-35-turbo",
"created": xxx,
"object": "chat.completion",
"choices": [
{
"index": 0,
"messages": [
{
"index": 0,
"role": "tool",
"content": "{\"citations\": [{\"content\": \"\基\本\的\なFAQ\ペ\ー\ジ\\n\オ\フ\ィ\ス\の\入\退\室\は\ど\う\す\れ\ば\い\い\で\す\か\。\\n\ド\ア\の\横\に\あ\る\装\置\に\セ\キ\ュ\リ\テ\ィ\カ\ー\ド\を\か\ざ\し\て\く\だ\さ\い\。\音\が\鳴\り\、\ロ\ッ\ク\が\解\除\さ\れ\ま\す\。\入\室\時\、\退\出\時\と\も\に\忘\れ\ず\か\ざ\し\て\く\だ\さ\い\。\\n\出\張\時\に\セ\キ\ュ\リ\テ\ィ\カ\ー\ド\が\な\い\場\合\は\ど\う\す\れ\ば\い\い\で\す\か\。\\n\人\事\部\に\連\絡\く\だ\さ\い\。\一\時\利\用\の\セ\キ\ュ\リ\テ\ィ\カ\ー\ド\を\お\渡\し\し\ま\す\。\\n\受\付\の\電\話\を\受\け\る\に\は\ど\う\す\れ\ば\い\い\で\す\か\。\\n\近\く\で\鳴\っ\て\い\る\電\話\の\受\話\器\を\取\り\、\「*1\」\を\押\し\て\く\だ\さ\い\。\\n\荷\物\を\発\送\す\る\に\は\ど\う\す\れ\ば\い\い\で\す\か\。\\n\人\事\部\横\の\棚\に\あ\る\発\送\伝\票\や\梱\包\材\を\使\っ\て\く\だ\さ\い\。\\n\ゴ\ミ\は\ど\こ\に\捨\て\れ\ば\よ\い\で\す\か\。\\n\オ\フ\ィ\ス\の\角\に\あ\る\ゴ\ミ\箱\の\分\類\に\従\っ\て\捨\て\て\く\だ\さ\い\。\\n\ゴ\ミ\の\収\集\日\は\い\つ\で\す\か\。\\n\毎\週\水\曜\日\で\す\。\", \"id\": null, \"title\": \"\基\本\的\なFAQ\ペ\ー\ジ\", \"filepath\": \"faq_basic.docx\", \"url\": \"https://xxx.blob.core.windows.net/fileupload-sample/faq_basic.docx\", \"metadata\": {\"chunking\": \"orignal document size=451. Scores=7.8840075 and None.Org Highlight count=92.\"}, \"chunk_id\": \"0\"}], \"intent\": \"\オ\フ\ィ\ス\の\入\退\室\は\ど\う\す\れ\ば\い\い\で\す\か\。\"}",
"end_turn": false
},
{
"index": 1,
"role": "assistant",
"content": "オフィスの入退室に関する情報は、[doc1]のFAQページにあります。入室時には、ドアにあるカードリーダーにカードをかざしてください。退室時には、カードをかざす必要はありません。カードリーダーから音が鳴り、ロックが解除されます。カードがない場合は、人事部に連絡してください。また、受付には一時利用のカードがあります。[doc1]",
"end_turn": true
}
]
}
]
}
role は従来"system"、"user"、"assistant"の 3 種類でしたが、ここでは"tool"というものが使われています。
content には JSON が含まれていますが、抜き出すと下記のような形式になっています。
{
"citations": [
{
"content": "基本的なFAQページnオフィスの入退室はどうすればいいですか。nドアの横にある装置にセキュリティカードをかざしてください。音が鳴り、ロックが解除されます。入室時、退出時ともに忘れずかざしてください。n出張時にセキュリティカードがない場合はどうすればいいですか。n人事部に連絡ください。一時利用のセキュリティカードをお渡しします。n受付の電話を受けるにはどうすればいいですか。n近くで鳴っている電話の受話器を取り、「*1」を押してください。n荷物を発送するにはどうすればいいですか。n人事部横の棚にある発送伝票や梱包材を使ってください。nゴミはどこに捨てればよいですか。nオフィスの角にあるゴミ箱の分類に従って捨ててください。nゴミの収集日はいつですか。n毎週水曜日です。",
"id": null,
"title": "基本的なFAQページ",
"filepath": "faq_basic.docx",
"url": "https://xxx.blob.core.windows.net/fileupload-sample/faq_basic.docx",
"metadata": {
"chunking": "orignal document size=451. Scores=7.8840075 and None.Org Highlight count=92."
},
"chunk_id": "0"
}
],
"intent": "オフィスの入退室はどうすればいいですか。"
}
citations の要素に含まれる各キーは Cognitive Search のインデックスのフィールド名と一致しています。Cognitive Search で検索した結果がここに含まれていると思われます。
role が"assistant"のメッセージの中に含まれる"[doc1]"といった表記は citations の要素を参照していると推測されますが、ドキュメントには記載されていないようです。
Microsoft のサンプルでこの表記を処理している箇所があったので、ソースを確認したところ、docN は citations の N 番目の要素として扱っているようでした。
呼び出し側でデータの加工が必要な箇所がいくつかありますが、Completions extensions API を使って、Cognitive Searchに格納した独自データからChatGPTによる回答を得られることが確認できました。