使用并行Claude团队构建C编译器
摘要
Anthropic研究员展示了如何使用16个并行Claude实例自主构建一个基于Rust的C编译器,该编译器能够编译Linux内核。文章详细介绍了这一多智能体自主编码实验的架构、成本和经验教训。
暂无内容
查看缓存全文
缓存时间: 2026/05/08 09:29
# 用并行 Claude 团队构建 C 编译器
来源:https://www.anthropic.com/engineering/building-c-compiler
*作者:Nicholas Carlini,Anthropic 安全团队研究员*
我一直在试验一种监督语言模型的新方法,我们称之为"智能体团队"。
在智能体团队中,多个 Claude 实例在共享代码库上并行工作,无需人工主动干预。这种方法大幅扩展了 LLM 智能体可实现任务的规模。
为了对其进行压力测试,我指派了 16 个智能体从零开始编写一个基于 Rust 的 C 编译器,要求能够编译 Linux 内核。在近 2,000 次 Claude Code 会话和 20,000 美元的 API 成本后,智能体团队产出了一个 10 万行的编译器,可以在 x86、ARM 和 RISC-V 上构建 Linux 6.9。
这个编译器本身是一个有趣的成果(https://github.com/anthropics/claudes-c-compiler),但我在这里重点介绍我在设计长时间自主运行智能体团队的框架方面的经验:如何编写测试让智能体在无人工监督的情况下保持正轨,如何组织工作让多个智能体并行推进,以及这种方法在哪里会触及天花板。
## 让 Claude 长时间自主运行
现有的智能体脚手架如 Claude Code 要求操作者在线并协同工作。如果你要求解决一个长期而复杂的问题,模型可能解决一部分,但最终会停下来等待继续输入——一个问题、状态更新或澄清请求。
为了激发持续自主的进展,我构建了一个框架,将 Claude 置于一个简单的循环中(如果你见过 Ralph-loop,这应该看起来很熟悉)。当它完成一个任务时,立即开始下一个。**(请在容器中运行,不要在实际机器上)**
```bash
#!/bin/bash
while true; do
COMMIT=$(git rev-parse --short=6 HEAD)
LOGFILE="agent_logs/agent_${COMMIT}.log"
claude --dangerously-skip-permissions \
-p "$(cat AGENT_PROMPT.md)" \
--model claude-opus-X-Y &> "$LOGFILE"
done
```
在智能体提示中,我告诉 Claude 要解决什么问题,并要求它通过将问题分解为小模块来推进,跟踪正在处理的内容,确定下一步该做什么,并有效地持续完善直到完美。(关于最后一点,Claude 别无选择。循环永远运行——尽管有一次,我看到 Claude 意外执行了 `pkill -9 bash`,从而杀死了自己并结束了循环。哎呀!)
## 并行运行 Claude
并行运行多个实例可以解决单智能体框架的两个弱点:
- 一个 Claude Code 会话一次只能做一件事。尤其是随着项目范围扩大,并行调试多个问题要高效得多。
- 运行多个 Claude 智能体可以实现专业化。当一些智能体被指派解决手头实际问题时,其他专业智能体可以被调用来做(例如)维护文档、监控代码质量或解决专业子任务。
我实现的并行 Claude 非常基础。创建一个新的裸 git 仓库,为每个智能体启动一个 Docker 容器,将仓库挂载到 `/upstream`。每个智能体克隆一份本地副本到 `/workspace`,完成后从自己的本地容器推送到 upstream。
为了防止两个智能体同时尝试解决同一个问题,框架使用了一个简单的同步算法:
1. Claude 通过在 `current_tasks/` 中写入文本文件来"锁定"任务(例如,一个智能体可能锁定 `current_tasks/parse_if_statement.txt`,另一个锁定 `current_tasks/codegen_function_definition.txt`)。如果两个智能体尝试认领同一任务,git 的同步机制会迫使第二个智能体选择不同的任务。
2. Claude 处理任务,然后从 upstream 拉取,合并其他智能体的更改,推送自己的更改,并移除锁定。合并冲突频繁发生,但 Claude 足够聪明能够解决。
3. 无限智能体生成循环在新的容器中启动一个新的 Claude Code 会话,循环重复。
这是一个非常早期的研究原型。我还没有实现智能体之间的其他通信方式,也没有强制执行管理高层目标的流程。我没有使用编排智能体。
相反,我让每个 Claude 智能体自行决定如何行动。在大多数情况下,Claude 会选择"最明显"的下一个问题。当卡在某个 bug 上时,Claude 通常会维护一个运行文档,记录失败的方法和剩余的任务。在项目的 git 仓库(https://github.com/anthropics/claudes-c-compiler)中,你可以浏览历史记录,观察它如何对各项任务进行锁定。
## 与 Claude 智能体团队编程的经验教训
脚手架让 Claude 在循环中运行,但这个循环只有在 Claude 知道如何推进时才有用。我的大部分精力都花在了设计 Claude 周围的环境上——测试、环境、反馈——让它能够自我定位,无需我介入。这些是我发现的最有助于编排多个 Claude 实例的方法。
### 编写极高质量的测试
Claude 会自主工作来解决我给它的任何问题。因此任务验证器必须近乎完美,否则 Claude 会解决错误的问题。改进测试框架需要寻找高质量的编译器测试套件,为开源软件包编写验证器和构建脚本,并观察 Claude 犯的错误,然后在识别出失败模式时设计新的测试。
例如,在项目接近尾声时,Claude 每次实现新功能时都会频繁破坏现有功能。为了解决这个问题,我构建了一个持续集成流水线,并实施了更严格的强制执行,让 Claude 更好地测试其工作,确保新提交不会破坏现有代码。
### 站在 Claude 的角度思考
我必须不断提醒自己,这个测试框架是为 Claude 写的,不是为我自己写的,这意味着我需要重新思考很多关于测试应该如何传达结果的假设。
例如,每个智能体被投入一个没有上下文的新容器中,会花费大量时间进行自我定位,尤其是在大型项目中。在到达测试之前,为了帮助 Claude 自助,我在指令中要求维护详尽的 README 和进度文件,应频繁更新当前状态。
我还牢记语言模型存在固有局限性,在这种情况下需要围绕这些局限性进行设计。这些包括:
- **上下文窗口污染:** 测试框架不应打印数千字节的无用信息。最多,它应该只打印几行输出,并将所有重要信息记录到文件中,以便 Claude 在需要时能找到。日志文件应易于自动处理:如果有错误,Claude 应该写入 ERROR 并将原因放在同一行,以便 grep 能找到。预先计算聚合汇总统计信息很有帮助,这样 Claude 就不必重新计算。
- **时间盲区:** Claude 无法感知时间,如果放任不管,它会愉快地花费数小时运行测试而不是推进工作。框架很少打印增量进度(以避免污染上下文),并包含默认的 `--fast` 选项,运行 1% 或 10% 的随机样本。这个子样本对每个智能体是确定性的,但在不同 VM 之间是随机的,因此 Claude 仍然覆盖所有文件,但每个智能体可以完美识别回归。
### 让并行化变得容易
当存在许多不同的失败测试时,并行化是微不足道的:每个智能体选择一个不同的失败测试来处理。在测试套件达到 99% 通过率后,每个智能体致力于让不同的小型开源项目(例如 SQLite、Redis、libjpeg、MQuickJS、Lua)能够编译。
但当智能体开始编译 Linux 内核时,它们卡住了。与拥有数百个独立测试的测试套件不同,编译 Linux 内核是一个巨大的任务。每个智能体都会遇到相同的 bug,修复那个 bug,然后覆盖彼此的更改。运行 16 个智能体没有帮助,因为每个都卡在解决同一个任务上。
解决方案是使用 GCC(https://gcc.gnu.org/)作为在线的已知良好编译器参考进行对比。我写了一个新的测试框架,随机使用 GCC 编译大部分内核,只使用 Claude 的 C 编译器编译剩余文件。如果内核能工作,那么问题就不在 Claude 的那部分文件中。如果它坏了,就可以通过用 GCC 重新编译其中一些文件来进一步细化。这让每个智能体可以并行工作,修复不同文件中的不同 bug,直到 Claude 的编译器最终能够编译所有文件。(在这奏效后,仍然有必要应用 delta 调试技术来找到成对失败但单独工作时正常的文件。)
### 多种智能体角色
并行化还实现了专业化。LLM 编写的代码经常重复实现现有功能,因此我指派一个智能体来合并它发现的任何重复代码。我让另一个负责提升编译器本身的性能,第三个负责输出高效的编译后代码。我请另一个智能体从 Rust 开发者的角度批判项目设计,并对项目进行结构性改进以提升整体代码质量,还有一个负责文档工作。
## 对智能体团队极限的压力测试
这个项目被设计为一个能力基准测试。我有兴趣压力测试 LLM 今天刚好能够到的极限,以帮助我们为模型未来能够可靠实现的目标做准备。
我一直在整个 Claude 4 模型系列中使用这个 C 编译器项目作为基准。与之前的项目一样,我从草拟我想要的目标开始:一个从零开始、无依赖的优化编译器,兼容 GCC,能够编译 Linux 内核,并设计为支持多后端。虽然我指定了设计的某些方面(例如,它应该有 SSA IR 以支持多种优化遍),但我没有详细说明如何实现。
之前的 Opus 4 模型勉强能够产出一个功能性编译器。Opus 4.5 是第一个跨过阈值、能够产出通过大型测试套件的功能性编译器的版本,但它仍然无法编译任何真正的大型项目。我对 Opus 4.6 的目标是再次测试极限。
### 评估
在近两周的 2,000 次 Claude Code 会话中,Opus 4.6 消耗了 20 亿输入 token,生成了 1.4 亿输出 token,总成本略低于 20,000 美元。与即使最昂贵的 Claude Max 套餐相比,这都是一个非常昂贵的项目。但这个总额只是我亲自完成这项工作成本的一小部分——更不用说一整个团队了。
这是一个洁净室实现(Claude 在开发过程中没有任何互联网访问);它仅依赖 Rust 标准库。这个 10 万行的编译器可以在 x86、ARM 和 RISC-V 上构建可启动的 Linux 6.9。它还能编译 QEMU、FFmpeg、SQLite、postgres、redis,并且在大多数编译器测试套件上达到 99% 的通过率,包括 GCC torture test suite(https://gcc.gnu.org/onlinedocs/gccint/Torture-Tests.html)。它还通过了开发者的终极试金石:它能编译并运行 Doom。
然而,这个编译器并非没有局限性。这些包括:
- 它缺少从实模式启动 Linux 所需的 16 位 x86 编译器。为此,它调用 GCC(x86_32 和 x86_64 编译器是它自己的)。
- 它没有自己的汇编器和链接器;这些是 Claude 最后开始自动化的部分,仍然有些 bug。演示视频是使用 GCC 的汇编器和链接器制作的。
- 编译器成功构建了许多项目,但并非全部。它还不能直接替代真正的编译器。
- 生成的代码效率不高。即使启用了所有优化,它输出的代码效率也低于 GCC 关闭所有优化时的输出。
- Rust 代码质量尚可,但远未达到专家级 Rust 程序员可能产出的质量。
由此产生的编译器几乎已经达到了 Opus 能力的极限。我(努力地!)尝试修复上述几个局限性,但没有完全成功。新功能和 bug 修复经常破坏现有功能。
作为一个特别具有挑战性的例子,Opus 无法实现启动进入 16 位实模式所需的 16 位 x86 代码生成器。虽然编译器可以通过 66/67 操作码前缀输出正确的 16 位 x86,但编译后的输出超过 60KB,远超 Linux 强制执行的 32K 代码限制。相反,Claude 在这里干脆作弊,调用 GCC 来完成这个阶段(这仅适用于 x86。对于 ARM 或 RISC-V,Claude 的编译器可以完全自行编译。)
编译器的源代码已开放(https://github.com/anthropics/claudes-c-compiler)。下载它,阅读代码,并在你最喜欢的 C 项目上试试。我一直以来发现,理解语言模型能做什么的最佳方式是将其推向极限,然后研究它们在哪里开始崩溃。在接下来的几天里,我会继续让 Claude 推送新的更改,如果你想关注 Claude 持续尝试解决这些局限性的过程。
## 展望未来
每一代语言模型都开辟了与它们工作的新方式。早期模型在 IDE 中用于代码补全。不久之后,模型可以根据文档字符串补全函数体。Claude Code 的推出将智能体带入主流,让开发者可以与 Claude 结对编程。但这些产品都基于一个假设:用户定义任务,LLM 运行几秒或几分钟后返回答案,然后用户提供后续指令。
智能体团队展示了自主实现整个复杂项目的可能性。这让我们作为这些工具的使用者,可以对自己的目标更加雄心勃勃。
我们仍处于早期阶段,完全自主的开发伴随着真正的风险。当人类在开发过程中与 Claude 坐在一起时,他们可以确保质量一致并实时捕捉错误。对于自主系统,很容易看到测试通过就假设工作完成了,而事实很少如此。我以前从事渗透测试工作,利用大型公司产品中的漏洞,想到程序员部署自己从未亲自验证过的软件,这是一个真正的担忧。
因此,虽然这个实验让我兴奋,但它也让我感到不安。构建这个编译器是我最近最有趣的体验之一,但我没想到这在 2026 年这么早就能实现。语言模型以及我们用来与它们交互的脚手架的快速发展,开启了编写大量新代码的大门。我预期积极应用会超过消极应用,但我们正在进入一个需要新策略来安全导航的新世界。
### 致谢
特别感谢 Josef Bacik、Edwin Chen、Bernardo Meurer Costa、Jake Eaton、Dan Kelley、Felix Klock、Jannet Park、Steve Weis 以及 Anthropic 内外的许多其他人提供的帮助和贡献。
相似文章
用 Zig 写一个 C 编译器
一位开发者记录了用 Zig 语言、按照 Nora Sandler 的教程系列构建名为 paella 的 C 编译器的全过程。
面向长时应用开发的Harness设计
Anthropic工程师详细介绍了一种多智能体Harness设计,利用生成器与评估器智能体提升Claude在长时间内自主构建完整、高质量前端应用的能力。
The Autonomous Stack
一套面向生产环境的架构框架,用于构建基于 Claude 的自主智能体,已在 Product Hunt 发布。
@jdnichollsc:@trq212 的《我们如何使用 Claude Code》工作坊:https://github.com/anthropics/cwc-workshops… 祝 Claude 编码愉快!<3 #AI #Clau…
Anthropic 发布了“Code with Claude”工作坊材料,涵盖模型选择、多智能体系统、AI辅助产品工作流以及基于评估的智能体开发。
开源面板可视化 AI 编程代理(Claude Code)
开发者发布了一款中世纪主题的开源面板,将多个 Claude Code 代理以 2D 村庄角色的形式可视化,简化并行编码会话的实时跟踪。