从零实现多步规划agent,包含self-critic反思、五选一动作、max_steps防循环、503优雅降级。用Llama 3.1 8B真实测试。
Agent 最可怕的故障模式,不是某一步出错,而是陷入无限循环,或者在工具不可用时编造答案。我的「Agentic AI from Zero」系列项目 3,是一个 ReAct 规划 Agent,设计目标就是确保这两种情况都不会发生:它在循环中进行推理和行动,但绝不会无限循环;它会批判性地检查自己的进展;遇到困境时,它会如实降级,而不是伪装任务已成功完成。整个项目纯手工实现,没有使用任何框架。我使用 NVIDIA NIM(meta/llama-3.1-8b-instruct,temperature 0)进行了真实测试,记录下来的运行过程既展示了成功解决问题,也展示了面对真实模型输出时如何诚实降级。
每次迭代时,模型都会输出严格的 JSON {thought, action, action_input}。随后,工具执行并返回 observation,再通过一次独立的自我批判调用进行反思——包括 on_track?、批评意见和下一步提示——然后将反思结果写入 transcript,供下一次 thought 读取。
模型每一步可以从五种 action 中选择一种:三个工具(calculator、knowledge_lookup、web_search)、final 或 give_up。max_steps 上限默认为 6,这意味着这个 for 循环永远不可能失控。
任务是:虚构公司 Zephyr Labs 在发射卫星上花费了多少钱?要回答这个问题,需要执行两次知识查询,再进行一次乘法计算。这是一个真正的多步骤计划,模型必须自行安排执行顺序:
step 1 knowledge_lookup satellites_launched -> 47
step 2 knowledge_lookup cost_per_satellite_musd -> 12
step 3 calculator 47 * 12 -> 564
step 4 knowledge_lookup cost_per_satellite_musd_unit -> [ERROR] no such key
reflect: on_track=False — spurious unit lookup, recover
step 5 final -> 564 million USD SOLVED ✓ (4/6 steps, 11.84s)
第 4 步最值得关注。这个小模型开始怀疑原本正确的结果,偏离方向,尝试查询一个并不存在的 "unit" key。工具返回了错误,自我批判模块将其标记为 on_track=False,下一步则成功恢复,并给出了正确的最终答案。
这正体现了自我批判模块存在的价值:错误转向会被及时发现并纠正,而不是让整次运行偏离轨道。
第二个任务需要一个只有 web_search 才能提供的实时数据——当前市场份额。我让搜索后端进入模拟故障状态,因此每次调用都会抛出 SearchBackendError(模拟 HTTP 503)。正是这条执行路径,区分了演示项目和真正可用的 Agent:
step 1 web_search ... -> [ERROR] 503 (simulated outage)
step 2 knowledge_lookup ... -> [ERROR] no such key (critic: switch tools)
step 3 web_search ... -> [ERROR] 503
step 4 web_search ... -> [ERROR] 503
step 5 give_up -> DEGRADED ⚠ "Unable to find … due to repeated search outages"
每次工具故障都会作为 ERROR observation 返回,循环始终没有崩溃。自我批判模块持续将状态标记为 on_track=False,并推动 Agent 改变处理方式——它先从 web_search 切换到 knowledge_lookup,之后又切换了回来。
由于确实没有任何办法获得这个数据,Agent 最终诚实地返回了部分答案并说明原因,而不是编造一个市场份额数字。与此同时,max_steps 上限作为最后一道硬性保障,就守在 give_up 后面。
循环——观察 → 思考 → 行动 → 反思;每次 observation 之后都会进行一次反思。
最大迭代次数——设置硬性的步骤上限,因此它永远不会无限运行;如果达到上限,则返回当前能够得到的最佳答案。
自我批判——通过一次独立的 LLM 调用评估每个步骤;它发现了 Demo A 中的错误转向,也重新引导了 Demo B 中的工具选择。
优雅降级——工具会将异常转换为 ERROR observation,避免程序崩溃;give_up 会返回部分答案和原因,绝不会用幻觉伪装成功。
这四道护栏存在的意义在于,底层的推理器并不稳定——这是一个会怀疑正确工具结果的 8B 模型——但这些护栏仍然能限制它的行为,让它保持诚实。
能解决时就解决,不能解决时就诚实降级,并且永远不要弄虚作假。你可以阅读完整的运行记录,并亲自运行:
https://dev48v.infy.uk/agentic/project3-react-planning.html
https://github.com/dev48v/agentic-ai-from-zero
如果还需要采取进一步措施,可以考虑屏蔽此人和/或举报滥用行为。