lukaswalter.devで最初に公開されたものです。
Pythonでは、プロンプト圧縮の定番の選択肢としてLLMLinguaのようなライブラリがあります。 .NETでは、まだ同等のものが直接はありませんが、同じパターンを実装するための構成要素はそろっています。
問題: 「トークン税」
取得したドキュメントの10,000トークンを、毎回のクエリごとにプレミアムモデルへ送信すると、コストとレイテンシの両方が増えます。そのコンテキストの大部分は定型文です。HTMLタグ、冗長なヘッダー、繰り返されるナビゲーション、あるいは無関係な段落などです。
解決策: 2つのアーキテクチャパス
1. 「安価なモデル」サマライザ
生データをプレミアムモデルに送る代わりに、より小さく安価なワーカーモデルを使って、事前にコンテキストを前処理します。
Semantic Kernelを使っている場合は、ONNX Runtime GenAI経由でローカルのPhiモデル、またはまず最初により小さなホスト済みモデルを使って、RAGの結果をパイプできます。たとえば次のようなプロンプトを使用します: "このコンテキストからRAGシステム用に必須の技術的事実と識別子だけを抽出してください。文章(プローズ)をすべて削除してください。"
2. ミドルウェアパターン
Microsoft.Extensions.AIはこのパターンに適しています。IChatClientは、パイプライン形式の合成をサポートしているためです。実際のモデルクライアントにリクエストが渡される前に、コンテキストをクリーンアップまたは圧縮するDelegatingChatClientを実装できます。
using Microsoft.Extensions.AI;
public sealed class ContextCompressionChatClient(IChatClient innerClient)
: DelegatingChatClient(innerClient)
{
public override async Task<ChatResponse> GetResponseAsync(
IEnumerable<ChatMessage> messages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
// 1. 定型文を削除(HTMLのクリーンアップ、繰り返されるヘッダーなど)
// 2. 価値の低いRAGチャンクをフィルタ
// 3. 任意: コンテキストを圧縮するためにより小さなモデルを呼び出す
var compressedMessages = CompressContext(messages);
return await base.GetResponseAsync(
compressedMessages,
options,
cancellationToken);
}
}
なぜ役に立つのか
| 機能 | 重要な理由 |
|---|---|
| レイテンシの低減 | 入力トークンが少ないほど、通常はリクエストが速くなり、初回トークンまでの時間も改善します。 |
| コスト管理 | 価値の低いテキストに対して、プレミアムモデルの価格を支払うことをやめられます。 |
| クリーンアーキテクチャ | ビジネスロジックはプロンプトに非依存のまま維持されます。圧縮はパイプラインで行われます。 |




