00:00:00Anthropicがとんでもないことを成し遂げました。16体のClaudeエージェントを動員して
00:00:05Cコンパイラを構築させたのです。2週間フル稼働させた結果、なんと実際にコンパイル可能な
00:00:11コンパイラが完成しました。Linuxカーネルをコンパイルし、Doomを動かすことさえできます。これは旧バージョンの
00:00:16Opus 4では到底不可能だった、極めて印象的な成果です。しかし、この成果を「釣り」だとか
00:00:22「不完全な真実」と呼ぶ人々もいます。この結果を導き出したAnthropicの手法に疑問の声が上がっているからです。
00:00:28果たしてAnthropicはズルをしたのでしょうか? チャンネル登録をして、一緒に真相を確かめましょう。
00:00:31この動画は3つのパートに分かれています。まず、実験のセットアップ方法について説明し、
00:00:37次に、開発者なら誰もが学びを得られるであろう主要な発見を見ていきます。
00:00:42そして最後に、この結果が正当なものかどうかを検証します。というのも、Anthropicの構築手法については
00:00:47私なりの意見があるからです。さて、この実験はニコラス・カルリーニ氏によって行われました。
00:00:52彼は非常に聡明な人物です。まずは、彼がどのような環境を構築したのか見てみましょう。
00:00:58実際のプロジェクトは「Upstream」というディレクトリにあり、これが
00:01:0316個の異なるDockerコンテナにマウントされていました。図には4つしかありませんが、16個あると想像してください。
00:01:08各Dockerコンテナ内ではOpus 4.6を搭載したClaude Codeが動作しており、
00:01:15UpstreamリポジトリをWorkspaceにクローンし、変更を加えてからUpstreamへプッシュするという流れでした。
00:01:21これは非常に賢い方法です。各エージェントが他の作業を妨げることなく、隔離された環境で並行して作業できるからです。
00:01:27もしマージ競合が発生しても、Claudeがそれを賢く解決し、Upstreamに反映させます。
00:01:32各エージェントはタスクの一覧から作業を選択します。
00:01:38これらのタスクが人間によって作成されたのか、テスト結果に基づいてエージェントが生成したのかは不明ですが、
00:01:44名前の付いたタスクが存在しており、各エージェントは新しいタスクを引き受けるたびに、
00:01:50新しいセッションを作成します。エージェントを長時間稼働させ続けるために、Ralphループが使用されました。
00:01:56エージェントがタスクを完了してUpstreamにプッシュすると、新しいセッションでまた別のタスクに取り掛かる、
00:02:02という作業を延々と繰り返す仕組みです。以前のRalphに関する動画を見た方ならお分かりかと思いますが、
00:02:08エージェントを長期稼働させる鍵は、タスクを明確に定義することにあります。しかし、16体のエージェントを
00:02:13同時に動かす場合、どうすればタスクの重複を避けられるでしょうか? そこで「タスクのロック」が必要になります。
00:02:19著者は明記していませんが、その仕組みはこうです。タスクのリストが存在し、
00:02:24エージェントがタスクを選ぶとそのタスク名に一致するテキストファイルを作成し、
00:02:30それをコミットしてUpstreamにプッシュすることで「自分だけが作業中である」ことをロックします。
00:02:36もし他のエージェントが同じタスクを選んで同じテキストファイルを作ろうとしても、
00:02:42Upstreamにプッシュする際に、Gitが「ファイルが既に存在する」として拒否するため、
00:02:48そのエージェントは別のタスクに回ることになります。これが、カルリーニ氏がOpus 4.6を搭載した
00:02:53長期稼働型エージェントの能力をストレス分析した基盤であり、その結果は実に見事なものでした。
00:03:00この実験を通じて、開発者の皆さんが学べる興味深い知見がいくつか得られています。
00:03:071つ目は、テストハーネス(テスト実行スクリプト)の重要性です。
00:03:12ニック(ここでは親しみを込めてそう呼びますが)が実験をしていた際、Claudeが
00:03:17新しい機能を開発するたびに、既存の機能を壊してしまうという現象が起きました。
00:03:23そこで彼は、SQLite、libjpg、Redisといった有名なオープンソースプロジェクトから、高品質なテスト群を集めたハーネスを構築しました。
00:03:29また、コンテキストの汚染を防ぐため、テストハーネスにはエージェントにとって有用な情報、
00:03:35つまりエラーログだけを出力させるようにし、それ以外のログは別ファイルに保存して、Claudeが必要な時にだけ参照できるようにしました。
00:03:41しかし、数千ものテストがあると、全テストを実行するだけでエージェントの作業時間が何時間も奪われてしまいます。
00:03:47これは時間の無駄です。そこでニックは非常に巧妙な策を講じました。
00:03:52テストハーネスに「fastフラグ」を追加したのです。これにより、各エージェントは設定に応じて
00:03:58全テストの1%から10%程度だけを実行するようになります。全エージェントが10%ずつ実行すれば、
00:04:05合計で160%のテストをカバーすることになり、十分すぎるほどです。しかもこれは悪いことではありません。
00:04:13各エージェントが実行するテストはランダムに選ばれますが、シード値を固定することで
00:04:19決定的な動作(再現性のあるランダム性)を持たせました。こうして、各エージェントが異なるテストを担当することで、
00:04:251体で全テストを回すよりも遥かに早くテストスイート全体を網羅できるようになったのです。
00:04:31次のポイントも巧妙ですが、既存の技術を活用するという点で、少し議論を呼ぶかもしれません。
00:04:36ここまでは各エージェントが個別のユニットテストを分割して実行していましたが、
00:04:41Linuxカーネルのコンパイルとなると、事情が変わります。ソースファイルが個別のテストとして
00:04:46独立しているわけではないため、各エージェントが全体をコンパイルしようとして同じエラーにぶつかり、
00:04:53互いの修正を上書きし合うという問題が発生したのです。
00:04:58そこでニックがとった解決策は、各エージェントにコンパイルの一部だけを担当させ、
00:05:04残りは本物のGCC(GNUコンパイラ)に実行させるというものでした。
00:05:09ニックはGCCを「神託(オラクル)」と呼びました。LinuxカーネルはGCCであれば完璧にコンパイルできるはずだからです。
00:05:15もしエージェントが自分の担当箇所を自作コンパイラでコンパイルし、残りをGCCで処理してエラーが出れば、
00:05:22原因は間違いなく自作コンパイラ側にあります。これにより、他のエージェントが作ったバグに惑わされることなく、
00:05:27自分の担当箇所の修正に集中できるようになったのです。
00:05:34これが議論を呼んでいるのは、Claudeに「ゼロから作る」ように求めたはずのタスクに、
00:05:40既存のコンパイラを利用しているからです。これについては動画の後半で詳しくお話しします。
00:05:46次のポイントは、エージェントに「記憶」を持たせることです。
00:05:51新しいタスクは、それまでの経緯を全く知らないフレッシュなClaudeセッションによって行われるため、
00:05:57ニックはREADMEファイルを更新したり、進捗状況や指示を記した進捗ファイルを活用したりしました。
00:06:03これにより、新しいセッションがこれまでの流れを把握し、既に修正済みのバグを再発させるのを防ぎました。
00:06:09最後のポイントは、エージェントに異なる「役割」を与えることです。
00:06:13複数のエージェントを並行して動かす醍醐味は、同じコードベースに対して同時に複数のアプローチができることです。
00:06:18新しいコードを書いていない時、ニックはエージェントに独自の役割を割り振りました。
00:06:23コードの重複をチェックする役、パフォーマンスを最適化する役、さらには
00:06:29Rust開発者の視点から設計を批評する役まで用意しました(そのエージェントが他のエージェントに「僕はRust使いだよ」とアピールしていないことを願いますが)。
00:06:35さて、プロジェクトは成功しましたが、本当の疑問は「Anthropicはズルをしたのか?」ということです。
00:06:40答えは「ある意味ではイエス」です。タスクはCコンパイラをゼロから構築することであり、
00:06:45エージェントはインターネットに接続せず、すべてのコードを自力で考え出しました。
00:06:51……本当にそうでしょうか? オープンソースのテストスイートや、コンパイル済みのGCCにはアクセスできたわけです。
00:06:57つまり、GCCに様々な入力を与えてその出力を観察し、そこから得た情報を
00:07:03Rustで書かれた自作コンパイラの設計に流用することは技術的に可能でした。しかし公平に見て、
00:07:10もし私がゼロからCコンパイラを作るとしても、同じことをするでしょう。
00:07:16既存のコンパイラがどう実装されているかを調べ、それを参考に自分のコンパイラの方向性を決めるはずです。
00:07:24全く新しい言語のためのコンパイラを作るのであれば話は別で、難易度は格段に上がります。
00:07:31Claudeが本当にゼロからコンパイラを生み出せるか試すには、そちらの方が良いテストになるかもしれません。
00:07:36ニックにとっての次の課題になるかもしれませんが、次に「自律性」について見ていきましょう。
00:07:41確かにClaudeはすべてのコードを書きましたが、そこには人間による「重い操縦」がありました。
00:07:47どのテストスイートを実行するかを決めたのも人間。ループを開始し、Ralphの使用を決めたのも人間。
00:07:53テストハーネスを構築し、エージェントに特定の役割を与えたのも人間です。
00:07:57「コンパイラを作って」と言って丸投げして放置していたわけではありません。
00:08:04もし人間が一切関与していなかったら、これほどのものは完成しなかったでしょう。その意味で、
00:08:11100%自律的なエージェントによって書かれたコードとは言い難い部分があります。
00:08:16また、人間が設計したシステムの上であっても、ClaudeのCコンパイラには重大な制限がありました。
00:08:22例えば、アセンブラとリンカはGCCのものを使用せざるを得ませんでした。自作のものはバグが多すぎたためです。
00:08:28Linuxを起動するためには、GCCの16ビットx86コンパイラも必要でした。さらに追い打ちをかけるように、
00:08:33生成されたコードの効率も良くありませんでした。Claudeのコンパイラの最高に最適化されたバージョンでも、
00:08:39GCCの最も最適化されていないバージョンよりパフォーマンスが低かったのです。
00:08:46どうやら開発者の仕事がすぐになくなることはなさそうです。少なくとも、今のところはね。
00:08:54the code wasn't very efficient. The most optimized version of the Claude's compiler was less
00:09:00performant than the least optimized version of the GCC compiler. So it looks like developers
00:09:05aren't going anywhere anytime soon, or at least for now.