AI大模型实战篇:AI Agent设计模式 - ReAct
段落;小标题根据原文层级合理使用
和,未过度模板化;语言风格生动、有节奏,像资深专家的行业分析报告。
```html
前言

说到AI Agent,ReAct模式是绕不开的起点。在之前的文章里,我们简单梳理过AI Agent的八种设计模式,并且用一张图理清了它们之间的关系——这张图是理解整个Agent家族的钥匙。
从ReAct出发,延伸出两条清晰的发展路线:一条偏重规划能力,包括REWOO、Plan & Execute、LLM Compiler;另一条偏重反思能力,包括Basic Reflection、Reflexion、Self Discover、LATS。接下来,我们会沿着这张图的脉络,结合产品流程和源代码,逐个拆解这八种模式。
为什么要死磕源代码?原因很简单——AI大模型时代,概念和方法都太新了。光靠文档和示意图,产品经理很难真正吃透背后的逻辑。只有把代码跑一遍、把数据流摸清楚,才能知道什么能做、什么不能做,AI的边界到底在哪,以及如何与人类经验配合。下面,咱们就从ReAct开始。
ReAct的概念
ReAct的概念来自论文《ReAct: Synergizing Reasoning and Acting in Language Models》。这篇论文提出了一种新方法:在语言模型中融合推理(reasoning)和行动(acting),来解决多样化的语言推理和决策任务。ReAct最大的亮点是——它提供了一种更易于人类理解、诊断和控制的决策过程。
典型的流程可以用一个有趣的循环来概括:
思考(Thought)→ 行动(Action)→ 观察(Observation)
- :面对一个问题,先深入思考——怎么定义问题?需要什么关键信息?推理步骤是什么?
思考(Thought)
- :思考有了方向,就动手行动——采取相应措施或执行具体任务,推动问题解决。
行动(Action)
- :行动之后,必须仔细观察结果——验证行动是否有效,是否接近答案。
观察(Observation)
- :如果观察结果不理想,就回到思考阶段重新审视。就这么一圈一圈转,直到找到解决方案。
循环迭代
和ReAct相对应的是两种极端模式:Reasoning-Only和Action-Only。Reasoning-Only模式下,大模型会基于任务逐步思考,但不管有没有结果,它都会把每一步推理执行到底——有点像“只管想,不管做”。而Action-Only模式下,大模型完全没规划,先干再说,边干边调,结果往往不可控。可以打个比方:Reasoning-Only像纸上谈兵,Action-Only像无头苍蝇,ReAct则是智勇双全的实干家。
举个例子,假设我们在构建一个智能日程助手:
- :你说“我明天有个会议”,助手分析后告诉你“明天下午3点,公司会议室”——它只分析,不帮你改日程。
Reasoning-Only
- :你说“把我明天的会议改到上午10点”,助手立刻执行修改,然后简单确认“已改到上午10点”——它不思考合不合理,只管动手。
Action-Only
- :你说“我明天有个会议,但我想提前到上午10点”。助手先分析(原来会议几点?),然后执行修改(改时间),最后确认并补充信息“已改好,会议地点不变”——既思考又行动,闭环完成。
ReAct
ReAct的实现过程
下面我们通过实际的源代码,一步步拆解ReAct模式的实现方法。所有代码示例都来自可运行的工程,感兴趣的读者可以直接复现验证。
第一步:准备Prompt模板
实现ReAct的第一步,是设计一个清晰的Prompt模板。这个模板需要包含几个关键元素:
- :展示推理过程,告诉LLM我们要做什么,以及前置条件是什么。
思考(Thought)
- :根据思考结果,生成与外部交互的指令,比如“搜索天气”。
行动(Action)
- :执行行动所需的参数,比如搜索的关键词。这一步可以验证LLM是否能提取准确的参数。
行动参数(Action Input)
- :与外部交互后得到的结果,比如搜索返回的数据。
观察(Observation)
一个典型的Prompt模板长这样:
Answer the following questions as best you can. You ha ve access to the following tools:
{tool_names}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {query}"""
第二步:构建Agent
一个ReAct Agent需要定义以下核心元素:
- :背后使用的大模型
llm
- :后续会用到的工具集合
tools
- :什么情况下停止循环
stop
代码中,我们用类 LLMSingleActionAgent 来封装这些属性:
class LLMSingleActionAgent {
llm: AzureLLM
tools: StructuredTool[]
stop: string[]
private _prompt: string = '{input}'
constructor({ llm, tools = [], stop = [] }: LLMSingleActionAgentParams) {
this.llm = llm
this.tools = tools
if (stop.length > 4) throw new Error('up to 4 stop sequences')
this.stop = stop
}
}
第三步:定义Tools
每个工具最关键的两个参数是 name 和 description。name就是函数名,description则是工具的自然语言描述——LLM根据这个描述来决定是否使用该工具。因此,描述必须非常清晰:说明工具的功能、使用时机以及不适用的情况。
export abstract class StructuredTool {
name: string
description: string
constructor(name: string, description: string) {
this.name = name
this.description = description
}
abstract call(arg: string, config?: Record): Promise
getSchema(): string {
return `${this.declaration} | ${this.name} | ${this.description}`
}
abstract get declaration(): string
}
我们简单提供四个算术工具:加法、减法、除法、乘法。有意思的是,这几个工具函数甚至不需要实际实现代码——大模型靠自身的推理能力就能完成运算。但更复杂的工具(比如搜索、数据库查询)还是得老老实实写代码。
第四步:循环执行
Executor是Agent的运行时,负责协调各个组件并驱动TAO循环。它的核心逻辑很简单:不断重复“规划→执行→观察→记忆”这一过程,直到问题解决或达到最大迭代次数。
class AgentExecutor {
agent: LLMSingleActionAgent
tools: StructuredTool[] = []
maxIterations: number = 15
constructor(agent: LLMSingleActionAgent) {
this.agent = agent
}
addTool(tools: StructuredTool | StructuredTool[]) {
const _tools = Array.isArray(tools) ? tools : [tools]
this.tools.push(..._tools)
}
}
Executor内部的事件循环大致如下:
- 根据之前所有步骤(Thought、Action、Observation)和用户问题,规划下一步Action
- 检查是否已达成目标——如果是ActionFinish,直接返回结果;否则继续执行
- 根据Action调用具体工具,等待返回Observation
- 将当前步骤存入记忆上下文,然后重复
async call(input: promptInputs): Promise {
const toolsByName = Object.fromEntries(
this.tools.map(t => [t.name, t]),
)
const steps: AgentStep[] = []
let iterations = 0
while (this.shouldContinue(iterations)) {
const output = await this.agent.plan(steps, input)
console.log(iterations, output)
// Check if the agent has finished
if ('returnValues' in output) return output
const actions = Array.isArray(output)
? output as AgentAction[]
: [output as AgentAction]
const newSteps = await Promise.all(
actions.map(async (action) => {
const tool = toolsByName[action.tool]
if (!tool) throw new Error(`${action.tool} is not a valid tool, try another one.`)
const observation = await tool.call(action.toolInput)
return { action, observation: observation ?? '' }
}),
)
steps.push(...newSteps)
iterations++
}
return {
returnValues: { output: 'Agent stopped due to max iterations.' },
log: '',
}
}
第五步:实际运行
我们来看看Agent怎么通过ReAct方式解决一个实际问题:
“一种减速机的价格是750元,一家企业需要购买12台。每台减速机运行一小时的电费是0.5元,企业每天运行这些减速机8小时。请计算企业购买及一周运行这些减速机的总花费。”
describe('agent', () => {
const llm = new AzureLLM({
apiKey: Config.apiKey,
model: Config.model,
})
const agent = new LLMSingleActionAgent({ llm })
agent.setPrompt(REACT_PROMPT)
agent.addStop(agent.observationPrefix)
agent.addTool([new AdditionTool(), new SubtractionTool(), new DivisionTool(), new MultiplicationTool()])
const executor = new AgentExecutor(agent)
executor.addTool([new AdditionTool(), new SubtractionTool(), new DivisionTool(), new MultiplicationTool()])
it('test', async () => {
const res = await executor.call({
input: '一种减速机的价格是750元,一家企业需要购买12台。每台减速机运行一小时的电费是0.5元,企业每天运行这些减速机8小时。请计算企业购买及一周运行这些减速机的总花费。'
})
expect(res).toMatchInlineSnapshot(`
{
"log": "Final Answer: The total cost of purchasing and operating the gearboxes for a week is 9336 yuan.",
"returnValues": {
"output": "The total cost of purchasing and operating the gearboxes for a week is 9336 yuan.",
},
}
`)
}, { timeout: 50000 })
})
我们来看看Agent在推理过程中是如何思考和行动的:
Question:一种减速机的价格是750元,一家企业需要购买12台。每台减速机运行一小时的电费是0.5元,企业每天运行这些减速机8小时。请计算企业购买及一周运行这些减速机的总花费
Thought: I need to calculate the total cost of purchasing and operating the gearboxes for a week.
Action: Multiplication Tool
Action Input: [750, 12]
Observation: 9000
Thought: Now I need to calculate the cost of operating the gearboxes for a day.
Action: Multiplication Tool
Action Input: [0.5, 8, 12]
Observation: 48
Thought: Now I need to calculate the cost of operating the gearboxes for a week.
Action: Multiplication Tool
Action Input: [48, 7]
Observation: 336
Thought: Now I need to calculate the total cost of purchasing and operating the gearboxes for a week.
Action: Addition Tool
Action Input: [9000, 336]
Observation: 9336
可以看到,通过Thought→Action→Observation的循环,Agent一步步拆解问题,最终输出了正确答案(9336元)。整个过程清晰、可追溯。
总结
在AI Agent的多种实现模式中,ReAct是最早出现、也是目前应用最广泛的。它的核心思想就是模拟人类“思考→行动→观察”的闭环,让大模型一步步逼近目标。
当然,ReAct并非没有短板:
- :这是大模型的通病——不仅回答内容波动,复杂问题的分析能力也存在不确定性。
输出不稳定
- :由于无法事先预知任务的拆解步数和循环次数,Token消耗可能因复杂任务而激增。
成本不可控
- :LLM本身响应就在秒级,ReAct模式下多轮调用更是雪上加霜。把它做成同步接口几乎不现实,而异步方式又会拖累用户体验,限制了应用场景。
响应时间不可控
但无论如何,ReAct框架提供了一种极其宝贵的思路,让现有应用获得了一次智能化的进化机会。如今,智能客服、知识助手、个性化营销、智能销售助理等领域,都已经出现了成熟的ReAct Agent应用。它或许不完美,但它打开的这扇门,值得认真研究。
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名