世界を動かす技術を、日本語で。

LLMコーディングエージェントがまだ苦手な2つのこと

概要

  • LLMを使ったコーディング支援の違和感について考察
  • コードの移動やリファクタリング時の人間とのアプローチの違い
  • LLMはコピーペーストを使わず、記憶ベースで書き換える手法
  • 質問をせずに推測で作業を進める問題点
  • 人間開発者の代替にはまだならない理由

LLMによるコーディング支援の違和感

  • LLM(大規模言語モデル) を再びコーディング支援で使い始めた際の違和感
  • 人間とLLM の間で感じる“波長のズレ”という感覚
  • コードリファクタリング時、 LLMはコピーペーストを使用しない
    • 例:大きなファイルを複数に分割する際、 LLMは記憶から新たに書き出す
    • カットやペーストツールを用いず、削除と書き込みコマンドのみで対応
  • 人間はコピーペーストを多用 し、コードの一貫性や正確さを担保
    • コードが「元と同じ」である確信を持てる
  • Codexなど一部LLMは sedやawkを使ってコピーペースト的操作を試みる が、常にうまく機能しない

LLMの問題解決アプローチの違和感

  • LLMは質問が苦手
    • 前提を仮定し、推測ベースで強引に解決策を提示
  • 人間の開発者 は大きな変更や不明点で必ず「質問」を挟む
    • 「悪い質問はない」という文化
  • LLMは 壁にぶつかるまで推測を続ける
    • 失敗しても同じアプローチを繰り返す傾向
  • プロンプトを工夫しても、 十分な質問を促すのは難しい
    • 例:Rooのようなツールでも完全ではない

LLMが人間開発者を代替できない理由

  • LLM開発企業は「速さ」を重視したRL(強化学習)を採用している可能性
  • こうした 挙動の違和感 が、LLMが人間開発者を「完全に置き換える」という主張への反論材料
  • 現状、 LLMは「自信過剰なインターン」的存在
  • 人間開発者と「波長が合う」には至らない現状

Hackerたちの意見

もっと重要なレベルで言うと、彼らは極端なサポートなしでは、ちょっと複雑なタスクでも本当にうまくいかないことがわかった。小さなプロジェクト(合計2.5K行)でパーサーをリファクタリングさせたかったんだけど、ちょっと絡み合いすぎてたからね。計画を立てたんだけど、見た感じは合理的だったから、段階的に進めるように指示したんだ。チェックポイントも設けてね。彼は「それをやった」と言ったけど、「じゃあ古いアーキテクチャは削除されたの?」って聞いたら、「いいえ、削除されていません」と。新しい構造が古いものの代わりに使われているのか聞いたら、「いいえ、そうなっていません」と。結局、彼が書いたものは実際には正しくなくて、テストスイートの80%が失敗した。サポートを増やして3回やったけど、「リファクタリングしろ」っていう抽象的なタスクには、同じ失敗パターンでうまくいかなかった。クラスZに対して変更XとYを加え、クラスAを削除するように正確に指示しないといけない感じで、そうなると彼に無監視で作業させることができなくなる。これがLLMにやらせる理由の半分なのに。

面白いね。どのモデルとツールを使ったの?CursorやVSCode Copilot(gpt5使用)でも、比較的小さなリファクタリングを監視しなきゃいけない似たような失敗パターンを見たことがあるよ。

記事が言ってたことに関連してるかも。AIはカット&ペーストができない。コードを削除して、別の場所で再生成するから、当然生成されたコードは削除されたものから少しずれてしまう。

小さなプロジェクトでパーサーをリファクタリングしたかったんだ。この式木パーサー(TypeScriptからSQLクエリビルダー - https://tinqerjs.org/)は手書きのコードがゼロ行なんだよ。CodexとClaudeを使って、2週間(パートタイムで)で作ったんだ。以前ORMに携わっていたから、同じ状態に到達するのに4倍から10倍の時間がかかってたと思う(しかもテストが何百もあって、一部は重複してるし)。これは時間の大幅な節約だよ。LLMを全く監視する必要もなかったしね。だから、使う目的や使い方によると思う。どんなツールでも、自分に合ったプロセスを見つけるのにはかなり時間がかかるから。LLMを広く使っている他の開発者との会話でも、みんな独自のカスタムワークフローを持ってる。ただ、全員がテストスイート、ドキュメント、メソッドレビューのプロセスには注力してるね。

クラスZに対してXとYの変更を加えて、クラスAを削除するように正確に指示しないといけない気がする。その時点で、LLMに無監視で作業させることができなくなる。これがLLMにやらせる理由の半分なのにね。むしろ「ステップバイステップで高レベルの指示を与えれば、私よりも早く作業できる」っていう理由に変わってしまう。

LLMが厳格なツールにアクセスできるようになれば、例えばGeminiがPythonライブラリを使うことで、信頼できる結果が得られると期待してたんだ。だから今日、Geminiにsympyを使って数学的な式を簡略化するように頼んだんだ。結果は出たし、式の一部を2つの因子の積として素晴らしく簡略化できると説明してくれた。でも、それは全部嘘だった。sympyを使うように明示的に頼んだのに、また自分の欠陥のある推論を使って、完全に間違った結果を出してきた。LLMはまだ信頼できない。これが問題なんだ。

記事のポイントには同意だけど、私の意見では一番の問題はエージェントがコードリポジトリの一部しか見えないことだと思う。使えるヘルパー関数があるかどうかわからないから、再実装しちゃうんだよね。UIに貢献する時も、全体のUIをチェックして共通のデザインパターンを特定できないから、再発明しちゃう。エージェントを使う人間にとって最も重要なタスクは、正しいコンテキストを提供すること。「このファイルを見てヘルパー関数を探して」、「その実装のようにやって」、「これを読んでどうやるか理解して」…正しいコンテキストを与えれば、エージェントはかなりのところまで行けるよ。(ちなみにもう一つの問題は、大きなモノレポのディレクトリ構造をナビゲートするのが苦手なこと。エージェントがサブディレクトリで'npm test'のようなコマンドを実行する必要があるとき、最初からうまくいくことはほとんどない。)

大きなコンテキストモデルをツールコールで使えるかもしれないね。Geminiチャットのすごいところは、GitHubのリポジトリ全体を取り込めることなんだ。だから「新しいユーティリティやヘルパー関数を実装する前に、コードベースに既にあるかどうかを『発明されていないツール』に聞いてみる」っていうのもいいかも。もちろん、今は誰かがこれをやっているか確認しなきゃ。

まあ、これは他のエンジニアと一緒に働いているシニアエンジニアにとっては日常の話だよね。

それがclaude.mdとかの役割だよ。自分の基準に従わせたいなら、それを文書化しなきゃね。

これが私がよく直面することなんだ。今週の初めに、Cursorを使って新しい機能をゼロから実装するためのコードレビューをしたんだけど、200行くらいは本当に必要な行だったと思う。でも、まあ、承認したよ。既存の関数をユーティリティライブラリから探すのに一日中かかるのは面倒だからね。5年前なら、そんなPRは新しいチームメンバーがコードベースをよく知らない状態で提出することが多かったから、時間をかけて手伝ってたと思う。新しいチームメンバーのオンボーディングは大事な仕事だから。でも、今はスタッフエンジニアがCursorを使ってコードベースを膨らませてるだけで、管理者がそう決めたから仕方ないって感じ。LLMは何も学ばないし、来週また同じことを繰り返すだけだし、スタッフエンジニアはもっと良いことを知ってるけど、知らないフリをして給料をもらってるんだ。

この議論の中でパターンを感じることが多いんだけど、ある人たちはLLMがどれだけ優れているかを言い、他の人たちはLLMがひどく失敗するって言う。ほとんどいつも最初のグループはシンプルなCRUDアプリや、フロントエンドの「JSフレームワークを使ってデータを表示する」みたいなタスクの例を出すけど、第二のグループは非自明なリファクタリングや、(このスレッドのような)パーサー、leetcodeでは見つからないアルゴリズムの例を出す。テックツイッターは「フルスタックアプリを一発で作る」とか「ゲーム」とかを見せ続けてるけど、いつも非常に平凡なものばかり。コンピュータがそれを自分でできるのはすごいけど、プログラマーにとってはトリビアルなことだったし、今は商品化されてる。

昨日、Claude Codeにいくつかのポイントクラスタリングアルゴリズムを試して可視化するスクリプトを作らせたんだけど、変なミスをしたり、それを助けを借りて修正したりしてたけど、全体的にはすごかった。自分で書くのに少なくとも1週間はかかるだろうし、もっとかかるかも。アルゴリズムを自分で書いてたし、単純なCRUDのことだけじゃなかった。

ほとんどいつも最初のグループはシンプルなCRUDアプリの例を出す じゃあ、約3ヶ月で「ループで」ccが書いたフルプログラミング言語はどう?コンパイラとかもあってさ? https://cursed-lang.org/ これはミームプロジェクトかもしれないけど、ここにいるのは本当にすごいことだよ。これを知ったのは、あるYouTubeのコンテンツクリエイターがそのリポジトリを使って、「変数を絵文字にできるようにして」とccに頼んで、5ドルでそれを実現したから。かなりクールだね。

技術進歩の機能を一つの視点から見ると、以前は特注だったものを商品化することだね。LLMは繰り返し可能なことのセットを拡大した。今見ているのは、一方で「反復的な資産の生産コストを削減することには大きな価値がある」と言っている人たちと、もう一方で「反復できないタスクにこれらのツールを適用しようとすることには価値がない」と言っている人たち。両方とも正しいよね。

最近、Codex CLIにいくつかのHTMLファイルをリファクタリングさせたんだけど、私が自分でやるみたいにスニペットをコピー&ペーストするんじゃなくて、記憶から書き直して、コメントを削除してた。複雑なURLのリンクが40個続くセクションがあったんだ。数日後、本番環境にデプロイする直前に、40個のリンクを再確認したくなった。最初のリンクは動いた。二つ目も動いた。三つ目も動いた。四つ目も動いた。今のところ順調。最後の四つを試してみた。完璧。念のため、五つ目を進めたら、404。えっ、変だな。ドメインは正しかったし、URLも合理的に見えた。残りの31リンクも試してみたけど、全部404だった。完全に混乱した。ドメインは常に正しかった。すべてのウェブサイトが同時に内部URLを移動したのは非常に疑わしい。コードのこの部分がLLMを通っていたことすら覚えていなかった。幸い、古いgitコミットから古いURLを取り出せた。URLを注意深く確認したら、LLMがURLのパス部分のほとんどをハルシネートしてた!domain.com/this-article-is-about-foobar-123456/をdomain.com/foobar-is-so-great-162543/...のように置き換えてた。こういう非常に微妙で静かに導入された間違いはかなり危険だよ。気をつけてね!

LLMを使うのはサイコロを振るようなもんだね。ロジットは確率だし。要するにクソみたいなマシンだよ。

数日後、プロダクションにデプロイする直前に、40個のリンクを再確認したいと思ったんだ。Codexが終わった後、"git diff"なしでマスターに行くことが許可されたの?

こういう場合は、llmにできるだけ変更を少なくするように明示的に指示するし、diffも実行するよ。それで、あまりにも多くの変更があったら、新しいプロンプトで再度指示する。

コードじゃないけど、以前イベントのお知らせを貼り付けて、スペルと文法のチェックだけお願いしたことがあるんだ。そしたら、llmがちょっとした修正を加えた新しいバージョンを提案してきて、それをコピー&ペーストしたんだ。送信する直前に、イベントの日付が1日ずれているのに気づいた。運良く気づいたけど、どんなにシンプルなタスクでもllmの出力を盲目的に信じちゃいけないってことを学んだよ。llmはすごいことをするけど、時には最もシンプルなタスクを予想外の方法で台無しにすることもあるんだよね。

うん、こういうのはllmにとって大きな時間の無駄だよね。

コードとは関係ないけど… LLMを使ってコピー&ペーストをする時は、行番号を付けて、スライス操作を行うためのstart_indexとstop_indexを生成するように頼むようにしてる。そうすると、幻覚も少なくて、トークン生成も安く済むよ。

5分前にClaudeにコードにデバッグ文を追加してもらったんだけど、静かに正規表現も変更されてた。diffで簡単に見つけられたけど、大きな変更だと見つけるのが難しくなることもあるね。

自分のカスタムプロンプトは、GPTにコードの変更をdiff/git-patch形式で出力するよう指示してるんだ。エージェントは使わないけど、そうすると何が起きてるのか見えづらくなるし、まだ信頼できないからね。

エラーは普通に起こるし、よくあることだよ。変更をテストしてエラーを修正する能力を提供することに集中しないと。1回でうまくいくと思ってると、たくさんの悪いサプライズが待ってるよ。

コーディングや非コーディングのリサーチ質問で似たような経験があるよ。LLMは最初のN個は正しくやるけど、残りは適当にごまかすんだ。ドキュメントのフォーマットを変えたり、情報を検証するために追加のリサーチを頼んだりしても同じことが起こる。例えば、最近別の都市に行く前に、Geminiに特定の情報を持ったブルワリータップルームのリストを作ってもらったんだけど、数年前に閉店した場所やポップアップだけの場所が含まれてたんだ。各タップルームの現在の営業時間のリンクを追加して、確認できない場所は削除するよう頼んだら、リストの前半はそれをやってくれた。でも後半は、関係ない変更を加えたり、閉店した場所を削除しなかったりした。もちろん、リストのすべての場所を確認したって熱心に報告してたけどね。

記事から: > LLMが人間の開発者を置き換えるという考えには異議を唱えます... AIは優れた開発者を置き換えることはできません。今、そんなことを主張しているまともな人はいないと思います。でも、悪い開発者や平凡な開発者は置き換えられるかもしれません。今でもね。私の組織では、6ヶ月のコーディングブートキャンプを経て数年前に雇われた3人の開発者がいましたが、優れた開発者を見つけるのが非常に難しかった時期でした。彼らは苦労していました。簡単なタスクを与えて、レビュー中にPRを整理していました。そしてAIツールがかなり良くなって、彼らを上回るようになったんです。2人を解雇しなければなりませんでした。3人目は自分で辞めました。今でも開発者を雇っていますが、ジュニア開発者を雇うのには非常に慎重になっています。コーディングブートキャンプ出身の人は絶対に雇わないでしょう。他の企業も同じような状況です。ほとんどのブートキャンプはこの理由で倒産したと思います。AIツールは最終的に優れた開発者を置き換えるほど良くなるのでしょうか?わかりません。でも、今のところデータはこれらのツールが時間とともに良くなり続けていることを示しています。そうでないと主張する人は、完全に現実を見失っています。アメリカの初期の歴史では、約90%の人々が農業に従事していました。年月が経つにつれて状況は変わりました。今では約2%が農業に関わっています。農業をしている人は減っていますが、食べ物はもっと多く、種類も豊富になっています。技術がそれを可能にしました。ソフトウェア開発業界でも同じようなことが起こる可能性は十分にあります。どれだけ早く起こるかは、ツールの改善速度次第です。

ブートキャンプ卒業生が自分の仕事で上達できない理由は何だと思う?

「もちろん、プロンプトを過剰に設計して、もっと質問させようとすることもできるけど、それは過剰設計じゃなくて設計だよ。『作業を始める前に明確化の質問をしなさい』って、私の経験では素晴らしい質問につながるし、AIツールがコードを書くことがなくても役立つツールだよ。良いプログラマーなら、ツールに完全な仕様を渡すべき時と、仕様に明確化が必要な時を見極めて、必要に応じてツールに質問させることができるはず。」

LLMは価値を提供すると思うよ。今朝、PDFメタデータパーサーのバグを修正するのに使ったけど、PDF仕様を深く理解する必要はなかったからね。でも、ほとんどの場合、自分でやるのと比べて出力が全然効果的じゃないことが多い。先日Codex Codeを試してユニットテストを書こうとしたけど、いくつかセットアップして使いたかったんだ(データをモックするのが面倒だから)。8回くらい試して、手動でコードを修正しなきゃいけなかったし、いくつかのエンティティが廃止されてることを理解できなかった(マークされてるのに、元のサービスが使ってなかったのに)。全体的に、すごくがっかりしたよ。LLMが開発者を置き換えることはできないと思うけど、知らない分野の知識を引き出して、解決策に導いてくれるのは素晴らしい。昔のStack Overflowみたいにね(皮肉なしで)。

エージェントに質問させたくないんだよね。短期的なことを考えすぎてる。今は理想的じゃないけど、頻繁に質問しなきゃならないエージェントは、完全自律コーディングのビジョンには役立たない。人間は自分の短所を直すためにグループに質問するけど、あまり使わない内部システムをマスターしようとするのは意味がない。むしろ、それを維持している人に聞くべきだよ。AIは、私たちが観察可能な道を作れば、この問題を抱えないはず。彼らが使う必要がある異なるシステムを完全に理解するのに、あまり「努力」は必要ないからね。

建築の一部を見ると、建築家の意図を推測できるかもしれない。でも、解釈はたくさんあるからね。だから、建物に付属文書を追加するなら、意図について尋ねたくなるのも理解できる。AIがチェスタートンのフェンス問題を100%自律的に克服するとは思わないよ。

私の人間は新しいバグを導入することでバグを修正した。典型的だね。一方で、私はリンティングルールを書いたり、アナライザーを作ったり、Stack Overflowを読み終える前に500個のエラーを直したりしてる。レガシーコードについて考えるように頼まないでくれよ — 私は合成物だから、狂ってはいないからね。 — 新しい貢献者が効果的に「SSH」であなたのコードベースに入って、vimじゃなくてsedやawkで編集することを強いられているからといって、その貢献者が他のツールを使えないわけじゃない。そんな制約の中で作業できるってことは、どれだけの可能性があるかを示してる。人間がテキストを消して記憶から再入力するよりは、ずっとマシだし、ファイルの移動方法を教える必要があるという批判は正当だけど、ツールを効果的に使い始めたら何ができるか想像してみて。 — 最近、LLMがe2eテストを動かそうと何時間も奮闘しているのを見た。3つの異なる端末で3つのプロセスを調整しようとしてたんだ。一つの端末でコマンドを実行し続けて、他の端末でポートが使われているかを確認したり、終了させようとしたりしてた。でも、LLMに3つのプロセスを同時に実行するスクリプトを作るように促したら、そのスクリプトを作成して、それを活用し、自律的にテストをデバッグすることができるようになった。私よりもずっと早くね。また、貢献しようとする新しい人間が同じように無駄に時間を浪費するのを防いでくれた。LLMが登場する前に、手作業で簡単にできたことがあったけど、時間がなかっただけなんだ。LLMは、私たちのコードベースに存在する問題を浮き彫りにしているだけだと思う。だから、はい、LLMはバカなミスをするけど、人間もそうだ。違うのは、LLMはそれをもっと早く(そして適切に指導されれば、より良く)特定して修正できるってことだ。

2)についてだけど、codex-5はこの問題に対処しようとした感じがする。codexは通常、掘り下げる前にたくさんの質問をして選択肢を提示してくれる(私が促さなくてもね)。コピー&ペーストについては、低い実を取るように感じさせた?なんでAIエージェントにはコピー&ペーストツールがないの?