mcpField
A
azure-ai-openai-dotnet

azure-ai-openai-dotnet

github.com/sickn33開発48.7k75 回インストール今日更新
リポジトリ

azure-ai-openai-dotnet について

.NET 開発者向けに、Azure.AI.OpenAI と OpenAI SDK から Azure OpenAI Service を利用する方法をまとめたスキルです。チャット、埋め込み、画像・音声 API、認証、リクエスト例を扱います。

主な機能

  1. 01チャット補完とストリーミング
  2. 02構造化 JSON Schema 出力
  3. 03テキスト埋め込み
  4. 04画像生成と音声 API
  5. 05API キーと Entra ID 認証
  6. 06関数呼び出し

活用シーン

  1. 01.NET チャットアプリの構築
  2. 02テキストの埋め込み生成
  3. 03画像・音声機能の開発
  4. 04構造化されたモデル応答の設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill azure-ai-openai-dotnet

インストール後、Claude Code で/azure-ai-openai-dotnetを入力して読み込まれたか確認します。

詳細

Azure.AI.OpenAI(.NET)

GPT-4、GPT-4o、埋め込み、DALL-E、Whisper などの OpenAI モデルを利用できる Azure OpenAI Service クライアントライブラリです。

インストール

dotnet add package Azure.AI.OpenAI

# For OpenAI (non-Azure) compatibility
dotnet add package OpenAI

過去のサンプルの基準バージョン:2.1.0。互換性のある Azure.AI.OpenAI/OpenAI のバージョンを確認し、固定してください。以下の新しい v1 API のサンプルでは、より新しいパッケージが必要になる場合があります。

環境変数

AZURE_OPENAI_ENDPOINT=https://<resource-name>.openai.azure.com
AZURE_OPENAI_API_KEY=<api-key>                    # For key-based auth
AZURE_OPENAI_DEPLOYMENT_NAME=<deployment-name>    # Azure deployment, not necessarily the model ID

クライアント階層

AzureOpenAIClient (top-level)
├── GetChatClient(deploymentName)      → ChatClient
├── GetEmbeddingClient(deploymentName) → EmbeddingClient
├── GetImageClient(deploymentName)     → ImageClient
├── GetAudioClient(deploymentName)     → AudioClient
└── GetAssistantClient()               → AssistantClient

認証

API キー認証
using Azure;
using Azure.AI.OpenAI;

AzureOpenAIClient client = new(
    new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
    new AzureKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!));
Microsoft Entra ID(本番環境で推奨)
using Azure.Identity;
using Azure.AI.OpenAI;

AzureOpenAIClient client = new(
    new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
    new DefaultAzureCredential());
Azure で OpenAI SDK を直接使用する
using Azure.Identity;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel.Primitives;

#pragma warning disable OPENAI001

BearerTokenPolicy tokenPolicy = new(
    new DefaultAzureCredential(),
    "https://cognitiveservices.azure.com/.default");

ChatClient client = new(
    model: "gpt-4o-mini",
    authenticationPolicy: tokenPolicy,
    options: new OpenAIClientOptions()
    {
        Endpoint = new Uri("https://YOUR-RESOURCE.openai.azure.com/openai/v1")
    });

チャット補完

基本的なチャット
using Azure.AI.OpenAI;
using OpenAI.Chat;

AzureOpenAIClient azureClient = new(
    new Uri(endpoint),
    new DefaultAzureCredential());

ChatClient chatClient = azureClient.GetChatClient("gpt-4o-mini");

ChatCompletion completion = chatClient.CompleteChat(
[
    new SystemChatMessage("You are a helpful assistant."),
    new UserChatMessage("What is Azure OpenAI?")
]);

Console.WriteLine(completion.Content[0].Text);
非同期チャット
ChatCompletion completion = await chatClient.CompleteChatAsync(
[
    new SystemChatMessage("You are a helpful assistant."),
    new UserChatMessage("Explain cloud computing in simple terms.")
]);

Console.WriteLine($"Response: {completion.Content[0].Text}");
Console.WriteLine($"Tokens used: {completion.Usage.TotalTokenCount}");
ストリーミングチャット
await foreach (StreamingChatCompletionUpdate update 
    in chatClient.CompleteChatStreamingAsync(messages))
{
    if (update.ContentUpdate.Count > 0)
    {
        Console.Write(update.ContentUpdate[0].Text);
    }
}
オプションを指定したチャット
ChatCompletionOptions options = new()
{
    MaxOutputTokenCount = 1000,
    Temperature = 0.7f,
    TopP = 0.95f,
    FrequencyPenalty = 0,
    PresencePenalty = 0
};

ChatCompletion completion = await chatClient.CompleteChatAsync(messages, options);
複数ターンの会話
List<ChatMessage> messages = new()
{
    new SystemChatMessage("You are a helpful assistant."),
    new UserChatMessage("Hi, can you help me?"),
    new AssistantChatMessage("Of course! What do you need help with?"),
    new UserChatMessage("What's the capital of France?")
};

ChatCompletion completion = await chatClient.CompleteChatAsync(messages);
messages.Add(new AssistantChatMessage(completion.Content[0].Text));

構造化出力(JSON Schema)

using System.Text.Json;

ChatCompletionOptions options = new()
{
    ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
        jsonSchemaFormatName: "math_reasoning",
        jsonSchema: BinaryData.FromBytes("""
            {
                "type": "object",
                "properties": {
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "explanation": { "type": "string" },
                                "output": { "type": "string" }
                            },
                            "required": ["explanation", "output"],
                            "additionalProperties": false
                        }
                    },
                    "final_answer": { "type": "string" }
                },
                "required": ["steps", "final_answer"],
                "additionalProperties": false
            }
            """u8.ToArray()),
        jsonSchemaIsStrict: true)
};

ChatCompletion completion = await chatClient.CompleteChatAsync(
    [new UserChatMessage("How can I solve 8x + 7 = -23?")],
    options);

using JsonDocument json = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine($"Answer: {json.RootElement.GetProperty("final_answer")}");

推論モデル(o1、o4-mini)

ChatCompletionOptions options = new()
{
    ReasoningEffortLevel = ChatReasoningEffortLevel.Low,
    MaxOutputTokenCount = 100000
};

ChatCompletion completion = await chatClient.CompleteChatAsync(
[
    new DeveloperChatMessage("You are a helpful assistant"),
    new UserChatMessage("Explain the theory of relativity")
], options);

Azure AI Search との統合(RAG)

using Azure.AI.OpenAI.Chat;

#pragma warning disable AOAI001

ChatCompletionOptions options = new();
options.AddDataSource(new AzureSearchChatDataSource()
{
    Endpoint = new Uri(searchEndpoint),
    IndexName = searchIndex,
    Authentication = DataSourceAuthentication.FromApiKey(searchKey)
});

ChatCompletion completion = await chatClient.CompleteChatAsync(
    [new UserChatMessage("What health plans are available?")],
    options);

ChatMessageContext context = completion.GetMessageContext();
if (context?.Intent is not null)
{
    Console.WriteLine($"Intent: {context.Intent}");
}
foreach (ChatCitation citation in context?.Citations ?? [])
{
    Console.WriteLine($"Citation: {citation.Content}");
}

埋め込み

using OpenAI.Embeddings;

EmbeddingClient embeddingClient = azureClient.GetEmbeddingClient("text-embedding-ada-002");

OpenAIEmbedding embedding = await embeddingClient.GenerateEmbeddingAsync("Hello, world!");
ReadOnlyMemory<float> vector = embedding.ToFloats();

Console.WriteLine($"Embedding dimensions: {vector.Length}");
バッチ埋め込み
List<string> inputs = new()
{
    "First document text",
    "Second document text",
    "Third document text"
};

OpenAIEmbeddingCollection embeddings = await embeddingClient.GenerateEmbeddingsAsync(inputs);

foreach (OpenAIEmbedding emb in embeddings)
{
    Console.WriteLine($"Index {emb.Index}: {emb.ToFloats().Length} dimensions");
}

画像生成(DALL-E)

using OpenAI.Images;

ImageClient imageClient = azureClient.GetImageClient("dall-e-3");

GeneratedImage image = await imageClient.GenerateImageAsync(
    "A futuristic city skyline at sunset",
    new ImageGenerationOptions
    {
        Size = GeneratedImageSize.W1024xH1024,
        Quality = GeneratedImageQuality.High,
        Style = GeneratedImageStyle.Vivid
    });

Console.WriteLine($"Image URL: {image.ImageUri}");

音声(Whisper)

文字起こし
using OpenAI.Audio;

AudioClient audioClient = azureClient.GetAudioClient("whisper");

AudioTranscription transcription = await audioClient.TranscribeAudioAsync(
    "audio.mp3",
    new AudioTranscriptionOptions
    {
        ResponseFormat = AudioTranscriptionFormat.Verbose,
        Language = "en"
    });

Console.WriteLine(transcription.Text);
テキスト読み上げ
BinaryData speech = await audioClient.GenerateSpeechAsync(
    "Hello, welcome to Azure OpenAI!",
    GeneratedSpeechVoice.Alloy,
    new SpeechGenerationOptions
    {
        SpeedRatio = 1.0f,
        ResponseFormat = GeneratedSpeechFormat.Mp3
    });

await File.WriteAllBytesAsync("output.mp3", speech.ToArray());

関数呼び出し(ツール)

ChatTool getCurrentWeatherTool = ChatTool.CreateFunctionTool(
    functionName: "get_current_weather",
    functionDescription: "Get the current weather in a given location",
    functionParameters: BinaryData.FromString("""
        {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"]
                }
            },
            "required": ["location"]
        }
        """));

ChatCompletionOptions options = new()
{
    Tools = { getCurrentWeatherTool }
};

ChatCompletion completion = await chatClient.CompleteChatAsync(
    [new UserChatMessage("What's the weather in Seattle?")],
    options);

if (completion.FinishReason == ChatFinishReason.ToolCalls)
{
    foreach (ChatToolCall toolCall in completion.ToolCalls)
    {
        Console.WriteLine($"Function: {toolCall.FunctionName}");
        Console.WriteLine($"Arguments: {toolCall.FunctionArguments}");
    }
}

主な型のリファレンス

型用途
AzureOpenAIClientAzure OpenAI の最上位クライアント
ChatClientチャット補完
EmbeddingClientテキスト埋め込み
ImageClient画像生成(DALL-E)
AudioClient音声の文字起こし/TTS
ChatCompletionチャット応答
ChatCompletionOptionsリクエスト設定
StreamingChatCompletionUpdateストリーミング応答チャンク
ChatMessage基本メッセージ型
SystemChatMessageシステムプロンプト
UserChatMessageユーザー入力
AssistantChatMessageアシスタントの応答
DeveloperChatMessage開発者メッセージ(推論モデル)
ChatTool関数/ツールの定義
ChatToolCallツール呼び出しリクエスト

ベストプラクティス

  1. 本番環境では Entra ID を使用する — API キーを避け、DefaultAzureCredential を使用します
  2. クライアントインスタンスを再利用する — 一度作成し、複数のリクエストで共有します
  3. レート制限に対処する — 429 エラーに対して指数バックオフを実装します
  4. 長い応答ではストリーミングを使用する — UX を向上させるため、CompleteChatStreamingAsync を使用します
  5. 適切なタイムアウトを設定する — 長い補完ではタイムアウトを延長する必要がある場合があります
  6. 構造化出力を使用する — JSON schema によって一貫した応答形式を確保します
  7. トークン使用量を監視する — コスト管理のために completion.Usage を追跡します
  8. ツール呼び出しを検証する — 実行前に必ず関数の引数を検証します

エラー処理

using System.ClientModel;

try
{
    ChatCompletion completion = await chatClient.CompleteChatAsync(messages);
}
catch (System.ClientModel.ClientResultException ex) when (ex.Status == 429)
{
    Console.WriteLine("Rate limited. Retry after delay.");
    await Task.Delay(TimeSpan.FromSeconds(10));
}
catch (System.ClientModel.ClientResultException ex) when (ex.Status == 400)
{
    Console.WriteLine($"Bad request: {ex.Message}");
}
catch (System.ClientModel.ClientResultException ex)
{
    Console.WriteLine($"Azure OpenAI error: {ex.Status} - {ex.Message}");
}

関連 SDK

SDK用途インストール
Azure.AI.OpenAIAzure OpenAI クライアント(この SDK)dotnet add package Azure.AI.OpenAI
OpenAIOpenAI との互換性dotnet add package OpenAI
Azure.Identity認証dotnet add package Azure.Identity
Azure.Search.DocumentsRAG 向け AI Searchdotnet add package Azure.Search.Documents

参考リンク

リソースURL
NuGet パッケージhttps://www.nuget.org/packages/Azure.AI.OpenAI
API リファレンスhttps://learn.microsoft.com/dotnet/api/azure.ai.openai
移行ガイド(1.0→2.0)https://learn.microsoft.com/azure/ai-services/openai/how-to/dotnet-migration
クイックスタートhttps://learn.microsoft.com/azure/ai-services/openai/quickstart
GitHub ソースhttps://github.com/Azure/azure-sdk-for-net/tree/main/sdk/openai/Azure.AI.OpenAI

使用する場面

このスキルは、概要で説明されているワークフローまたはアクションを実行する場合に適用できます。

制限事項

  • このスキルは、タスクが上記の説明された範囲に明確に合致する場合にのみ使用してください。
  • 出力を、環境固有の検証、テスト、専門家によるレビューの代わりとして扱わないでください。
  • 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。

例は個別の断片であり、コンパイル可能なアプリケーションではありません。必要なインポート、変数、モデル固有のデプロイ名を追加してください。チャット/音声/画像の機能やオプションは、デプロイや API のバージョンによって異なります。通常、Whisper による文字起こしと音声生成には異なるデプロイが必要です。インデックス化する前に、拒否、終了理由、コンテンツ数を確認してください。構造化出力であっても、拒否されずに正常な応答が得られるとは限りません。取得したテキストやツールの引数は信頼できないものとして扱い、副作用を伴う操作は個別に認可してください。再試行の回数に上限を設け、再試行のヒントに従ってください。一度スリープするだけでは再試行ループにはなりません。プロンプト、引用、機密データを含む生のサービスエラーをログに記録しないでください。ここで示すモデル名、パッケージのバージョン、プレビュー API は過去の例であり、現在利用可能であることを示すものではありません。

コメント