在代理工程中的重构经济效益
重构直接降低 AI 令牌成本
对代理生成的代码库进行重构能够通过减少 AI 代理在实现新功能时必须处理的输入令牌数量,带来可衡量的经济收益。在一次受控实验中,将一个 17,155 行的 Rust 文件重构为模块化结构,使代表性变更所需的输入令牌从 159,564 降至 27,360,实现了 83% 的令牌消耗节省。
这种节省并非因为代码总量减少——数据访问层的整体行数基本保持不变——而是因为模块化使代理能够只识别并读取最小必要的文件子集。当代码被合并到单个巨大的文件中时,代理必须读取整个文件以保持上下文,导致成本上升且执行更慢。
重构实验
为了量化代码结构对令牌使用的影响,使用了约 150,000 行代码(主要是 Rust)的应用程序。该应用程序完全由代理(Claude Code 和 Cursor)编写,未经过人工代码审查。随着时间推移,数据访问层演变为一个超过 17,000 行的单文件,表现出高度重复和缺乏内部抽象。
方法论
实验为每次测试使用一个“全新”代理,以确保先前步骤的学习不会污染结果。过程遵循以下步骤:
- 建立基线: 向子代理提示一个代表性变更(添加新 trait 和实现),记录初始令牌成本。
- 迭代重构: 基于严格的重构纪律(参考 Martin Fowler 的 Refactoring 第 2 版),执行 15 步重构。
- 测量: 每完成一次重构后,向全新的子代理再次提示完全相同的代表性变更,测量输入令牌、输出令牌和执行时间的变化。
定量结果
| 指标 | 基线 | 第 15 步后 | 变化 |
|---|---|---|---|
| 数据访问层行数 | 17,155 | 16,608 | -2.9% |
| 最大文件行数 | 17,155 | 3,695 | -78.4% |
| 每次变更的输入令牌 | 159,564 | 27,360 | -83% |
| 每次变更的输出令牌 | 1,705 | 2,113 | +23.9% |
| 每次变更的时间(秒) | 342 | 454 | +32.7% |
当最大文件大小下降时,输入令牌“骤然下降”,而输出令牌相对保持稳定。这表明重构使 AI 更容易 阅读 代码,但并不一定让生成的代码 更短。
关键技术洞察
模块化 vs. 简单拆分
仅仅把大文件随机拆分成小文件不足以实现这些节省。实验表明,最显著的令牌减少仅在代码被逻辑上重构以抽取重复并建立可复用核心后出现。这种结构使代理的检索机制能够成功定位相关文件,而不是在多个小文件中搜索所需逻辑。
重构中的“代理鸿沟”
尽管能够生成大量代码,实验发现当前的 AI 代理(尤其是 Claude)在实际进行重构时仍然困难重重:
- 缺乏主动性: 代理不会自行提出或执行重构来改进代码库,需要明确的人类指导和详细计划。
- 执行错误: 代理在执行机械性的重构操作(移动代码、更新 import)时常常不可靠,必须借助外部 Python 脚本配合
grep和sed来确保正确性。 - 需要指导: 必须有具备深厚软件工程知识的人类来编写提示和重构计划,以实现期望的架构结果。
社区观点综合
工程师们围绕这些发现的讨论凸显了 AI 与软件架构交叉的若干关键点:
“乏味”最佳实践的回归
许多观察者指出,所谓“令人兴奋”的新发现——重构有助于 AI——其实是对基本软件工程原则的再发现。正如一位贡献者所言:
“乏味:重构让你的开发者在长期内更高效。令人兴奋:重构让你的 AI 在长期内更高效。”
对推理与正确性的影响
除了令牌成本外,有人认为更紧凑的上下文提升了 AI 的推理能力。通过更好的抽象降低代码的“熵”,可能增加 AI 生成能够良好泛化、而非仅通过特定测试用例的正确软件的概率。
人在回路中的必要性
普遍共识是,虽然代理可以编写代码,但高层次的架构愿景仍然是人类的职责。要在多个存储类型上提示实现特定的 async trait,需要的领域专业知识目前仍是代理无法独立综合的。一些人甚至认为我们正进入“氛围编码”(vibe coding)时代:人类充当架构师,AI 充当高速实现者。