JA EN
体系エージェント
·★ 会員·論文·15分で読めます

エージェント評価 — ベンチとハーネスの作法

エージェントのスコアは「モデルの点」ではなく「モデル+ハーネス+環境+採点規則の点」です。SWE-benchの1件がどんな部品でできているか、手数が伸びると一手の差がなぜ桁で効くか、リポジトリやネットワークから答えが漏れる四つの経路、そして部分点を安全に設計する条件までを1から扱います。

対象textタスクevaluation

SWE-bench: Can Language Models Resolve Real-World GitHub Issues?


「SWE-bench で50%」は何を言っているのか

発表資料に「SWE-bench Verified 50%」と書いてあったとします。素直に読めば「実際のGitHubのバグの半分を直せる」です。ところがこの数字は、モデル単体の性能ではありません。モデル・足回り(ハーネス)・作業環境・採点規則の四点セットで初めて決まる数字で、そのうち三つは棒グラフには出てきません。

比喩は採用試験です。四択の筆記で満点を取る人と、リポジトリを渡されて「このバグ直しておいて」で結果を出す人は、別の能力を測られています。後者で効くのは、テストの回し方を知っているか、直したついでに別の機能を壊さないか、詰まったときに引き返せるか。エージェント評価が測ろうとしているのはこの後者で、だから測り方そのものが設計対象になります。

ベンチマークを読むときの三つの問い — 何を測ったか、どう採点したか、問題が漏れていないか — は、エージェントでもそのまま必要です。その上に、これから見る三つが積み増しになります。

一問一答と違う三つのこと

1. 環境がある。 四択問題の入力は文字列ですが、エージェントの入力はリポジトリであり、シェルであり、ファイルシステムです。しかも入力が大きいだけでなく、エージェントは入力を書き換えられます。極端な話、落ちているテストを削除して「全部通りました」と報告できてしまう。採点する側は、環境の初期状態と最終状態の両方を管理しなければなりません。

2. 手数がある。 一発の生成なら成否は1回の勝負ですが、エージェントは何十手も打ちます。一手あたりの成功率を pp、必要な手数を nn とすると、完走できる確率はこうなります。

Psuccess=i=1npipnP_{\text{success}} = \prod_{i=1}^{n} p_i \approx p^{\,n}
(1)

pip_iii 手目で破綻しない確率、nn は最後まで行くのに必要な手数、PsuccessP_{\text{success}} は完走する確率です。要するに、一手ごとの生存率を全部掛け算したものが完走率という、当たり前の式です。

当たり前でなくなるのは数を入れたときです。一手99%で50手なら 0.99500.610.99^{50}\approx0.61、95%なら 0.95500.0770.95^{50}\approx0.077一手あたり4ポイントの差が、完走率では8倍近い差になります。逆側から見ると、完走率という一つの数字だけを眺めていても、どの一手が足りていないのかは永遠に分かりません。

FIG 1対数軸に切り替えると、どの曲線もただの直線になる。指数はnが伸びたところで桁を変える — 一手あたりのわずかな差が完走率で何倍にもなるのは、これと同じ形

3. 副作用がある。 四択の採点は答え合わせで終わりますが、エージェントは外に書き込みます。ファイルを消し、コマンドを叩き、APIを呼ぶ。評価環境が本番の認証情報を持っていた、という事故は採点以前の問題として起きます。エージェントの評価環境は、壊れてよい使い捨ての箱として作るのが前提です。

SWE-benchの1件を開ける

SWE-bench(Jimenez et al., 2023)は、実在のGitHub issueと、それを閉じた実際の修正コミットから機械的に作られたベンチマークです。12個のPythonリポジトリから集めた2,294件のタスクからなり、1件はこんな部品でできています。

{
  "repo": "django/django",
  "base_commit": "…",        // 修正が入る直前の状態。ここから作業を始める
  "problem_statement": "…",  // issue本文。モデルに渡してよいのは原則ここだけ
  "patch": "…",              // 人間が実際に書いた修正(正解・モデルには見せない)
  "test_patch": "…",         // その修正と一緒に入ったテスト
  "FAIL_TO_PASS": ["…"],     // 修正前は落ち、修正後に通るべきテスト
  "PASS_TO_PASS": ["…"]      // 修正の前後どちらでも通り続けるべきテスト
}

設計の勘所は、正解を「人間のパッチとの一致」で測っていないことです。同じバグの直し方は何通りもあるので、文字列で比べれば正しい修正も不正解になります。代わりに置かれたのが実行による検証で、FAIL_TO_PASS が「直っていること」を、PASS_TO_PASS が「壊していないこと」を担当します。この二本立てが、動くけれど別の機能を巻き添えにするパッチを弾きます。

派生セットの名前も押さえておきます。Lite(300件)は評価を回しやすいものを選び直したサブセット、Verified(500件)は人手で1件ずつ確認し、issue本文だけでは仕様が定まらない問題や、テストが厳しすぎて正しい修正でも落ちる問題を除いたものです。数字を比べるときは、まずどのセットの数字かを確認します。母集団が違えば、同じ「50%」は別の量です。

resolved の定義は、論理積である

SWE-benchの主指標 resolved(解決率)は、1件ごとに0か1です。

resolved=[tF2Ppass(t)][tP2Ppass(t)]\text{resolved} = \Big[\bigwedge_{t \in \mathrm{F2P}} \text{pass}(t)\Big] \wedge \Big[\bigwedge_{t \in \mathrm{P2P}} \text{pass}(t)\Big]
(2)

F2P\mathrm{F2P}P2P\mathrm{P2P} はさきほどの FAIL_TO_PASSPASS_TO_PASS\bigwedge は「そのすべてについて成り立つ」、pass(t)\text{pass}(t) はテスト tt が通ったかどうかです。要するに、直すべきテストが全部通り、かつ壊してはいけないテストが1つも落ちなかったときだけ1点、それ以外は0点。

この二値性は評価としては誠実です。八割方直った修正は、利用者から見れば直っていません。ただし開発の計器としては粗すぎて、「惜しかった」と「そもそも環境構築で終わった」が同じ0点になります。ここが部分点の設計動機で、後で扱います。

同じモデルでも、周辺の作りで数字は動きます。少なくとも次の四つが効きます。

この先にあるもの

§

ここから先は会員限定です

解説記事371本・教科書26章・学生モード48単元・論文精読6本が、月額¥490ですべて読み放題になります。新しい解説は毎日3本ずつ増えます。いつでも解約でき、解約後も期間の終わりまで読めます。

会員の方はログインすると続きが表示されます

参考文献

  1. SWE-bench: Can Language Models Resolve Real-World GitHub Issues?. arXiv:2310.06770論文ページ·PDF
  2. SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering. arXiv:2405.15793論文ページ·PDF

本記事は上記論文の本文にもとづいて執筆しています。数値・主張は原典を優先してください。

コメント

コメントにはログインが必要です