引言

ReAct(Reasoning and Acting)是一种让大语言模型交替进行推理和行动的提示框架。与纯推理型CoT不同,ReAct在推理过程中引入外部工具调用,使模型能够获取实时信息、执行计算和与环境交互。这一框架是现代AI Agent的核心范式之一。本文深入ReAct的原理、模板设计和工程实践。

ReAct的核心思想

推理与行动的交替

ReAct的核心思想是:模型在解决复杂问题时,不应仅依赖内部知识进行推理(可能产生幻觉),也不应盲目调用工具而不思考(可能浪费资源或产生错误操作)。正确的做法是在推理和行动之间交替:

  1. Thought:基于当前已知信息进行推理,决定下一步行动
  2. Action:执行推理得出的行动(如搜索、计算、查询)
  3. Observation:获取行动结果作为新的已知信息
  4. 循环以上步骤直到得出最终答案

与纯CoT的区别

纯CoT的所有推理都在模型内部完成,无法获取外部信息。当问题需要实时数据或精确计算时,纯CoT容易产生事实性错误。ReAct通过工具调用弥补了这一缺陷。

与纯工具调用的区别

纯工具调用模式下,模型直接根据用户请求选择工具并执行,缺乏显式推理过程。这在简单任务中可行,但在需要多步规划和条件判断的复杂任务中容易出错。ReAct的推理步骤提供了决策透明性和可调试性。

ReAct模板设计

基础模板

你是一个能够使用工具解决任务的AI助手。请按照以下格式回答问题:

问题:[用户问题]

Thought:[分析当前情况,推理下一步行动]
Action:[工具名称]
Action Input:[工具输入参数]
Observation:[工具返回结果]

...(重复Thought/Action/Observation直到得出答案)

Thought:[最终推理]
Final Answer:[最终答案]

# 可用工具
1. search(query: string): 搜索网络信息
2. calculator(expression: string): 数学计算
3. lookup(keyword: string): 在当前文档中查找信息

# 规则
- 每次只执行一个Action
- 必须在Action之前给出Thought
- 当有足够信息时给出Final Answer
- 如果工具返回错误,分析原因并调整策略

工具描述规范

工具描述的质量直接影响ReAct的效果。一个好的工具描述应包含:

工具名:search_web
描述:搜索互联网获取实时信息。适用于需要最新数据、事实查询、新闻检索的场景。
参数:
  - query (string, 必填): 搜索关键词,建议使用简洁明确的查询词
返回:搜索结果摘要列表,每条包含标题、摘要和URL
限制:每次搜索最多返回5条结果
示例:
  Action: search_web
  Action Input: {"query": "2024年诺贝尔物理学奖获得者"}

复杂推理模板

对于需要深度推理的任务,增强Thought部分的结构:

Thought:
1. 当前目标:[当前需要解决的子问题]
2. 已知信息:[列出所有已知事实]
3. 信息缺口:[还缺少什么信息]
4. 行动计划:[基于以上分析,下一步应该做什么]
5. 预期结果:[执行行动后预期能获得什么信息]

工程实践

工具调用解析

ReAct框架需要从模型输出中解析Action和Action Input:

import re
import json

def parse_react_response(response: str):
    """解析ReAct格式的响应"""
    # 提取Thought
    thought_match = re.search(r'Thought:\s*(.*?)(?=\nAction:|\nFinal Answer:)', 
                               response, re.DOTALL)
    
    # 提取Action
    action_match = re.search(r'Action:\s*(\w+)', response)
    
    # 提取Action Input
    input_match = re.search(r'Action Input:\s*(.*?)(?=\nObservation:|\Z)', 
                             response, re.DOTALL)
    
    # 提取Final Answer
    final_match = re.search(r'Final Answer:\s*(.*)', response, re.DOTALL)
    
    if final_match:
        return {"type": "final", "answer": final_match.group(1).strip()}
    else:
        return {
            "type": "action",
            "thought": thought_match.group(1).strip() if thought_match else "",
            "action": action_match.group(1) if action_match else "",
            "action_input": input_match.group(1).strip() if input_match else ""
        }

错误处理与恢复

工具调用可能失败,需要完善的错误处理机制:

def react_loop(model, prompt, tools, max_steps=10):
    """ReAct主循环"""
    messages = [{"role": "user", "content": prompt}]
    
    for step in range(max_steps):
        response = model.generate(messages)
        parsed = parse_react_response(response)
        
        if parsed["type"] == "final":
            return parsed["answer"]
        
        # 执行工具调用
        try:
            tool = tools.get(parsed["action"])
            if tool is None:
                observation = f"错误:未知工具 '{parsed['action']}'。可用工具:{list(tools.keys())}"
            else:
                observation = tool(parsed["action_input"])
        except Exception as e:
            observation = f"工具执行错误:{str(e)}。请检查输入参数或换一种方法。"
        
        # 将结果追加到对话中
        messages.append({"role": "assistant", "content": response})
        messages.append({"role": "user", "content": f"Observation: {observation}"})
    
    return "达到最大推理步数,未能得出答案。"

步数控制

ReAct循环可能无限运行,必须设置步数上限。建议策略:

  • 默认最大步数:10步
  • 简单任务:5步
  • 复杂研究任务:20步
  • 接近上限时提醒模型总结当前发现并给出答案

上下文管理

长ReAct对话可能超出上下文窗口。管理策略:

  • 压缩历史:将早期的Thought/Observation对压缩为摘要
  • 只保留最近N轮:删除最早的Thought/Observation,只保留最近几轮
  • 关键信息提取:从Observation中提取关键事实,丢弃原始返回

高级技巧

工具选择指导

当可用工具较多时,模型可能选择不当。在Prompt中添加工具选择指导:

# 工具选择规则
- 需要最新信息时,优先使用search_web
- 需要精确计算时,使用calculator,不要自己算
- 需要查找特定文档内容时,使用lookup
- 如果不确定需要什么信息,先用search_web获取概况
- 同一个工具连续调用不超过3次,如果3次仍无结果,换一种方法

并行行动

对于可以并行执行的任务,允许模型一次提出多个行动:

Thought:我需要同时查询A和B的信息
Action:search_web, calculator
Action Input:{"query": "A的信息"}, {"expression": "B的计算"}
Observation:[搜索结果], [计算结果]

反思机制

在ReAct循环中引入反思步骤:

Thought:[推理]
Action:[行动]
Observation:[结果]

Reflection:这个结果是否符合预期?如果不是,可能的原因是什么?我应该如何调整策略?

Thought:[基于反思的调整后推理]

常见问题

模型不遵循格式

部分模型可能不严格遵循Thought/Action/Observation格式。解决方案:使用更强的模型、在Prompt中提供更多示例、使用结构化输出(如function calling)替代文本解析。

工具调用参数错误

模型可能生成格式错误的工具参数。解决方案:参数Schema验证、参数自动修正、在工具描述中提供清晰的参数示例。

推理循环

模型可能陷入"思考但不行动"的循环。解决方案:限制连续Thought的次数、检测重复推理模式并强制触发行动。

结语

ReAct框架通过交替推理和行动,使大语言模型能够利用外部工具解决复杂问题,是构建AI Agent的核心范式。掌握ReAct的关键在于:精心设计工具描述、稳健的输出解析、完善的错误处理和合理的步数控制。随着Agent能力的增强,ReAct框架也在不断演进,但其"先思考再行动"的核心思想始终不变。

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。