🛠️

Azure OpenAI Service を HttpClient + マネージド ID でアクセスする

に公開

はじめに

Azure OpenAI Service には API キーと ID ベースの 2 種類の認証方式があります。API キーは簡単ですが、可能であればよりセキュアな ID ベースの認証を利用したいところです。Azure Web Apps や Azure Functions から Azure OpenAI Service を呼び出す場合、マネージド ID を利用するとシークレットが不要になります。

Azure OpenAI Service に対してマネージド ID でアクセスする場合、Azure OpenAI クライアント ライブラリを利用するのが簡単です。

https://learn.microsoft.com/ja-jp/dotnet/api/overview/azure/ai.openai-readme?WT.mc_id=M365-MVP-5002941#create-openaiclient-with-an-azure-active-directory-credential

ただし、Azure OpenAI クライアント ライブラリはプレビューであり、まだ使いづらい部分もあります。より低レイヤーな HttpClient クラスを使って Azure OpenAI Service にアクセスしたい場合もあります。

サンプル コード

https://github.com/karamem0/samples/tree/main/azure-openai-with-http-client-and-managed-id

DefaultAzureCredential クラスは GetToken メソッドまたは GetTokenAsync メソッドによってアクセス トークンを取得できます。これらのメソッドはパラメーターとしてスコープを要求します。Azure OpenAI クライアント ライブラリのコードを見ると、スコープは https://cognitiveservices.azure.com/.default であることがわかります。ここまでわかれば、あとは簡単です。

public static class Program
{
    private static readonly string[] Scopes = new[] { "https://cognitiveservices.azure.com/.default" };
    private static readonly string Endpoint = "https://{{resource-name}}.openai.azure.com/openai/deployments/{{deployment-name}}/chat/completions?api-version={{api-version}}";

    private static async Task Main()
    {
        var credential = new DefaultAzureCredential();
        var token = await credential.GetTokenAsync(new TokenRequestContext(Scopes));
        var httpClient = new HttpClient();
        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, Endpoint)
        {
            Content = new StringContent(
                JsonSerializer.Serialize(
                    new Dictionary<string, object>()
                    {
                        ["messages"] = new List<Dictionary<string, object>>()
                        {
                            new Dictionary<string, object>()
                            {
                                ["role"] = "system",
                                ["content"] = "あなたは優秀なAIアシスタントです。慎重に考え自信を持って回答してください。"
                            },
                            new Dictionary<string, object>()
                            {
                                ["role"] = "user",
                                ["content"] = "日本の首都はどこにありますか?"
                            }
                        }
                    }
                ),
                new MediaTypeHeaderValue("application/json"))
        };
        httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
        var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
        var httpResponseContent = await httpResponseMessage.Content.ReadAsStringAsync();
        Console.WriteLine(httpResponseContent);
        Console.ReadLine();
    }
}

おわりに

DefaultAzureCredential はこれまで Azure SDK を利用する場合にしか使っていませんでした。今回、GetToken メソッドや GetTokenAsync メソッドが用意されていることをはじめて知りました。調べてみることで新たな発見があると改めて感じました。

Discussion