感覚の罠
あなたはagentを作りました。30分間会話しました。賢そうに見えました。リリースしました。
3日後、ユーザーが「基本的な質問に対して自信満々に間違った答えを返した」と報告してきます。再テストすると問題なく動きます。肩をすくめます。モデルの調子が悪かっただけだろう、と。
これが感覚の罠です。非公式な印象を品質シグナルとして使うことです。趣味レベルなら成り立ちます。しかし、実際のユーザー、実際のお金、実際のリスクが絡んだ途端に破綻します。
Evalsが出口です。
Evalとは実際何か
Evalはpromptと期待される動作を受け取り、スコアを返す関数です。それだけです。始めるのに複雑なインフラは不要です。
書ける中で最もシンプルなeval:
interface EvalCase {
input: string;
expected: string;
check: (output: string) => boolean;
}
const cases: EvalCase[] = [
{
input: "What is 2 + 2?",
expected: "4",
check: (out) => out.includes("4"),
},
{
input: "Summarize: 'The quick brown fox jumps over the lazy dog'",
expected: "mentions fox and dog",
check: (out) => out.toLowerCase().includes("fox") && out.toLowerCase().includes("dog"),
},
];
async function runEvals(model: (prompt: string) => Promise<string>) {
let pass = 0;
for (const c of cases) {
const output = await model(c.input);
if (c.check(output)) {
pass++;
console.log(`✓ ${c.input.slice(0, 40)}`);
} else {
console.log(`✗ ${c.input.slice(0, 40)}`);
console.log(` Got: ${output.slice(0, 100)}`);
}
}
console.log(`\n${pass}/${cases.length} passed (${Math.round(pass / cases.length * 100)}%)`);
}
promptを変えるたびにこれを実行してください。これでリグレッションスイートができあがります。
必要な3種類のチェック
1. 完全一致 — 構造化された出力、コード、ID、yes/noの判定に使います。バイナリ。高速。
2. 含有チェック — 正確な表現は変わっても重要な事実が含まれるべきproseの出力に使います。「出力に'パリ'が含まれている」の方が「出力が'パリはフランスの首都です'と等しい」より堅牢です。
3. モデルによる評価 — 意味的な判断が必要な複雑なタスクに使います。2番目の(より安価で高速な)モデルに尋ねます。「この回答は質問に正しく答えていますか?YES か NO で1つ理由を添えて答えてください。」これは主観的な品質、トーン、推論の連鎖にまでスケールします。
async function modelGrade(output: string, criterion: string): Promise<boolean> {
const verdict = await callModel(
`Criterion: ${criterion}\nOutput: ${output}\nDoes the output meet the criterion? Reply YES or NO only.`
);
return verdict.trim().startsWith("YES");
}
最初に何をevalするか
ゼロから始める場合は、この順番でevalしてください。
-
ハッピーパス — agentが明示的に設計された5〜10件の入力。これらはすべて通過するはずです。通過しなければ、動作するagentではなくデモがあるに過ぎません。
-
すでに失敗が確認されているエッジケース — テストで壊れたものすべて。すぐにエンコードしてください。すべてのバグはevalケースです。
-
adversarial入力 — 空の入力、不正な形式の入力、ドメイン外の質問、prompt injectionの試み。あなたのagentはグレースフルに劣化できる必要があります。
-
リグレッションセット — すべての変更時に実行する50〜100件の固定セット。グリーンは何も壊していないことを意味します。レッドは意思決定が必要なことを意味します。
Evalのワークフロー
Promptの変更 → Evalを実行 → スコアデルタを確認 → デルタ > 閾値ならリリース → 完了
閾値はリスクによって異なります。趣味プロジェクトなら -2% を許容するかもしれません。顧客データを扱う本番agentは +0% 以上を要求すべきです。「小さな」prompt調整後にスコアが4%下がったときにプレッシャーの中で判断しなくて済むよう、始める前に明示的に設定しておいてください。
知っておく価値のあるツール
- Braintrust — evalの実行、ロギング、モデル比較。寛大な無料枠があります。
- Promptfoo — オープンソース、ローカルで動作、red-teamingに優れています。
- Langfuse — observabilityとevalを兼ね備え、スコアと並行してトレーシングも行いたい場合に適しています。
- DIYスクリプト — シンプルなagentなら、50行のTypeScriptスクリプトで十分なことが多いです。作り込みすぎないこと。
不快な真実
agentの失敗のほとんどはpromptの失敗であり、モデルの失敗ではありません。新しいモデルは必要ありません。今のpromptがどこで壊れるかを把握して修正することが必要です。
Evalsはそれを教えてくれます。感覚は教えてくれません。
次の機能を追加する前にevalハーネスを構築してください。未来のあなたが感謝するはずです。
