Semantic Kernel の使い方:パターン、プロンプト、プラグインを用いた実践ガイド
アプリに LLM を組み込もうとして、プロンプト、ヘルパー関数、状態がもろく絡み合った状態になってしまったことはありませんか?Semantic Kernel (SK) は、まさにそれを解決するために存在します。これは、自然言語、ツール、メモリを組み合わせて、コードベースをプロンプトスパゲッティにすることなく、AI ファーストなアプリを構築するための、Microsoft の軽量なオープンソースオーケストレーションフレームワークです。
このガイドでは、Semantic Kernel をゼロから本番環境のパターンまで、実践的かつソリューション指向で解説します。プロンプトの構成、ツールのプラグイン、メモリの追加、複数のモデルの呼び出し、一貫して動作するエージェントのデプロイ方法を学びます。例を具体的に示し、重要なポイントを解説します。
Semantic Kernel とは?そして、なぜそれを使うのか?
Semantic Kernel は、以下のことを支援する SDK です。
- 構成(「スキル」/プラグイン)をパイプラインに構成する。
- 複数のモデル (OpenAI、Azure OpenAI、ローカルモデル) を相互に呼び出す。
- コンテキストと長期的なリコールのためにメモリを追加する(埋め込み経由)。
- 信頼性の高い状態で、複数ステップのタスクを計画およびオーケストレーションする。
- ツール(API、データベース、ファイル I/O)を安全かつ決定論的に統合する。
SK は、LLM、アプリのロジック、ユーザーデータを調整するコントローラーと考えてください。長いプロンプトやアドホックなツール呼び出しをハードコーディングする代わりに、明確な入力/出力を持つ再利用可能なセマンティック関数とネイティブ関数を定義します。
一般的なユースケース:
- 検索拡張生成(RAG)による顧客サポートコパイロット
- ワークフローエージェント(要約 → 分類 → アクション実行)
クイックスタート:最初の Semantic Kernel アプリ
以下は、チャットモデルと簡単なプロンプトで Semantic Kernel を使用する方法を示す最小限のフローです。わかりやすくするために C# を使用します。Python や Java でも同様のことができます。
1) パッケージのインストール
# .NET
dotnet add package Microsoft.SemanticKernel
# オプション:コネクタとプランナーはバージョンによって異なります
2) カーネルとモデルの構成
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
var builder = Kernel.CreateBuilder;
// プロバイダーを選択:OpenAI または Azure OpenAI
builder.AddOpenAIChatCompletion(
modelId: "gpt-4o-mini", // またはお好みのモデル
apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")
);
var kernel = builder.Build;
3) セマンティック関数(プロンプト)の定義
using Microsoft.SemanticKernel.SemanticFunctions;
var prompt = @"あなたは簡潔な説明者です。
初心者向けに、'{topic}'の概念を3つの箇条書きで説明してください。";
var explainFunc = kernel.CreateFunctionFromPrompt(prompt);
var result = await explainFunc.InvokeAsync(kernel, new { ["topic"] = "vector embeddings" });
Console.WriteLine(result);
これがコアです:カーネル、モデル、そして入力を持つ再利用可能な関数に変換されたプロンプト。
セマンティック関数 vs. ネイティブ関数
- セマンティック関数:プロンプト駆動。テンプレートから作成し、変数を渡し、テキストまたは構造化された出力を取得します。
- ネイティブ関数:SK がツールとして LLM に公開する通常のコード関数。
API から天気を取得し、モデルに公開するネイティブ関数の例:
public class WeatherPlugin
{
[KernelFunction, Description("都市の天気を取得")]
public async Task<string> GetWeatherAsync(
[Description("都市名")] string city)
{
// ここで天気 API を呼び出す
var temp = 22; // プレースホルダー
return $"Weather in {city}: {temp}°C and clear";
}
}
// プラグインの登録
var weather = new WeatherPlugin;
kernel.Plugins.AddFromObject(weather, pluginName: "weather");
これで、プロンプトはツールとして weather.GetWeatherAsync を呼び出すことができ、モデルは実際のデータに基づいて応答することができます。
実際に機能するプロンプトパターン
Semantic Kernel の使い方を学ぶ際に、最も早く成果を上げるには、規律あるプロンプトパターンを使用することです。
- システムファースト:強力なシステムメッセージを使用して、トーン、ペルソナ、安全性、出力形式を固定します。
- 変数スロット:プレースホルダーに明確な名前を付け(例:
{topic}、{audience})、入力を検証します。
- 出力契約:JSON のような構造化された形式を要求します。プロンプトにスキーマを含めます。
- Few-shot:コンテンツの肥大化ではなく、スタイルと形式に関する簡潔な例を提供します。
- ガードレール:制約を含めます(「データがない場合は、最初に明確にするための質問をしてください」)。
SK 内の構造化されたプロンプトの例:
var prompt = @"
あなたは分類エンジンです。
タスク:`message`を[Billing, Tech Support, Sales]のいずれかに分類します。
厳密な JSON を返します:{ \"label\": string, \"confidence\": number }
message: {message}
";
var classify = kernel.CreateFunctionFromPrompt(prompt);
var output = await classify.InvokeAsync(kernel, new { ["message"] = "I can’t log into my account." });
Console.WriteLine(output); // {"label":"Tech Support","confidence":0.89}
メモリの追加:埋め込み、RAG、およびコンテキストウィンドウ
LLM は忘れます。メモリはそれらを役立つものにします。
- 長期メモリ:ユーザーのメモ、ドキュメント、またはイベントの埋め込みを保存し、コンテキストに関連するチャンクを取得します。
- RAG:生成関数を呼び出す前に、ベクターストアにクエリを実行し、結果をプロンプトに挿入します。
例:埋め込みを使用してテキストメモリを追加し、コンテキストを取得します。
using Microsoft.SemanticKernel.Memory;
var memory = new MemoryBuilder
.WithMemoryStore(new VolatileMemoryStore) // ベクトルDB(Qdrant、Pinecone、Azure AI Search)と交換
.WithTextEmbeddingGeneration(
new OpenAITextEmbeddingGeneration("text-embedding-3-small", Environment.GetEnvironmentVariable("OPENAI_API_KEY")))
.Build;
await memory.SaveInformationAsync(
collection: "policies", id: "refund-policy",
text: "領収書の証明があれば、購入後30日以内にお客様は払い戻しを請求できます。"
);
// 後で:取得してプロンプトに詰め込む
var results = memory.SearchAsync("refund window", collection: "policies", limit: 3, minRelevanceScore: 0.7);
await foreach (var item in results)
{
Console.WriteLine($"Relevant: {item.Metadata.Text}");
}
次に、上位一致をコンテキスト変数としてセマンティック関数にフィードします。ヒント:チャンクを小さく(200〜400トークン)保ち、重複排除します。
ツールの使用と計画:複数ステップのワークフロー
Semantic Kernel は、ユーザーの目標をステップに分解し、どの関数を呼び出すかを選択できるプランナーをサポートしています。これは、ネイティブ関数とセマンティック関数のツールボックスがある場合に最適です。
パターン:
- 計画(引数を持つ関数呼び出しのシーケンス)を草案します。
- ステップごとに実行し、出力を検証し、エラーから回復します。
擬似コードの例:
// 1) 以前と同様にプラグイン(セマンティック + ネイティブ)を定義します
// 2) プランナーを使用します(API サーフェスはバージョンによって異なる場合があります)
var goal = "添付されたポリシーを要約し、リスクを分類し、レポートをメールで送信します";
// プラグインがあると仮定します:files, summarize, classify, email
// プランナーは計画を組み立てます:files.Load → summarize.Run → classify.Run → email.Send
// 計画を順番に実行し、ステップ間で JSON 出力を検証します
ベストプラクティス:
- ネットワーク化されたツールで再試行/バックオフを使用します。
- 可観測性のために入力/出力をログに記録します(ただし、PII をスクラブします)。
マルチモデル戦略:ジョブに適したモデルを選択する
Semantic Kernel を使用すると、タスクを異なるモデルにルーティングできます。
実際には:
var kernel = Kernel.CreateBuilder
.AddOpenAIChatCompletion("gpt-4o-mini", apiKey)
.Build;
var fastKernel = Kernel.CreateBuilder
.AddOpenAIChatCompletion("gpt-4o-mini", apiKey) // 速度最適化
.Build;
// より単純なプロンプトを fastKernel にルーティングします。複雑なタスクは kernel にルーティングします
または、同じカーネルで複数のサービスを構成し、関数ごとに選択します。
プロトタイプから本番環境へ:ガードレールとテスト
実際のアプリで Semantic Kernel の使い方を学ぶにつれて、信頼性が重要になります。
- スキーマファーストの出力:JSON スキーマと
TryParse ゲートを使用します。
- 必要な場合の決定論:温度を低く設定し、出力を制約します。
- 安全フィルター:コンテンツフィルターとレッドチームプロンプトを追加します。
- キャッシュ:RAG の結果と安定した生成をキャッシュします。
- 可観測性:プロンプトテンプレート、変数、レイテンシー、トークン使用量をログに記録します。
- ユニットテスト:スナップショット比較によるゴールデンテストプロンプト。
例:JSON 出力を検証します。
record Classification(string label, double confidence);
bool TryParseClassification(string text, out Classification cls)
{
try { cls = System.Text.Json.JsonSerializer.Deserialize<Classification>(text)!; return true; }
catch { cls = default!; return false; }
}
再利用できる実際のパターン
- RAG チャットボット:引用付きの
retrieve(context) → answer(question, context)。
- 承認ワークフロー:classify → generate draft → human review → send。
- コンテンツ運用:outline → draft → fact-check → tone adjust → publish。
- ツール付きエージェント:calendar.lookup, docs.search, email.send; 計画とメモリ付き。
ヒント:各ステップを関数(セマンティックまたはネイティブ)としてカプセル化し、それらをパイプラインに構成します。
例:引用付きのドキュメント Q&A
RAG を使用してソースを引用する簡単な Q&A パイプラインを作成しましょう。
// 1) ドキュメントをメモリに取り込む
await memory.SaveInformationAsync("handbook", "vacation-policy",
"従業員は1か月あたり1.5日の有給休暇を取得し、5日間繰り越すことができます。");
// 2) 質問のコンテキストを取得する
var top = memory.SearchAsync("有給休暇の繰り越し", "handbook", limit: 3, minRelevanceScore: 0.75);</a5><a6>var top = memory.SearchAsync("carry over PTO", "handbook", limit: 3, minRelevanceScore: 0.75);
var contexts = new List<string>;
await foreach (var r in top) contexts.Add(r.Metadata.Text);
// 3) コンテキストと引用リクエストで質問する
var qaPrompt = @"
提供されたコンテキストから厳密に回答してください。ない場合は、知らないと言ってください。
1 から始まるコンテキスト項目のインデックスを使用して、[source i] のようなインライン引用を含めます。
コンテキスト:
1) {{ctx1}}
2) {{ctx2}}
質問:{{q}}
";
var qa = kernel.CreateFunctionFromPrompt(qaPrompt);
var variables = new KernelArguments
{
["ctx1"] = contexts.ElementAtOrDefault(0) ?? "",
["ctx2"] = contexts.ElementAtOrDefault(1) ?? "",
["q"] = "有給休暇は何日繰り越せますか?"
};
var answer = await qa.InvokeAsync(kernel, variables);
Console.WriteLine(answer);
一般的な落とし穴(とその回避方法)
- 単一の巨大なプロンプト:関数に分割します。必要なコンテキストのみを渡します。
- 出力契約なし:常に機械可読なステップのスキーマを定義します。
- 衛生なしの RAG:適切にチャンク化し、重複排除し、関連性と新しさでランク付けします。
- ツールの拡散:プラグインインターフェースを小さく保ち、ドキュメント化します。
- ヒューマンインザループなし:リスクの高いアクションの承認を追加します。
フロントエンドで Semantic Kernel を使用する方法
- Web アプリ:API レイヤーで SK オーケストレーションをホストします。トークンを UI にストリーミングします。
- チャット UI:会話状態をサーバー側で維持します。プルーニングと要約を行います。
- 認証:偽装セーフコール—モデルにトークンを発行させないでください。バックエンドを介してツール呼び出しをゲートします。
デプロイメントチェックリスト
- 可観測性ダッシュボード(レイテンシー、コスト、エラー)
FAQ 形式のトラブルシューティング
- 「RAG があってもモデルが幻覚を見る。」 指示を厳しくする:「コンテキストからのみ回答する」および拒否の例を含めます。取得の特異性を高め、温度を下げます。
- 「JSON が壊れ続ける。」 有効な JSON のミニ例を追加し、解説を禁止します。失敗時に事後検証と言い換えを行います。
- 「レイテンシーが高い。」 より少なく、より関連性の高いチャンクを取得します。単純なステップをより小さなモデルに切り替えます。独立したステップを並行化します。
- 「コストが急上昇している。」 キャッシュ、コンテキストの圧縮、および簡単なタスクをより安価なモデルにルーティングします。
注目に値する:Sider.AI でより速く構築する
プロンプトのプロトタイプ作成、ツールフローのテスト、またはモデル間での応答の比較を行っている場合は、Sider.ai のようなコンパニオンを使用すると、イテレーションを高速化できます。Semantic Kernel テンプレートに移動する前に、プロンプトの作成、A/B 比較の実行、および再利用可能なスニペットのキャプチャを行うことができます。これは、指示と出力スキーマをシャープにするのに最適です。 次のステップ:これを動作するエージェントに変える
- 1 つの明確なタスクから始めます(例:サポートメールの分類)。
- 厳密な入力/出力でセマンティック/ネイティブ関数を定義します。
- メモリは、回答が測定可能に改善される場合にのみ追加します。
- すべてを計測します。実際のサンプルでテストします。
- サンドボックスを使用してプロンプトを反復処理し、SK で体系化します。
主なポイント:
- Semantic Kernel は、プロンプト、ツール、メモリを信頼性の高いワークフローに構成するのに役立ちます。
- 堅牢性とコスト管理のために、出力スキーマ、プランナー、およびマルチモデルルーティングを使用します。
- RAG とガードレールは、常に巨大なプロンプトに勝ります。
これらのパターンで Semantic Kernel の使い方をマスターすると、印象的なデモだけでなく、信頼できるシステムである AI 機能をリリースできます。
FAQ
Q1:Semantic Kernel は AI アプリで何に使用されますか?
Semantic Kernel は、LLM プロンプト、ツール(ネイティブ関数)、およびメモリを組み合わせた AI ワークフローを構築するためのオーケストレーション SDK です。タスクの構造化、RAG の追加、および複数のモデルの信頼性の高い呼び出しに役立ちます。
Q2:ドキュメントで RAG に Semantic Kernel を使用するにはどうすればよいですか?
SK のメモリ API を介してドキュメントをベクターストアに取り込み、クエリごとに最も関連性の高いチャンクを取得して、プロンプトに挿入します。これにより、精度が向上し、幻覚が軽減されます。
Q3:Semantic Kernel は外部 API およびサービスを呼び出すことができますか?
はい。API をプラグインのネイティブ関数としてラップし、モデルがツールとして使用できるようにカーネルに登録します。インターフェースを小さく保ち、入力/出力の検証を強制します。
Q4:どのモデルが Semantic Kernel で動作しますか?
Semantic Kernel は、OpenAI、Azure OpenAI、およびその他のコネクタをサポートしています。タスクを異なるモデルにルーティングできます。たとえば、ドラフトにはより小さなモデル、推論を多用するステップにはより大きなモデルなどです。
Q5:Semantic Kernel の出力を一貫性のあるものにするにはどうすればよいですか(例:JSON)?
厳密な JSON を要求し、最小限の例またはスキーマを含む構造化されたプロンプトを使用します。温度を低く設定し、呼び出し後に出力を検証し、解析が失敗した場合は再試行または修復します。