系统设计复盘:为什么 Agent 的 ReAct 循环必须内嵌确定性保护层——以 FitMind 健康助手的路由与步骤控制为例

1. 复盘主题(系统问题)

为什么 Agent 不能完全依赖 LLM 的自由推理循环?

具体表现:在 FitMind 的 ReAct 实现中,单纯让 LLM 决定"下一步做什么"会引发路由崩坏、步骤死锁与副作用误触发,最终必须在 Planner 与 Router 之间嵌入多层确定性保护,才能让多工具 Agent 安全上线。


2. 背景问题(Why)

FitMind 是一个面向个人健康管理的 AI 助手,用户输入极其口语化且意图混杂,比如:

  • "感觉今天吃咸了,会不会水肿?"
  • "帮我把刚刚那顿记一下,大概一碗米饭、两个鸡腿。"
  • "练完腿之后膝盖不舒服,正常吗?"

系统需要完成的动作跨越:

  • 自然语言查询(检索健康知识)
  • 结构化数据查询(查运动/饮食日志、用户档案)
  • 数值计算(BMI、热量估算)
  • 写库操作(记录饮食/运动)

显然,单一工具无法覆盖所有请求,必须采用多步推理与工具组合。ReAct(Reasoning + Acting)范式天然适合:让模型在循环中思考(Thought)、选工具(Action)、读结果(Observation),直到形成最终答案。

但问题在于:用户请求的开放性与系统状态的严肃性之间存在根本矛盾。我不能允许模型随意调用写库工具,也不能让一个简单的 BMI 查询陷在 5 步推理中消耗大量 Token 和时间。


3. 原始方案(Initial Design)

最初设计极其"信任 LLM":

  • 所有用户消息首先经过一个 LLM Router,它判断"是否需要多步处理"以及"路由类型(顺序/并行)"。
  • 如果需要,就交给 ReAct Planner ,Planner 内部维持一个无约束的 Thought-Action-Observation 循环,直到模型输出 final_answer
  • 唯一的安全措施是一个较大的 MAX_STEPS = 10,用来防止真的跑飞。

架构草图(原始):

复制代码
User Input → LLM Router → [Simple / Complex] 
                  ↓(Complex)
             ReAct Planner (LLM 自由循环)
                  ↓
            ToolRegistry → 真实工具执行

我当时的假设:

  • LLM Router 能准确理解用户的真实意图。
  • ReAct 循环中,模型会合理利用 Observation,不会卡死或重复。
  • 工具本身都是幂等的或可重放,风险可控。

4. 遇到的问题(Core Problem)

问题 1:路由误判触发写操作

用户输入:

"昨天我吃够 2000 卡了吗?"

Router(LLM)将其分类为 需要多步处理 ,因为句子包含"吃"和卡路里数值,触发了"记录饮食"的倾向。进入 ReAct 循环后,模型第一步就调用了 log_diet,试图写入一条只有日期和卡路里目标但没有具体食物的记录。这导致了脏数据,并且用户实际想问的是"查询昨天的饮食记录并汇总热量"。

危险原因:写操作被无确认执行,且 Router 的错误判断将查询意图扭曲为修改意图。

问题 2:ReAct 循环中的步骤死锁

用户在对话中途问:

"那我现在的 BMI 是多少?"

Planner 生成的步骤:

  1. Thought: 需要身高体重 → Action: get_user_profile → Observation: {height: 175, weight: 80}
  2. Thought: 现在可以计算 BMI → Action: calculate_bmi → Observation: {bmi: 26.1}
  3. Thought: 嗯,我还需要确认一下最新的体重,可能变化了 → Action: get_user_profile → Observation: (同前)
  4. Thought: 好,再算一次 → Action: calculate_bmi → Observation: (同前)
    然后循环,直到 MAX_STEPS 耗尽。

危险原因 :模型在获得足够信息后,没有推进到 final_answer,反而陷入无意义的重复查询。虽然数据没坏,但延迟巨大,用户体验极差,Token 成本剧增。

问题 3:简单的单一工具查询走了长链推理

用户问:"帮我算下 BMI"。

Router 判定为复杂问题,启动 ReAct。Planner 执行了:

  • Thought: 需要身高体重 → get_user_profile
  • Thought: 得到数据了,计算 → calculate_bmi
  • Thought: 现在可以回答了 → final_answer

总共 3 步,但其实整个流程本可以压缩成一次直接工具调用,无需语言模型反复思考。这导致响应时间从 1 秒拉长到 5 秒,且浪费计算。


5. 问题根因分析(Root Cause)

表面看是 prompt 不够好或者模型能力不足,但本质是架构层面的信任边界错误

LLM 本质是概率性的下一个 token 生成器,它没有内建的状态机来保证:

  • 步骤 唯一性(是否已经执行过同一动作)
  • 进展性(每一步是否推动任务更接近目标)
  • 副作用安全(是否应该执行不可逆操作)

在标准 ReAct 论文中,这些可以通过环境给予的 reward 或强大的基础模型隐式解决,但在真实产品中,我无法承受概率性的失败。尤其是写库、发送通知等有副作用的动作,必须由确定性代码把关。

因此,问题不是"LLM 不够聪明",而是架构错误地将流程决策权完全交给了概率模型


6. 最终方案(Final Design)

我重构为 "双层路由 + 带围栏的 ReAct 循环"

架构图

复制代码
User Input
    │
    ▼
┌───────────────┐
│ Rule Router   │  ← 确定性层:关键词/模式匹配
│ (deterministic)│
└───────┬───────┘
        │ 未命中规则
        ▼
┌───────────────┐
│ LLM Router    │  ← 概率层:语义分类 (SEQUENTIAL/PARALLEL/DIRECT)
└───────┬───────┘
        │ 需要多步推理
        ▼
┌──────────────────────────────┐
│  ReAct Planner (受控循环)    │
│  - executed_sigs 去重检查    │ ← 确定性保护
│  - MAX_STEPS=5              │
│  - JSON 容错退出            │
└──────────────────────────────┘
        │
        ▼
  ToolRegistry (含副作用工具隔离)

各层职责

Rule Router(确定性层)

根据预定义模式直接分流:

  • 匹配 "算下BMI" → 直接调用 calculate_bmi 并返回,不启动 ReAct。
  • 匹配 "记录饮食"+ 明确食物 → 可进入确认流程,但不进入自由 ReAct。
    这样保证了高频明确请求的响应速度和安全性。

LLM Router(语义层)

仅当规则无法覆盖时才启用,利用 LLM 理解模糊意图,返回路由决策。但即便路由到 ReAct,其后续步骤依然受保护。

ReAct Planner 内嵌围栏

  • 步骤去重executed_sigs 记录已经执行过的 action:params 签名,若检测到完全相同的调用,立即中止循环并返回"检测到重复操作,请重新组织请求"。
  • 硬性步数限制MAX_STEPS = 5,足够覆盖"查询档案→计算→搜索知识→合成答案"的典型链,同时避免无限徘徊。
  • 输出合规性检查:要求 LLM 输出严格 JSON,解析失败则记录错误并安全退出,不执行任何动作。

为什么这样设计?

  • 确定性层兜底:把最危险和最确定的路径固化,不受模型波动影响。
  • 概率层处理长尾:保持灵活性,但同时被围栏约束,不会失控。
  • 分层解耦:Router 与 Planner 的保护机制独立演进,互不干扰。

7. Trade-off(代价)

新方案显著提升了稳定性和安全,但引入了明显的代价:

维度 代价
维护成本 Rule Router 需要持续更新关键词库,容易出现冲突或遗漏,需要定期分析线上日志来补全规则。
灵活性受限 严格的步数限制和去重机制可能阻断某些真正需要重试的场景(如"刚才网络错误,再查一次"会被误判为重复动作)。
规则与 LLM 冲突 某些模糊表达可能被 Rule Router 强行截胡,导致本应由 LLM 深入理解的需求被简单化处理。
调试复杂度 多层决策导致 trace 变长,定位问题需要同时检查规则命中日志和 LLM 决策日志。

这些代价都是为了换取确定性必须支付的,而且从线上稳定性来看,完全值得。


8. 为什么不用其他方案(架构判断)

  • 为什么不用纯 LLM Router + 无保护 ReAct?

    前面问题已证明:不可控。副作用安全、死循环、成本三方面都无法接受。产品级系统不能建立在"模型应该不会出错"的假设上。

  • 为什么不用纯规则系统?

    FitMind 的核心价值在于理解"今天随便吃了点"这样的自然语言,纯规则无法穷举饮食表达的多样性。语义歧义必须用 LLM 解码。

  • 为什么不用固定 workflow(比如 LangChain 预设链)?

    用户意图无法在编码时预判全部。固定链在处理组合查询时(如同时需要知识检索和用户数据)显得僵化,且会退化成一个巨大的 if-else,最终不可维护。

所以混合路由 + 受控 ReAct 是当前条件下最平衡的方案。


9. 和 AI 系统设计的关系(高价值抽象)

这次重构让我深刻意识到一个普遍法则:

在 AI 原生系统中,LLM 的最佳角色是"策略提议者",而不是"状态控制器"。

任何涉及关键状态转换、事务性写入、安全边界的环节,都必须由确定性代码来最终拍板。这与自动驾驶中的"感知-规划-控制"分层类似:LLM 可以作为"规划层"提供候选动作,但"控制层"必须是确定性的,它根据规则和 safety monitor 来决定是否真的执行。

这也是为什么在 Agent 架构中,我们常会看到Guardrails、沙箱、审批流、human-in-the-loop 等机制------它们的本质都是为了给概率性推理穿上确定性的铠甲。


10. 我的新理解(认知变化)

以前我以为:

Agent 开发的核心是选好模型、写好 prompt、把工具描述清楚,剩下的让 ReAct 循环自己跑就行。

现在我发现:

真正困难的不是让 LLM 生成 Thought/Action,而是如何设计一套不依赖模型自控力的安全网。包括:

  • 哪些路径可以走捷径?
  • 如何防止模型在循环中迷失?
  • 写操作如何与人确认?
  • 失败如何降级而不是硬崩?

Agent 的工程难点,80% 在于"约束 LLM",而不是"释放 LLM"。


11. 如果重新设计

如果今天从头开始,我会做以下几项调整:

  1. 在 Router 层引入置信度评分

    让 LLM Router 输出一个 confidence,低于阈值时主动转向澄清反问,而不是硬着头皮走进 ReAct。

  2. 将步骤去重升级为语义去重

    当前的 executed_sigs 只是字符串匹配,如果模型换了等价参数(如 weight=80 vs weight=80.0)就会绕过。应该用工具定义的幂等键来做更智能的去重。

  3. 提前设计带外审批的写操作

    一开始就把 log_diet 等工具做成二段式:生成记录 → 用户确认 → 真实写入。目前是重构后才加上的,成本更高。


12. 后续优化方向

  • 长期记忆压缩:当对话较长时,Observation 历史堆叠导致 prompt 膨胀,模型更容易忽略早期信息。计划加入记忆摘要模块,定期将旧 trace 压缩成简明的状态描述。
  • 离线路由评估:收集线上 Router 决策和最终用户反馈,定期分析路由错误率,驱动规则库更新。
  • 更细粒度的状态机:将 ReAct 循环变成显式状态机(如:收集信息→推理→确认动作→执行→合成答案),每个状态对应不同的 prompt 和安全规则,进一步降低模型越权风险。

13. 一句话总结

这是"确定性工作流与概率性推理的协同问题"------可靠 Agent 的关键,不是 LLM 有多聪明,而是我为它的不确定性修建了多少条确定性的沟渠。


相关推荐
@蔓蔓喜欢你1 小时前
数据可视化入门:让你的数据说话
人工智能·ai
2401_832298101 小时前
破解智能体幻觉难题,OpenClaw思维链重构,夯实工业级执行可靠性
人工智能
沪漂阿龙1 小时前
面试题详解:检索链路设计全攻略——RAG 检索架构、查询理解、多路召回、混合检索、Rerank、上下文构造与评估闭环
大数据·人工智能·架构
金融小师妹1 小时前
基于AI通胀预期模型与美元流动性监测框架的黄金6周新低行分析:美元五连涨周期下贵金属定价机制重构研究
大数据·人工智能·重构·逻辑回归·线性回归
gaosushexiangji2 小时前
DIC系统推荐:基于千眼狼三维数字图像相关的无人机旋翼疲劳试验全场应变与位移测量
人工智能·算法
智慧医养结合软件开源2 小时前
智慧养老系统医生管理模块:专业赋能,筑牢老人诊疗安全防线
大数据·人工智能·安全·生活
测试修炼手册2 小时前
[自动化测试] Playwright MCP实战:让AI直接操作浏览器做测试
人工智能
一颗牙牙2 小时前
安装mmcv
开发语言·python·深度学习
Mininglamp_27182 小时前
从单体大模型到Agent网络:当AI互联网取代信息互联网,底层架构需要怎么变?
人工智能·ai·ai agent·moa·分布式ai·多agent协作·scaling out