SemanticKernelにおけるSKプロンプトテンプレート構文とは?
Semantic Kernelは、大規模な学習モデル(LLM)AIに特定の応答を引き出すために、ユーザーやプログラムがモデルに与える入力やクエリです。
プロンプトは、自然言語の文や質問、コードの断片やコマンド、テキストやコードの組み合わせなど、ドメインやタスクに応じてさまざまな形式で表現されます。
プロンプトはネストやチェーンすることもでき、つまり、1つのプロンプトの出力を別のプロンプトの入力として使用することができます。これにより、モデルとのより複雑で動的なインタラクションを作成することができます。
SKプロンプトテンプレート構文
Semantic Kernelのプロンプトテンプレート言語は、テキストを使用してAI関数を定義し、組み合わせるためのシンプルでパワフルな方法です。この言語を使用して、自然言語のプロンプトを作成したり、応答を生成したり、情報を抽出したり、他のプロンプトを呼び出したり、テキストで表現できる他のタスクを実行したりすることができます。
この言語は、変数を含めること、外部関数を呼び出すこと、関数にパラメータを渡すことの3つの基本的な機能をサポートしています。
コードを書いたり外部ライブラリをインポートしたりする必要はありません。かっこ括弧{{…}}を使用して、プロンプトに式を埋め込みます。Semantic Kernelはテンプレートを解析し、その背後のロジックを実行します。このようにして、最小の労力と最大の柔軟性でAIをアプリケーションに統合することができます。
変数
テキストに変数の値を含めるには、{{$変数名}}の構文を使用します。たとえば、ユーザーの名前を保持する変数nameがある場合、次のように書くことができます。
こんにちは{{$name}}さん、Semantic Kernelへようこそ!
これにより、ユーザーの名前を含んだ挨拶が生成されます。
スペースは無視されるため、より読みやすくするために次のように書くこともできます。
こんにちは{{ $name }}さん、Semantic Kernelへようこそ!
関数呼び出し
外部関数を呼び出して結果をテキストに埋め込むには、{{namespace.functionName}}の構文を使用します。たとえば、場所を指定して天気予報を返すweather.getForecastという関数がある場合、次のように書くことができます。
今日の天気は{{weather.getForecast}}です。
これにより、デフォルトの場所に対する天気予報を含んだ文が生成されます。入力変数にはカーネルが自動的に値を設定します。たとえば、上記のコードは次と同じです。
今日の天気は{{weather.getForecast $input}}です。
関数パラメータ
外部関数を呼び出してパラメータを渡すには、{{namespace.functionName $varName}}や{{namespace.functionName “value”}}の構文を使用します。たとえば、天気予報関数に異なる入力を渡したい場合は、次のように書くことができます。
{{$city}}の今日の天気は{{weather.getForecast $city}}です。
Schioの今日の天気は{{weather.getForecast "Schio"}}です。
これにより、city変数に格納された都市と、プロンプトテンプレートにハードコードされた”Schio”の2つの異なる場所の天気予報を含んだ2つの文が生成されます。
デザイン原則
テンプレート言語は、シンプルでレンダリングが高速であり、自然言語を使用して関数を作成することができるように設計されています。特別な構文を最小限に抑え、エッジケースを最小限にするため、特殊な構文を最小限に抑え、一般的なプログラミングコードからの明確な分離を実現しています。
テンプレート言語では、関数呼び出しと変数の区別が明確になるように、「$」記号を意図的に使用しています。
“if”や”for”などの分岐機能やコードブロックは、SKのテンプレート言語の一部ではありません。これは、SKができるだけ自然言語を使用し、従来のプログラミングコードと明確に分離するというSKの設計原則を反映しています。
シンプルな言語を使用することで、カーネルは複雑なパーシングや外部の依存関係を回避し、高速かつメモリ効率の良い処理を実現できます。
Semantic Functionの例
Semantic Functionは、SKのPrompt Template言語を使用してテキストファイル(例:「skprompt.txt」)に記述された自然言語の関数です。以下は、Prompt Templateを使用して定義されたシンプルなSemantic Functionの例です。
== ファイル: skprompt.txt ==
私の名前:{{msgraph.GetMyName}}
私のメールアドレス:{{msgraph.GetMyEmailAddress}}
私の趣味:{{memory.recall "my hobbies"}}
受信者:{{$recipient}}
返信するためのメールアドレス:
=========
{{$sourceEmail}}
=========
メールに対して返信するための応答を生成し、応答後に元のメールを引用してください。
これをC#で記述すると、次のようになります。
async Task<string> GenResponseToEmailAsync(
string whatToSay,
string recipient,
string sourceEmail)
{
try {
string name = await this._msgraph.GetMyName();
} catch {
...
}
try {
string email = await this._msgraph.GetMyEmailAddress();
} catch {
...
}
try {
// 5つの与えられた変数を使用してAIを使用してメールを生成する
// リトライロジック、AIのコストの追跡などに注意する
string response = await ...
return response;
} catch {
...
}
}
特殊文字に関する注意事項
Semantic Functionテンプレートはテキストファイルであるため、改行やタブなどの特殊文字をエスケープする必要はありません。ただし、特殊な構文を必要とする2つのケースがあります。
- プロンプトテンプレート内で二重の中括弧を含める場合
- 引用符を含むハードコードされた値を関数に渡す場合
二重中括弧を必要とするプロンプト
二重中括弧は、変数や値、関数をテンプレートに埋め込むために特別な用途で使用されます。
プロンプト内に {{ と }} のシーケンスを含める必要がある場合(特別なレンダリングロジックをトリガーする可能性がある場合)、最適な解決策は、”{{ “{{” }}”と “{{ “}}” }}”という形式のクォートで囲まれた文字列値を使用することです。
たとえば:
{{ “{{” }} and {{ “}}” }} are special SK sequences.
は次のようにレンダリングされます:
{{ and }} are special SK sequences.
引用符を含む値とエスケープ
値はシングルクォートとダブルクォートで囲むことができます。
シングルクォートを含む値を扱う場合は、シングルクォートで値を囲むことをお勧めします。同様に、ダブルクォートを含む値を使用する場合は、値をシングルクォートで囲みます。
たとえば:
...text... {{ functionName "one 'quoted' word" }} ...text...
...text... {{ functionName 'one "quoted" word' }} ...text...
この場合、次のようにレンダリングされます:
...text... one 'quoted' word ...text...
...text... one "quoted" word ...text...
シングルクォートとダブルクォートの両方を含む値の場合、エスケープを行うために特殊な構文を使用する必要があります。その場合、特殊な「\」記号を使用してエスケープします。
ダブルクォートで値を囲む場合、値の中にダブルクォート記号を含めるには「\”」を使用します。
... {{ "quotes' \"escaping\" example" }} ...
同様に、シングルクォートを使用する場合は、「\’」を使用してシングルクォートを値の中に含めます。
... {{ 'quotes\' "escaping" example' }} ...
この場合、次のようにレンダリングされます:
... quotes' "escaping" example ...
一貫性のために、シーケンス「\’」と「\”」は常に「’」と「”」にレンダリングされます。エスケープが必要ない場合でも、一貫性を保つためにエスケープすることができます。
たとえば:
... {{ 'no need to \"escape" ' }} ...
は次のと等価です:
... {{ 'no need to "escape" ' }} ...
両方とも次のようにレンダリングされます:
... no need to "escape" ...
バックスラッシュを引用符の前にレンダリングする必要がある場合、バックスラッシュ文字自体は特殊な意味を持ちますので、それもエスケープする必要があり、特殊なシーケンス「\\\’」および「\\\”」を使用します。
たとえば:
{{ ‘two special chars \\\’ here’ }}
は次のようにレンダリングされます:
two special chars \’ here
シングルクォートとダブルクォート以外の場合、バックスラッシュ文字は特別な意味を持たず、そのままレンダリングされます
たとえば:
{{ “nothing special about these sequences: \0 \n \t \r \foo” }}
は次のようにレンダリングされます:
nothing special about these sequences: \0 \n \t \r \foo
コメント