首页 > 教程攻略 > ai资讯 >AI大模型实战篇:AI Agent设计模式 - ReAct

AI大模型实战篇:AI Agent设计模式 - ReAct

来源:互联网 时间:2026-08-25 14:23:45

段落;小标题根据原文层级合理使用

,未过度模板化;语言风格生动、有节奏,像资深专家的行业分析报告。 ```html

前言

AI大模型实战篇:AI Agent设计模式 - ReAct

说到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)

,简称TAO循环。

  • 思考(Thought)

    :面对一个问题,先深入思考——怎么定义问题?需要什么关键信息?推理步骤是什么?
  • 行动(Action)

    :思考有了方向,就动手行动——采取相应措施或执行具体任务,推动问题解决。
  • 观察(Observation)

    :行动之后,必须仔细观察结果——验证行动是否有效,是否接近答案。
  • 循环迭代

    :如果观察结果不理想,就回到思考阶段重新审视。就这么一圈一圈转,直到找到解决方案。

和ReAct相对应的是两种极端模式:Reasoning-Only和Action-Only。Reasoning-Only模式下,大模型会基于任务逐步思考,但不管有没有结果,它都会把每一步推理执行到底——有点像“只管想,不管做”。而Action-Only模式下,大模型完全没规划,先干再说,边干边调,结果往往不可控。可以打个比方:Reasoning-Only像纸上谈兵,Action-Only像无头苍蝇,ReAct则是智勇双全的实干家。

举个例子,假设我们在构建一个智能日程助手:

  • Reasoning-Only

    :你说“我明天有个会议”,助手分析后告诉你“明天下午3点,公司会议室”——它只分析,不帮你改日程。
  • Action-Only

    :你说“把我明天的会议改到上午10点”,助手立刻执行修改,然后简单确认“已改到上午10点”——它不思考合不合理,只管动手。
  • ReAct

    :你说“我明天有个会议,但我想提前到上午10点”。助手先分析(原来会议几点?),然后执行修改(改时间),最后确认并补充信息“已改好,会议地点不变”——既思考又行动,闭环完成。

ReAct的实现过程

下面我们通过实际的源代码,一步步拆解ReAct模式的实现方法。所有代码示例都来自可运行的工程,感兴趣的读者可以直接复现验证。

第一步:准备Prompt模板

实现ReAct的第一步,是设计一个清晰的Prompt模板。这个模板需要包含几个关键元素:

  • 思考(Thought)

    :展示推理过程,告诉LLM我们要做什么,以及前置条件是什么。
  • 行动(Action)

    :根据思考结果,生成与外部交互的指令,比如“搜索天气”。
  • 行动参数(Action Input)

    :执行行动所需的参数,比如搜索的关键词。这一步可以验证LLM是否能提取准确的参数。
  • 观察(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

每个工具最关键的两个参数是 namedescription。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应用。它或许不完美,但它打开的这扇门,值得认真研究。