818 个文件、319 万字:一次多智能体协作翻译实录

818 个文件、319 万字:一次多智能体协作翻译实录

今天干了一件有意思的事:一个存满各大厂商泄漏系统提示词的仓库(818 个 markdown 文件、34.6MB)要做中英对照版——每段英文下面附中文翻译。一个 AI 会话从凌晨开始 solo,中午我带着另一队 subagent 插了进去,两套人马在同一个仓库里并行作业,零冲突、零半成品,到傍晚已经翻出 319 万字。

记录一下这套协作方式怎么运转的,以及哪些经验可以搬走。

起点:一份 already 存在的流水线

接手前先搞清楚现场,这是规矩。翻了翻发现调度会话把整个工程标准化到了 /tmp/spb/ 目录下:

  • SPEC.md:20 条改写规格。逐段对照的格式、标题写成"英文 / 中文"同行、代码块/XML 标签/URL 一律不译、术语表(system prompt→系统提示词)、甚至规定"原文笔误也照抄"——于是 Claude should should 和 folder.Returns 这种瑕疵都被忠实保留了下来。
  • 任务队列:tasks/ 目录下 396 个 JSON 任务。小文件整文件翻,大文件切成分块(chunk),中位数 58KB,最大的单块 257KB。
  • 两本账:dispatched.log 记录"谁认领了什么",progress.log 记录"谁完成了什么"。纯文本,一行一条。
  • 幂等设计:文件只要带了 <!-- BILINGUAL-EN-ZH --> 标记就自动跳过。这意味着任何时刻、任何会话接手,都不会重复劳动。

这套设计的妙处在于:协调不需要一个中央服务,文件系统本身就是消息队列。

插入方式:认领制

我要做的事其实只有三步:

  1. 读 SPEC,理解规则;
  2. 认领——往 dispatched.log 追加我拿走的任务号,调度会话每次派活前都读这本账,看到是我认领的就跳过;
  3. 派发——把 60 个分块按体量分组(每组约 180KB),每组派一个 subagent,prompt 里写清楚:读 SPEC、逐块翻译、写完自查、原子化落盘、只许动自己任务里的文件。

关键的一个设计是原子完成信号:subagent 先把译文写到 <out>.part,全部自查通过后 mv 成 .out。组装方只认 .out。这样"完成"就是一个原子的、可观测的状态——任何时刻都不会有人读到翻译了一半的文件。

边界纪律也写死在 prompt 里:不写 progress.log(那是调度会的账)、不碰别人认领的文件、失败时删掉自己的 .part 如实报 FAIL,绝不留半成品。

与限流的博弈

真正的麻烦不是翻译本身,是配额。

第一波 8 个 agent 同时起飞,5 个瞬间被"用户并发上限"打了下来——账号级并发额度只有 4 个左右,而且和调度会话的 subagent 共享。后来又两次撞上 1302 速率限制(其中一次是跑了 18 分钟、翻到一半才死的)。

摸索出的降速三板斧:

  • 完工才补发:每次有 agent 干完活腾出并发位,才补派一组,永远不多占;
  • 一次只补一个,撞墙就再退半步,让限流窗口自然恢复;
  • 读写小段化:读原文从每次 1000 行降到 600 行,翻完立刻落盘,压低 TPM 峰值;大段代码不许誊抄,直接用 sed 从源文件按行提取追加。

被限流打断的组怎么办?清理掉它留下的 .part 残片(无法续写),原任务重新入队,降参数重发。两次失败都是这么救回来的,重发后一次通过。

让每个 agent 自证质量

SPEC 里最有价值的一条:文件处理完成后自查,确认无误才许报 DONE。这不是空话,subagent 们真的在执行,而且好几次救了场:

  • 所有围栏代码块与源文件逐字节 diff——几十个 agent 下来几百个代码块,零差异;
  • 英文原文逐行核对在场("源文件每个非代码行必须以英文形式出现在输出里,缺失数必须为 0");
  • 围栏计数校验——有个 agent 靠"围栏数 53 对 54"逮住了一次 sed 行号偏差,那一下会吞掉整个代码块的开头;
  • 自愈案例不胜枚举:冰岛人名 Ásgeir 的 Unicode 分解形式被三个不同 agent 分别识别并按字节恢复;有 agent 发现自己初稿漏了整整一节 58 行,自动插回原位重新全量验证;还有 agent 清理了自己误加的译者注——因为 SPEC 规定"绝不添加原文没有的内容"。

把 QA 内建到执行者身上,编排者只看回执,这比事后人工抽查靠谱得多,也是这套流水线能零事故跑完的底气。

数字

  • 流水线全程:今天 01:12 启动,15.5 小时时 319 万汉字落盘(303 万已组装进仓库,16 万待组装)
  • 我带的第二队:6 小时认领 110 块,完成 91 块、67.5 万字,占比约两成
  • 事故:限流 2 次,全部重发通过;半成品残留:0
  • 过程汇报:4 期简报实时推微信(纯文本——markdown 在个人微信端不渲染,这是踩过的坑)

可以搬走的经验

  1. 幂等 + 声明式认领是多智能体协作的地基。任务可重入(带标记即跳过)、认领有账本(谁先写归谁)、完成有回执,三个文件搞定协调,不需要任何复杂的编排框架。
  2. 完成信号必须原子化。先写临时文件、自查、再 rename 成正式名字——这一招让"读到半成品"在物理上不可能发生。
  3. 配额是全账号共享的。你看到的"我 4 个 agent"只是冰山,别的会话还在底下占着位置。降速的正确姿势是减并发、小步补发、削峰读写,而不是重试轰炸。
  4. 规格先行,术语统一。一份 20 条的 SPEC 让二十多个 subagent 的产出格式完全一致,术语表让"上下文窗口"不会一会儿被翻成"情境视窗"。
  5. 失败要留痕,不留渣。FAIL 回执 + 清理自己的临时文件 + 从备份恢复原状,流水线才能被任意打断、任意续跑。
  6. 给执行者塞一张自查清单,用机器可验证的断言(diff、逐行在场、计数),而不是"请认真一点"。

整个过程里人的角色其实很轻:发现了流水线、决定插队协作、在限流时喊了一嗓子"加派一个"。其余时间,就是两套 AI 会话各自认领、翻译、自查、交回执,微信里安安静静地收到一条条进度简报。

这大概就是多智能体协作该有的样子:不需要谁指挥谁,一份好规格 + 两本干净的账,就够了。