😎

プログラミングでLLMを動かすDSPyの紹介

に公開

先に結論

  • DSPyを用いることで、プロンプトではなく、プログラミング言語でLLMの動作を定義可能
  • 出力結果の構造化や型指定だけでなく、APIからコールする時のようにtemperature等のパラメータも指定可能
  • lm.historyコマンドにより、過去叩いたプロンプトの出力結果やコスト等も構造化された状態で出力を得ることが可能

DSPyの概要

  • プロンプトではなく、プログラミング(Python)で言語モデルを学習させる為のPythonモジュール
  • LLMに出力結果を強制させる構造化出力等のプロンプトエンジニアリング的な手法ではなく、プログラミング言語で書く関係で保守もしやすい。

実装

前準備

普通のpipパッケージと同様に下記でDSPyをインストールする。

pip install -U dspy

gitでの最新版が欲しい場合は

pip install git+https://github.com/stanfordnlp/dspy.git

Google Colaboratoryを用いている場合、鍵マークからAPIキーを登録。

  • Notebook accessをオンにし、Notebookからアクセスできるようにする
  • Nameに呼び出したい環境変数名の設定(例.GEMINI_API_KEY)
  • Valueに実際のAPIキーを直接貼り付け

    Google ColaboratoryのAPIキー登録画面
    その後、GEMINIのAPIの場合、下記のコマンドで言語モデルをセットする。
    ※他のAPIの場合はDSPyのドキュメントを参照
import dspy
# google colaboratoryで環境変数を読むためのコマンド
from google.colab import userdata
api_key = userdata.get('GEMINI_API_KEY')
# google colaboratoryではない場合、環境変数を定義後、下のコマンドのみで良い。
lm = dspy.LM("gemini/gemini-2.5-flash", api_key=api_key)
dspy.configure(lm=lm)

実装例

DSPyのチュートリアルを触ってみて感じた特徴としては主に下記の3点がある

  • コードの出力結果は構造化出力のようにJSON形式かつ、型もこちらで指定できる。
  • 構造化出力とは異なり、前準備でLLMをセット後は書き方が全て同じな為、LLM毎の書き方を学ばなくても良い
  • 計算や分類等、用途に応じて適切な関数をこちらで調整選べる為、LLMの意図しない挙動を防ぎやすい。

出力調整

通常のAPI経由で呼び出すと同様にTemperature(出力結果の創造性)やトークン数等のパラメータも調整可能

dspy.settings.configure(
    lm=dspy.LM(
        "openai/gpt-5-mini", #ここはモデルごとに変更
        model_type="responses",
        temperature=1.0,
        max_tokens=16000,
    ),
)

実装

下記のような計算問題や分類問題を与えた場合は下記の通り。サンプルは英語だったが、日本語でも問題なく、出力を得ることができる。コードを見てもわかるように、用途に応じて計算ならmath、分類ならclassify等、用途毎に出力を調整できる。

math = dspy.ChainOfThought("question -> answer: float")
math(question="コインを10回投げて裏が出続ける確率は?")


mathコマンドの出力結果、結果だけでなく、計算過程も出力されている

from typing import Literal

class Classify(dspy.Signature):
    """与えられた文章を感情毎に分類する"""

    sentence: str = dspy.InputField()
    sentiment: Literal["positive", "negative", "neutral"] = dspy.OutputField() 
    confidence: float = dspy.OutputField()

classify = dspy.Predict(Classify)
classify(sentence="この店の料理は美味しいが、店員の対応はあまり良くなかった")


classifyコマンドの出力結果、今回の場合は感情は中立と90%の確率で判定されている

出力確認

llmの過去の出力を確認したい場合はlm.historyコマンドで行う。
※uuidやidは念の為、隠している。

len(lm.history) #出力結果の数を確認
last_history = len(lm.history)-1 # 最後の出力結果が格納されているインデックスを取得
lm.history[3] #最後の出力結果の確認


lm.historyコマンドの出力結果、今回の場合は先のclassifyコマンドの出力が得られている

より詳しく知りたい方向け

Discussion