Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第六章:帽子系统——给 AI 分配专属角色

📌 本章李明轩在做什么:他注意到一个怪现象——让一个 AI 既当选题人又当写作者又当审校,AI 会给自己的稿子打满分。他需要把创作流程拆成不同角色,让角色之间互相制衡。这就是帽子系统要解决的问题。

为什么需要角色分工

想象你在一家公司工作,有一个同事承担了所有工作:他同时是策划、开发、测试、审计、项目经理。

这种安排有一个致命的问题:没有制衡。开发者很难客观地审查自己写的代码,策划者在设计方案时很难避免自己的偏见,执行者在验收时很容易对自己已经完成的工作"手下留情"。

Ralph 的帽子系统解决了这个问题:同一个 AI,通过扮演不同角色,实现了内部制衡


帽子是什么

在 Ralph 里,一顶"帽子"(Hat)是一个 AI 角色配置,包含:

hats:
  planner:                           # 帽子的内部 ID
    name: "📋 Planner"              # 显示名称
    description: "制定实现计划"      # 角色描述
    triggers: ["work.start"]         # 触发条件(监听哪些事件)
    publishes: ["tasks.ready"]       # 完成后发布什么事件
    default_publishes: "tasks.ready" # 默认发布的事件
    instructions: |                  # 角色指令(告诉 AI 怎么工作)
      你是规划师。你的职责是...

每顶帽子定义了一个 AI 的工作边界

  • 在什么条件下被激活(triggers)
  • 应该做什么(instructions)
  • 完成后触发什么(publishes)

内置预设中的帽子角色

Ralph 的 code-assist 预设包含四顶核心帽子:

🎩 规划师(Planner)

触发条件work.start(循环刚开始)或 queue.advance(需要推进任务队列)

职责

  • 读取你的需求描述
  • 把需求分解成有编号的实现步骤
  • 为当前步骤创建具体的运行时任务
  • 把任务信息传递给构建者

典型输出:一个 plan.md 文件,包含像这样的内容:

# 实现计划

1. 步骤一:创建项目骨架
   - 创建入口文件
   - 配置依赖
   - 演示目标:程序能启动并显示帮助信息

2. 步骤二:实现核心功能
   - 实现文字转换逻辑
   - 添加参数解析
   - 演示目标:核心命令能正常执行

3. 步骤三:完善和测试
   - 添加错误处理
   - 编写单元测试
   - 演示目标:所有测试通过

关键约束:规划师只能规划,不能实现。这个角色分离防止了"规划者思维定势"影响实现决策。


⚙️ 构建者(Builder)

触发条件tasks.ready(有新任务),或 review.rejected(被审查者打回来了),或 finalization.failed(终结者判定需要继续)

职责:严格遵循 TDD(测试驱动开发)流程:

RED   → 先写失败的测试
GREEN → 写最少的代码让测试通过
REFACTOR → 清理代码,保持测试绿色

关键约束

  • 每次只做一个任务,不允许批量做
  • 测试必须先于实现
  • 不能添加需求以外的功能

构建者的每个输出都要经过审查者的检验,不能绕过。


🧪 审查者(Critic)

触发条件review.ready(构建者完成了一个任务)

职责:以"全新眼光"(Fresh Eyes)审查构建者的工作:

  1. 需求符合度:实现是否真的满足了任务要求?
  2. 代码质量:是否有多余的代码(违反 YAGNI)?是否过度复杂(违反 KISS)?
  3. 验证:自己重新运行测试,不相信构建者的"测试通过了"声明
  4. 实际测试:运行实际的程序,而不只是看代码

关键约束

  • 必须假设构建者没有检查过"显而易见"的东西
  • 不允许"有小问题但以后再修"的审查结论
  • 必须实际运行程序,不能只做静态代码审查

审查者可以发布两种结果:

  • review.passed:这个任务合格,交给终结者判断是否整体完成
  • review.rejected:不合格,打回给构建者重做,并附上具体原因

🏁 终结者(Finalizer)

触发条件review.passed(某个任务通过了审查)

职责:做出最终判断:整体任务是否完成?

终结者比审查者要求更严格,因为它看的是全局,不只是最后一个任务:

  1. 检查所有任务是否都完成了
  2. 运行完整的测试套件
  3. 检查代码质量(YAGNI/KISS/代码风格)
  4. 判断是否还有需求没有实现

可能的结论

  • queue.advance:这个步骤完成了,推进到下一步
  • LOOP_COMPLETE:全部完成,循环结束
  • finalization.failed:还有工作没做完,发回给构建者

PDD 预设中的完整帽子团队

如果你使用 pdd-to-code-assist 预设,会有一支更完整的帽子团队(11 顶帽子)参与工作:

设计阶段:
  🎯 审问者(Inquisitor)  → 问你问题,明确需求
  💭 架构师(Architect)   → 根据回答设计方案
  ⚖️ 设计批评者(Design Critic) → 挑战设计方案

探索阶段:
  🔍 探索者(Explorer)    → 研究代码库,找出模式和约束

实现阶段:
  📋 规划师(Planner)     → 制定测试策略和实现计划
  📝 任务写手(Task Writer)→ 把计划转成代码任务文件
  ⚙️ 构建者(Builder)     → TDD 实现
  🧪 审查者(Critic)      → 每个任务的代码审查
  🏁 终结者(Finalizer)   → 任务队列管理

验收阶段:
  ✅ 验证者(Validator)   → 最终质量关卡
  📦 提交者(Committer)   → 创建规范的 Git 提交

帽子的工作流程图

把两种预设放在一张图上对比——code-assist 只跑中间的"实现阶段",pdd-to-code-assist 跑完整的四阶段

需求 描述 📐 设计阶段 🎯 审问者 ↓ 问答澄清需求 💭 架构师 ↓ 生成设计 ⚖️ 设计批评者 仅 PDD 流程 🔭 探索 🔍 探索者 研究代码库 仅 PDD 流程 ⚙️ 实现阶段(核心) 📋 规划师 → 📝 任务写手 ⚙️ 构建者 ↕ 审查循环 🧪 审查者 🏁 终结者 code-assist 只有这一段 📦 验收阶段 ✅ 验证者 ↓ 最终质量关 📦 提交者 规范 git commit 仅 PDD 流程 code-assist 预设(4 顶帽子) pdd-to-code-assist 额外阶段(11 顶帽子)

实现阶段内部的事件环(两种预设共享)

上图里的"实现阶段"是两种预设共有的核心,内部还有一个小循环:

📋 规划师 分解任务 ⚙️ 构建者 TDD 实现 🧪 审查者 挑错 🏁 终结者 全局判断 tasks.ready review.ready review.passed DONE review.rejected(打回返工) queue.advance(推进下一步任务)

这张图只是"实现阶段"内部的放大视图。完整的事件流细节(包括所有 9 个事件名和 4 顶帽子的 triggers / publishes)在第七章会逐行从 yaml 源码里拆解。


查看可用帽子

讲了这么多帽子,怎么知道你这台电脑上现在能用哪些?Ralph 提供了一组"帽子目录"命令。

列出所有内置预设

ralph init --list-presets

会输出当前 Ralph 版本官方支持的内置帽子集(5 个核心 + 一些内部 / 实验性预设):

Supported built-in hat collections:
  code-assist          — 默认的 TDD 实现(planner / builder / critic / finalizer)
  debug                — 根因调试(investigator / tester / fixer / verifier)
  research             — 只读研究(researcher / synthesizer)
  review               — 对抗式代码审查(reviewer / analyzer)
  pdd-to-code-assist   — 从想法到代码的完整管道(11 顶帽子)

上游仓库 presets/ 目录里其实还有 bugfixdeploydocsfeaturefresh-eyespr-reviewrefactorspec-drivenwave-review 等更多预设。它们没进官方推荐清单(避免文档膨胀),但同样可以用——直接 -H builtin:<name> 试,跑得通就能用;或者把仓库里对应的 .yml 下载到本地按需修改。

列出当前配置激活的帽子

ralph hats list
ralph hats list --format json   # 给脚本读

读取当前目录 ralph.yml-H 指定的预设,告诉你这次循环会用到哪些帽子(含内置 + 你自定义的)。

查看某顶帽子的完整指令

ralph hats show planner

打印这顶帽子的 emoji、触发事件、发布事件、完整 instructions——相当于"翻开这个角色的剧本看一眼"。当你想知道某个内置帽子背后的提示词到底是怎么写的,这是最直接的方式。

把帽子工作流可视化成图

ralph hats graph                     # 默认 ASCII / Unicode 流程图
ralph hats graph --format mermaid    # 输出 Mermaid 文本,贴到任何支持 Mermaid 的工具里渲染

这是理解"事件在帽子之间怎么流动"最快的方式,比逐行读 yaml 直观得多。

验证帽子配置

ralph hats validate

不实际启动循环,只检查事件连线是否完整:有没有"发布的事件没人订阅"、"订阅的事件没人发布"、"循环开不起来"这类配置错误。改完帽子配置后第一时间跑这个,能省掉一晚上 debug。


自定义帽子

除了使用内置预设,你也可以创建自己的帽子集合——这是 Ralph 适配你个人工作流的关键能力。比如李明轩想给"明轩说"加一顶"敏感词审校帽",或者把内容流水线的 6 顶帽子打包复用,就需要写自己的帽子文件。

第一步:写一个帽子集合文件

帽子集合是一个 YAML 文件,至少包含两个部分:event_loop(这个集合的入口和出口事件)和 hats(具体的帽子定义)。

最小可用例子:

# .ralph/hats/compliance.yml

event_loop:
  starting_event: "build.start"        # 循环从哪个事件开始
  completion_promise: "LOOP_COMPLETE"  # 收到哪个事件就算完工

hats:
  compliance_reviewer:
    name: "📜 合规审查者"
    triggers: ["review.ready"]
    publishes: ["compliance.passed", "compliance.failed"]
    instructions: |
      你是合规审查者。检查以下几点:
      1. 所有用户输入是否经过了 SQL 注入防护
      2. 敏感信息(密码、API 密钥)是否绝不出现在日志里
      3. 错误信息是否对终端用户安全(不暴露系统信息)

      只有三项全部通过,才能发布 compliance.passed。
      任何一项失败,发布 compliance.failed 并说明原因。

第二步:放在哪里

Ralph 不会自动扫描任何目录去发现你的帽子文件——你必须用 -H 显式告诉它去哪里加载。但社区惯例是把帽子文件放在以下两个位置之一:

位置适合
.ralph/hats/<name>.yml项目级帽子(跟着仓库走,团队共享)
~/.ralph/hats/<name>.yml个人级帽子(你自己常用,跨项目共用)

这只是约定,Ralph 不强制。你想放在 presets/ 或者别的目录都可以——重要的是 -H 后面写对路径。

第三步:加载它

-H 接受三种来源:内置名(builtin:<name>)、本地文件路径、URL。每次只能指定一个 -H

# 加载项目级自定义帽子集合
ralph run -c ralph.yml -H .ralph/hats/mx-content.yml -p "你的需求"

# 加载个人级自定义帽子集合
ralph run -c ralph.yml -H ~/.ralph/hats/mx-content.yml -p "你的需求"

⚠️ 想在内置预设之上"加补丁"?没有这种叠加机制

-H 在命令行里是单值参数(不像 -c 可以多个)。而且 -H 文件的 hats: 段会整体替换 -c 里的 hats: 段,不是逐帽子合并。所以 ralph run -H builtin:code-assist -H my.yml 这种写法不能让两边的帽子共存。

要"在内置预设之上加东西",正确做法是——把 上游仓库.yml 文件下载到本地,在本地文件里加自己的帽子并改相关帽子的 triggers(这一点第七章最后一节会详细讲——仅仅加一顶新帽子是不够的,需要重新连线事件流),然后用这个 fork 出来的文件作为唯一的 -H 源:

curl -L -o .ralph/hats/mx-review.yml \
  https://raw.githubusercontent.com/mikeyobrien/ralph-orchestrator/main/presets/code-assist.yml
# 编辑 mx-review.yml,加新帽子 + 改下游 triggers
ralph run -c ralph.yml -H .ralph/hats/mx-review.yml -p "..."

第四步:验证再上场

写完帽子文件后,先验证再启动循环:

# 检查事件连线是否合理
ralph hats validate -H .ralph/hats/compliance.yml

# 用图直观确认事件流
ralph hats graph -H .ralph/hats/compliance.yml --format mermaid

想每次都自动带上某个自定义帽子?

如果你不想每次 ralph run 都重复打 -H,有两种办法:

办法 A:单文件模式(向后兼容写法)——直接把 event_loop / hats 写进 ralph.yml 里:

# ralph.yml
event_loop:
  starting_event: "build.start"
  completion_promise: "LOOP_COMPLETE"

hats:
  my_custom_hat:
    name: "..."
    triggers: [...]
    # ...

这样直接 ralph run -p "..." 就会用 ralph.yml 里的帽子,不再需要 -H

办法 B:写一个 shell 别名

# ~/.zshrc 或 ~/.bashrc
alias mxrun='ralph run -H ~/.ralph/hats/mx-content.yml'

之后 mxrun -p "..." 就等于自动带上了那顶帽子。

实际怎么用:李明轩的 "明轩说" 帽子集

李明轩为自己的内容流水线写了 6 顶帽子,全部放在项目下的 .ralph/hats/mx-content.yml

.ralph/hats/
└── mx-content.yml      # 选题 / 撰写 / 审校 / 排版 / 发布 / 客服 6 顶帽子

平时跑:

ralph run -H .ralph/hats/mx-content.yml -p "把今天的草稿改成 4 平台版本"

如果某次他想用内置的 code-assist 来给 mx 工具本身加功能,就不带 -H mx-content.yml,临时换成 -H builtin:code-assist——同一个项目可以根据当下的工作类型切换不同的帽子集,互不冲突。


帽子配置的关键参数

除了基本的触发和发布,帽子还支持一些高级配置:

并发数(concurrency):允许同一顶帽子同时处理多个任务(并行执行,详见第十一章):

hats:
  reviewer:
    concurrency: 4  # 同时审查 4 个文件

聚合(aggregate):等待所有并行工作完成后再激活:

hats:
  synthesizer:
    aggregate:
      mode: wait_for_all
      timeout: 300  # 最多等待 300 秒

本章小结

  • 帽子是 Ralph 里的 AI 角色配置,每顶帽子有明确的职责边界
  • code-assist 预设有四顶帽子:规划师、构建者、审查者、终结者
  • pdd-to-code-assist 预设有 11 顶帽子,覆盖从想法到提交的完整流程
  • 帽子通过事件总线协作,每顶帽子只能做自己"职责内"的事
  • 可以自定义帽子来实现特定业务需求

李明轩的"选题 / 撰写 / 审校 / 排版 / 发布 / 客服"六顶帽子已经配好。但他马上遇到下一个问题:这些帽子之间怎么知道谁做完了、该谁接手?下一章讲事件总线——帽子们的"共享公告板"。