💻

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

2024/01/31に公開

はじめに

Azure OpenAI Service には API キーと ID ベースの 2 種類の認証方式があります。API キーは簡単ではあるものの、可能であればよりセキュアな ID ベースの認証を使いたいところです。Azure App Service や 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