零基础 | 使用LangChain框架实现ReAct Agent

文章目录


文档信息


项目概述

这是一个使用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,重点分享:

  1. 工具的定义和使用 - 使用@tool装饰器将普通函数转换为Agent可调用的工具
  2. 提示词的构建 - 设计ReAct模式的Prompt模板,指导Agent的推理过程
  3. Agent的组装 - 集成工具和LLM,创建完整的Agent执行器
  4. Agent的执行过程 - 通过示例展示Agent如何询问水果单价、计算总价等具体步骤
  5. 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公斤香蕉多少钱",它会这么思考:

  1. Thought: 我得先查苹果和香蕉的单价
  2. Action: 调用ask_fruit_unit_price工具
  3. Action Input: 苹果
  4. Observation: 苹果单价是10元/公斤
  5. Thought: 现在查香蕉价格
  6. Action: 调用ask_fruit_unit_price工具
  7. Action Input: 香蕉
  8. Observation: 香蕉单价是6元/公斤
  9. Thought: 知道价格了,现在计算总价
  10. Action: 调用calculate工具
  11. Action Input: 3 * 10 + 2 * 6
  12. Observation: 42
  13. Thought: 算出来了,可以回答了
  14. 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加一个汇率查询工具,让它能计算美元换人民币

相关推荐
坠入暮云间x1 小时前
React Native for OpenHarmony开发环境搭建指南(一)
前端·react native·开源
爱上妖精的尾巴1 小时前
7-12 WPS JS宏 this、return用构造函数自定义类-1:对象内部函数,外部调用的写法
前端·javascript·wps·js宏·jsa
白鳯1 小时前
分形世界:React实现交互式分形图绘制与导出
react.js·前端框架·cursor·分形·vibe coding·分形绘制·数学之美
har01d2 小时前
AI生成的 vue3 日历组件,显示农历与节日,日期可选择,年月可切换
前端·vue.js·节日
冲刺逆向2 小时前
【js逆向案例六】创宇盾(加速乐)通杀模版
java·前端·javascript
我穿棉裤了2 小时前
文字换行自动添加换行符“-”
前端·javascript·vue.js
six+seven2 小时前
Node.js内置模块fs
前端·node.js
少莫千华2 小时前
【HTML】CSS绘制奥运五环
前端·css·html
沛沛老爹2 小时前
Web开发者转型AI安全核心:Agent Skills沙盒环境与威胁缓解实战
java·前端·人工智能·安全·rag·web转型升级