📚

Semantic Kernelのプロンプトをファイルに書く

2023/12/21に公開

始めに

Semantic Kernelが日本時間2023/12/19に正式リリースされました。今後は破壊的変更も落ち着くと思われます。
まだ、Semantic Kernelの公式ドキュメントが日本語化されていないことからこれを機に少しずつSemantic Kernelの使用方法についてまとめていきたいと思います。

前提

Semantic Kernel 1.0.1
.NET 8

プロンプトのファイル化

プロンプトを別ファイルに出すことでプログラム本体とプロンプトやLLMの設定部分を外出しにすることでロジックの実装に集中できるようになります。

フォルダー構成

Promptsフォルダをつくり、その下にchatフォルダを作りchatフォルダ配下にconfig.jsonとskprompt.txtを作成しました。
2つのファイルは必須です。

skprompt.txt

skprompt.txtのほうにいわゆるプロンプトを書いていきます。
前回と同様の内容で書いておきます。

skprompt.txt
{{$history}}
User: {{$message}}
Assistant:

このプロンプトでは「history」と「message」の2つの変数を持っているためプロンプトを実行する時にこれらの値を含めることができます。

config.json

config.json
{
  "schema": 1,
  "type": "completion",
  "description": "ユーザーとの楽しい応答をします。",
  "execution_settings": {
    "default": {
      "max_tokens": 1000,
      "temperature": 0
    },
    "gpt-3.5-turbo": {
      "model_id": "gpt-3.5-turbo-0613",
      "max_tokens": 4000,
      "temperature": 0.1
    },
    "gpt-4": {
      "model_id": "gpt-4-1106-preview",
      "max_tokens": 8000,
      "temperature": 0.3
    }
  },
  "input_variables": [
    {
      "name": "message",
      "description": "ユーザーからのメッセージです。",
      "required": true
    },
    {
      "name": "history",
      "description": "応答の履歴を示します。",
      "required": true
    }
  ]
}

ここには、chat関数の設定を入れておきます。
いくつか必須の設定があります。

  • type : プロンプトのタイプ
  • description : プロンプトの動作の説明。プランナーがこの関数を使用して自動的に動作させようとするときに使用します。
  • input_variables プロンプト内で使用される変数を定義します

プロンプトを呼び出す

using Microsoft.Extensions.Configuration;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

Kernel kernel = Kernel.CreateBuilder()
 .AddAzureOpenAIChatCompletion(
    "デプロイ名",
    "エンドポイント",
    "APIキー").Build();
Console.WriteLine(System.Environment.CurrentDirectory);
var prompts = kernel.CreatePluginFromPromptDirectory("Prompts"); // 実行方法によってカレントディレクトリが異なるのでそこは要考慮

ChatHistory history = [];
while (true)
{
    Console.Write("User: ");
    string? message = Console.ReadLine();
    if (message == "exit")
    {
        break;
    }
    else
    {
        var result = await kernel.InvokeAsync(prompts["chat"], new() {
            { "message", message},
            { "history", string.Join("\n", history.Select(x => x.Role + ": " + x.Content))},
        });
        Console.WriteLine(result.ToString());
        history.AddUserMessage(message!);
        history.AddAssistantMessage(result.ToString());
    }


}

コメントを一カ所入れたところで先ほどのプロンプトを呼び出しているが実行するカレントディレクトリによってパス解決が変動するので要考慮。

Program.csのあるパスで実行することを前提のソースになっています。

実行結果

きちんと動いてそう。

Discussion