/claude-api hillclimbで評価データを使いモデルとeffortを探索する
/claude-api hillclimbは評価をtrainとtestに分け、モデル・effort・プロンプトの変更を1周ずつ試します。前提条件、分割の考え方、停止条件、結果の読み方をまとめます。
/claude-api hillclimbは評価を使って設定変更を反復探索するコマンド
/claude-api hillclimbは、既存の評価(eval)に対してアプリを反復改善するClaude Codeのコマンドです。評価データをtrain(訓練)とtest(検証)に分け、モデル・effort・プロンプトなどの変更を1周ずつ試します。失敗したtrainの事例を読んで次の変更を決め、最終的な設定はtestの成績で採否を決めます。
狙いは2種類あります。スコアを上げることと、スコアを保ったままコストやレイテンシを下げることです。コスト削減が目的なら、モデルを一段安いものへ替え、足りなくなった分をプロンプトで補う探索になります。
使える条件は次のとおりです。
- Claude Code v2.1.259以降(
build-evalとhillclimbの要件) - コマンドラインから実行でき、固定のプロンプト集に対してスコアを出す評価スクリプトがあること
評価が無いときは、/claude-api build-evalで先に作ります。評価なしで走らせると、編集して祈るだけの作業になるためです。コスト削減の全体像はClaude Platformのコストを削減する3つの実装レバーにあります。この記事は、その3つ目にあたるhillclimbの手順だけを掘り下げます。
実行前に決まる4つの確認事項
hillclimbはスキルの手順書(eval-hillclimb.md)に沿って進みます。最初の数ステップは、ループを始める前の確認です。
評価が実行できるかを確かめる
Claudeはまず、評価コマンドとその結果の出力先を尋ねます。評価の各実行では、ケースごとの全文トランスクリプト、使用モデル、トークン使用量、採点結果を残す必要があります。合計スコアだけでは足りません。
再試行(retry)の扱いも確認されます。再試行でやっと通ったケースは、既定では失敗として数えます。再試行の分もコストに計上されます。
評価が改善を検出できるかを確かめる
次に、評価そのものが信頼できるかを調べます。ラウンド1の前に、次の3つの数字がユーザーに示されます。
| 数字 | 意味 |
|---|---|
| ノイズフロア | 意味現在のケース数と反復数での、差の信頼区間の半幅 |
| 余地(ヘッドルーム) | 意味満点とベースラインの差 |
| 動く価値のある最小の改善幅 | 意味ユーザーが採用を決められる最小の差 |
ノイズフロアが余地や最小改善幅より大きいと、ループは本物の改善を示せません。その場合は、反復数を増やす、ケースを増やす、より細かい指標に替えるといった提案が先に出ます。
そのほかに、次の検査が入ります。
- 採点結果の合計を、ケース別の生データから自分で再計算する
- ベースラインで最も低い数ケースを読み、採点が公正か、正解値が正しいかを確かめる
- 応答に含まれる
modelを見て、想定のモデルで動いたかを確かめる
出来すぎた数字は、手で照合するまで測定バグとして扱われます。
何を最適化するかを選ぶ
目的は選択式で聞かれます。スコアを上げる、リクエストあたりのコストを下げる、レイテンシを下げる、別モデルへ移ってスコアを取り戻す、のいずれかです。
答えは3つのことを決めます。分析役が狙う主指標、停止条件の指標、そして保護対象の指標です。たとえばコストを目標にしたなら、正解率は「ノイズの範囲を超えて悪化してはいけない」制約に変わります。目標は_state.jsonに記録され、再開したセッションが勝手にスコア改善へ戻ることはありません。
どこを触ってよいかを決める
次に、変更してよい対象を聞かれます。システムプロンプト、スキルや指示ファイル、ツール説明、モデルやeffort・thinking・max_tokensなどのAPIパラメータ、エージェントループ本体が候補です。触ってはいけない範囲も同時に確認されます。この禁止リストは厳守されます。
評価を実行するスクリプトや採点コードは「ハーネスのパス」として登録します。登録したファイルが承認後に書き換わると、実行が止まります。知らないうちに評価が変わることを防ぐ仕組みです。
trainとtestの分割はどう決まるか
hillclimbの信頼性は分割で決まります。分析役は失敗事例を読み、その失敗を直す変更を出します。その事例は設計上、成績が上がりやすくなります。だから報告する数字は、分析役が一度も読んでいないケースから出す必要があります。
既定はtrain/testの2分割
既定の分け方は次のとおりです。
- train: 各ラウンドで分析役がトランスクリプトを読むケース
- test: 毎ラウンド採点はするが、分析役は決して開かないケース。勝ったラウンドを選ぶ基準であり、最終的な成績になる
分割は、tags[0]で層別したランダム抽出で行います。ベースラインのスコアで分けてはいけません。低得点のケースだけをtrainに集めると、分析役は極端な失敗にだけ最適化し、それらは再実行すれば平均へ戻ります。trainは伸びるのにtestが動かない場合は、この兆候です。
ベースライン測定のあと、trainとtestの平均がノイズの範囲で一致するかを確認します。ずれていれば、ラウンド1の前に引き直します。分割は一度決めたら変えません。
testの件数と誤差の関係
二値の正解率では、95%信頼区間の半幅はおよそ1/sqrt(n·反復数)です。testが25件で反復2回なら約±14ポイント、50件で反復2回なら約±10ポイントになります。件数と反復数は同じダイヤルの2つのつまみで、どちらを増やしても誤差は縮みます。
この誤差の読み方はモデル評価の統計的手法にも詳しくあります。
分割しないほうがよい場合
ケース数が少ない評価や、順位付けのようにケースをまたいで成立する指標では、分割しません。全件を毎ラウンド採点し、反復でノイズを抑えます。このとき各ラウンドの数字は「方向を示す値(directional)」として扱われます。公開用の数字にはなりません。
約150件以上と多い場合は、勝者選びに使う検証用スライスを別に切り、testを最後まで温存する3分割も選べます。
1ラウンドで起きること
ループは「分析、適用、実行、記録」の繰り返しです。守られるルールは2つあります。読むのはtrainのトランスクリプトだけであること。評価セットと予算を、ユーザーに戻らず変えないことです。
分析役はtrainだけを読む
次の変更が自明でなければ、まっさらな分析役(サブエージェント)が起動します。渡されるのはtrainのトランスクリプトと採点結果だけです。メインのセッションは、変更を選ぶ段階ではトランスクリプトを読まず、スコアだけを見ます。testの情報が提案へ漏れない構造です。
分析役への指示には、次の方針が含まれます。
- 失敗の「内容」でなく「振る舞い」を書く。trainの固有名詞や語句をプロンプトに貼ると、trainだけ伸びる過学習の変更になる
- 1ラウンド1仮説にする。無関係な修正を束ねると、効いた部分も戻すべき部分も分からなくなる
- 効果が見えない変更に周回を使わない
評価で測れない小さな言い換えには周回を使わない
3つ目の方針は、v2.1.284で挙動が改善された点です。この版から、hillclimbは評価で測れないほど小さいプロンプトの言い換えにラウンドを使わなくなりました。
背景にはノイズフロアの考え方があります。効果がノイズフロアより小さい変更は、残るか戻るかが偶然で決まります。そのため、失敗の原因を根から直す変更(節の書き直し、欠けているルールやツールの追加、effortの変更)を優先します。一文の言い換えは対象外です。差分の長さでなく、効果で測ります。
効果を出せる量にも上限があります。ある振る舞いを直して得られるのは、その振る舞いで落としているケースの分までです。落とし分がノイズフロアに届かないなら、変更を膨らませず、停滞として扱います。
適用と実行
変更は、既定ではClaudeが適用します。顧客向け文面や法務・医療のような領域では、各ラウンドの差分を実行前にユーザーへ見せる承認モードも選べます。適用の前には、意味のない一般論を削る作業(de-fluff)が毎回入ります。
評価は毎ラウンド全件を実行します。件数を絞ると過去ラウンドと比べられなくなるためです。実行はrun_in_backgroundのBashで走らせ、完了通知を待つ間も会話は使えます。effortのようなサーバー側で検証される設定は、まず1ケースだけ流して受理されるかを確かめてから全件を走らせます。
記録と採否
各ラウンドの結果はvN/ディレクトリに保存されます。状態は次のような構成です(公式ガイドの既定レイアウトに沿った形)。
.claude/hillclimb/<flow>/
_state.json # ラウンド番号・分割ID・best・goal
narrative.md # 各ラウンドの効果を要約した実行サマリ
baseline/ # results.jsonl / summary.json / traces/
v1/ # change.md / change.patch / 結果一式
v2/_state.jsonのgoalには最適化の狙いが入ります。コスト削減を狙うときの記録例は次のとおりです。
{
"goal": {"target": "cost_usd", "direction": "lower", "hold": ["pass"]},
"approve_each_round": false,
"train_ids": ["case_01"],
"test_ids": ["case_02"],
"harness_paths": ["eval/run-eval.mjs", "eval/grade.mjs"]
}採否のルールは明快です。trainが上がってtestが上がらないなら、trainで読んだケースへの過学習として変更を戻します。trainも下がったなら、次に積む前に戻します。trainが下がってtestだけ上がった場合は、反復が少ないときのノイズとして扱い、再実行で同じ傾向が出たときだけ残します。
探索が止まったときの分類
数ラウンドの間、testがノイズの帯を越えなくなったら、内容の追加をやめて失敗を分類します。残った失敗の原因が、対象のプロンプトや設定だとは限らなくなるからです。ここで分析役が、trainの失敗を原因別に分けます。
- 採点側の不一致: 出力は正しく見えるのに採点が誤りにしている。採点を直し、全ラウンドを保存済みの出力から再採点する
- 構造の問題: 内容は存在するのにモデルが到達していない。ファイルを整理し直す
- ばらつき: 同じコードでの再実行の差が、ラウンド間の差と同じ大きさ。反復を増やすか目標を変える
このほか、失敗が小さな塊に分かれて散らばっている場合は、一括で軽く網羅する「幅出しの周回」も提案されます。
結果はtestの差で読む
終了時、コードベースはtestで勝った版に置かれます。見るべきはtestのスコアがベースラインから勝者へどれだけ動いたかです。trainの伸びは過程であって、成果ではありません。信頼区間つきで報告され、差がノイズの範囲内なら、マージを勧めないと明言する設計です。
ブログの例が、この読み方を具体的に見せています。カスタマーサポートのベンチマークで、Opus 4.8を既定の高effortで走らせた状態から出発しました。
- Opus 5を低effortで試し、prompt-auditで必須のツール呼び出し儀式・スクラッチパッド手順・矛盾するルールを削った。train正解率は98.9%で、1チケットあたり2.6セントになった
- Sonnet 5の低effortへ下げた。1セントとさらに安くなったが、正解率は88.9%まで落ちた
- 失敗したtrainのチケットを読み、ルーティング規則と返金上限の相互参照をプロンプトに追加した。Sonnet 5で98.9%に戻り、コストは同じ
最後に、探索が一度も見なかった14件のtestチケットで採点しました。最終設定は90.5%で、元の設定の78.6%を上回り、コストは約5分の1です。
注目点は、trainの98.9%でなくtestの90.5%が結果として示されていることです。
レポートの出力
各ラウンドの後、report.htmlが作られます。全ラウンドのスコア推移、トランスクリプトの比較、ラウンドごとの差分を1ファイルで見られます。ラウンド後の報告には、このパスが末尾に添えられます。
レポート以外の表示がほしい場合は、report.htmlの隣に追加のページとして作らせます。v2.1.284以降、その追加ページは外部を読み込まない単一のローカルファイルとして生成されます。社内のドキュメントに貼るときに、ネットワークへ依存しない形です。
コストを見積もるには
ラウンドごとに全件を評価するため、ループ全体のコストはベースラインを含めて(ラウンド数 + 1) × 反復数 × 1回あたりのコストが目安です。採点にモデルを使うなら、判定の呼び出し分も加えます。
予算を聞かれたときは、ケースごとのusageを合計し、価格表でドルへ換算し、実際に1回流した所要時間を測って見積もります。負担を減らす手段は、ラウンド数を減らす、反復を減らす、判定モデルを安くする、判別力の高いケースに絞ってから最後に全件で確認する、の4つです。ただし既定では、ラウンド中に評価セットを黙って絞ることはしません。予算は目安であり壁ではありません。上限に近づいてスコアが伸びているときは、延長を提案する設計です。
コスト削減そのものが目標なら、キャッシュの健全性、prompt-audit、モデルとeffortの階段、プロンプト調整の順に進める専用ガイド(cost-hillclimb.md)を参照するよう指示されます。この段取りは、個別のコマンドである/claude-api cost-optimizeやprompt-auditと重なります。
導入時に確認したい注意点
- 正解データを隠す: 参照回答や採点基準は、モデルの文脈から読めない場所に置く。プロンプトへ「答えを見るな」と書いても防御にならない
- レビュー役を決める: 承認モードにするか、自動適用にするか。顧客向けの文面を含むなら承認モードが選択肢になる
- 1つのループでは1つの評価を使う: 評価の中身を途中で変えると、過去のラウンドと比べられない
- 評価を作る: 評価が無いなら、先に
/claude-api build-evalで作る。評価の設計自体はプロンプト評価の実践ガイドが参考になる
モデルを替える移行が目的なら、移行ガイドの内容も踏まえて変更が提案されます。effortの意味や設定はmodelSettingsのeffortをモデル別に編集する方法に整理されています。
実行の流れをまとめると
呼び出しは、評価が用意できているプロジェクトで/claude-api hillclimbを実行するだけです。
/claude-api hillclimbあとはClaudeが評価コマンドの場所、目標、対象範囲、停止条件を順に尋ね、計画の承認を求めます。承認後に分割とベースラインの測定が始まります。
hillclimbは、探索そのものより「本物の差か」の判断を重く見る作りです。testを守る、ノイズフロアを先に測る、効果が見えない周回に予算を使わない。この3点があるから、出てきた勝者設定はtestの差として読めます。
個別の変更履歴はClaude Code v2.1.284のリリースノートにもあります。