AI Prompt Engineering · レッスン

DSPyパイプラインの評価

自動評価のためのメトリクス、開発用データセット、evaluate()関数を学びます。

レッスン 4/413 ステップ

「DSPyパイプラインの評価」はCoddyKit上の無料AI Prompt Engineeringレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Prompt Engineering学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Prompt Engineeringコースには全4レッスンが含まれています。

DSPyで評価が重要な理由

DSPyの最適化の良し悪しは、評価次第です。弱い評価指標を使うと、その指標では高いスコアを獲得しても、本番環境では失敗するコンパイル済みプログラムができてしまいます。適切な評価ハーネスがあれば、最適化前と最適化後のプログラムを比較し、パイプラインを更新した際のリグレッションを検出できます。

dspy.Evaluateクラス

dspy.Evaluateはデータセット上でプログラムを実行し、評価指標を適用して、集計スコアを報告します。大規模なデータセットを高速に評価できるよう、num_threadsによる並列処理をサポートしています。

import dspy

# Build a devset of labeled examples
devset = [
    dspy.Example(question='What is 7 * 8?', answer='56').with_inputs('question'),
    dspy.Example(question='Name the largest planet.', answer='Jupiter').with_inputs('question'),
    # ... more examples
]

# Create evaluator
evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,  # Your metric function
    num_threads=4,              # Parallel evaluation
    display_progress=True,      # Show progress bar
    display_table=True,         # Show per-example results
)

# Run
score = evaluate(my_program)
print(f'Overall score: {score:.1%}')

評価指標関数の作成

評価指標関数のシグネチャは(example, prediction, trace=None) -> floatです。プログラムの予測を、example内の正解データと比較します。

traceパラメーターがNone以外になるのは、評価時ではなく最適化時です。これを使って、コンパイル時と評価時で異なるロジックを適用できます。

import dspy

def exact_match_metric(example, prediction, trace=None):
    return float(
        example.answer.strip().lower() == prediction.answer.strip().lower()
    )

def contains_metric(example, prediction, trace=None):
    """Check if expected answer appears anywhere in prediction."""
    return float(example.answer.lower() in prediction.answer.lower())

def length_penalized_metric(example, prediction, trace=None):
    """Reward correct answers, penalize overly long ones."""
    correct = float(example.answer.lower() in prediction.answer.lower())
    length_ok = float(len(prediction.answer.split()) <= 20)
    return correct * (0.8 + 0.2 * length_ok)

# Use any of these as the metric parameter
evaluate = dspy.Evaluate(devset=devset, metric=contains_metric)

合否のしきい値パターン

二値の評価指標では、しきい値を定義できます。予測が最低限の品質基準を満たしていれば「合格」と判定します。これは、ブートストラップ最適化でfew-shotデモをフィルタリングする場合に便利です。

import dspy

def quality_metric(example, prediction, trace=None):
    """
    Multi-factor metric with pass/fail threshold.
    Returns float 0.0 to 1.0.
    During compilation (trace is not None), DSPy uses this to decide
    which traces to bootstrap as demos.
    """
    score = 0.0

    # Factor 1: Factual correctness (0.6 weight)
    if example.answer.lower() in prediction.answer.lower():
        score += 0.6

    # Factor 2: Conciseness (0.4 weight)
    word_count = len(prediction.answer.split())
    if word_count <= 15:
        score += 0.4
    elif word_count <= 30:
        score += 0.2

    # During optimization: only use examples scoring >= 0.6
    if trace is not None:
        return score >= 0.6

    return score

データの分割:トレーニング、開発、テスト

DSPyでも、MLで標準的なデータ分割の慣行に従ってください。

  • トレーニングセット:オプティマイザーがデモをブートストラップするために使用します(20~200例)
  • 開発セット:探索中の検証にオプティマイザーが使用します
  • テストセット:完全に取り分け、最終評価にのみ使用します
import random

# All labeled examples
all_examples = load_examples()  # Returns list of dspy.Example
random.shuffle(all_examples)

total = len(all_examples)
train_end = int(total * 0.6)
dev_end   = int(total * 0.8)

trainset = all_examples[:train_end]    # 60% for optimization
devset   = all_examples[train_end:dev_end]  # 20% for validation
testset  = all_examples[dev_end:]      # 20% held out

print(f'Train: {len(trainset)}, Dev: {len(devset)}, Test: {len(testset)}')

最適化後と最適化前の比較

コンパイル済みプログラムは、必ず同じテストセット上でベースライン(未コンパイル)プログラムとベンチマーク比較してください。これにより、最適化によって実際に改善したことを証明し、改善幅を定量化できます。

import dspy

evaluate = dspy.Evaluate(
    devset=testset,
    metric=exact_match_metric,
    num_threads=4,
    display_progress=True,
)

# Baseline: unoptimized program
baseline_score = evaluate(unoptimized_program)
print(f'Baseline (no optimization): {baseline_score:.1%}')

# BootstrapFewShot compiled
bs_score = evaluate(bootstrap_compiled_program)
print(f'BootstrapFewShot compiled:  {bs_score:.1%}')

# MIPRO compiled
mipro_score = evaluate(mipro_compiled_program)
print(f'MIPRO compiled:             {mipro_score:.1%}')

# Pick the winner
print(f'Best improvement: +{max(bs_score, mipro_score) - baseline_score:.1%}')

num_threadsによる並列処理

大規模な評価セットを逐次処理すると、何時間もかかることがあります。dspy.Evaluateのnum_threadsを使うと予測を並列実行できるため、実時間を比例して短縮できます。

num_threadsはAPIのレート制限に合わせてください。スレッド数が多すぎると、レート制限エラーが発生します。

import dspy
import time

devset = [...]  # 200 examples

# Sequential evaluation
start = time.time()
evaluate_seq = dspy.Evaluate(devset=devset, metric=metric, num_threads=1)
score_seq = evaluate_seq(program)
print(f'Sequential: {time.time()-start:.0f}s')

# Parallel evaluation (4 threads)
start = time.time()
evaluate_par = dspy.Evaluate(devset=devset, metric=metric, num_threads=4)
score_par = evaluate_par(program)
print(f'Parallel (4 threads): {time.time()-start:.0f}s')
# Typically ~4x faster — same score, less wait time

評価結果の解釈

display_table=Trueを指定すると、DSPyは各例、予測、評価指標に合格したかどうかを含む詳細な表を表示します。失敗パターンを診断するうえで非常に役立ちます。

次の点に注目してください。特定の種類の質問で体系的に失敗していないか、評価指標におけるエッジケースがないか、トレーニングセットでカバーできていない例がないかを確認します。

import dspy

evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,
    num_threads=2,
    display_progress=True,
    display_table=10,  # Show first 10 rows of results table
    return_outputs=True,  # Return (score, outputs) tuple
)

score, outputs = evaluate(program, return_all_scores=True)

# Find failing examples
failures = [
    (ex, pred, s)
    for ex, pred, s in outputs
    if s == 0.0
]
print(f'Failures: {len(failures)}/{len(devset)}')
for ex, pred, _ in failures[:3]:
    print(f'Q: {ex.question}')
    print(f'Expected: {ex.answer}')
    print(f'Got: {pred.answer}')

LLMで評価する評価指標の利用

完全一致では評価できない自由記述形式の出力には、LLMを使って品質を評価してください。DSPyを使えば簡単に実現できます。評価指標関数自体でDSPyの予測器を呼び出せます。

import dspy

class GradeAnswer(dspy.Signature):
    """Grade whether the predicted answer is correct given the reference."""
    question: str = dspy.InputField()
    reference_answer: str = dspy.InputField()
    predicted_answer: str = dspy.InputField()
    is_correct: bool = dspy.OutputField(
        desc='True if the predicted answer is semantically correct'
    )

grader = dspy.Predict(GradeAnswer)

def llm_graded_metric(example, prediction, trace=None):
    result = grader(
        question=example.question,
        reference_answer=example.answer,
        predicted_answer=prediction.answer,
    )
    return float(result.is_correct)

# Use this metric when answers can vary in phrasing
evaluate = dspy.Evaluate(devset=devset, metric=llm_graded_metric)

評価によるリグレッションテスト

DSPyの評価スイートをテストスイートと同じように扱ってください。シグネチャ、モジュールアーキテクチャ、トレーニングデータを更新するたびに評価を再実行し、スコアを比較してリグレッションを検出します。

import json
import dspy

def run_and_save_evaluation(program, program_name, testset, metric):
    evaluate = dspy.Evaluate(
        devset=testset,
        metric=metric,
        num_threads=4,
    )
    score = evaluate(program)

    # Save score to history file
    history_file = 'eval_history.json'
    try:
        with open(history_file) as f:
            history = json.load(f)
    except FileNotFoundError:
        history = []

    history.append({'program': program_name, 'score': score})
    with open(history_file, 'w') as f:
        json.dump(history, f, indent=2)

    print(f'{program_name}: {score:.1%}')
    return score

評価のベストプラクティス

DSPyパイプラインにおける評価の主な原則は次のとおりです。

  • テストセットは厳密に取り分け、決して最適化に使用しない
  • 信頼できるスコアを得るため、少なくとも50~100個のテスト例を用意する
  • 評価指標を実際の本番環境の目標に合わせる
  • 複数のオプティマイザーを比較する。結果はタスクによって異なる
  • スコアを時系列で追跡し、リグレッションを検出する
  • 失敗を手動で調査し、トレーニングデータを改善する

理解度チェック:評価指標関数のtraceパラメーター

DSPyの評価指標関数で、traceパラメーターがNone以外になるのは何を示していますか?

まとめ:DSPyパイプラインの評価

dspy.Evaluateはラベル付きの開発セット上でプログラムを実行し、評価指標関数を適用して、集計スコアを報告します。評価指標関数は(example, prediction, trace=None) -> floatというパターンに従います。並列評価にはnum_threadsを使用し、失敗の診断にはdisplay_table=Trueを使用してください。最適化後のプログラムと最適化前のプログラムは、必ず取り分けたテストセット上で比較します。自由記述形式の出力では、LLMによる評価指標のほうが文字列の完全一致より優れています。

無料で開始

AI チューターと学ぶ AI Prompt Engineering — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
53
レッスン
199

よくある質問

「DSPyパイプラインの評価」レッスンは無料ですか?

はい。「DSPyパイプラインの評価」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Prompt Engineeringコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Prompt Engineeringコースには全4レッスンが含まれています。

「DSPyパイプラインの評価」で何を学びますか?

自動評価のためのメトリクス、開発用データセット、evaluate()関数を学びます。 ブラウザで直接実行するハンズオンコードでAI Prompt Engineeringを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Prompt Engineeringを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Prompt Engineeringは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「DSPyパイプラインの評価」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Prompt Engineeringレッスンでコードを書いて実行できますか?

はい。すべてのAI Prompt Engineeringレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. DSPy Framework入門
  2. シグネチャとモジュールの定義
  3. プロンプトのコンパイルと最適化
  4. DSPyパイプラインの評価
← AI Prompt Engineeringに戻る