这道题其实问的是,怎么让大模型不光会想,还能动手。[[ReAct]]这个框架的核心,就是把推理和行动串成一个循环,模型每想一步就调用一次工具,拿到反馈再接着想,直到把问题解决。它不是先生成一个完整的计划再去执行,而是一边干一边调整,有点像人做复杂任务的时候,走一步看一步。
具体说一下几个关键模块。首先是Plan,很多人以为Plan就是一开始定好的步骤,其实不是。ReAct里的Plan是动态的,每一步的Thought都在根据最新的Observation重新评估,说白了就是推理链本身就成了计划。举个例子,你要查一个产品的价格,第一步可能先搜产品名,看到结果发现有两个型号,第二步就得搜具体型号,这个分支就是动态生成的。
然后是提示词设计。这里有个硬约束:必须让模型按固定格式输出。我一般会用类似这样的模板:Thought: 推理过程; Action: 工具名; Action Input: 参数。然后系统拿到这个Action去调用工具,把结果填回Observation字段。模型看到Observation才能继续下一轮。这个格式一旦乱了,整个循环就断了,所以提示词里要反复强调格式。
Observation是什么呢?就是工具返回的结果,可以是文本、结构化数据,甚至API报错。它直接作为下一轮推理的输入。这里有个常见坑:如果工具返回的信息不完整或者有噪声,模型可能被带偏。所以Observation的质量直接决定了[[Agent]]的效果,上线前我会花大量时间打磨工具的输出格式和异常处理。
我拿一个具体的业务场景举例吧,比如客服系统里,用户问“我买的手机订单为什么还没发货”。ReAct的流程大概是:第一轮,模型想“先查订单信息”,调用订单查询工具,输入订单号,拿到订单状态。第二轮,看到状态是“已发货但物流未更新”,又想“查物流详情”,调用物流查询工具,拿到快递单号和最新物流记录。第三轮,看到物流显示“运输中”,但用户催得急,模型可能会再调一个客服备注工具,记录用户诉求。最后综合所有信息给出回答:“您的订单已发货,目前运输中,预计明天到达,我已备注加急。”整个过程就是Thought、Action、Observation循环,直到能给出Final Answer。
不过ReAct有个明显短板:如果模型在Thought里推理错了,比如误解了Observation,后面的步骤就会越走越偏。所以我在实际落地时,会考虑结合[[Self-Refine]]或者[[Reflexion]]机制,让模型自己检查自己的输出,发现错误就回溯重来,而不是一条路走到黑。
总结一下我的看法。ReAct框架特别适合那种需要多步工具调用的场景,比如客服、信息检索、数据分析。但前提是工具本身要稳定,返回结果要结构化,而且必须对模型的输出做严格的格式解析和校验,否则很容易被格式错误打断。我更倾向于把它看成一种模式,而不是一个固定的框架,实际项目中经常和Agent的其他设计混用,比如加上记忆模块或者多Agent协作。