DSPyで始めるプロンプト最適化:仕組みと使い方、評価の進め方
DSPyによるプロンプト最適化の仕組みを、シグネチャ、モジュール、評価指標から解説します。俳句を生成する最小コードと、サポートチケットを分類する小規模な実験で、導入から評価までを確認。実行回数と料金の試算、主要オプティマイザーの違い、手書きプロンプトやファインチューニングとの使い分けも整理します。
公開日

DSPyは、繰り返し行うAIタスクの結果を採点でき、プロンプトの手直しが保守作業になってきたときに試す価値があります。プロンプト最適化の作業をPythonプログラムと最適化ループに移せるためです。この記事で紹介する小規模な初回実験は、リトライを除き、単一ステップのプログラム実行を最大100回に収める設計です。業務として何を正解とするか合意できていないなら、DSPyを導入する前に、まずそこを決めましょう。
本記事の内容は2026年10月15日に、DSPyの現行ドキュメント、PyPI、Googleのモデル料金と照合しています。PyPIに掲載されているのは、2026年10月12日リリースのDSPy 3.4.1です。対応するPythonは3.10以上、3.16未満で、インストールするパッケージ名はdspyです。PyPIのパッケージメタデータ。
DSPyとは?「コンパイル」で何が変わるのか
DSPyは、言語モデルに任せるタスクをプログラムとして定義し、そのプロンプトや、特定のオプティマイザーを使う場合にはモデルの重みを改善する、オープンソースのPythonフレームワークです。強みは、自分たちで定義した成功基準に沿って、改善を繰り返せることにあります。最初に生成したプロンプトが、丁寧に手書きしたプロンプトを上回ると約束するものではありません。DSPyの概要。
舞台のリハーサルに置き換えると、シグネチャは演目の要件、モジュールは演じ方、評価指標は審査基準に当たります。オプティマイザーは何かを変えて結果を確かめ、有効だった変更を残します。審査基準がなければ、演じ方をいくら変えても、よくなったかどうかは判断できません。
シグネチャでタスクを定義する
シグネチャは、入力、出力、タスクの指示を宣言します。"ticket -> category"なら、チケットを入力し、カテゴリを出力するという意味です。クラスで定義するシグネチャでは、型付きのフィールドや、タスクを説明するdocstringを追加できます。ただし、どのフィールドを設けるかは依然として重要です。業務上の「緊急」の定義が曖昧なままでは、オプティマイザーにも解決できません。シグネチャのドキュメント。
モジュールで処理の進め方を決める
モジュールは、タスクを実行する方法を実装します。dspy.Predictは、予測処理の基本となる部品です。dspy.ChainOfThoughtは回答の前に推論フィールドを追加します。dspy.ReActは推論とツール利用を繰り返すループに対応します。モデルを1ステップ呼び出すだけでは足りない場合は、Pythonでモジュールを組み合わせられます。モジュールのドキュメント。
サポートチケットの振り分けなら、まずはPredictから始めましょう。短いメッセージを分類するためにツール利用のループを加えると、その必要性を確認する前に構成が複雑になります。
コンパイルは最適化の処理を指す
オプティマイザーは、サンプルと評価指標を使い、プログラムの一部を変更します。プロンプト最適化では、.compile()が返すのは、指示やデモンストレーション、つまりプロンプトに含める例を更新したプログラムです。アプリケーションをネイティブの実行ファイルに変換したり、以後のモデル呼び出しを不要にしたりするわけではありません。重みを学習させるには、それに対応するオプティマイザーを別途選びます。オプティマイザーの選び方。
DSPyの使い方:現行ドキュメントの最小サンプルを動かす
現行の入門プログラムは俳句を生成します。データベースやツール、最適化の探索を持ち込まずに、DSPyのインターフェースを確認できる小さな例です。
Python環境に、確認済みのリリースをインストールします。
python -m pip install 'dspy[litellm]==3.4.1'環境変数GEMINI_API_KEYに、有効なGoogle Gemini APIキーを設定してください。次のコードをfirst_dspy.pyとして保存し、python first_dspy.pyで実行します。
import os
import dspy
lm = dspy.LM(
"gemini/gemini-2.5-flash-lite",
api_key=os.environ["GEMINI_API_KEY"],
engine="litellm",
)
dspy.configure(lm=lm)
haiku_signature = "subject -> haiku"
haiku_generator = dspy.Predict(haiku_signature)
result = haiku_generator(subject="computer science")
print(result.haiku)最後の4行は、現行ドキュメントの最初のプログラムです。初期設定はDSPyのモデル設定方法に沿っていますが、後述の実験でも安価な同じモデルを使えるよう、Google Gemini 2.5 Flash-Liteに差し替えています。プロバイダーを指定する文字列はLiteLLMのGemini連携に従っており、バックエンドの明示的な指定はDSPy LM APIでサポートされています。
DSPyはシグネチャからプロンプトを組み立て、設定したモデルに送信し、返された結果からhaikuフィールドを取り出します。これは推論のサンプルであり、最適化の実行例ではありません。特定の俳句が生成されることや、品質が向上することを示すものでもありません。
DSPyのプロンプト最適化には評価指標が必要
評価指標がなければ、最適化の成果を判断できません。 評価指標は、予測をスコアに変換する関数です。チケットの振り分けなら、予測されたカテゴリと人が承認したラベルを比較できます。生成された回答の正しさを判定するには、採点基準や実行可能な検証処理が必要になることもあります。DSPyの評価指標インターフェースには自分で用意した採点関数を渡せますが、業務として何を高く評価すべきかをフレームワークが決めてくれるわけではありません。評価指標と評価の進め方。
だからこそ、小規模でもラベル付きの評価データが重要です。「簡潔に」と「短く回答して」を入れ替える作業に疲れたなら、実際の失敗を集めましょう。たとえば、返金依頼が技術サポートに回されたケース、ログインの問題が請求の問い合わせと誤認されたケース、2つの依頼を含むメッセージなどです。新しいプロンプトの出力を見る前に、望ましい結果をラベルとして付けておきます。
初回の試行では、重複のない60件のサンプルを用意し、学習用20件、検証用20件、最終テスト用20件に分けます。これは実験規模の提案であり、DSPyの必須条件でも、本番での信頼性を示す件数でもありません。
- 学習用サンプルは、オプティマイザーが学ぶための材料になります。
- 検証用サンプルは、バージョンを比較し、開発上の判断をするために使います。
- 最終テスト用サンプルは、候補プログラムと評価ルールを確定するまで手を付けません。
同じ顧客や同じインシデントに関係するチケットは、同じ分割先にまとめます。そうしないと、よく似たサンプルが別の分割先にも入り込み、最適化したプロンプトの汎化性能を実際より高く見せてしまいます。簡単なケースばかりで埋めず、頻度が低くても重要な失敗を含めてください。

「評価指標がなければ」という説明には、厳密には補足が必要です。最適化していないDSPyプログラムは評価指標なしでも実行でき、LabeledFewShotは採点せずに例を付加できます。ただし、それは設定であって、変更によってタスクの結果が改善した証拠にはなりません。また、すべてのタスクに人が書いた参照回答が必要なわけでもありません。実行可能な正誤判定処理から評価信号を得ることもできます。業務上の分類タスクでは、承認済みのラベルが通常は最も明確な出発点です。Few-shotのベースライン。
DSPyのオプティマイザー:現行ドキュメントの名前を整理する
まずは、具体的に説明できる失敗に対処する、最も単純なオプティマイザーを選びましょう。探索を増やして意味があるのは、評価指標が候補の良し悪しを見分けられる場合だけです。
現行のオプティマイザーAPI一覧には、次の名前が掲載されています。BetterTogether、BootstrapFewShot、BootstrapFewShotWithRandomSearch、BootstrapFinetune、BootstrapRS、COPRO、Ensemble、GEPA、InferRules、KNN、KNNFewShot、LabeledFewShot、MIPROv2、SIMBAです。
これらがすべて独立した探索アルゴリズムというわけではありません。BootstrapRSはBootstrapFewShotWithRandomSearchの別名で、KNNはKNNFewShotが使う検索用の補助機能です。現行の選択ガイドには、エージェント型のプログラム向けにAvatarOptimizerも挙げられていますが、上記のAPI一覧には含まれていません。Few-shot系の詳細、選択ガイド。
MIPROv2は指示文を提案し、過去のスコアを手がかりに探索するベイズ最適化を使って、指示文とデモンストレーションの組み合わせを調べます。SIMBAはミニバッチ単位で処理を進め、ルールやデモンストレーションを提案します。両者は異なる手法であり、BootstrapFewShotの名前を変えただけのものではありません。MIPROv2 API、SIMBA API。
GEPAは、実行時のフィードバックを振り返り用のモデルに読み込ませ、指示文の変更を提案させます。たとえば「返金依頼は、機能の不具合に言及していても請求担当に振り分ける」という具体的な説明がスコアに添えられていれば、失敗を示す数値だけよりも有用な手がかりになります。詳細ドキュメントでは数値のみの評価指標も認められていますが、その場合は豊かなフィードバックが失われると説明されています。GEPAの仕組み。
最初の最適化実験には上限を設ける
小規模なBootstrapFewShotの実験なら、際限なく指示文を探索するよりも、処理量を把握しやすくなります。ここでは、Predictモジュール1つと、ラベルの一致で決定的に採点する評価指標を使い、教師役と予測役に同じモデルを用います。
DSPyのBootstrapFewShotを小さく試す
train.jsonl、validation.jsonl、test.jsonlを用意し、それぞれに、人がラベルを付けた重複のないチケットを20件入れます。各行はtextとlabelを持つJSONオブジェクトとし、ラベルにはbilling、technical、account、otherを使います。たとえば、請求書の住所変更依頼にはbillingを付けられます。俳句の生成結果ではなく、自分たちのタスクに合ったサンプルを用意してください。
以下を別のスクリプトoptimize_tickets.pyとして保存し、先ほどと同じAPIキーを設定して実行します。
import json
import os
from typing import Literal
import dspy
lm = dspy.LM(
"gemini/gemini-2.5-flash-lite",
api_key=os.environ["GEMINI_API_KEY"],
engine="litellm",
cache=False,
)
dspy.configure(lm=lm)
class RouteTicket(dspy.Signature):
"""Choose the support queue responsible for the ticket's main request."""
text: str = dspy.InputField()
label: Literal["billing", "technical", "account", "other"] = (
dspy.OutputField()
)
def load_examples(path):
with open(path, encoding="utf-8") as source:
rows = [json.loads(line) for line in source if line.strip()]
assert len(rows) == 20
return [dspy.Example(**row).with_inputs("text") for row in rows]
train = load_examples("train.jsonl")
validation = load_examples("validation.jsonl")
test = load_examples("test.jsonl")
assert len({e.text for e in train + validation + test}) == 60
def correct_label(example, prediction, trace=None):
return prediction.label == example.label
program = dspy.Predict(RouteTicket)
evaluate = dspy.Evaluate(
devset=validation, metric=correct_label, num_threads=1
)
print("Baseline validation:", evaluate(program).score)
optimizer = dspy.BootstrapFewShot(
metric=correct_label,
max_bootstrapped_demos=4,
max_labeled_demos=0,
max_rounds=1,
)
optimized = optimizer.compile(program, trainset=train)
print("Optimized validation:", evaluate(optimized).score)
# Freeze this candidate before opening the final test results.
final_test = dspy.Evaluate(
devset=test, metric=correct_label, num_threads=1
)
print("Baseline final test:", final_test(program).score)
print("Optimized final test:", final_test(optimized).score)
optimized.save("candidate_ticket_router.json")これは、ドキュメントに記載されたBootstrapFewShotのコンストラクターと評価インターフェースを応用した例であり、ベンチマークの結果を示すものではありません。成功したデモンストレーションを最大4件集め、各学習サンプルにつきブートストラップを1回まで試し、元のラベル付きサンプルをそのままデモンストレーションとして追加することはしません。保存されるファイルはレビュー用の候補であり、自動的に本番へ採用されるものではありません。
この設計の実行回数は、次のように整理できます。
- ベースラインを検証データで評価:プログラム実行20回。
- 学習データでブートストラップ:教師役の実行が最大20回。十分な数のデモンストレーションが合格すれば、それより少なくなります。
- 最適化後のプログラムを検証データで評価:プログラム実行20回。
- 両バージョンを最終テストデータで評価:プログラム実行40回。
評価を含めて、単一ステップの実行が最大100回です。このうち、コンパイルだけにかかるのは最大20回です。各実行でモデルへのリクエストが1回で成功し、リトライも解析失敗時のフォールバックもなければ、タスク用モデルの呼び出しは最大100回になります。先ほどの俳句による動作確認は、この回数には含みません。LLMによる採点、エージェントのループ、リトライ、最適化の再実行があれば、合計は変わります。

GoogleのGemini 2.5 Flash-LiteのStandard有料テキスト料金は、入力100万トークン当たり$0.10、出力100万トークン当たり$0.40です。1回当たりの平均を入力1,000トークン、出力100トークンと仮定すると、100回の呼び出しは$0.014になります。計算式は、100,000 ÷ 1,000,000 × $0.10 + 10,000 ÷ 1,000,000 × $0.40です。 Googleの料金表。
これはモデル利用料だけの計算であり、実測した請求額や支出の上限ではありません。入力トークンの想定には、DSPyによる書式設定や付加されるデモンストレーションも含める必要があります。チケットが長い場合、出力が大きい場合、課金対象の思考処理がある場合には、金額が増えます。この試算にはバッチやキャッシュの割引を含めていません。費用の確認には、実際のプロバイダー利用記録を使ってください。
DSPyと手書きプロンプト、ファインチューニングはどう使い分ける?
測定可能なプログラムを繰り返し改善する仕組みが必要なら、DSPyを使います。手書きのプロンプトですでにタスクの要件を満たしているなら、そのまま維持しましょう。プロンプトの変更だけでは不十分だという根拠があり、モデルの学習がデプロイの制約にも収まる場合に、ファインチューニングを検討します。
これらの手法は併用できます。DSPyにはBootstrapFinetuneがあり、BetterTogetherはプロンプトと重みの最適化を組み合わせます。実務上の違いは、何を変更し、何を保守するかです。どの名前が先進的に聞こえるかではありません。プロンプトと重みの最適化。
使い分けの転換点は、運用にあります。モデルの変更や新たな失敗のたびに、エンジニアが複数のプロンプトを手作業で直しているなら、採点に基づく最適化ループの価値が高まります。一方、短いプロンプトですでに合格基準を満たしている場合、フレームワークへの置き換えで効果が得られるとは実証されていません。
今すぐ使うべき人、待つべき人、導入を見送るべき人
エンジニアが導入を進めるべきなのは、繰り返し行うタスク、動くベースライン、実際の利用を代表する失敗例がそろっている場合です。 チケットの振り分けや構造化された情報の抽出は、期待する出力を確認できるため、よい出発点になります。システムを広げる前に、小さな部品を最適化しましょう。DSPyの限界を決めるのは、目的設定の質です。評価指標が望ましくない振る舞いを高く採点していれば、スコアの高い候補を選べても、業務にとっては改善になりません。
業務担当者は、ラベルとエラーの優先順位に責任を持つ必要があります。 サポート責任者にとっては、一般的な請求の質問よりも、アカウントにアクセスできない問題を誤った担当へ振り分けるほうが、はるかに重大かもしれません。両者を同じ重さで採点すると、最適化が責任者の優先順位に反する可能性があります。エンジニアにスコア改善を依頼する前に、その方針を決めてください。
導入を判断する側は、未見のサンプルでの根拠を求めましょう。 どのベースラインと比較したのか、どのケースが悪化したのか、本番で回答を返すプログラムに何が追加されたのか、ワークフローが今もレイテンシ要件を満たすのかを確認します。オプティマイザーの名前だけでは、採用の根拠になりません。評価の進め方を整えたいチームには、当サイトのPromptfooレビューも参考になります。
たまに行う文章作成や単発の調査、サンプルが集まる前に変わってしまうワークフローなら、業務チームはDSPyの導入を見送りましょう。 Pythonコードを保守できる人がいない場合や、採点ルールに合意できない場合も同様です。適切なプロンプト、チェックリスト、人によるレビューのほうが、仕事の規模に合うこともあります。本当の課題が元データの不足やプロセスの未定義なら、導入は待つべきです。文言を最適化しても、足りないデータやプロセスは補えません。
DSPyはどこまで期待してよいのか
「プロンプティングではなくプログラミング」という表現でも、プロンプトがなくなるわけではありません。DSPyがプロンプトを生成・管理し、人は引き続きタスクを定義し、失敗を判断し、結果を受け入れられるかを決めます。
「コンパイル」は、モデルが永続的に学習したという意味ではありません。プロンプト用オプティマイザーで学習の成果として残るのは、指示文やデモンストレーションです。推論時には引き続きモデルを呼び出し、デモンストレーションはプロンプトのスペースを使います。学習した状態はJSONとして保存し、新しいプログラムに読み込めます。保存と読み込み。
「自動最適化」も、自動的な性能向上を意味しません。意味のある比較は、未見の入力に対して既存の方法と比べることです。開発中のスコアが上がっても、過学習、甘い採点、損失の大きい失敗を含まないデータセットが原因かもしれません。
また、評価指標の呼び出し回数と、プロバイダーへの呼び出し回数は別です。GEPAのmax_metric_callsが制限するのは採点処理の回数です。振り返りにもモデルを使い、採点されるプログラム自体が複数のリクエストを送る場合もあります。autoの設定から、どの環境でも同じ請求額になると考えることはできません。GEPAの実行予算の設定。
エンジニアが知っておきたいDSPyの疑問
DSPyはどのように動きますか?
シグネチャで入力と出力を宣言し、モジュールを選ぶか組み合わせて、言語モデルを設定します。アダプターがメッセージを組み立て、結果を解析します。そのうえで、オプティマイザーがサンプルと評価指標を使い、対象となる部分を改善できます。
DSPyは本番環境で使えますか?
本番で使えるかどうかは、自分たちのプログラムで判断してください。パッケージとモデル設定を固定し、ベースラインを残し、実際の利用を代表する失敗をテストして、ロールバックの基準を決めます。現行リリースが存在するだけでは、そのワークフローの本番利用が保証されるわけではありません。
DSPyは今でも使う価値がありますか?
はい。繰り返し実行し、結果を測定できる言語モデルのタスクで、プロンプトの保守が必要なら価値があります。単純なプロンプトですでに要件を満たしている場合や、安定した評価ルールがないタスクでは、得られる価値は小さくなります。
LangChainとDSPyの主な違いは何ですか?
LangChainは、モデルやツールとの連携を使ってエージェントを構築するためのフレームワークです。DSPyの特徴は、モデルのタスクを宣言し、評価指標に基づいてプログラムを最適化することを重視している点です。エージェントの構成要素をつなぎたいのか、採点できるタスクを体系的に改善したいのか、解決する問題に合わせて選びましょう。LangChainの概要。
DSPyでプロンプト最適化はできますか?
はい。オプティマイザーに応じて、デモンストレーションの選択、指示文の修正、または両方の探索ができます。プロンプト最適化では、基盤となるモデルの重みは変わりません。ファインチューニングは別の方法です。
DSPyを開発したのは誰ですか?
DSPyはOmar Khattabと共同研究者によって開発されました。リポジトリはStanford NLPの下で保守されており、パッケージに掲載された研究の引用情報に、貢献した著者が記載されています。プロジェクトと著者。
DSPyのGEPAはどのように動きますか?
GEPAは、プログラム実行から得たフィードバックを基に、振り返り用のモデルを通じて指示文の変更を提案し、候補を評価して、選んだプログラムを返します。失敗に関する具体的なフィードバックがあれば、スコアだけの場合よりも情報に基づいて探索できます。ただし、品質向上を保証するものではありません。
DSPyは何の略ですか?
公式パッケージの説明にあるとおり、DSPyはDeclarative Self-improving Pythonの略です。
次に取り組むこと
月曜日に、繰り返し起きるチケットの振り分けミスか情報抽出の失敗を1つ選び、業務プロセスの責任者に、実際の利用を代表するサンプルへのラベル付けを依頼しましょう。ベースラインを固定し、採点ルールを決め、上限を設けた実験を1回行います。候補を承認する前に、変化した回答を確認してください。スコアを定義できないなら、次に取り組むべきなのは業務ルールへの合意です。
- 公開日
- カテゴリー
- Build
- 言語








