演習 - Azure OpenAI サービスを実装する

完了

まず、ごく簡単なサービスである OpenAiService から始めましょう。 このサービスには、基本的なプロンプトと入力候補をすぐに実装できるように、実装する必要があるメソッドが 2 つだけ含まれています。 Azure Cosmos DB for NoSQL データ サービスは後になるまで実装しないため、デバッグ セッション間でセッションを保持することはまだできません。

この演習では、いくつかの重要な要件があります。

  • ユーザーから AI アシスタントに質問を送信し、応答を求めます。
  • 一連のプロンプトを AI アシスタントに送信し、会話の要約を求めます。

AI モデルに質問する

まず、システム プロンプト、質問、セッション ID を送信して質問と回答の会話を実装し、AI モデルが現在の会話のコンテキストで回答を提供できるようにします。 プロンプトを解析して応答 (またはこのコンテキストでの完了) を返すために必要なトークンの数を測定してください。

  1. Services/OpenAiService.cs ファイルを開きます。

  2. GetChatCompletionAsync メソッド内で、既存のプレースホルダー コードをすべて削除します。

    public async Task<(string completionText, int completionTokens)> GetChatCompletionAsync(string sessionId, string userPrompt)
    {
    }
    
  3. systemMessage という名前の ChatRequestSystemMessage 変数を作成します。 この変数では、User ロールと、内容に対する _systemPrompt 変数を使用します。

    ChatRequestSystemMessage systemMessage = new(_systemPrompt);
    
  4. userMessage という名前の ChatRequestUserMessage 変数を作成します。 この変数の場合、ロールは ChatRole.User である必要があり、メッセージの内容に userPrompt コンストラクター パラメーターを使用する必要があります。

    ChatRequestUserMessage userMessage = new(userPrompt);
    
  5. options という名前の ChatCompletionsOptions 型の新しい変数を作成します。 2 つのメッセージ変数を Messages リストに追加し、User の値を sessionId コンストラクター パラメーターに設定し、MaxTokens4000 に設定して、残りのプロパティを次の推奨値に設定します。

    ChatCompletionsOptions options = new()
    {
        DeploymentName = _modelName,
        Messages = {
            systemMessage,
            userMessage
        },
        User = sessionId,
        MaxTokens = 4000,
        Temperature = 0.3f,
        NucleusSamplingFactor = 0.5f,
        FrequencyPenalty = 0,
        PresencePenalty = 0
    };
    

    ヒント

    gpt-35-turbo モデルのトークンの最大数は 4096 です。 ここでは、作業を簡略化するために単に丸め込みます。

  6. Azure OpenAI クライアント変数 (_client) の GetChatCompletionsAsync メソッドを非同期的に呼び出します。 作成した options 変数を渡します。 結果を completions という名前のChatCompletions 型の変数に格納します。

    ChatCompletions completions = await _client.GetChatCompletionsAsync(options);
    

    ヒント

    GetChatCompletionsAsync メソッドは、Task<Response<ChatCompletions>> 型のオブジェクトを返します。 Response<T> クラスには、T 型への暗黙的な変換が含まれており、アプリケーションのニーズに基づいて型を選択できます。 結果は、応答から完全なメタデータを取得するための Response<ChatCompletions> として、または結果自体の内容のみを考慮する場合は単に ChatCompletions として格納できます。

  7. 最後に、GetChatCompletionAsync メソッドの結果として、文字列としての入力候補の内容、プロンプトに関連付けられたトークンの数、および応答のトークンの数と共にタプルを返します。

    return (
        response: completions.Choices[0].Message.Content,
        promptTokens: completions.Usage.PromptTokens,
        responseTokens: completions.Usage.CompletionTokens
    );
    
  8. Services/OpenAiService.cs ファイルを保存します。

AI モデルに会話の要約を求める

次に、AI モデルに別のシステム プロンプト、現在の会話、セッション ID を送信して、AI モデルが会話をいくつかの単語で要約できるようにします。

  1. SummarizeAsync メソッド内で、既存のプレースホルダー コードをすべて削除します。

    public async Task<string> SummarizeAsync(string sessionId, string conversationText)
    {
    }
    
  2. systemMessage という名前の ChatRequestSystemMessage 変数を作成します。 この変数では、User ロールと、内容に対する _summarizePrompt 変数を使用します。

    ChatRequestSystemMessage systemMessage = new(_summarizePrompt);
    
  3. userMessage という名前の別の ChatRequestUserMessage 変数を作成します。 User ロールをもう一度使用し、メッセージの内容に対しては conversationText コンストラクター パラメーターを使用します。

    ChatRequestUserMessage userMessage = new(conversationText);
    
  4. Messages リスト内の 2 つのメッセージ変数を使用して、options という名前の ChatCompletionsOptions 変数を作成し、UsersessionId コンストラクター パラメーターに設定し、MaxTokens200 に設定し、残りのプロパティを次の推奨値に設定します。

    ChatCompletionsOptions options = new()
    {
        DeploymentName = _modelName,
        Messages = {
            systemMessage,
            userMessage
        },
        User = sessionId,
        MaxTokens = 200,
        Temperature = 0.0f,
        NucleusSamplingFactor = 1.0f,
        FrequencyPenalty = 0,
        PresencePenalty = 0
    };
    
  5. options 変数をパラメーターとして使って、_client.GetChatCompletionsAsync を非同期的に呼び出します。 結果を completions という名前のChatCompletions 型の変数に格納します。

    ChatCompletions completions = await _client.GetChatCompletionsAsync(options);
    
  6. SummarizeAsync メソッドの結果として、入力候補の内容を文字列として返します。

    return completions.Choices[0].Message.Content;
    
  7. Services/OpenAiService.cs ファイルを保存します。

作業を確認

この時点で、アプリケーションには、アプリケーションをテストできる、十分な Azure OpenAI サービスの実装が必要になります。 まだデータ ストアを実装していないため、会話はデバッグ セッション間で保持されないことに注意してください。

  1. 新しいターミナルを開きます。

  2. dotnet watch を使って、ホット リロードを有効にしてアプリケーションを起動します。

    dotnet watch run --non-interactive
    

    ヒント

    アプリケーションのコードを少し修正する必要がある場合は、ホット リロード機能をここで有効にします。 詳細については、「ASP.NET Core での .NET ホット リロードのサポート」を参照してください。

  3. Visual Studio Code により、Web アプリケーションが実行中の状態で、ツール内の単純なブラウザーが再起動されます。 Web アプリケーションで、新しいチャット セッションを作成し、AI アシスタントに質問します。 AI アシスタントは、モデルによって作成された入力候補を使用して応答するようになりました。 また、トークン UI フィールドに、入力候補とプロンプトごとの実際のトークン使用量が設定されていることにも注意してください。

    Screenshot of the application running with a connection Azure OpenAI.

  4. ターミナルを閉じます。