このエントリは2024/02/23現在の情報に基づいています。将来の追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
問い合わせ
いつもの人から、以下のような問い合わせが届いた。
現在Azure OpenAI Service (AOAI) で新たに追加されたAssistants APIを試している。Pythonを使って直接AOAIにアクセスする場合にはチュートリアルを無事に完了できたが、API Management (APIM) をAOAIの前に挟むと、一部動作しない場合があった。どうすればよいか?
「ほんま流行りものが好きやな」と思いつつも、ちょっとわかりづらかったので確認してみた。
まず、チュートリアルは以下のもの。
Azure OpenAI Assistants (プレビュー) の概要 / Getting started with Azure OpenAI Assistants (Preview)
https://learn.microsoft.com/azure/ai-services/openai/how-to/assistant
問題があったのは以下の2点。
- APIMからAOAIのアクセスにて、API Keyを使う場合には正しく動作したが、Managed Identityを使う場合だと、401が返ってくる
- サインカーブのイメージを取得しようとしたが、該当するAPIが見当たらない
勘の良い人ならわかるかもしれない。
原因と対策
1. 401のエラー
これはCognitive Services OpenAI UserロールをManaged Identityに付与していたから。確かに通常のAOAI利用であれば、Userロールの付与で正しい。しかし、Assistants APIではThreadを作るなど、これまでのAPIとは異なり、Assistants APIを使う場合にはCognitive Services OpenAI Contributorロールを付与しなければならない。実際に確認するのがいちばんわかりやすいと思うので、スクリーンショットをつけて説明する。
まずは、UserロールをAPIMのManaged Identityに付与した状態で、以下のAPIを使ってアシスタントを作成する。
アシスタントを作成する / Create an assistant
https://learn.microsoft.com/azure/ai-services/openai/assistants-reference?tabs=python#create-an-assistant
すると、

401 PermissionDenied
が返っていることがわかる(エラーメッセージがわかりづらいのでなんともあれではあるが)。これを見る限り、APIのOperationに対する権限がない、ということで、POSTメソッドを呼び出すアシスタント作成にあたっては、Userロールではだめ、ということがわかる。
対して、Contributorロールを付与した場合。

ということで、無事に200が返ってくる。
APIおよびそのOperationによって必要な権限が違うが、対策は文字通り、Cognitive Services OpenAI Contributorロールを付与する、ということに尽きる。
Assistants APIはこれまでのchat completion APIなどと異なり、複数のAOAIインスタンスへの負荷分散はできない点にも注意が必要。
2. 該当するAPIが見当たらない
ここで言っているのは、
GET /files/{file_id}/content
のAPIがAOAIのOpenAPI Specにない、ということ。確かに2024-02-15-previewでは見つからない。
Azure OpenAI Service API
https://github.com/Azure/azure-rest-api-specs/blob/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/preview/2024-02-15-preview/inference.json
対して、本家のOpenAIのOpenAPI Specを見ると、以下の抜粋の通り存在する。
The OpenAI REST API
https://github.com/openai/openai-openapi/blob/master/openapi.yaml#L1549
...
/files/{file_id}/content:
get:
operationId: downloadFile
tags:
- Files
summary: Returns the contents of the specified file.
parameters:
- in: path
name: file_id
required: true
schema:
type: string
description: The ID of the file to use for this request.
responses:
"200":
description: OK
content:
application/json:
schema:
type: string
x-oaiMeta:
name: Retrieve file content
group: files
returns: The file content.
examples:
request:
curl: |
curl https://api.openai.com/v1/files/file-abc123/content \
-H "Authorization: Bearer $OPENAI_API_KEY" > file.jsonl
python: |
from openai import OpenAI
client = OpenAI()
content = client.files.retrieve_content("file-abc123")
node.js: |
import OpenAI from "openai";
const openai = new OpenAI();
async function main() {
const file = await openai.files.retrieveContent("file-abc123");
console.log(file);
}
main();
...
ではなぜ直接AOAIにアクセスする場合には問題なかったのか?それは単にこのAPI Specを使わず、直接アクセスしているから。そのため、APIM経由で利用する場合には、AOAIのOpenAPI Specインポート後、本家OpenAIのOpenAPI specに従って、明示的に上記APIを追加する必要がある。こうすれば、APIM経由でも問題なく使えるようになる。以下は実際に呼び出して取得した結果。
