ディスカッション (11件)
LLMをバックエンドのコード生成に活用しようとした際、複雑な要件や制約がエージェントとの対話を通じて徐々に曖昧になったり、無視されたりしてしまう現象が確認されています。これを「Constraint Decay(制約の減衰)」と呼びます。エージェントが長期のコンテキストや厳格なルールを維持できず、結果として生成されるコードの品質や安全性が崩れていくメカニズムについて、皆さんの現場ではどのような対策を講じていますか?
最近の論文で、LLMに様々な分野の文書編集タスクを委任する件について扱っていたのを思い出した[1]。その論文では、ほとんどのLLMがエラーを蓄積させたり文書を壊したりせずに長期的なタスクを実行できるのは、プログラミングだけだったという結果だった。
まだ要約しか読んでないけど、今回の論文はプログラミングに焦点を絞ってより詳しく検証し、同じような現象を示しているみたいだね。ただ、長期的なタスクというよりは、構造的な制約のセットが大きい「長いスタイルのホライゾン」についての話のようだ。
[1] https://arxiv.org/abs/2604.15597 (https://arxiv.org/abs/2604.15597)
議論: https://news.ycombinator.com/item?id=48073246 (https://news.ycombinator.com/item?id=48073246)
「私たちの体系的な研究により、LLMベースのコーディングエージェントにおいて『制約の減衰(constraint decay)』という現象が明らかになった。現在のモデルは制約のない生成には秀でているが、明示的なアーキテクチャ上のルールに従わせようとすると性能が低下する。エンドユーザーにとって、この二分法は、エージェントはラピッドプロトタイピングには信頼できるが、プロダクショングレードのバックエンド開発には依然として信頼できないことを意味している」
この研究の大きな弱点は、コストの理由でフロンティアモデルを完全にはテストしていない点だから、具体的なパフォーマンス結果は割り引いて考える必要があるね。ただ、振る舞いとアーキテクチャの両方が正しくなければならない状況でモデルの性能が低下するという結論自体は興味深いし、注目しておくべき点だと思う。
それに、彼らはPythonやJSのような動的型付け言語を使っていたよね。私の経験では、静的型付けのコードベースの方が人間にとって保守しやすいから、おそらくエージェントにとっても同じことなんじゃないかな。
CodexやClaude Codeを使ってGoコードを書いている時、エージェントが変更を加えてビルドを実行し、エラーを見つけて修正する、という流れを一体何回繰り返したか数え切れないよ。
8つのWebフレームワークにまたがるタスク
LLMって、既存のフレームワークを使うよりも、純粋なHTML+CSS+JSを書かせた方がいい結果を出すと思ってる人、他にもいないかな?
これ、「チャットが長くなればなるほどガードレールが曖昧になる」問題の別バージョンって感じだね。コンテキストウィンドウをフル活用できないのは、最後の方で制約(またはガードレール)を守れなくなるからだけど、プロダクションレベルのコードを確実に生成するには、モデルに広範な認識力を持たせる必要があって、それがすぐにコンテキストウィンドウを埋めてしまう。「6つのディレクトリすべてを考慮に入れて、このチケットの変更を実装して」なんて言うと、すべてを把握しようとするだけでコンテキストが一杯になって、結局制約に従う能力を失ってしまうんだよね。
長期的なエージェントによるコーディング1をかなり実験しているんだけど、私も特定のアークテクチャパターンを強制されるとエージェントのパフォーマンスが落ちることに気づいた。後から制約を追加するよりも、最初からプロセスに組み込んでいく方が少しマシだと分かったよ。「石灰化(calcification)」と呼んでいる副作用のようなものがあって、あるパターンがコードベースに出現し始めると、エージェントがそのパターンを真似しすぎて、コンテキストを支配し、自己増殖的に繰り返してしまうんだ。これはコードベースの質によっては強みにも弱みにもなり得るね。最初からアーキテクチャのガイドラインを含めてゼロから実行するテストが完了したら、また詳しく共有するよ。
私の結論は、計画を立てる価値はある、ということ。
少し複雑な変更をする時は、いつもCodex (5.5-high) をプランニングモードで最初に動かしている。AGENTS.mdから様々なdocs/{ARCHITECTURE,BACKEND-GUIDELINES,NESTJS-DI,..}.mdなどにリンクを貼っておいて、必要な時だけ関連するドキュメントを素早く参照できるようにしているんだ。バックエンドの問題を扱っている時にReact特有の知識なんて必要ないしね。新鮮なコンテキストでエージェントが立てた計画は、自分でプロンプトを書いたのと同等なので、基本的にはそのまま承認する。これが一番上手くいく。
ただ、/goal を使うと、常に詰め込みすぎて勝手に進めようとするから、当然雑になる。チケットを「プランニングモードのプロンプト」に変換するステートマシンがあって、その後にガードレール的な承認(例えば「プロダクトマネジメントの視点」で計画を修正・承認するようなもの)を挟んで、最後にそれほど能力の高くない、あるいは推論能力を抑えたエージェントに計画を実行させれば、最強になるんじゃないかと思う。
コードベースの一部をイディオマティック(慣用的)な状態に整えて、そのファイルを「例」として@でメンションすることをおすすめするよ。マークダウンで指示しようとするより、こっちの方がずっと上手くいく。FastAPIならこれで結構いけるけど、JavaScriptは最悪だね。ガイドラインや例を提示しても、指定されたAPIを使うより、ゴミみたいなコードをインラインで書き散らす方を好む傾向がある。
業界全体がコード生成プロセスを最適化するために、スキル、ルール、テスト、レビュー、Lint、フィードバック付きのエージェントループ、サブエージェント、コードランナーといったものに多大な労力を費やしてきたのはこのせいだね。もはや単にLLMがコードを書いているわけじゃなくて、エコシステム全体で協力し合っているんだ。
コードベースが大きくなるほどLLMがコード生成に苦戦するというのは同感。動機がうまく噛み合っていないんだろうね。エージェントは文脈を消費しすぎずに孤立したタスクを完了させたいのに対し、POC段階ではアプリの大部分を把握できるけど、3万行を超えるとナビゲートするには複雑すぎるコードベースになってしまう。
https://engine.build (https://engine.build) を作っているんだけど、これは明確な制約のもとで開発を行い、最終成果物が仕様書や要件定義と一致することを保証するための、きちんとした構造を持つ外部エージェントオーケストレーターなんだ。モデルをいちいち手取り足取り監視する必要はない。
実装フェーズでは、仕様と一致させるために5〜10回のレビューと修正サイクルを通すのが一般的だ。時間はかかるけど、詳細な要件がある長期的なタスクで実際に良い結果を出すにはそれが必要なんだよ。近々フルオープンソース化する予定だ。