当前位置:首页 > AI编程类

AI Agent 是怎么边想边做的?ReAct 推理-行动循环原理拆解

1周前 (10-05)AI编程类19

会聊天的模型很多,能自己动手办成一件件的"Agent"却难得多。让模型去查个数据、调个接口、再拿结果做判断,光靠"一次性的问答"不够,它得在"想"和"做"之间来回掰。这个来回掰的办法里,被反复提起、也相当经典的一套,叫 ReAct——Reasoning + Acting 的合称。

这篇不空谈概念,直接看一个具体任务是怎么被 ReAct 一步步跑完的,再从这条轨迹里,把它的设计和坑拆出来。

纯想不动,和只做不想,各有各的窟窿

react-cover.jpg

ReAct 解决的是两种"单脚走路"的毛病。

一种是纯靠想,也就是让模型一路推理(类似思维链),不碰任何工具。它的问题在于"想"会脱离现实——模型内部没有的外部信息,它只能编。比如问它"今天上海下没下雨",它闭门造车,报出来的是幻觉。

另一种是纯靠做,模型一上来就调工具,但缺乏整体计划。它可能东一榔头西一棒子,工具是调了一堆,却没串成一条能指向答案的路,甚至因为缺少反思,在同一条错路上反复打转。

ReAct 的做法,是让"想"和"做"交替插队:想一步,就去外部干一步,把干回来的结果接进思考,再决定下一步。思考能纠正方向,行动能给思考喂真实的料。两者互相补,幻觉和瞎忙活就都被压下去一截。

一个具体任务,看 ReAct 怎么一步步走

假设让一个 Agent 回答:"现在上海适不适合户外跑步?"没有直接答案,模型得自己去查。ReAct 会把整个过程展开成"思考—行动—观察"三个动作交替的轨迹,大致长这样:

Thought 1:要判断适不适合跑步,先得知道上海现在的天气和降雨概率。
Action 1:调用 search_weather(city="上海")
Observation 1:晴,20℃,湿度 65%

Thought 2:20℃晴天,温度合适,湿度偏高但不至于难受。还想确认会不会下雨。
Action 2:调用 search_rain_probability(city="上海")
Observation 2:降雨概率 5%

Thought 3:温度、湿度、降雨概率都合适,可以给出结论了。
Final Answer:适合户外跑步,20℃晴天,降雨概率只有 5%,可以放心去。

注意这条轨迹里的节奏:没有一步是"埋头想完一整段",也没有一步是"不问缘由地乱调工具"。每一步思考都引出一次有针对性的行动,每一次观察又成为下一步思考的输入。

其中三个角色的分工很清楚。Thought 是模型内部的推理文字,决定"现在该做什么、为什么";Action 是一次真实的外部调用,落成工具名和参数;Observation 是工具返回的结果,被原样接回上下文。末了以 Final Answer 收口,整轮任务结束。

它和 Function Calling,不是一回事

很多人会把这俩搅在一起。Function Calling(函数调用)是"动作"那一步的协议——它规定了工具怎么描述、参数怎么给、返回怎么认。而 ReAct 是更高一层的编排循环,管的是"什么时候该想、什么时候该调工具、调完怎么接着走"。

可以这么看:一次 ReAct 循环里,每个 Action 落地时,靠的就是 Function Calling 这套约定去真正把工具调起来。Function Calling 解决"怎么调",ReAct 解决"按什么节奏调"。两者是配合关系,不是一个替换另一个。

拆开看:循环能转起来,靠三个工程细节

ReAct 这套循环看着简单,真要在代码里跑稳,有几个地方得焊死。

一是上下文要累积。每一轮 Thought、Action、Observation 都要按顺序追加进对话上下文,模型才能"记住"前面查到了什么。断了一环,后面的思考就成了无源之水。

二是要设停止条件。循环不能一直转,得有个明确的出口——要么模型给出 Final Answer 就停,要么设一个轮数上限,到了上限还没收口就强制终止,把中间结果整理后返回。没有上限的 Agent,碰上死结会无限打转,token 烧起来没底。

三是工具要白名单化。模型给出的 Action,只是"想调什么工具、给什么参数",真正执行前要过一道校验:工具名在不在允许清单里、参数类型符不符合定义。这一层拦不住,模型的幻觉会变成真刀真枪的副作用——比如它"想"删个文件,代码就真去删了。

ReAct 好在哪里,又栽在哪里

它的好处落在两点:可解释,好排错。整个轨迹摊开,每一步为什么这么做、拿到了什么结果,一目了然,出问题能直接定位到某一轮。

代价也有。一是慢,一个任务拆成好几轮来回,token 和延迟都往上翻;二是依赖工具够不够用,工具清单里没有的能力,模型再会想也办不成;三是循环本身可能发散,模型偶尔在几轮之间来回横跳、重复同样动作,得靠停止条件和一些稳定性手段去兜。

小结

把 ReAct 收一下:它解决的是"只推理会幻觉、只行动会瞎忙"这两个老问题,办法是让 Thought、Action、Observation 交替滚动,把外部真实信息接进思考,把思考拆成可执行的动作;循环能落在工程里,靠的是上下文累积、停止条件、工具白名单三道保险;它和 Function Calling 是"编排循环 vs 调用协议"的配合关系,不是一个东西。

理解了这条轨迹,再看市面上的各种智能体,基本都是在 ReAct 这套骨架上的扩展——有的加了规划、有的加了记忆、有的多个智能体分工。内核那根"想—做—看—再想"的轴,没有变。

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。