文章目录
文档信息
- 创建时间:2026-01-22
- 作者:zuozewei
- 功能:使用LangChain框架实现ReAct Agent
- 技术栈:Python、LangChain、OpenAI API、DeepSeek
- 源代码:https://github.com/zuozewei/blog-example/tree/master/AI-LLM
项目概述
这是一个使用LangChain框架实现ReAct Agent的完整示例项目,展示如何创建能够调用工具的智能Agent。Agent可以处理需要多步骤推理和工具调用的复杂问题。
Agent与链的区别
Agent和链最大的区别在于执行方式。链是线性的,一步接一步走完就结束;而Agent是动态的,它会根据执行结果自己决定下一步该干什么。
这就需要AgentExecutor来负责循环调度,让大模型不断思考、行动、观察,直到得出最终答案。这种机制让Agent能处理更复杂的任务,自主决策、动态调整执行路径。
工具与工具包:Agent的武器库
在Agent的架构中,工具(Tool)和工具包(Toolkit)是核心概念:
-
工具(Tool):负责与模型交互,其输入由模型产生,输出会回传给模型。工具是Agent执行具体任务的载体。
-
工具包(Toolkit):一组相关的工具集合,提供特定领域的完整解决方案。
开发一个Agent,很多时候就是在开发工具和集成工具。学习编写工具是构建基于LangChain的Agent的关键点。LangChain社区提供了大量的工具,可以用它们来改造代码,实现新的Agent。
今天要聊什么
最近在项目中用LangChain搭了个Agent,踩了不少坑,也总结了一些经验。这篇文章会带你从零开始实现一个ReAct Agent,重点分享:
- 工具的定义和使用 - 使用
@tool装饰器将普通函数转换为Agent可调用的工具 - 提示词的构建 - 设计ReAct模式的Prompt模板,指导Agent的推理过程
- Agent的组装 - 集成工具和LLM,创建完整的Agent执行器
- Agent的执行过程 - 通过示例展示Agent如何询问水果单价、计算总价等具体步骤
- AgentExecutor的作用 - 介绍如何使用执行器来运行Agent并输出结果
项目结构
使用LangChain框架实现ReAct Agent/
├── tools.py # 工具定义
├── agent.py # Agent配置
├── main.py # 入口程序
└── .env # 环境变量配置
核心文件说明
1. 工具定义 - tools.py 📝
使用LangChain的@tool装饰器将普通函数转换为Agent可调用的工具。
python
from langchain_core.tools import tool
@tool
def calculate(expression: str) -> float:
"""执行计算并返回结果 - 使用 Python 语法,必要时请使用浮点数语法"""
return eval(expression)
@tool
def ask_fruit_unit_price(fruit: str) -> str:
"""询问水果的价格"""
fruit = fruit.strip()
if fruit.casefold() in ["apple", "苹果"]:
return "苹果单价是 10元/公斤"
if fruit.casefold() in ["banana", "香蕉"]:
return "香蕉单价是 6元/公斤"
return f"{fruit} 单价是 20元/公斤"
@tool装饰器怎么用
@tool装饰器会自动把函数转换成Agent能识别的工具:
- 函数名 → 工具名称(建议用英文,方便模型理解)
- Docstring → 工具描述(这里很关键!模型靠这个判断什么时候用哪个工具)
- 参数类型注解 → 工具参数schema(一定要写对,否则模型传参会报错)
⚠️ 踩坑提醒:Docstring写得太模糊会导致模型乱用工具,比如"计算函数"就不如"执行数学表达式计算"准确。
工具说明
- calculate: 执行数学表达式计算,使用Python的eval机制
🚨 安全警告:生产环境千万别直接用eval!这里只是演示用。实际项目建议用ast.literal_eval或者专门的数学表达式解析库,否则会被注入恶意代码。
- ask_fruit_unit_price: 查询水果单价,支持中英文水果名称(apple/苹果、banana/香蕉),其他水果默认价格为20元/公斤
2. Agent配置 - agent.py ⚙️
使用LangChain框架创建ReAct模式的Agent执行器,集成自定义工具并配置LLM参数。
python
import os
import dotenv
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from tools import calculate, ask_fruit_unit_price
ReAct Prompt模板
python
prompt = PromptTemplate.from_template('''Answer the following questions as best you can. You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}''')
Prompt占位符说明
{tools}: 可用工具列表及其描述{tool_names}: 工具名称列表{input}: 用户输入的问题{agent_scratchpad}: 存储推理历史(Thought/Action/Observation序列)
Agent创建函数
python
def create_agent() -> AgentExecutor:
"""创建ReAct Agent执行器"""
dotenv.load_dotenv()
llm = ChatOpenAI(
openai_api_key=os.getenv("OPENAI_API_KEY"),
openai_api_base=os.getenv("OPENAI_API_BASE"),
model=os.getenv("AI_MODEL", "deepseek-chat"),
temperature=0.1, # 推理场景使用低temperature保证确定性
)
tools = [calculate, ask_fruit_unit_price]
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt)
return AgentExecutor(
agent=agent,
tools=tools,
verbose=True # 打印详细执行过程
)
配置说明
LLM参数配置:
-
temperature=0.1: 推理任务一定要用低温度!我试过用0.7,模型有时候会瞎猜工具,导致循环次数暴涨。建议0-0.2之间
-
model: 默认用deepseek-chat,性价比不错。如果你追求效果可以换GPT-4,但成本会高10倍以上
-
max_tokens: 建议设个上限,防止模型陷入死循环疯狂输出(我遇到过一次跑了5000+ tokens的情况...)
💡 成本优化:每次Agent调用都会消耗不少tokens,建议先在本地用小模型测试,确认逻辑没问题再上生产。
AgentExecutor参数:
- agent: ReAct Agent实例
- tools: 工具列表
- verbose=True: 打印详细执行过程,便于调试(生产环境建议关闭)
ReAct模式到底怎么工作
ReAct(Reasoning + Acting)说白了就是让模型"边想边做"。举个例子,问它"3公斤苹果和2公斤香蕉多少钱",它会这么思考:
- Thought: 我得先查苹果和香蕉的单价
- Action: 调用ask_fruit_unit_price工具
- Action Input: 苹果
- Observation: 苹果单价是10元/公斤
- Thought: 现在查香蕉价格
- Action: 调用ask_fruit_unit_price工具
- Action Input: 香蕉
- Observation: 香蕉单价是6元/公斤
- Thought: 知道价格了,现在计算总价
- Action: 调用calculate工具
- Action Input: 3 * 10 + 2 * 6
- Observation: 42
- Thought: 算出来了,可以回答了
- Final Answer: 总共42元
这个过程会一直循环,直到模型觉得"我知道答案了"才停止。
3. 入口程序 - main.py 🚀
python
from agent import create_agent
if __name__ == '__main__':
# 创建Agent
agent = create_agent()
# 执行Agent
result = agent.invoke({
"input": "3公斤苹果和2公斤香蕉的总价格是多少?"
})
# 打印结果
print(result)
运行示例
执行程序后,输出如下:
bash
> Entering new AgentExecutor chain...
我需要计算总价格。首先,我应该找到苹果和香蕉的单价。
Thought: 我需要找到苹果的单价
Action: ask_fruit_unit_price
Action Input: 苹果
Observation: 苹果单价是 10元/公斤
Thought: 现在我需要找到香蕉的单价
Action: ask_fruit_unit_price
Action Input: 香蕉
Observation: 香蕉单价是 6元/公斤
Thought: 我已经知道了两种水果的价格。苹果是10元/公斤,香蕉是6元/公斤。现在我需要计算总成本:3公斤苹果和2公斤香蕉。
Action: calculate
Action Input: 3 * 10 + 2 * 6
Observation: 42
Thought: 我现在知道最终答案了
Final Answer: 3公斤苹果和2公斤香蕉的总价格是42元。
> Finished chain.
{'input': '3公斤苹果和2公斤香蕉的总价格是多少?', 'output': '3公斤苹果和2公斤香蕉的总价格是42元。'}
环境要求
- Python 3.8+
- LangChain
- OpenAI API Key(或兼容的API,如DeepSeek)
安装依赖
bash
pip install langchain langchain-openai langchain-core python-dotenv
配置环境变量
创建.env文件:
bash
OPENAI_API_KEY=your_api_key_here
OPENAI_API_BASE=https://api.deepseek.com/v1 # 或其他兼容的API端点
AI_MODEL=deepseek-chat
扩展示例
查询其他水果价格
python
result = agent.invoke({
"input": "5公斤橙子多少钱?"
})
复杂计算
python
result = agent.invoke({
"input": "如果我买2公斤苹果和3公斤香蕉,并且有10%的折扣,我需要付多少钱?"
})
扩展建议 🔧
工具扩展
- 添加输入验证,防止eval执行危险代码
- 实现更多实用工具(搜索、API调用、文件操作等)
- 添加工具使用日志和错误处理
Agent优化
- 调整Prompt模板,优化Agent推理能力
- 添加更多工具,扩展Agent能力范围
- 实现自定义Agent类型,满足特定需求
- 添加回调函数,监控Agent执行过程
💬 评论区聊聊 :你在项目中用过Agent吗?遇到过什么坑?
🎯 课后挑战:试着给Agent加一个汇率查询工具,让它能计算美元换人民币