3. 使用ReAct框架的Agent
任务目标
构建一个基于ReAct(Reasoning + Acting)框架的Agent,使其能够通过Thought → Action → Observation的循环,自主解决数学问题。Agent需要具备推理能力(决定下一步做什么)和行动能力(调用工具执行计算),并在多轮循环后得出最终答案。
核心实现
本案例使用LangChain的create_react_agent方法,配合一个数学计算工具。Agent通过ReAct提示模板驱动,在循环中交替输出思考过程和工具调用,直到获得最终答案。核心依赖为langchain、langchain-和langchain-community。
# requirements.txt
# langchain>=0.2.0
# langchain->=0.1.0
# langchain-community>=0.2.0
import os
from langchain_ import ChatOpenAI
from langchain.agents import create_react_agent, AgentExecutor
from langchain.agents import Tool
from langchain import hub
from langchain_community.utilities import SerpAPIWrapper
# 1. 设置环境变量(请替换为你的真实)
os.environ["_"] = "your--"
# 如果使用SerpAPI搜索工具,需要设置;本案例仅用数学工具,可注释掉
# os.environ["SERPAPI_"] = "your-serpapi-key"
# 2. 定义数学计算工具(本案例核心工具)
def math_calculator(expression: str) -> str:
"""
安全地计算数学表达式。
仅支持基本四则运算、幂、括号,不支持变量赋值。
"""
# 移除潜在的危险字符(仅允许数字、运算符、括号、小数点)
allowed_chars = set("0123456789+-*/(). ")
if not all(c in allowed_chars for c in expression):
return "错误:表达式包含非法字符"
try:
# 使用eval但限制命名空间为空,仅允许数学运算
result = eval(expression, {"__builtins__": {}}, {})
return str(result)
except ZeroDivisionError:
return "错误:除零"
except Exception as e:
return f"错误:{str(e)}"
# 3. 创建工具列表
tools = [
Tool(
name="math_calculator",
func=math_calculator,
description="用于计算数学表达式。输入应为合法的数学表达式,如 '3*5+2' 或 '(4+5)*6'。返回计算结果。"
)
]
# 4. 初始化语言模型(使用支持工具调用的模型)
llm = ChatOpenAI(model="-mini", temperature=0)
# 5. 获取ReAct提示模板(LangChain官方hub中的标准模板)
prompt = hub.pull("hwchase17/react")
# 6. 创建ReAct Agent
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt)
# 7. 创建Agent执行器,设置最大迭代次数防止死循环
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印Thought/Action/Observation过程
max_iterations=5, # 最多5轮思考-行动循环
handle_parsing_errors=True
)
# 8. 运行Agent解决数学问题
if __name__ == "__main__":
# 测试问题1:需要多步计算的表达式
question1 = "计算 (15 + 3) * 4 - 20 / 5 的结果"
print("="*50)
print(f"问题: {question1}")
result1 = agent_executor.invoke({"input": question1})
print(f"最终答案: {result1['output']}")
# 测试问题2:需要验证中间结果的表达式
question2 = "如果 x = 7,计算 3*x^2 + 2*x - 5 的值"
print("="*50)
print(f"问题: {question2}")
result2 = agent_executor.invoke({"input": question2})
print(f"最终答案: {result2['output']}")
运行与验证
运行方式:
- 安装依赖:
pip install langchain langchain- langchain-community - 将代码中的
your--替换为真实有效的 - 直接运行脚本:
python react_agent.py
验证方法与通过条件:
- 观察执行过程:设置
verbose=True后,控制台会打印完整的ReAct循环。应能看到模型依次输出Thought(推理)、Action(选择工具)、Action Input(传给工具的具体表达式)、Observation(工具返回结果),最后以Final Answer结束。 - 验证结果正确性:问题1的正确答案为
68((15+3)*4=72,20/5=4,72-4=68)。问题2的正确答案为156(3*49+14-5=156)。Agent最终输出的答案应与这两个数值一致。 - 多轮循环验证:问题1需要Agent先计算括号内加法,再计算乘法和除法,最后做减法,至少需要2次工具调用,可验证Agent具备多步推理能力。
常见问题
- 无效:确保环境变量已正确设置,且账户有可用额度。
- 工具调用格式错误:如果模型输出的Action格式不符合规范,
handle_parsing_errors=True会自动重试,但会消耗额外调用次数。 - 死循环:
max_iterations=5限制了最大循环次数,防止模型陷入无限推理。若问题过于复杂,可适当增大该值。 - eval安全性:本案例的
math_calculator通过白名单字符过滤和空命名空间限制,仅允许纯数学运算,不执行任意代码。实际生产环境建议使用ast模块或专用数学解析库(如sympy)替代。