Azure OpenAI ServiceのAssistants APIのチュートリアルが完了できない場合がある

このエントリは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点。

  1. APIMからAOAIのアクセスにて、API Keyを使う場合には正しく動作したが、Managed Identityを使う場合だと、401が返ってくる
  2. サインカーブのイメージを取得しようとしたが、該当する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経由でも問題なく使えるようになる。以下は実際に呼び出して取得した結果。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください