AI Agent 核心原理解析:一文看懂 ReAct 规划框架(附手搓代码)

提到 2024 年和 2025 年 AI 领域最火的词,AI Agent(智能体) 绝对榜上有名。我们不再满足于仅仅和 ChatGPT 聊天,而是希望它能变成一个超级助理:帮我们查资料、订机票、跑代码、处理 Excel。

但是,大语言模型(LLM)本质上是一个"缸中之脑",它被困在服务器里,没有手脚,也无法感知当下真实的世界。为了让它成为真正能干活的 Agent,我们需要赋予它一套行动规划框架

今天,我们就来深度扒一扒目前最经典、应用最广泛的 Agent 规划框架------ReAct

一、 为什么我们需要 ReAct?

在 ReAct 出现之前,我们通常是怎么使用大模型的?

  1. Standard Prompting(标准提示) :直接问"北京今天穿什么?"模型根据历史数据瞎猜一个温度回答你。(缺点:容易幻觉,缺乏实时信息
  2. Chain of Thought / CoT(思维链) :在 Prompt 里加一句"请一步步思考"。模型会输出:"因为北京现在是冬天,所以天气应该很冷..."(缺点:虽然逻辑变好了,但依然基于旧知识,无法与外部世界交互
  3. Act-Only(纯行动) :直接让模型输出调用天气的代码。(缺点:缺乏前置思考,一旦报错,模型不知道如何补救

2022 年,普林斯顿大学和 Google 联合提出了一篇神仙论文:《ReAct: Synergizing Reasoning and Acting in Language Models》

作者发现:如果把"推理(Reasoning)"和"行动(Acting)"结合起来,大模型的能力会发生质的飞跃。 就像人类解决问题一样:先想一想,做个动作,看看结果,再接着想。

二、 什么是 ReAct?(核心机制拆解)

ReAct 是 Re asoning(推理)和 Acting(行动)的缩写。

它的核心思想是让大模型在一个死循环里不断执行以下三个步骤,直到任务完成:

  • 🤔 Thought(思考):当前我应该做什么?
  • 🛠️ Action(行动):为了实现这个想法,我需要调用什么工具?(比如:搜索引擎、计算器、本地 API)
  • 👀 Observation(观察):工具执行后返回了什么结果?

💡 举个栗子:查询北京天气并建议穿搭

如果我们用 ReAct 框架来处理 "北京今天天气怎么样?我该穿什么?" 这个任务,大模型的内心戏和外部动作是这样的:

User: 帮我看看北京今天天气如何,推荐一下穿搭。

Thought 1: 用户想知道北京的天气和穿搭建议。我需要先获取北京今天的实时天气。 Action 1: 调用工具 get_weather(location="北京") Observation 1: (系统执行工具后返回) 【北京今天气温:-5℃,大风】

Thought 2: 现在我知道北京很冷,只有-5℃,而且有大风。我可以根据这个信息给出穿搭建议了。 Action 2: 调用工具 Finish(answer="北京今天气温-5℃,有大风。建议穿厚羽绒服,戴好防风帽和围巾。")

看到没有?通过 Thought -> Action -> Observation 的交替循环,模型不再是盲目瞎猜,而是有理有据、步步为营地解决问题。


三、 手搓 ReAct 核心代码(告别调包侠)

很多同学学习 Agent 时直接上手 LangChain,但 create_react_agent 一行代码隐藏了所有细节。为了让大家看透本质,我们不使用任何高级 Agent 库,用最原生的 Python 代码手写一个极简 ReAct 引擎

1. 定义系统 Prompt

我们需要明确告诉大模型它的行为规则,并且告诉它有哪些工具可用。

python 复制代码
system_prompt = """
你是一个聪明的 AI 助手,你可以通过遵循以下格式来解决用户的问题。
你必须严格按照这三个步骤循环:
Thought: 思考你需要做什么
Action: 执行具体的动作,必须是如下格式:函数名(参数)
Observation: 观察动作的结果

你可以使用的工具有:
1. calculate(expression: str): 计算数学表达式,例如 calculate("2 + 2")
2. search_weather(city: str): 查询城市天气,例如 search_weather("北京")

当你得到了最终答案,请使用以下格式结束:
Thought: 我已经知道了最终答案
Action: Finish("你的最终回答")
"""

2. 模拟外部工具(Tools)

准备几个简单的 Python 函数当作外部环境。

python 复制代码
def calculate(expression):
    try:
        return str(eval(expression))
    except Exception as e:
        return f"计算错误: {e}"

def search_weather(city):
    # 这里模拟调用天气 API
    weather_data = {"北京": "晴,-2度", "上海": "小雨,10度", "广州": "阴,20度"}
    return weather_data.get(city, "未知天气信息")

# 工具路由字典
tools_map = {
    "calculate": calculate,
    "search_weather": search_weather
}

3. 实现 ReAct 循环控制引擎

这就是 Agent 的"大脑控制中枢"。它不断调用 LLM 获取思考和动作,拦截动作去执行工具,再把结果喂回给 LLM。

python 复制代码
import openai
import re

# 注意:请替换为你自己的 API 密钥和客户端初始化逻辑
client = openai.Client(api_key="your_api_key")

def react_agent(query):
    # 初始化历史对话记录
    messages =[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": query}
    ]
    
    max_iterations = 5  # 防止死循环的保险丝
    
    for i in range(max_iterations):
        print(f"\n--- 第 {i+1} 轮思考 ---")
        
        # 1. 让 LLM 输出 Thought 和 Action
        response = client.chat.completions.create(
            model="gpt-4", # 或其他模型
            messages=messages,
            stop=["Observation:"] # 核心技巧:一旦 LLM 准备输出 Observation,就立刻停住!
        )
        
        llm_output = response.choices[0].message.content.strip()
        print(llm_output)
        messages.append({"role": "assistant", "content": llm_output})
        
        # 2. 解析 Action(使用正则提取工具名和参数)
        if "Finish" in llm_output:
            final_answer = re.search(r'Finish\("(.*?)"\)', llm_output, re.S)
            print("\n🎉 任务完成:", final_answer.group(1) if final_answer else llm_output)
            break
            
        action_match = re.search(r'Action:\s*(\w+)\((.*?)\)', llm_output)
        if action_match:
            func_name = action_match.group(1)
            arg_str = action_match.group(2).strip('"\'')
            
            # 3. 执行工具,生成 Observation
            print(f"🔧 系统拦截到动作,执行工具:[{func_name}] 参数:[{arg_str}]")
            if func_name in tools_map:
                obs_result = tools_map[func_name](arg_str)
            else:
                obs_result = "错误:找不到该工具"
                
            observation = f"\nObservation: {obs_result}"
            print(observation)
            
            # 4. 把 Observation 加入上下文,进入下一轮
            messages.append({"role": "user", "content": observation})
        else:
            print("解析 Action 失败,要求重试...")
            messages.append({"role": "user", "content": "请严格遵循 Thought 和 Action 格式"})

# 测试我们手搓的 Agent
react_agent("北京的天气怎么样?如果温度加上25度是多少?")

4. 运行过程全解析

当你运行这段代码,你会看到控制台打印出如下类似的神奇过程:

--- 第 1 轮思考 --- Thought: 用户问了两个问题,第一个是北京的天气,我需要先查一下北京天气。 Action: search_weather("北京") 🔧 系统拦截到动作,执行工具:[search_weather] 参数:[北京] Observation: 晴,-2度

--- 第 2 轮思考 --- Thought: 刚才查到了北京气温是-2度。第二个问题是温度加上25度是多少。我需要计算 -2 + 25。 Action: calculate("-2 + 25") 🔧 系统拦截到动作,执行工具:[calculate] 参数:[-2 + 25] Observation: 23

--- 第 3 轮思考 --- Thought: 我已经计算出了结果,可以回答用户了。 Action: Finish("北京今天是晴天,气温-2度。将温度加上25度后的结果是23度。")

🎉 任务完成:北京今天是晴天,气温-2度。将温度加上25度后的结果是23度。

💡 划重点 :注意代码中的 stop=["Observation:"]。这是一个非常关键的 Trick。如果不加这个,LLM 可能会自言自语,连带把伪造的观察结果也一起输出(即幻觉)。通过 Stop 参数,我们在它"准备看结果"的那一刹那打断它,让真实的程序接管工具调用,再把真实的观测塞回去。

四、 ReAct 框架的优缺点

通过手写代码,我们已经完全理解了它的机制。在真实的生产环境中,我们不得不正视它的优缺点:

🌟 优点

  1. 可解释性极强 :每一步都有 Thought 记录,如果 Agent 出错了,开发者可以立刻看出是"想错了"还是"工具用错了",极其方便 Debug。
  2. 容错能力(Self-Correction):如果遇到 API 报错,Observation 会返回错误信息。模型在下一轮 Thought 看到错误后,通常会自动调整策略(比如换一个搜索词)。

⚠️ 局限性

  1. Token 消耗巨大:每一轮都要把之前所有的 Thought、Action、Observation 历史作为 Prompt 传进去。如果任务需要十几个步骤,上下文会迅速膨胀,既贵又慢。
  2. 陷入死循环:对于弱智一点的模型(或者小参数模型),可能会出现反复调用同一个工具,或者在 Action 和 Observation 之间来回震荡"死机"的情况。
  3. 缺乏宏观规划 :ReAct 偏向于"走一步看一步"。对于需要拆解为几十个子任务的超级复杂目标,它容易"迷失方向"。(这也催生了后来的 Plan-and-Solve 等更高级的框架)。

五、 总结

ReAct 本质上并不是什么高深晦涩的算法底层,而是一种巧妙的 Prompt 提示工程结构 + 程序循环控制。它巧妙地利用了 LLM 强大的文本推理能力,将其与外部真实世界搭起了一座桥梁。

了解了最原始的 ReAct 循环,以后你再去阅读 LangChain、AutoGPT 或是 LlamaIndex 的源码时,就会有一种"拨云见日"的感觉:它们底层无非是在包装这个循环,处理更复杂的工具输入输出解析而已。

关于 AI Agent 的探索才刚刚开始。 从 ReAct 出发,未来我们还有 Multi-Agent(多智能体协同)、Plan-and-Execute 等等更有趣的架构。


如果这篇文章让你对 AI Agent 有了更清晰的认识,欢迎点赞、收藏并在评论区交流探讨! 你在开发 Agent 时遇到过哪些坑?欢迎在评论区分享~ 👇

相关推荐
神奇小汤圆2 小时前
高并发写入场景:MySQL 事务隔离级别与行锁策略设计
后端
武子康2 小时前
大数据-243 离线数仓 - 实战电商核心交易增量导入(DataX - HDFS - Hive 分区
大数据·后端·apache hive
得物技术2 小时前
搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术
c++·后端·测试
工边页字2 小时前
AI 开发必懂:Context Window(上下文窗口)到底是什么?
前端·人工智能·后端
任聪聪2 小时前
OpenClaw详细windows系统本地部署安装教程
后端
我叫黑大帅2 小时前
golang的fs除了定权限还能干什么?
后端
白衣鸽子2 小时前
Java 多线程进阶-01:ThreadLocal
后端
白衣鸽子2 小时前
Java 线程同步-06:volatile 内存屏障
后端
小码哥_常2 小时前
Spring Boot隐式参数注入:代码优雅升级指南
后端