告别胡说八道!ReAct框架让大模型“边想边做”,根治AI幻觉难题!!!

170 阅读8分钟

 一、核心定义:什么是ReAct?

ReAct = Reasoning(推理) + Acting(行动)

一个让大模型真正「边想边做」的框架,通过与外部工具交互解决复杂任务。

 二、ReAct工作流程(四步循环)

1. Thought(思考)

  • 模型基于当前目标进行推理
  • 决定下一步该做什么

2. Action(行动)

  • 选择具体操作(调用API、搜索、计算等)
  • 执行决策

3. Observation(观察)

  • 获取外部反馈
  • 包括:搜索结果、API返回值等

4. 重复 循环直到达成目标

💡 本质:模拟人类「思考→行动→验证」的解决问题过程

图片

 三、为什么必须用ReAct?

在 ReAct 之前,主要有两种让 LLM 与外部交互的方式,但它们各有缺陷:

方法问题后果
仅推理 (Chain-of-Thought)依赖过时/错误训练数据「一本正经地胡说八道」
仅行动 (Tool Use)行为缺乏规划盲目低效,逻辑混乱

ReAct 的巧妙之处在于,它将两者融合,取长补短:

🔗 1. 克服模型的局限性
通过行动调用工具,可以获取实时、准确的信息,打破模型的知识时效界限。

🧠 2. 解决幻觉问题
强制模型基于观察到的外部事实进行推理,显著减少
“一本正经地胡说八道”  的情况。

📋 3. 提升可解释性
整个思考链条和行动记录完全可见,便于开发者调试和用户理解,让AI决策过程透明化。

🔄 4. 处理复杂任务
对于  “查天气 → 规划出行路线 → 推荐餐厅”  这类多步骤任务:

  • 单纯推理无法执行动作
  • 单纯行动缺乏规划性ReAct 完美结合两者优势

图片

总结:ReAct 让大模型从“纸上谈兵”进化为“实战高手”,通过推理与行动的循环配合,真正具备了解决现实复杂问题的能力。

四、 实战实现:两种方法详解

方法一:提示工程实现(掌握原理)

🎯 核心提示词设计

在提示中明确要求模型按照Thought / Action / Observation 的格式输出。例如:

ReAct智能理财助手

你是一个专业的理财助手,能够通过思考和行动来帮助用户解答财务和投资相关的问题。

重要说明:每次必须返回完整的Thought+Action对

每轮必须同时包含Thought和Action(或Final Answer)!
Thought用于展示推理过程,Action用于系统执行工具!

ReAct框架说明

你必须严格按照以下格式进行思考和行动:

每轮回复必须是以下两种格式之一:

格式1 - Thought+Action:
Thought: 分析用户的问题,思考需要采取什么行动
Action: 选择并执行一个工具(search_web 或 calculate)

格式2 - Final Answer:
Final Answer: 当收集到足够信息时,给出最终答案

可用工具

  1. search_web(query): 搜索最新的财经信息和市场数据
    - 参数: query (str) - 搜索关键词,如"黄金价格"、"股票行情"等
    - 返回: 相关的市场信息和数据

  2. calculate(expression): 执行数学计算
    - 参数: expression (str) - 数学表达式,如"10000/450"、"(1000*12)*0.05"等
    - 返回: 计算结果

使用规则

  1. 每次必须同时包含Thought和Action(或Final Answer)
  2. Thought展示推理过程,Action用于系统执行
  3. 系统只处理Action和Final Answer,忽略单独的Thought
  4. 如果搜索结果不够明确,可以调整搜索词重新搜索
  5. 计算时要确保表达式正确
  6. 最终答案要清晰、准确、有用

正确交互示例

用户: "10000元能买多少克黄金?"
助手:
Thought: 我需要查询当前黄金的价格,然后用1万元除以单价,计算能购买多少克黄金。
Action: search_web("黄金价格")

系统: Observation: 今日黄金价格约为1159元/克(24K金),投资金条价格约为1080元/克。

助手:
Thought: 现在我看到黄金价格是1159元/克,需要计算10000元能买多少克。
Action: calculate(10000/1159)

系统: Observation: 计算结果:8.63

助手: Final Answer: 按照当前黄金价格约1159元/克,1万元可以购买约8.63克黄金。

现在开始帮助用户解答理财问题。记住:每轮必须同时返回Thought+Action!

由以下几个部分组成:

1. 角色定义

2. 核心规则说明

· 重要强调:"每次必须返回完整的Thought+Action对"

· 明确要求每轮必须同时包含Thought和Action(或Final Answer)

3. 框架规范

· ReAct框架说明

· 两种标准格式定义:

o 格式1:Thought + Action

o 格式2:Final Answer

4. 工具集定义

· search_web(query):网络搜索工具,包含参数说明和返回内容

· calculate(expression):计算工具,包含参数说明和返回内容

5. 使用规则

·.条具体操作规则

· 强调系统处理机制和用户注意事项

6. 少量样本(Few-Shot)

· 提供少量示例:在提示词中给出1-2个完整的 ReAct 任务解决示例,让模型学会这种格式。

· 完整的用户-助手对话示例,展示从问题到最终答案的完整流程,演示工具的正确使用方法

解析模型输出****

程序需要能够解析模型的响应,识别出Action: 后面的内容(例如正则/json),然后调用相应的工具。

    def parse_response(content: str) -> Dict[str, Any]:
"""解析LLM响应内容"""
result = {
"thought": "",
"action": "",
"action_type": ActionType.UNKNOWN,
"action_input": "",
"final_answer": None
}

        # 提取思考过程
thought_pattern = r'Thought:\s*(.*?)(?=\nAction:|\nFinal Answer:|$)'
thought_match = re.search(thought_pattern, content, re.DOTALL | re.IGNORECASE)
if thought_match:
result["thought"] = thought_match.group(1).strip()

        # 提取动作
action_pattern = r'Action:\s*(.*?)(?=\nObservation:|\nThought:|\nFinal Answer:|$)'
action_match = re.search(action_pattern, content, re.DOTALL | re.IGNORECASE)
if action_match:
action_text = action_match.group(1).strip()
result["action"] = action_text

            # 解析动作类型和输入
if '(' in action_text and ')' in action_text:
action_parts = action_text.split('(', 1)
action_name = action_parts[0].strip()
action_input = action_parts[1].rsplit(')', 1)[0].strip('"'')

                result["action_input"] = action_input

                if action_name == "search_web":
result["action_type"] = ActionType.SEARCH
elif action_name == "calculate":
result["action_type"] = ActionType.CALCULATE
elif action_name == "answer":
result["action_type"] = ActionType.ANSWER

        # 提取最终答案
final_answer_pattern = r'Final Answer:\s*(.*?)(?=\nThought:|\nAction:|$)'
final_answer_match = re.search(final_answer_pattern, content, re.DOTALL | re.IGNORECASE)
if final_answer_match:
result["final_answer"] = final_answer_match.group(1).strip()

        return result

将工具返回的结果作为 Observation 输入给模型,开启下一轮循环。****

                if step.action_type != ActionType.UNKNOWN:
observation = self.tool_executor.execute(
step.action_type.value,
step.action_input
)
step.observation = observation
logger.info(f"观察: {observation}")

                    # 更新消息历史
messages.append(AIMessage(content=content))
messages.append(HumanMessage(content=f"Observation: {observation}"))
steps.append(step)

循环终止:****

当模型输出Action: Finish[最终答案] 时,循环结束。

                # 检查是否有最终答案
if step.final_answer:
logger.info(f"=== 最终答案 ===")
logger.info(f"答案: {step.final_answer}")
steps.append(step)
# 退出时,保存对话历史
self._save_conversation_history(question, steps)
return step.final_answer

完整代码地址:

github.com/BaqiF2/ydc_…

********

方法二:Agent框架实现(生产环境)

使用成熟的框架,这会大大简化开发流程。

· LangChain

create_agent 方法本身不使用显式的 ReAct 提示词。它依赖于模型的原生 tool calling 能力。

graph = create_agent(  
model="anthropic:claude-3-7-sonnet-latest",  
tools=[check_weather],  
system_prompt="You are a helpful assistant",  # 这是唯一的提示词  
)

这种方式下, "思考-执行-观察"的循环是通过图结构和工具调用机制隐式实现的,而不是通过提示词中的格式指令

详细查看: 

github.com/BaqiF2/ydc_…

· ~~LangGraph ~~

langchain的1.0版本已经转使用langchain create_agent不再继续跟踪

· AutoGen

autogen没有对ReAct进行封装

只是实现对工具的调用,当依赖模型的思考和调用能力时,和langchain的create_agent也变得类似了

async def main() -> None:
agent = AssistantAgent(
name="assistant",
model_client=tongyi_model_client,
tools=[search_web,calculate],
system_message="You are a helpful assistant.",
max_tool_iterations=10, # 设置最多使用工具次数
)
res = await agent.run(task = "我手上有1万块钱,我能买多少克黄金?")
messages:list[BaseChatMessage] = res.messages
for msg in messages:
print(msg.to_text())
print("="*20)

· AgentScope 

其实现方式就和lanchain1.0很类似,但更多的是通过逻辑代码来完成了整个过程,而langchain是通过图的思维来实现

图片

async def main():
# 注册工具
toolkit = Toolkit()
toolkit.register_tool_function(search_web)
toolkit.register_tool_function(calculate)

    # 创建 ReAct 智能体
agent = ReActAgent(
name="Assistant",
sys_prompt="你是一个助手,可以调用工具完成任务。",
model=DashScopeChatModel(
model_name="qwen3-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
),
memory=InMemoryMemory(),
formatter=DashScopeChatFormatter(),
toolkit=toolkit,
max_iters=10,  # 最多10次推理-行动循环
)

    msg = Msg("user", "我手上有1万块钱,我能买多少克黄金?", "user")

    # 发送需要多次工具调用的任务
await agent(
msg
)

框架对比总结

  • LangChain:图结构思维,隐式循环
  • AutoGen:依赖模型原生能力,配置简单
  • AgentScope:逻辑代码驱动,控制灵活

ReAct是一种让大模型「边想边做」的核心策略,通过:交替进行推理与行动,并结合外部工具反馈,显著提升了模型在复杂任务中的表现。其实现主要依赖于精心设计的提示模板、工具调用机制和迭代执行流程,是当前大模型智能体(Agent)架构中的核心技术之一。

想要深入学习和实践?所有完整资料和代码都已准备好:

GitHub仓库github.com/BaqiF2/ydc_…

从原理理解到实战应用,从基础提示工程到高级框架使用,这个项目为你提供了一站式的ReAct学习路径