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 -->标记就自动跳过。这意味着任何时刻、任何会话接手,都不会重复劳动。
这套设计的妙处在于:协调不需要一个中央服务,文件系统本身就是消息队列。
插入方式:认领制
我要做的事其实只有三步:
- 读 SPEC,理解规则;
- 认领——往
dispatched.log追加我拿走的任务号,调度会话每次派活前都读这本账,看到是我认领的就跳过; - 派发——把 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 在个人微信端不渲染,这是踩过的坑)
可以搬走的经验
- 幂等 + 声明式认领是多智能体协作的地基。任务可重入(带标记即跳过)、认领有账本(谁先写归谁)、完成有回执,三个文件搞定协调,不需要任何复杂的编排框架。
- 完成信号必须原子化。先写临时文件、自查、再 rename 成正式名字——这一招让"读到半成品"在物理上不可能发生。
- 配额是全账号共享的。你看到的"我 4 个 agent"只是冰山,别的会话还在底下占着位置。降速的正确姿势是减并发、小步补发、削峰读写,而不是重试轰炸。
- 规格先行,术语统一。一份 20 条的 SPEC 让二十多个 subagent 的产出格式完全一致,术语表让"上下文窗口"不会一会儿被翻成"情境视窗"。
- 失败要留痕,不留渣。FAIL 回执 + 清理自己的临时文件 + 从备份恢复原状,流水线才能被任意打断、任意续跑。
- 给执行者塞一张自查清单,用机器可验证的断言(diff、逐行在场、计数),而不是"请认真一点"。
整个过程里人的角色其实很轻:发现了流水线、决定插队协作、在限流时喊了一嗓子"加派一个"。其余时间,就是两套 AI 会话各自认领、翻译、自查、交回执,微信里安安静静地收到一条条进度简报。
这大概就是多智能体协作该有的样子:不需要谁指挥谁,一份好规格 + 两本干净的账,就够了。