一般的に生成AIに指示するのは自然言語のプロンプトだ。AIモデルの性能が上がっても、プロンプトの書き方がタスク成功の鍵となることに変わりはない。とは言え、効率的なプロンプトを書くのは大変だ。そこで、DSPyの出番となる。これを使うと、プログラムを作るように効率的なプロンプトを自動生成することができる。
DSPyとは?
DSPyは、LLMアプリケーションをプロンプト(AIに与える指示文)を書くのではなく、Pythonプログラムとして構築するためのフレームワークだ。
タスクの入力と出力を構造化して定義し、必要に応じてプロンプトの生成や改善、評価に基づく最適化を行える。DSPyの公式チュートリアルには「Program, don’t prompt.」とあり、これは「プロンプトを書くのではなく、プログラムしよう」という考え方を表している。
DSPyの中心的な考え方は、タスクを文章ではなく構造で表すことにある。たとえば、メールから予定を抽出するというタスクを考えてみよう。DSPyを使う場合、タスクを実現するために、長いプロンプトを書く代わりに、「入力はメール本文」「出力はイベント名と日付」といった形で定義する。
DSPyを使ってみよう
DSPyの説明を読んだだけでは、ちょっと分かりづらいと思うので、実際のプログラムを作ってDSPyを理解してみよう。
DSPyを使う場合、AIプロバイダーのAPIを使うことになる。ここでは、手軽にAPIが利用できる、OpenAIのAPIを利用してみよう。APIの利用登録などの手順は、こちらの姉妹連載で説明しているので、ここでは省略する。なお、Pythonから手軽にAPIを呼び出せるように、APIキーを取得したら環境変数OPENAI_API_KEYにAPIキーを登録しておこう。
次に、DSPyをインストールしよう。本稿執筆時点での最新版は、3.2.1だった。
pip install dspy==3.2.1
DSPyのインストールおよびAPIキーの環境変数への登録を終えたら、プログラムを作ってみよう。DSPyに簡単なタスクを与えて実行するには、次のようなプログラムを作る。
import dspy
# 利用するLLMをDSPyに登録 --- (*1)
lm = dspy.LM("openai/gpt-5-nano")
dspy.configure(lm=lm)
# 材料から料理を言い当てるAI --- (*2)
guess_dish = dspy.Predict("food_items -> dish")
# 実際に食材を与える → 料理名を答える --- (*3)
result = guess_dish(food_items="ニンジン, タマネギ, 牛肉, スパイス")
print(result.dish)
プログラムを確認してみよう。(*1)では、DSPyで利用する言語モデルを準備して登録している。ここでは、OpenAIの「openai/gpt-5-nano」というモデルを指定している。次に、(*2)では「材料を入力したら料理名を出す」という予測ルールを作るために「food_items -> dish」を指定している。入力はfood_items(食材)、出力はdish(料理名)という形だ。DSPyはこのように、細かい処理を手作業で書く代わりに、「何を入れて何を出したいか」を宣言する形でAIの仕事を定義できるのが特徴だ。(*3)では、実際に、food_itemsに「ニンジン, タマネギ, 牛肉, スパイス」という材料を渡して、AIに料理名を考えさせている。
上記のプログラムを「guess_dish.py」というファイル名で保存しよう。そして、ターミナルを起動してプログラムを実行してみよう。
python guess_dish.py
すると、次の画面のように「牛肉と野菜のカレー」などの答えが出力される。関数guess_dishに与える引数food_itemsを変更してみて、料理名が変化するのを確認してみよう。
クラスのシグネチャーを定義してみよう
次に、冒頭で言及したメールのテキストからイベントと日時を抽出するというタスクに挑戦してみよう。先ほどの例では、簡単なタスクしか指定できず、実際の複雑なタスクが記述できないように感じることだろう。そこで、もう少し複雑なタスクを指示したい場合に役立つ記述方法を確認しよう。
以下が、DSPyを利用してメールからイベント日時を抽出するプログラムだ。
import dspy
# サンプルテキストの指定 --- (*1)
sample_text = """
今後の予定についてお知らせします。
* * * * * *
2026/07/03 プロジェクトAの発表会
2026/07/10 関係者説明会
2026/08/05 社内カレー大会
* * * * * *
社内カレー大会は定期的に開催されます。
"""
# クラスベースでDSPyのシグネチャーを定義 --- (*2)
class EventExtractor(dspy.Signature):
"""メールに書かれたイベントとその日時の一覧を抽出する""" # ←ここに動作の説明
# 以下に入力と出力の指定
mail_text: str = dspy.InputField(desc="メール本文")
event_list: list[str] = dspy.OutputField(desc="イベントと日時のリスト")
# 利用するLLMをDSPyに登録
dspy.configure(lm=dspy.LM("openai/gpt-5-nano"))
# シグネチャーのインスタンスを生成 --- (*3)
extractor = dspy.Predict(EventExtractor)
# 実際にメールからイベントを抽出して表示 --- (*4)
result = extractor(mail_text=sample_text)
print("\n".join(result.event_list))
上記のプログラムを「extract_event.py」というファイル名で保存しよう。そして、ターミナルで次のコマンドを実行してみよう。
python extract_event.py
すると、次の画面のようにメールに書かれたイベントと日付を抽出して表示する。
プログラムを確認してみよう。(*1)では、メールのサンプルテキストを指定している。このサンプルでは、文章全体の中から必要な情報だけを拾い出せるかを試す形になっている。
(*2)では、クラスベースでDSPyのシグネチャーを定義している。ここで定義している「EventExtractor」というクラスは、AIにどんな役割を持たせるかをまとめた設計図のようなものだ。dspy.Signatureを継承することで、「入力は何か」「出力は何か」をクラスの中で明示できるようになっている。なお、クラスの説明文(DocString)が重要で、DSPyがプロンプトを生成する際に説明文を参照する仕組みとなっている。
クラスのプロパティとして、入力と出力の項目を定義している。mail_textは入力フィールドとして定義している。これはメール本文そのものを受け取るための項目であることを明示している。また、データ型を「str」にしているので、文字列を渡す想定にしている。次に、event_listを出力フィールドとして定義している。これは、抽出されたイベント一覧を受け取るための項目だ。型を「list[str]」と指定しているため、結果は文字列のリストとして返ってくる想定だ。AIにただ曖昧に「何か抽出して」と頼むのではなく、「入力は本文、出力はイベント一覧」という形をはっきり決めている点がポイントだ。
(*3)では、先ほど定義したシグネチャーをもとにインスタンスを作っている。最初に紹介したプログラムで「food_items -> dish」のような文字列ベースの指定に比べると、今回はクラスの中に型や説明を書けるため、より整理された書き方になっている。
(*4)では、実際にサンプルテキストを渡してイベントを抽出している。結果を変数resultに受け取っている。返ってくる結果は、単なる文字列ではなく、シグネチャーで定義した出力項目を持ったオブジェクトとなる。それで「result.event_list」という形で取り出せる。
なお、DSPyのWebサイトはこちらにあり、詳しいマニュアルが用意されている。
まとめ
以上、今回は、DSPyを使って、AIに与える指示をプログラムとして定義する方法を紹介した。最初の例では「材料を入力すると料理名を出力する」という単純な予測を、続く例では「メール本文からイベントと日付を抽出するタスク」を定義して利用してみた。
DSPyの利点は、自然言語の長いプロンプトを毎回書くのではなく、「何を入力し、何を出力するか」をPythonのコードとして整理できる点にある。入力や出力の名前、型、説明を明示しておけば、プログラムの中でAIの処理を部品のように扱いやすくなる。
DSPyを使えば、プロンプトそのものを直接作り込むのではなく、タスクの構造を定義することに集中できる。AIを単発のチャットとして使うだけでなく、アプリケーションの中に組み込んで利用したい場合に、DSPyは有力な選択肢となるだろう。


