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 クライアント ライブラリを利用するのが簡単です。
ただし、Azure OpenAI クライアント ライブラリはプレビューであり、まだ使いづらい部分もあります。より低レイヤーな HttpClient クラスを使って Azure OpenAI Service にアクセスしたい場合もあります。
サンプル コード
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