- 强类型 state
- 真实的大模型适配层
- 真实的系统提示词
- 真实的解析器(parser)
- 真实的工具
- 真实的
reduce()(归约,将观测结果与决策归约回状态)循环 - 真实的
qita追踪记录
examples/patterns/react.py 来学习,但这节课本身会把设计解释清楚,不要求你先反向阅读源码。
你要构建什么
任务非常小:- 打开
buggy_module.py - 修复
add(a, b),让它返回a + b - 运行验证命令
本课的设计选择
为什么从文本 ReAct 适配层开始
本课使用:messages -> text model output -> ReAct parser -> Decision -> tool execution
其中解析器负责将原始模型输出解析为决策(智能体每步的结构化决策),而协议(模型输出的格式契约)定义了输出的格式约定。我们不从原生工具调用、XML、JSON 或模型专属适配层开始,因为那些选择会在你还没理解核心循环之前,过早引入协议耦合。
系统提示词是协议,不是装饰
本课使用的 ReAct 提示词大致是:ReActTextParser 不是在猜模型输出,它是在消费这份明确约定好的协议。
本课最重要的第一条经验就是:
- 提示词格式与解析器选择,本质上是一项联合设计决策
- 改了其中一个,通常就要连另一个一起改
本课的模型适配层
示例里的模型构造通常长这样:- 它适用于 OpenAI 兼容端点
- 模型返回纯文本,便于观察
- 与基于提示词注入工具模式的路径天然兼容
- 让课程可以在不同供应商与本地网关间迁移
1
围绕下一步决策来设计 state
本课的 state 故意很小:为什么是这三个字段:
scratchpad:保存压缩后的最近轨迹,供下一步决策使用target_file:让智能体始终围绕单一工件行动test_command:把任务完成变成一个可执行成功条件
2
暴露尽量小的工具界面
示例使用手工注册表,让你能精确看到暴露给模型的能力:
CodingToolSet 本身是捆绑包,但它的界面仍是你主动裁剪出来的。对第 1 课来说,最合适的工具集合只需要覆盖:- 查看文件
- 编辑文件
- 运行验证命令
3
把提示词与解析器明确绑在一起
智能体构造函数里通常会这样写:要把这句话读成一个整体:这个智能体要求模型输出 ReAct 文本,并由 ReAct 解析器负责解析。在 QitOS 里,这个绑定本身就是适配层的一部分。
4
prepare 只组织下一步真正需要的上下文
prepare() 负责把 state 变成提示词就绪的文本:prepare() 不是 state 的全量转储,而是提示词视图。5
让归约决定智能体记住什么
ReAct 的学习发生在 这一个函数里藏着三条原则:
reduce() 里:- 不是每条观测结果(每步后智能体接收的结构化观察结果)都值得回灌进未来上下文
- state 是压缩工作记忆,而不是全量日志
final_result是成功的显式信号
6
理解本课还没有引入什么
第 1 课不使用:
decide()覆写- 显式规划
- 记忆适配器
- 自定义历史
- 上下文压缩(compaction)
- 模型专属协议覆写
7
运行示例,并用 qita 检查内核
运行:然后查看:在
qita 中重点检查:- 发送给模型的提示词是否符合预期
- 解析器是否干净地产生了
Thought与Action - 工具输出是否让成功条件变得明确
final_result是否在真正成功的第一时间被设置
为什么这一课不引入记忆或上下文压缩
本课最正确的记忆选择就是不用。 原因很简单:- 运行很短
scratchpad已足够容纳有效上下文- 过早引入检索或上下文压缩会模糊架构边界
完整示例
完整可运行代码位于:第 2 课会引入什么
第 2 课会保持相同的模型适配层和执行解析器,但引入一个新的设计点: 规划应该变成显式状态与显式控制边界,而不是藏在更长的思考里。下一课:PlanAct
加入规划器、游标与
decide() 门控,但不更换核心运行时相关参考:Kit
回看本课使用的
ReActTextParser、提示词模板与编码工具界面