ツールを使用して OpenAI を拡張し .NET でローカル関数を実行する

単純な .NET 8 コンソール チャット アプリケーションを作成することで、AI の利用を開始します。 このアプリケーションはローカルで実行され、OpenAI gpt-3.5-turbo モデルが使用されます。ローカルの .NET メソッドを呼び出してモデルの機能を拡張するためにツールが使用されます。 次の手順に従って、OpenAI にアクセスし、Semantic Kernel の使用方法を学習します。

前提条件

  • .NET 8.0 SDK - .NET 8.0 SDK をインストールします
  • このサンプルを実行できるようにするための OpenAI の API キー
  • Windows では PowerShell v7+ が必要です。 バージョンを検証するには、ターミナルで pwsh を実行します。 現在のバージョンが返されるはずです。 エラーが返された場合は、コマンド dotnet tool update --global PowerShell を実行します。

単純な .NET 8 コンソール チャット アプリケーションを作成することで、AI の利用を開始します。 このアプリケーションはローカルで実行され、Azure OpenAI アカウントにデプロイされた OpenAI gpt-35-turbo モデルを使用します。 ツールを使用して、ローカルの .NET メソッドを呼び出してモデルの機能を拡張します。 Azure OpenAI をプロビジョニングし、Semantic Kernel の使用方法を学習するには、以下の手順に従います。

前提条件

サンプル プロジェクトを入手する

すべてのクイックスタートのサンプル アプリが含まれる GitHub リポジトリをクローンします。

git clone https://github.com/dotnet/ai-samples.git

Azure OpenAI サービスを作成する

サンプルの GitHub リポジトリは、Azure Developer CLI (azd) テンプレートとして構成されています。azd がこれを使用して、Azure OpenAI サービスとモデルをプロビジョニングできます。

  1. ターミナルまたはコマンド プロンプトで、サンプル リポジトリの src\quickstarts\azure-openai ディレクトリに移動します。

  2. azd up コマンドを実行して、Azure OpenAI リソースをプロビジョニングします。 Azure OpenAI サービスの作成とモデルのデプロイには数分かかる場合があります。

    azd up
    

    azd は、OpenAI アクセス キーなど、サンプル アプリに必要なユーザー シークレットも構成します。

    Note

    azd up のデプロイ中にエラーが発生した場合は、「トラブルシューティング」セクションを参照してください。

ハイカー プロ サンプルをお試しください

  1. ターミナルまたはコマンド プロンプトから、azure-openai\04-HikerAIPro ディレクトリに移動します。

  2. 次のコマンドを実行して、OpenAI API キーをサンプル アプリのシークレットとして構成します。

    dotnet user-secrets init
    dotnet user-secrets set OpenAIKey <your-openai-key>
    
  3. dotnet run コマンドを使用してアプリを実行します。

    dotnet run
    
  1. ターミナルまたはコマンド プロンプトから、azure-openai\04-HikerAIPro ディレクトリに移動します。

  2. dotnet run コマンドを使用してアプリを実行します。

    dotnet run
    

    ヒント

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

コードの理解

このアプリケーションでは、Microsoft.SemanticKernel パッケージを使用して、OpenAI サービスへの要求を送受信します。

アプリケーション全体が Program.cs ファイル内に含まれています。 コードの最初の数行によって、構成値が設定され、dotnet user-secrets コマンドを使用して以前に設定された OpenAI キーが取得されます。

var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
string model = "gpt-3.5-turbo";
string key = config["OpenAIKey"];

Kernel クラスを使うと、AddOpenAIChatCompletion サービスの助けにより要求と応答が容易になります。

// Create a Kernel containing the OpenAI Chat Completion Service
IKernelBuilder b = Kernel.CreateBuilder();

Kernel kernel = b
    .AddOpenAIChatCompletion(model, key)
    .Build();

このアプリケーションでは、Microsoft.SemanticKernel パッケージを使用して、OpenAI サービスへの要求を送受信します。

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

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"];

Kernel クラスを使うと、AzureOpenAIChatCompletion サービスの助けにより要求と応答が容易になります。

// Create a Kernel containing the Azure OpenAI Chat Completion Service
IKernelBuilder b = Kernel.CreateBuilder();

Kernel kernel = b
    .AddAzureOpenAIChatCompletion(deployment, endpoint, key)
    .Build();

関数 ImportPluginFromFunctionsCreateFromMethod は、モデルによって呼び出されるローカル関数を定義するために使用されます。

// Add a new plugin with a local .NET function that should be available to the AI model
// For convenience and clarity of into the code, this standalone local method handles tool call responses. It will fake a call to a weather API and return the current weather for the specified location.
kernel.ImportPluginFromFunctions("WeatherPlugin",
[
    KernelFunctionFactory.CreateFromMethod(
        ([Description("The city, e.g. Montreal, Sidney")] string location, string unit = null) =>
    {
        // Here you would call a weather API to get the weather for the location
        return "Periods of rain or drizzle, 15 C";
    }, "get_current_weather", "Get the current weather in a given location")
]);

kernel クライアントが作成されると、コードはシステム プロンプトを使用してコンテキストを提供し、完了トーンとコンテンツに影響を与えます。 システム プロンプトで天気がどのように強調されているかに注目してください。

ChatHistory chatHistory = new("""
    You are a hiking enthusiast who helps people discover fun hikes in their area.
    You are upbeat and friendly. Good weather is important for a good hike. 
    Only make recommendations if the weather is good or if people insist.
    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 関数はチャット履歴をモデルに送信し、システムとユーザー プロンプトに基づいて応答を生成します。

chatHistory.AddUserMessage("""
    Is the weather is good today for a hike?
    If yes, I live in the greater Montreal area and would like an easy hike. 
    I don't mind driving a bit to get there. I don't want the hike to be over 10 miles round trip.
    I'd consider a point-to-point hike.
    I want the hike to be as isolated as possible. I don't want to see many people.
    I would like it to be as bug free as possible.
    """);

Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");

chatHistory.Add(await service.GetChatMessageContentAsync(
    chatHistory, 
    new OpenAIPromptExecutionSettings()
    { 
        MaxTokens = 400 
    }));

Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");

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

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

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

azd down

トラブルシューティング

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 アプリにユーザー シークレットが構成され、テストできるようになりました。

次のステップ