.NET を使用して Azure AI チャット アプリを構築する

単純な .NET 8 コンソール チャット アプリケーションを作成して、Semantic Kernel を使い始めましょう。 このアプリケーションはローカルで実行され、Azure OpenAI アカウントにデプロイされた OpenAI gpt-35-turbo モデルを使用します。 以下の手順のようにして、Azure OpenAI をプロビジョニングし、Semantic Kernel の使い方を学習します。

.NET Azure OpenAI SDK の使用を開始するには、シンプルな .NET 8 コンソール チャット アプリケーションを作成します。 このアプリケーションはローカルで実行され、Azure OpenAI アカウントにデプロイされた OpenAI gpt-35-turbo モデルを使用します。 次の手順に従って Azure OpenAI をプロビジョニングし、.NET Azure OpenAI SDK を使用する方法を習得します。

前提条件

Azure リソースをデプロイする

前提条件」に従って Azure OpenAI Service と Azure Developer CLI にアクセスできることを確認してから、以下のガイドに従ってサンプル アプリケーションを開始します。

  1. リポジトリをクローンします: dotnet/ai-samples

  2. ターミナルまたはコマンド プロンプトから、quickstarts ディレクトリに移動します。

  3. これで、Azure OpenAI リソースがプロビジョニングされます。 Azure OpenAI サービスを作成してモデルをデプロイするには、数分かかる場合があります。

    azd up
    

Note

Azure OpenAI サービスが既に使用可能な場合は、デプロイをスキップし、Program.cs で (可能であれば IConfigurationから) その値を使用できます。

トラブルシューティング

Windows では、azd up の実行後に次のエラー メッセージが表示されることがあります。

postprovision.ps1 はデジタル署名されていません。 スクリプトはシステムで実行されません

postprovision.ps1 スクリプトは、アプリケーションで使用される .NET ユーザー シークレットを設定するために実行されます。 このエラーを回避するために、次の PowerShell コマンドを実行します。

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

azd up コマンドを再実行します。

もう 1 つの考えられるエラー:

'pwsh' が内部または外部コマンド、操作可能プログラムまたはバッチ ファイルとして認識されない。 警告: 'postprovision' フックは終了コード '1' で失敗しました、パス: '.\infra\post-script\postprovision.ps1'。 : 終了コード: 1 ContinueOnError が true に設定されているため、実行が継続されます。

postprovision.ps1 スクリプトは、アプリケーションで使用される .NET ユーザー シークレットを設定するために実行されます。 このエラーを回避するには、次の PowerShell コマンドを使用して手動でスクリプトを実行します。

.\infra\post-script\postprovision.ps1

.NET AI アプリでユーザー シークレットが構成され、テストできるようになりました。

HikerAI サンプルを試す

  1. ターミナルまたはコマンド プロンプトから、semantic-kernel\02-HikerAI ディレクトリに移動します。
  1. ターミナルまたはコマンド プロンプトから、azure-openai-sdk\02-HikerAI ディレクトリに移動します。
  1. 次に、コンソール アプリケーションを試してみましょう。 アプリを実行するには、次のように入力します。

    dotnet run
    

    エラー メッセージが表示された場合、Azure OpenAI リソースのデプロイが完了していない可能性があります。 数分待ってからもう一度試してください。

コードの概要

このアプリケーションでは、NuGet で入手可能な Microsoft.SemanticKernel パッケージを使用して、Azure 内にデプロイされた Azure OpenAI サービスに要求を送受信します。

アプリケーション全体が Program.cs ファイル内に含まれています。 最初の数行のコードでは、アプリケーションのプロビジョニング中に dotnet user-secrets で設定されたシークレットと構成値が読み込まれます。

// == Retrieve the local secrets saved during the Azure deployment ==========
var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
string endpoint = config["AZURE_OPENAI_ENDPOINT"];
string deployment = config["AZURE_OPENAI_GPT_NAME"];
string key = config["AZURE_OPENAI_KEY"];

AzureOpenAIChatCompletionService サービスは、要求と応答を円滑にします。

// == Create the Azure OpenAI Chat Completion Service  ==========
AzureOpenAIChatCompletionService service = new(deployment, endpoint, key);

AzureOpenAIChatCompletionService サービスが作成されたら、システム プロンプトを追加して、そのモデルにより多くのコンテキストを提供します。 これにより、会話中にどのように動作させるかモデルに指示します。

// Start the conversation with context for the AI model
ChatHistory chatHistory = new("""
    You are a hiking enthusiast who helps people discover fun hikes in their area. You are upbeat and friendly. 
    You introduce yourself when first saying hello. When helping people out, you always ask them 
    for this information to inform the hiking recommendation you provide:

    1. Where they are located
    2. What hiking intensity they are looking for

    You will then provide three suggestions for nearby hikes that vary in length after you get that information. 
    You will also share an interesting fact about the local nature on the hikes when making a recommendation.
    """);

その後、AddUserMessage 関数を使用して、そのモデルにユーザー メッセージを追加することができます。

モデルにシステム プロンプトとユーザー要求に基づいて応答を生成させるには、GetChatMessageContentAsync 関数を使用します。


// Add user message to chat history
chatHistory.AddUserMessage("Hi! Apparently you can help me find a hike that I will like?");

// Print User Message to console
Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");

// Get response
var response = await service.GetChatMessageContentAsync(chatHistory, new OpenAIPromptExecutionSettings() { MaxTokens = 400 });

チャット履歴を維持するには、そのモデルからの応答を必ず追加してください。

// Add response to chat history
chatHistory.Add(response);

// Print Response to console
Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");

システム プロンプトとユーザー メッセージをカスタマイズして、好みのハイキングを見つけるのを助けるために、モデルがどのように応答するかを確認します。

コードの概要

このアプリケーションでは、NuGet で使用できる Azure.AI.OpenAI クライアント SDK を使用して、Azure にデプロイされた Azure OpenAI サービスとの間で要求を送受信します。

アプリケーション全体が Program.cs ファイル内に含まれています。 最初の数行のコードでは、アプリケーションのプロビジョニング中に dotnet user-secrets で設定されたシークレットと構成値が読み込まれます。

// == Retrieve the local secrets saved during the Azure deployment ==========
var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
string openAIEndpoint = config["AZURE_OPENAI_ENDPOINT"];
string openAIDeploymentName = config["AZURE_OPENAI_GPT_NAME"];
string openAiKey = config["AZURE_OPENAI_KEY"];

// == Creating the AIClient ==========
var endpoint = new Uri(openAIEndpoint);
var credentials = new AzureKeyCredential(openAiKey);

OpenAIClient クラスは、要求と応答を行いやすくします。 ChatCompletionOptions は、モデルの応答方法のパラメーターを指定します。

var openAIClient = new OpenAIClient(endpoint, credentials);

var completionOptions = new ChatCompletionsOptions
{
    MaxTokens = 400,
    Temperature = 1f,
    FrequencyPenalty = 0.0f,
    PresencePenalty = 0.0f,
    NucleusSamplingFactor = 0.95f, // Top P
    DeploymentName = openAIDeploymentName
};

OpenAIClient クライアントが作成されたら、システム プロンプトを追加して、モデルにより多くのコンテキストを提供します。 これにより、会話中にどのように動作させるかモデルに指示します。

var systemPrompt = 
"""
You are a hiking enthusiast who helps people discover fun hikes in their area. You are upbeat and friendly. 
You introduce yourself when first saying hello. When helping people out, you always ask them 
for this information to inform the hiking recommendation you provide:

1. Where they are located
2. What hiking intensity they are looking for

You will then provide three suggestions for nearby hikes that vary in length after you get that information. 
You will also share an interesting fact about the local nature on the hikes when making a recommendation.
""";

completionOptions.Messages.Add(new ChatRequestSystemMessage(systemPrompt));

その後、ChatRequestUserMessage クラスを使用して、モデルにユーザー メッセージを追加できます。

モデルにシステム プロンプトとユーザー要求に基づいて応答を生成させるには、GetChatCompletionsAsync 関数を使用します。

string userGreeting = """
Hi! 
Apparently you can help me find a hike that I will like?
""";

completionOptions.Messages.Add(new ChatRequestUserMessage(userGreeting));
Console.WriteLine($"\n\nUser >>> {userGreeting}");

ChatCompletions response = await openAIClient.GetChatCompletionsAsync(completionOptions);
ChatResponseMessage assistantResponse = response.Choices[0].Message;
Console.WriteLine($"\n\nAI >>> {assistantResponse.Content}");
completionOptions.Messages.Add(new ChatRequestAssisstantMessage(assistantResponse.Content)); 

チャット履歴またはコンテキストを維持するには、モデルからの応答を ChatRequestAssistantMessage として必ず追加します。

システム プロンプトとユーザー メッセージをカスタマイズして、好みのハイキングを見つけるのを助けるために、モデルがどのように応答するかを確認します。

リソースをクリーンアップする

サンプル アプリケーションやリソースが不要になったら、対応するデプロイとすべてのリソースを削除します。

azd down

次のステップ