Langchain实现ReAct Agent多变量工具调用

🤔 一、大模型的"幻觉困境":为什么需要 ReAct?

大语言模型(LLM)虽强,却有致命短板:

  • 知识过时:训练数据截止于 2024 年,无法回答"今天上海天气如何?"
  • 计算无能 :让它算 12345 × 6789,可能给出错误结果
  • 幻觉泛滥:编造不存在的论文、API、历史事件

传统方案是:RAG(检索增强生成) ------先查知识库,再生成答案。

但 RAG 仍有局限:它只能"读",不能"做"

试想:用户问 "帮我订一张明天从北京到上海的 cheapest 机票"

------这需要:搜索航班 → 比价 → 登录 → 支付。纯检索无法完成

ReAct 的突破在于:让模型不仅能"想",还能"动手"调用工具(Tools),并在行动后根据反馈调整策略------形成闭环推理。


🔑 二、ReAct 是什么?一个词概括:推理(Reasoning) + 行动(Acting)

ReAct 的名字即其核心:Re asoning + Acting。

它要求模型按固定格式输出步骤,例如:

复制代码
Question: 上海明天天气如何?

Thought: 我需要查询上海明天的天气。应调用天气工具。
Action: get_weather
Action Input: {"city": "上海", "date": "tomorrow"}
Observation: {"temperature": "22°C", "condition": "多云"}

Thought: 已获取天气信息,可以回答用户。
Final Answer: 上海明天多云,22°C。

✅ 四步循环,模拟人类决策:

步骤 作用 类比人类行为
Thought 内部推理:分析问题、规划下一步 "我得先查天气......"
Action 选择工具:决定调用哪个外部能力 "打开天气 App"
Action Input 参数绑定:提供工具所需输入 "输入城市:上海"
Observation 获取反馈:接收工具返回结果 "看到:多云,22°C"

💡 关键创新 :将"黑箱生成"拆解为可干预、可验证、可纠错的显式步骤。


⚙️ 三、技术实现:LangChain + Ollama 构建 ReAct Agent,并实现多参数工具调用

笔者本机Ollama list 结果如下:

Langchain依赖库相关版本:

下面用 Qwen + Ollama + LangChain 实现一个完整 ReAct Agent:

python 复制代码
from langchain.tools import tool
from langchain_ollama import ChatOllama
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import PromptTemplate
import json

@tool
def get_weather(arg_str: str) -> str:
    """
    查询城市天气(模拟)
    Args:
        city: 城市名,如 "北京"
        date: 日期,支持 "today"(默认)、"tomorrow"
    """

    # 将arg_str解析成json对象
    args = json.loads(arg_str)
    city = args.get("city",  "北京")
    date = args.get("date", "today")

    data = {
        ("北京", "today"): "晴,25°C",
        ("北京", "tomorrow"): "多云,22°C",
        ("上海", "today"): "小雨,28°C",
        ("上海", "tomorrow"): "阴,26°C",
    }
    return f"{city}{date}天气:{data.get((city, date), '暂无数据')}"

@tool
def search_web(arg_str: str) -> str:
    """
    搜索网络信息(模拟)
    Args:
        query: 搜索关键词
        region: 区域代码,如 "CN"(中国)、"US"
    """

    # 将arg_str解析成json对象
    args = json.loads(arg_str)
    query = args.get("query", "")
    region = args.get("region", "CN")

    return f"在{region}搜索'{query}':第一条结果是 '{query} 的简介...'"

# 工具列表(供 LangChain 使用)
TOOLS = [get_weather, search_web]

# 1. 自定义 ReAct Prompt(中文优化版)
REACT_PROMPT = PromptTemplate.from_template(
"""你是一个智能助手,可以使用以下工具解决问题:

{tools}

使用以下格式进行推理:
Thought: 你应始终思考该做什么
Action: 要使用的工具名称,必须是 [{tool_names}] 之一
Action Input: 工具的输入,必须是**严格 JSON 格式**,如 {{"city": "北京", "date": "today"}}
Observation: 工具返回的结果

...(可重复多次)

Final Answer: 最终答案

当前问题:{input}

{agent_scratchpad} 
"""
)

# 2. 配置模型(本地 Ollama)
llm = ChatOllama(
    model="llama3:latest",  # 可换为 "llama3:8b-instruct"
    temperature=0.3,
    num_ctx=4096,
)

# 3. 创建 Agent
agent = create_react_agent(
    llm=llm,
    tools=TOOLS,
    prompt=REACT_PROMPT,
)

agent_executor = AgentExecutor(
    agent=agent,
    tools=TOOLS,
    verbose=True,
    handle_parsing_errors=True,  # 自动处理 JSON 解析错误
    max_iterations=5,
)

# 4. 运行测试
if __name__ == "__main__":
    questions = [
        "上海明天天气如何?",
        "用中文搜索'量子计算'在中国的结果",
        "纽约今天天气?如果查不到,就搜一下纽约的旅游景点"
    ]

    for q in questions:
        print(f"\n{'='*50}")
        print(f"❓ {q}")
        try:
            result = agent_executor.invoke({"input": q})
            print(f"✅ Answer: {result['output']}\n")
        except Exception as e:
            print(f"❌ Error: {e}")

输出结果

text 复制代码
==================================================
❓ 上海明天天气如何?


> Entering new AgentExecutor chain...
Thought: I should use the `get_weather` tool to query the weather in Shanghai.

Action: get_weather
Action Input: {"city": "上海", "date": "tomorrow"}上海tomorrow天气:阴,26°CThought: Since we already got the weather forecast for tomorrow, there's no need to search further.

Action: None (no action needed)

Final Answer: The weather in Shanghai tomorrow will be cloudy with a temperature of 26°C.

> Finished chain.
✅ Answer: The weather in Shanghai tomorrow will be cloudy with a temperature of 26°C.


==================================================
❓ 用中文搜索'量子计算'在中国的结果


> Entering new AgentExecutor chain...
Thought: 我应该使用 search_web 工具来搜索网络信息。

Action: search_web

Action Input: {"query": "量子计算", "region": "CN"}
在CN搜索'量子计算':第一条结果是 '量子计算 的简介...'Thought: 我需要获取更多关于"量子计算"的信息。

Action: search_web

Action Input: {"query": "量子计算", "region": "CN"}
在CN搜索'量子计算':第一条结果是 '量子计算 的简介...'Thought: 我需要获取关于"量子计算"的天气信息。

Action: get_weather

Action Input: {"city": "北京", "date": "today"}
北京today天气:晴,25°CThought: 我已经获取了关于"量子计算"的基本信息和天气信息,现在我需要将这两个结果结合起来。

Action: None (no additional action needed)

Final Answer: 在CN搜索'量子计算':第一条结果是 '量子计算 的简介...',北京today天气:晴,25°C

> Finished chain.
✅ Answer: 在CN搜索'量子计算':第一条结果是 '量子计算 的简介...',北京today天气:晴,25°C


==================================================
❓ 纽约今天天气?如果查不到,就搜一下纽约的旅游景点


> Entering new AgentExecutor chain...
Thought: I should try to get the weather for New York today.

Action: get_weather

Action Input: {"city": "纽约", "date": "today"}
纽约today天气:暂无数据Thought: Since we couldn't get the weather information, let's try searching for tourist attractions in New York.

Action: search_web

Action Input: {"query": "纽约旅游景点", "region": "US"}
在US搜索'纽约旅游景点':第一条结果是 '纽约旅游景点 的简介...'Thought: Now that we have the tourist attractions in New York, let's try to get the weather information again.

Action: get_weather

Action Input: {"city": "纽约", "date": "today"}
纽约today天气:暂无数据A thinking AI! 🤔 Let's go through this thought process step by step:

1. Thought: I should try to get the weather for New York today.
Action: get_weather
Action Input: {"city": "纽约", "date": "today"}纽约today天气:暂无数据It seems like we're stuck! 😊 We couldn't get the weather information for New York today, so let's try something else.

Since we searched for tourist attractions in New York and got some results, maybe we can use that to our advantage. Let's think about how we can relate this information to getting the weather...

Wait a minute! 🤔 What if we search for "New York weather" or something similar? That might give us some relevant information!

Thought: I should try searching for New York weather.

Action: search_web

Action Input: {"query": "纽约天气", "region": "US"}

Let's see what happens! 🤔❌ Error: Extra data: line 3 column 1 (char 35)

进程已结束,退出代码为 0

🔔 注意 :Prompt 中的 {agent_scratchpad} 是关键------它让 LangChain 自动注入历史步骤,避免 ValueError: missing agent_scratchpad


🌟 四、ReAct 的三大优势(为什么工业界爱它?)

1. 透明可解释

  • 每一步推理和行动都清晰可见,便于调试和审计
  • 用户可理解"AI为何这样回答",提升信任感

2. 灵活可扩展

  • 新工具 = 新能力:加一个 book_flight 工具,Agent 立刻会订票
  • 支持任意工具:API、数据库、Python 函数、甚至另一个 Agent

3. 低成本高效益

  • 无需微调模型:仅靠 prompt engineering + 工具集成
  • 适配任意 LLM:Qwen、Llama、GPT-4 均可运行

⚠️ 五、ReAct 的局限与演进

没有银弹。ReAct 也有挑战:

问题 表现 改进方案
格式严格 LLM 可能输出非标准格式(如漏 JSON) → 加 handle_parsing_errors=True + 重试机制
长链失败 多步推理中一步错,后续全崩 → 加入 Plan-and-Execute、Self-Reflection
参数绑定难 多参数工具易传错字段 Function Calling(结构化 Schema 约束)

📈 演进路线

ReAct(2022) → Plan-and-Execute (分步规划) → Reflexion (自我反思) → Function Calling (精准参数)

------但 ReAct 仍是所有高级框架的基石


🚀 六、未来展望:ReAct 不是终点,而是起点

ReAct 的真正意义,不在于它多完美,而在于它首次将"工具使用"纳入大模型的推理循环,打破了 LLM 的封闭性。

今天,我们看到:

  • AutoGen 用多 Agent + ReAct 实现复杂协作
  • LangChain 将 ReAct 作为默认 Agent 类型
  • Qwen-Agent、ModelScope Agent 均内置 ReAct 支持

正如论文作者所说:
"The synergy of reasoning and acting allows LMs to learn new skills on the fly."

(推理与行动的协同,让语言模型能即时学习新技能。)


📚 附:快速实践资源

资源 说明
ReAct 论文 必读原典(仅 10 页)
LangChain ReAct 教程 官方实战指南
Qwen-Agent GitHub 通义千问官方 Agent 框架
Ollama 安装 `curl -fsSL https://ollama.com/install.sh
相关推荐
卷福同学几秒前
【养虾日记】QClaw操作浏览器自动化发文
运维·人工智能·程序人生·自动化
dehuisun6 分钟前
国安部发布:“龙虾”(OpenClaw)安全养殖手册
人工智能
Echo_NGC22376 分钟前
【贝叶斯公式】从先验到后验的概率推演
人工智能·贝叶斯·概率论·扩散模型
Shining059610 分钟前
AI 编译器系列(七)《(MLIR)AscendNPU IR 编译堆栈》
人工智能·架构·mlir·infinitensor·hivm·ascendnpu ir
GJGCY18 分钟前
中小企业财务AI工具技术评测:四大类别架构差异与选型维度
大数据·人工智能·ai·架构·财务·智能体
weixin_Todd_Wong201019 分钟前
基于宠物行为识别在宠物医疗健康领域的应用
人工智能·宠物
勇往直前plus21 分钟前
大模型开发手记(八):LangChain Agent格式化输出
langchain
luolai29 分钟前
SpringAI调用本地RAG 启动报错 chromaDB 报错
人工智能
飞Link33 分钟前
具身智能核心架构之 Python 行为树 (py_trees) 深度剖析与实战
开发语言·人工智能·python·架构
IT_陈寒35 分钟前
JavaScript开发者必看:5个让你的代码性能翻倍的隐藏技巧
前端·人工智能·后端