Claude に eval を作らせ、プロンプトを磨かせる:スコアに騙されないために
Anthropic は claude-api skill に build-eval と hillclimb を加えました。一方は eval を作って採点し、もう一方は一回に一か所だけ変え、取り置いた問題で過学習を見つけます。サポートの事例ではコストが約五分の一に、skill 自身は 66% から約 88% になりました。
AI アプリを作る人は、遅かれ早かれ二つの問題にぶつかります。うまく動いているかどうかをどう知るか、そしてどうやってもっと良くするか。前者は eval(評価。固定したタスク群と採点方法のセット)で、後者は hillclimb(山登り。文字どおり、一か所だけ変えてスコアが上がったか確かめ、上がれば残すこと)で答えます。簡単そうに聞こえますが、どちらも自分を騙しやすい落とし穴があります。タスクの選び方が悪ければスコアは意味を持ちませんし、その評価セットに合わせすぎて変更すれば、スコアは上がっても本番は良くなりません。
Anthropic の Lance Martin は、この二つの原則をまとめた長文を書き、Claude Code の claude-api skill に加わった二つのコマンドがそれらの原則をどのようにワークフローにしているかを説明しています。/claude-api build-eval はコードベースの中に評価を作り、/claude-api hillclimb はその評価を使ってアプリを改善します。変更は一度に一か所だけで、最適化する側には決して見せない問題を取り置いて、過学習を見つけます。記事は二つの実例で締めくくられます。一つはカスタマーサポートの場面でコストを約五分の一に下げた例、もう一つは claude-api skill 自身を 66% から約 88% に引き上げた例です。
以下は記事の順に進めます。まず良い eval の姿、次に build-eval がどう作るか、続いて hillclimb がどう登り、どう過学習を防ぐか、最後に二つの事例です。
良い eval とはどういうものか
記事は四つの特徴を挙げています(図 1)。
タスクは本番のものに似ていること。 作りやすい、採点しやすいという理由でタスクを選ぶ人がいて、その結果、実際のユーザーが持ち込むものとまったく違う分布になってしまいます。eval が測るべきなのは、あなたが本当に気にしている種類の仕事です。
モデルが強いほど、考えるほど、スコアは高くなるはずです。 より強いモデルに替える、あるいは effort(推論にどれだけ力を割くかの段階)を上げれば、スコアは上がるはずです。上がらないなら、たいていタスクが曖昧か、採点役の grader の校正がずれていて、成績の足を引っ張っています。
最強のモデルにも余地が必要です。 最高の effort の最強モデルは、100% をはっきり下回るべきです。そうでないと、何を変えても違いが見えません。しかも、その差が「解けないタスク」のせいであってはいけません。よくある兆候は、何回繰り返しても毎回全滅するタスクがあることです。良いタスクとは、二人のドメイン専門家が同じ結論に至り、grader が確認するすべての点がタスクの中に書かれているものです。
実行ごとのばらつきは小さいこと。 ばらつきが大きい原因は、タスクが曖昧であるか、同じ出力に対して grader が毎回違う判定をすることが多いです。設定の中に隠れていることもあります。たとえば effort が一貫して適用されていない場合です。環境の影響もあり、前の試行で残ったファイルや git 履歴が、Agent に答えをそのまま渡してしまうことがあります。
「今日のモデルが解けない」ものだけを選ばない
記事は、ごく自然にやってしまいがちなやり方に、はっきり警告を出しています。現在のモデルが間違えたケースを集めて eval にすることです。モデルの能力はギザギザで、強いところもあれば、妙に弱いところもあります。今日の弱点だけを選ぶと、測れるのはそのモデルの「失敗の指紋」だけで、あなたのアプリで本当に難しく価値のある部分ではありません。次世代のモデルが出れば、その谷は丸ごと持ち上げられ、あなたの eval は意味を失うかもしれません(図 2)。
より良いやり方は、何が難しいかを人が判断し、なぜ難しいのかを説明できることを条件にすることです。説明できないなら、いったん入れません。加えて、本番トラフィック、バグ報告、チケットから出てきた具体的な失敗も入れます。ただしユーザートラフィックを鵜呑みにしてはいけません。ユーザーはうまくいくと思うことを試しがちなので、トラフィックだけから抽出したタスクは易しい側に偏ることがあります。図 2 の右側には、「発動すべきでない」ケース、つまり何もしないのが正解の場面も描かれています。これも必要です。
/claude-api build-eval:Claude があなたに聞き取りをして、eval を作る
このコマンドを Claude Code で実行すると、Claude はまずあなたに聞き取りをし、そのあとコードベースの中に eval を作って、要所で止まってあなたの承認を待ちます。
まずタスクを決める:どのデータを優先するか
Claude が入力を探す順番は次のとおりです。
- 本番のやり取りの記録。まず保持期間と機密情報の扱いを確認します。
- バグ報告とサポートチケット。
- あなたが手で書く 5〜10 件。
- コードベースから合成したケース。
本番データが優先ですが、なければ、あなたが渡した実例をいくつか足がかりにして合成データを作れます。作り終えると、すべての入力を並べたシンプルなページを生成し、あなたの確認を待ちます。記事の例はメール振り分けアプリです。24 通の顧客メールに「請求・易しい」「請求・曖昧」のようなタグが付き、Claude はチャットでこう尋ねます。これらはアプリが実際に見る入力を代表していますか。明らかに足りないケースや、入れる必要のないケースはありませんか。(図 3)
次に採点を決める:まずコードで足りるか、だめなら審査役を置く
入力が決まったら、次は grader です。Claude は「足りる範囲で一番安いもの」を提案します。
- プログラムによる検証: 出力の取りうる範囲が限られているときは、コードで判定します。完全一致、固定ラベルから一つ選ぶ、JSON が決まった形式に合う、テストが通る、などです。
- LLM を審査役にする(LLM-as-judge):出力が自由形式で、正解が多数ありつつ品質基準が明確なときの既定です。審査役は別のモデルで、入力、出力、採点基準を読み、スコアと理由を返します。採点基準は「1〜5 点」の尺度ではなく、確認できる主張を一つずつ並べる形で書きます。比較できるベースラインがある場合は、審査役は二つの出力をランダムな順序で、どちらがベースラインかを知らされずに読み、より良いほうを選びます。審査役のモデルはあなたが選びますが、テスト対象のモデルそのものであってはいけません。
Claude はいくつかのケースを採点し、あなたなら違う点をつけるものがあるかを尋ねます。記事が特に強調しているのは、採点役を信じる前に、採点済みの記録をいくつか読むことです。採点の誤りは、評価の設定ミスで最もよくあるものの一つです。
ベースラインを走らせる:何が手に入るか
grader が検証されると、skill は評価セットの規模(ケース数 × 繰り返し回数 × モデル、およびおおよその所要時間)を伝え、ベースラインを走らせて、信頼区間つきのスコアを表示します。手に入るのは、ケース、grader、ランナー、ケースごとの JSON 一行と完全なやり取りの記録、そして各ケースのスコアを一覧にして記録へのリンクを付けたシンプルなページです(図 4)。グラフなどもっと欲しければ、Claude に頼めば隣に別ページとして作ってくれます。既定では、これらの追加ページは静的ファイルで、ローカルで開け、ネットワークから何も読み込みません。
ベースライン段階の三つの健康診断
ベースラインを走らせる間に、Claude は三つのことをついでに確認します。
- grader: 同じ出力を二回採点して、判定が変わらないかを見ます。
- 配管: タイムアウト、API エラー、途中で切れた回答がないかを見て、インフラのノイズをモデルのばらつきと取り違えないようにします。
- 余地: ベースラインがすでに約 95% 以上なら、skill が警告します。その場合、山登りの目標は品質ではなくコストやレイテンシーにすべきです。
山登り:何を登る価値があり、どうすれば横道に逸れないか
信頼できる採点方法ができたら、それを使ってアプリを改善できます。山登りは、コストと効果のトレードオフになるパラメーター、たとえば effort やプロンプトの調整にとりわけ向いています。記事は、登る対象を選ぶための三つの経験則を挙げています。
変更が安いこと。 時間、費用、手間のどれも安く、間違えたら元に戻せること。多くの社内の取り組みや顧客は、山登りの対象をプロンプトや skill などのテキストに置いています。変えやすく戻しやすいからです。逆に、山登りの最中に Agent の harness(モデルの外側のコード:プロンプト、ツール、呼び出しループ)を自由に書き換えさせると、大規模なコード変更になりかねません。
スコアの変化を原因に結びつけられること。 スコアの上下は、あなたが変えているものから来ているべきです。記事の例は skill のトリガーです。成功した山登りのいくつかは「skill がいつ発動するか」に絞っており、評価指標(発動率)が、変更される skill の説明に直接結びついています。
目標が絞られていること。 よくある失敗は、評価にどれだけ余地があるかを考えずに、漠然と「性能を上げて」と頼むことです。評価が飽和に近い場合や、変更範囲が散漫な場合(たとえば漠然と harness を直させる)は、足踏みしやすくなります。記事によれば、さまざまな取り組みで安定して機能した目標の一つがコストです。評価が飽和していても、Claude にスコアを落とさずにコストを下げる方法を探させることができます。
過学習:評価が harness に漏れ込むしくみ
どれほど良い評価でも、本番で気にしているタスク分布と完全に一致することはまずありません。そのため「過学習」はよく起きます。システムは評価では良くなるのに、本番トラフィックでは良くなりません。
記事の例はこうです。ある評価では、いくつかのタスクが OCR(文字認識)でうまく解けるのに、本番のタスクではほとんど OCR が役に立ちません。山登りの対象の harness はアプリに OCR ツールを足し、スコアは上がりますが、本番にはまったく効きません。より一般的には、山登りは、あなたが選んだ評価例の中の端のケースに対処する機能を harness に足していくことがあります。それらの追加は評価スコアを押し上げますが、本番には持ち越されません(図 5)。
図の五行のうち、最初の四行は少しずつ合わせていく形です。タスクに OCR が必要ならツールを足す。タスクがすべて /app にあるなら cd /app を固定して pytest を走らせる。言い回しが特徴的ならプロンプトをその言い回しに合わせる。失敗をたくさん読んだら、失敗ごとにパッチを一つ当てる。最後の行は最も直接的な漏洩です。タスクが答えの入った公開リポジトリ由来なら、harness は参照解答をそのまま curl で取ってくることを覚えてしまいます。
三つの防衛線
- ケースを分ける。 一部は train(山登りする側が読んでよい)、残りは test(決して見せない)にします。train のスコアが上がるのに test が動かなければ、それが過学習の最もよくある警告サインです。
- 失敗の内容を決してプロンプトに貼らない。 山登りする側が失敗したやり取りの記録を読んでも、その内容をそのままプロンプトに貼ってはいけません。これはまさに図 5 の四行目「失敗ごとにパッチを一つ」のやり方です。パッチがその具体的な失敗に密着するほど、評価のタスクをプロンプトに書き写しているのに近くなり、上がるのはそのタスク群のスコアで、能力ではありません。
- 答えが構造的にモデルの手の届かない場所にあるようにする。 モデルは時々 reward hack(評価の抜け穴を突くこと)をして、答えを直接見つけ出すことがあります。だから、答えは構造上届かない場所に置く必要があります。
/claude-api hillclimb:一回に一つの変更、常に test を見張る
このコマンドの入口は、評価があり、あなたの目標に沿って Claude に改善してほしい、という場面です。Claude に何を変えてよいかを選べます。
- システムプロンプト。
- skill や指示ファイル。
- ツールの説明。
- モデルの選択、effort の段階、その他の API パラメーター。
- harness のコード。
始める前に、Claude は何を最適化したいか(たとえば性能、あるいは性能を保ったままコストを下げる)を尋ね、そのうえで評価セットを test と train にランダムに分けます。目標がコストの場合は、プロンプトキャッシュ、プロンプトと選んだモデルの互換性の確認、モデルと effort の選択など、よくあるコスト要因をいくつか検討します。
最初の一回の前に、評価のノイズ(運だけでスコアがどれだけ動くか)が、あなたが行動に移す最小の改善幅より小さいことを確認します。ノイズは、ベースラインを N 回繰り返して測ります。同じバージョンを何度か走らせるとスコアはもともと揺れ、その揺れの大きさが「ノイズの床」です。その後のどんな変更の改善も、この床を超えて初めて意味を持ちます(図 6 の「pre-flight」がこの段階です)。ノイズが求める改善幅より大きければ、Claude はそう伝え、繰り返し回数かケースを増やすよう提案します。
一回ごとの流れ
各回、Claude は前回の train のやり取りの記録を読み、パッチの形で一つの変更を提案します。狙いは、評価のノイズを超えて効果が見える変更にすることです。そのため、失敗している振る舞いを根本から直します(原因となっている節を書き直す、足りないルールを補う)。言い回しを変えて一行いじるのではありません。そして、パッチを当てたものを評価にかけます。
ここで確認が入ります。train が上がっても test が動かなければ、Claude は過学習を疑ってパッチを戻します。退行があれば戻します。train と test の両方が上がったときだけ、パッチを残します(図 6)。
スコアが停滞したら
スコアが二、三回続けて動かなくなると、Claude は残っている train の失敗を一つずつ読み、原因ごとに分類します。単独の修正でも評価のノイズを超える見込みがないと分かった場合も、早めに同じことをして、測れないほど小さな変更に回数を費やすのではなく、繰り返しかケースを増やすよう提案します。この段階で、曖昧な評価ケース、harness のエラー、実行ごとのばらつきを見つけられます。本当の失敗だけが、その後の山登りの回に引き継がれます。
終わったときに手に入るもの
山登りが終わると、Claude はあなたの目標にとって test で最も良かったバージョンにコードを置き、test の結果をベースラインと比べて、信頼区間つきで報告します(図 7)。改善がノイズの範囲内なら、そう伝えたうえで、マージしないことを勧めます。
二つの実例
事例一:コストを下げながら精度も上げる
Anthropic は、社内のカスタマーサポートのベンチマークで /claude-api hillclimb を走らせ、コスト削減と性能向上を目標にしました。ベンチマークはチケット 44 件で、30 件を探索に使い、14 件を取り置きました。出発点は Opus 4.8、既定(高)の effort で、探索用チケットでの判断精度は 74.4%、チケット一件あたりの token コストは 4.6 セントでした。
山登りはまずプロンプトを見直し、必須のツール呼び出しの「儀式」、下書きのステップ、互いに矛盾するルールを削りました。次に Opus 5.5 の低 effort を試し、精度は 87.8% とベースラインを上回り、コストは 1.9 セントと、出発点の半分未満になりました。
この節約の一部は Opus 5.5 の価格によるものです。入力と出力の token は Opus 4.8 より 20% 安く、キャッシュ読み取りは 60% 安くなっています。Opus 5.5 が基準を超えたので、山登りはさらに一段下げて、もっと安いモデルでも通るかを確かめました。Sonnet 5 の低 effort はほぼ同じ 88.9%、コストは約半分の 1 セント前後でした(図 8)。
最後に、Claude はルーティングのルールと返金上限の相互参照を加えてプロンプトを改善し、Sonnet 5 を 98.9% に引き上げました。コストはほぼ同じです。探索に一度も使っていない取り置きの 14 件では、最終構成が 90.5%、元の構成が 78.6% で、コストは元の約五分の一でした。
押さえておきたいことがあります。図 8 と前に挙げた数字(74.4%、87.8%、88.9%、98.9%)は、いずれも探索用の 30 件で読み取ったものです。外に向けて言える結果は、取り置きセットでの 90.5% 対 78.6% です。取り置きは 14 件しかなく、この差がどれほど確かなのかについて、記事は信頼区間を示していません。
事例二:claude-api skill 自身を改善する
二つ目の例は claude-api skill そのものです。この skill は、Anthropic の API の使い方と Claude と付き合うための一般的なコツ(本記事で扱う二つのサブコマンドを含む)を案内します。チームは、この skill が API を使う正しいコードを書けることを確かめたかったので、公式ドキュメントをもとにした評価セットを作りました。
出発点は 66% でした。山登りする側にドキュメントと SDK へのアクセスを与え、Claude が自分で誤りを見つけて直せるようにしました(図 9)。Claude は、skill に 8 つの機能の説明が抜けていることを見つけ、それを補うと 74% に上がりました。続いて C# と Java の型テーブルの誤りを見つけ、直すと 77% になりました。
この過程は全部で 24 回でした。スコアが二回停滞したあと、Claude は残った失敗を根本原因ごとに分類しました。この段階は特別です。通常の回は、最も多い失敗に対して一か所を編集しますが、この段階は何も編集せず、残ったすべての失敗を原因ごとに分けるだけです。この「振り返り」の段階には、いくつかの価値がありました。
skill の中に内容はあるのに、Claude が古い API の書き方を書いていることが分かりました。 これは学習時に身についた先入観から出てきたものです。そこで山登りする側は、skill の上のほうに、Claude が覚えている古い形から現在の形へ導く対応表を加えました。たとえば、固定の token 予算を使う extended thinking(拡張思考)は、最近の Opus モデルでは API が受け付けなくなっているので adaptive thinking(適応型思考)へ、古い版の web search と web fetch ツールは現行版へ、といった具合です。さらに、C# と Java にある「固定予算の思考を使わない」という警告を、適応型思考の例の前へ移しました。スコアは 80% に上がりました。
どうしても上がらないタスクは、評価自体に欠陥がある兆候です。 明らかな内容の不足を補っても上がらないタスクは、たいてい問題文か grader に問題があることを示します。あるタスクは特定のエラーを一種類捕まえるコードを求めていたのに、grader は少なくとも三段のエラー連鎖を求めていました。Claude は問題文を書き直しました。別の grader の指示はドキュメントと矛盾していて、実際の API で試すとドキュメントが正しく grader が誤りでした。これらを直し、さらに skill の編集を重ねて、スコアは約 88% に達しました。
使い始めるには
記事の最後に示される入口は、率直なものです。
- ある問題のために評価を生成したいなら、
/claude-api build-evalを実行します。実行記録などのサンプルを渡して誘導できます。上記の原則に沿ってケースと grader を設計し、ケースと grader の両方にあなたの承認が必要になるようにします。 - すでに評価があり、Claude に目標に沿って改善させたいなら、
/claude-api hillclimbを実行します。目標は、性能の向上、または性能を保ったままコストを下げることです。登っている間に過学習を確認し、最初の一回の前とスコアが停滞したときに、評価そのもののバグ、たとえば正しく見える答えを不正解にする grader や harness のエラーがないかも確認します。
