AIのループが収束しないのは、評価する側まで生成させているから
まとめ
- 自動改善ループが収束しないのは、モデルの性能不足ではなく、評価する側まで生成物にしているから
- ものさしが毎周すげ替わるフィードバックループは、原理的に収束しない
- 直し方は、生成の担当を判断だけに絞り、翻訳と評価を決定論のプログラムへ渡すこと
- 周回ごとに全文を投げ直す設計は、収束する前に予算が尽きる
数日で数百万円溶かしたループ
ある開発組織が、こういう自動化を試した。
ライブラリと言語のバージョンアップを安全に進めたい。 そのために、既存の挙動を担保する保全テストが大量に要る。 バグも含めて、今の挙動でグリーンになるテストコードだ。 量が要るのだから、自動で回せばいい。
組んだのはこれだけだった。
while :; do cat PROMPT.md | claude-code ; doneループは回った。 人手を挟まず、止まらずに回り続けた。 順調に見える。
それでも品質は収束せず、数日で数百万円のトークン代が溶けた。
自動化が失敗したと聞くと、モデルが賢くなかったのだろうと読みたくなる。 発表資料はそこを明確に否定している。 原因はモデルの性能不足ではなく、一発で正解を出させる問題設定が大きすぎたことだ、と。
「回っている」と「良くなっている」の距離
失敗の分解が資料に書かれている。 要件と観点とコード生成と評価が、一つの生成に混ざっていた。 生成も、評価の反映も、同じ確率的な系の中にあった。 だからコンテキストが膨れ、周回のたびに改善方向が揺れる。
ここで効いているのは、評価まで生成物にしていた点だと思う。
フィードバックループは、測る仕組みが固定されているという前提の上に成り立っている。 制御系でいえばセンサーにあたる部分だ。 そのセンサーが毎周すげ替わったらどうなるか。
前の周より良くなったという判定が、毎回違う基準で下されることになる。 たとえば1周目に「このアサーションは甘い」と判定して直した箇所が、3周目には「過剰に厳しい」と判定されて戻る。 どちらの判定も、その周だけ見れば筋が通っている。 基準が違うだけだ。
改善方向が揺れる、というのはそういうことだろう。 勾配を下っているつもりで、実際にはランダムウォークしている。 そして周回ごとに全文を投げ直していれば、揺れている間ずっと課金され続ける。
中身を差し替えたら収束した
うまくいった形は、ループの形を保ったまま中身を差し替えたものだった、と資料は書いている。 これも意外だった。 ループをやめたのではなく、ループの中の役割分担を変えただけで結果が変わっている。
失敗形では、要件解釈から観点出し、コード生成、出来の評価、次の改善方針まで、ひとつの生成の中に全部が入っていた。 そのうえで周回のたびに全文を再投入していた。
差し替え後はこうなる。
- AIがテスト観点を出し、YAML形式の仕様書にする
- 決定論的なプログラムがYAMLからテストコードを生成する
- テスト実行とカバレッジ計測で評価する
- 足りない観点だけをAIに追加生成させ、次の周回へ渡す
生成が触るのは1と4だけになった。
資料はこれを「品質責任を決定論の評価系に寄せた」とまとめている。 ただ、この差し替えには独立した効果が四つ入っているように見える。
一つめは、ものさしが固定されたこと。 カバレッジ計測は、同じ入力に同じ数字を返す。 前の周より良くなった、が初めて定義できる。
二つめは、目的関数が単調な数値になったこと。 カバレッジは観点を足せば増えるので、方向のある勾配が生まれる。 失敗形の「良いテストか」は多次元で、勾配が存在しない。
三つめは、誤りの波及範囲が閉じたこと。 生成物がコードから仕様に変わったので、観点が足りなくても壊れたコードにはならない。 しかも不足は数値として出る。
四つめは、投入が差分になったこと。 不足観点だけを渡すので、周回コストがほぼ一定になる。 全文を投げ直す設計は、収束するかどうか以前に予算が先に尽きる。
三つめが構造として一番おもしろい。 YAMLという中間表現を挟んだことで、判断と翻訳が切り離されている。 何をテストすべきかは意味論が要るから生成に向く。 それをコードに起こすのは機械的な変換だからプログラムに向く。 適材適所を、設計上の境界として実装した形になっている。
自分のループを点検する
自動ループを組んだら、まず評価者が生成物になっていないか確認する。 なっていたら、そのループは回り続けるだけで収束しない。 評価は、同じ入力に同じ答えを返すものに限る。 テスト実行、カバレッジ、lint、型チェック、ビルドの成否、差分の有無。 どれも面白みはないが、揺れない。
そのうえで、生成には判断を任せ、翻訳は決定論に渡す。 あいだに中間表現を置くと境界が引きやすい。 そして周回ごとに投入が増える設計になっていないか見る。
一発で全部やらせないのも同じ話だ。 探索空間が広すぎる問題設定は破綻しやすい、という指摘は、 コンテキストに載った情報を全部「等しく真」として扱うという性質とも噛み合っている。 コンテキストが膨れるほど、何が判定の根拠なのかが平坦になっていく。 3回に1回は失敗する前提で導入するという話も、失敗を検知する側を確率の外に置いて初めて成立する。
ただし、ものさしが正しいとは限らない
この事例でカバレッジが目的関数として機能したのは、狙いが既存挙動の固定だったからだ。 今の挙動を全部踏むテストが欲しい、という目的と、カバレッジという数値は素直に対応する。
新機能の実装や設計の改善で同じことをやったらどうなるかは、資料からは読み取れない。 決定論の評価系は、ものさしが目的とズレていても、そのまま収束する。 間違った場所へ、静かに、確実に。
回らないループより、間違った方向へ収束するループのほうが気づきにくい気はしている。 ここはまだ自分でも答えを持っていない。