第八章:背压机制——让 AI 学会自我纠错
📌 本章李明轩在做什么:他给自己的发布流程立了三条铁律——错别字零容忍、敏感词必须过审、4 个平台的配图必须齐全。这一章的背压机制就是把这些铁律"硬塞"进 AI 的工作流里,不合格就打回重做。
一个关于关卡的比喻
想象一个工厂的流水线,生产汽车零件。每个工序之间,有一个质检员:
- 零件到达质检站
- 质检员检查是否符合规格
- 符合:零件继续进入下一道工序
- 不符合:零件被打回,重新加工,不合格的零件永远不会流向下一工序
这就是"背压"(Backpressure)的物理含义:上游的压力被限制,不符合质量的东西不会向下游传递。
在 Ralph 里,背压机制确保:不合格的代码不会被当成"任务完成"接受。
关卡的设计哲学是——Ralph 不告诉 AI "怎么做对",只告诉它 "什么算做对"。AI 有完全自由去决定怎么实现,但交付物必须能过关。过不了的那一刻,压力传回给 AI,它必须自己修。
背压的实现方式:通过帽子指令,而非自动执行
Ralph 的背压机制不是由 Ralph 框架直接拦截并执行命令行检查——而是通过帽子指令告诉 AI:在发出"完成"信号之前,必须自己运行验证命令,并把命令的实际输出结果附在事件载荷里作为证据。
这种设计哲学正是"背压优于规定"原则的体现:
- 规定式(脆弱):Ralph 框架在特定节点运行固定命令
- 背压式(健壮):AI 自己负责验证,把证据附在事件里,审查者帽子再核实证据
在帽子指令里定义验证要求
hats:
builder:
name: "⚙️ 构建者"
triggers: ["tasks.ready"]
publishes: ["review.ready"]
instructions: |
实现分配的任务。
## 背压要求
在发出 review.ready 之前,你必须已完成:
- tests: 通过(运行 python -m pytest)
- lint: 通过(运行 flake8 .)
- typecheck: 通过(运行 mypy src/)
在事件载荷里附上证据:
"tests: pass, lint: pass, typecheck: pass"
不要仅声称"测试通过",要提供实际的命令输出摘要。
在事件载荷里携带证据
AI 在完成工作后,用 ralph emit 发出完成信号,并附上验证证据:
# AI 运行这条命令来完成背压验证并发出事件
ralph emit "review.ready" "tests: pass (5/5), lint: pass, typecheck: pass"
审查者帽子核实证据
审查者帽子(Critic)被设计为不信任构建者的自我声明——它会重新运行验证命令来独立确认:
hats:
critic:
name: "🧪 审查者"
triggers: ["review.ready"]
instructions: |
不要相信构建者说"测试通过了"。
重新运行测试,自己验证。
如果测试失败,发出 review.rejected 并说明原因。
一个实际的背压流程
让我们用例子看看背压是如何工作的:
场景:AI 实现了一个功能,但测试实际上没有全部通过。
[Iteration 6/150]
⚙️ 构建者 完成工作:
→ 实现了 validate_email() 函数
→ 运行 pytest,声称"通过"(实际边界测试失败了)
→ 发出 review.ready 事件,载荷:"tests: pass"
[Iteration 7/150]
🧪 审查者 独立检查:
→ 自己运行 python -m pytest
→ 发现:
FAILED tests/test_validate.py::test_empty_email
FAILED tests/test_validate.py::test_none_input
→ 发出 review.rejected
原因:"声称测试全部通过,但边界情况测试失败"
[Iteration 8/150]
⚙️ 构建者 重新工作:
→ 读取 review.rejected 的具体原因
→ 修复 validate_email() 的边界情况处理
→ 重新运行测试,实际全部通过(5/5)
→ 发出 review.ready,载荷:"tests: pass (5/5)"
[Iteration 9/150]
🧪 审查者 再次独立验证:
→ 运行 pytest:5 passed
→ 发出 review.passed ✅
整个背压循环完全自动,不需要你介入。
背压验证的常见类型
在帽子指令里,你可以要求 AI 运行任何类型的验证命令:
测试类
hats:
builder:
instructions: |
完成实现后,在发出完成事件前必须通过:
- Python 项目:python -m pytest -v
- Node 项目:npm test
- Rust 项目:cargo test --all
把实际输出结果附在事件载荷里。
格式与 Lint 类
instructions: |
代码格式必须通过检查:
- Python:black --check . && isort --check-only .
- JavaScript:npm run lint
- Rust:cargo fmt --check && cargo clippy -- -D warnings
类型检查类
instructions: |
类型检查必须通过:
- Python:mypy src/
- TypeScript:tsc --noEmit
- Rust:cargo check(无 warnings)
综合验证示例(Rust 项目)
下面是 ralph-orchestrator 项目本身的实际使用方式——注意背压验证要求写在 Builder 帽子的 instructions 里:
hats:
builder:
name: "⚡ Builder"
instructions: |
Before emitting subtask.done, ALL must pass:
1. cargo fmt --all -- --check — formatting
2. cargo clippy --all-targets --all-features -- -D warnings — lints
3. cargo test -p <target-crate> — targeted tests
Include actual pass/fail output in scratchpad Notes.
Do not claim "pass" without running.
好的验证指令 vs. 坏的
好的(要求实际输出):
instructions: |
验证要求(发出 review.ready 之前):
- tests: 运行 pytest,把通过数/总数附在载荷里
- lint: 运行 flake8,确认 0 个错误
如果任何一项失败,先修复,再发出事件。
不要在测试失败的情况下发出 review.ready。
坏的(只是声明,没有要求证据):
instructions: |
完成后发出 review.ready。
(AI 可能直接发出而不实际运行测试)
什么情况下背压会无法自动修复
有些问题 AI 无法自动修复,背压会一直失败,直到:
-
达到最大迭代次数(默认 150 次):循环会停止,并告诉你卡在了哪里
-
AI 主动发布
build.blocked:AI 自己判断无法继续,需要人工介入 -
循环超时(默认 4 小时):超过配置的最长运行时间
这时你需要:
- 查看最后一次失败的具体信息
- 手动修复无法自动解决的问题(比如安装缺少的依赖)
- 重新启动循环,从断点继续
# 查看为什么卡住了
ralph events --topic blocked
cat .ralph/agent/memories.md # AI 可能记录了遇到的问题
# 手动修复后重新运行
ralph run -p "继续上次的任务,已经修复了 xxx 问题"
LLM-as-Judge:用 AI 评判主观质量
有些质量标准很难用命令行工具检查,比如:
- 代码的可读性
- 错误消息是否对用户友好
- 文档是否清晰
这类主观标准可以交给审查者帽子来判断,把它设计成专门针对这类问题的角色:
hats:
ux_reviewer:
name: "💬 UX 审查者"
triggers: ["review.ready"]
publishes: ["ux.passed", "ux.rejected"]
instructions: |
你是用户体验审查者。检查代码里的错误消息是否对普通用户友好:
判断标准:
- 不包含技术栈信息(如 'NullPointerException'、堆栈跟踪)
- 告诉用户如何解决问题,而不只是说"出错了"
- 语言清晰,不使用编程行话
如果全部通过,发出 ux.passed。
如果有不符合的,发出 ux.rejected 并列出具体的问题消息。
为什么背压比详细指令更有效
还记得第三章的"背压优于规定"原则吗?这里是一个具体的对比:
规定式(容易失效):
instructions: |
第一步,写测试文件
第二步,运行测试,确认它失败
第三步,写实现代码
第四步,运行测试,确认它通过
第五步,运行 flake8 检查格式
第六步,如果格式不通过,运行 black 修复
第七步,再次运行 flake8...
(如果 AI 跳过了某一步,或者文件路径不同,整个指令就失效了)
背压式(更健壮):
hats:
builder:
instructions: |
实现功能。
发出 review.ready 之前,必须已通过:
tests: pytest 全部通过
lint: flake8 0 个错误
把实际命令输出附在载荷里作为证据。
(不管 AI 怎么实现,最终都要提供可核实的验证证据)
背压机制关注结果,而不是过程,这让它对各种实现方式都有效。
本章小结
- 背压关卡是自动运行的质量检查点,不合格的代码不会被"通过"
- 可以配置测试、格式检查、类型检查、安全扫描等各类关卡
- 好的
on_fail消息能大大提高 AI 自动修复的成功率 - 关卡按顺序执行,建议快速检查放前面
- 背压比详细规定更健壮,关注结果而不是过程
- 支持 LLM-as-Judge 检查主观质量标准
质量门禁搞定了,但李明轩遇到新情况:付费社群周报今晚没写完,明晚接着写时 AI 已经把上下文全忘光了。他需要一个跨会话的"AI 笔记本"。下一章讲记忆与任务系统——让 AI 把学到的东西留在磁盘上。