用LangChain实现一个Agent
同时课程详细介绍了。
文章详细介绍了如何使用LangChain框架实现大模型Agent,通过对比原生实现和LangChain实现,展示了工具定义、提示词设计和Agent组装的全过程。重点讲解了@tool装饰器将普通函数转化为可调用工具的方法,以及使用create_react_agent和AgentExecutor构建和执行Agent的流程。最后介绍了LangChain提供的丰富工具和工具库,帮助开发者快速扩展Agent功能,实现复杂任务处理。
上面,我们抛开了 LangChain,基于 OpenAI Python 程序库实现了一个 Agent,主要是为了让你更好地理解 Agent 的运作机理。其中最核心的部分就是一个循环,不断地执行各种动作,直到判断运行的结果是停下来。
现在,你已经知道了 Agent 是怎样运作的,这一讲,我们再回来看看如何用 LangChain 实现一个 Agent,相信有了之前的铺垫,这一讲的代码就比较容易理解了。
基于 LangChain 实现的 Agent
从实现的功能上讲,我们这一讲要实现的功能和上一讲是完全相同的,只不过我们采用了 LangChain 的基础设施,代码如下所示:
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
@tool
def calculate(what: str) -> float:
"""Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessary"""
return eval(what)
@tool
def ask_fruit_unit_price(fruit: str) -> str:
"""Asks the user for the price of a fruit"
if fruit.casefold() == "apple":
return "Apple unit price is 10/kg"
elif fruit.casefold() == "banana":
return "Banana unit price is 6/kg"
else:
return "{} unit price is 20/kg".format(fruit)
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}''')
tools = [calculate, ask_fruit_unit_price]
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_react_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = agent_executor.invoke({
"input": "What is the total price of 3 kg of apple and 2 kg of banana?"
})
print(result)
工具
这一讲的代码与上一讲实现了完全相同的功能,主要是我们把上一讲的两个动作函数几乎原封不动地搬了过来。
@tool
def calculate(what: str) -> float:
"""Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessary"""
return eval(what)
@tool
def ask_fruit_unit_price(fruit: str) -> str:
"""Asks the user for the price of a fruit"""
if fruit.casefold() == "apple":
return "Apple unit price is 10/kg"
elif fruit.casefold() == "banana":
return "Banana unit price is 6/kg"
else:
return "{} unit price is 20/kg".format(fruit)
之所以要说几乎,是我们给这两个函数添加了一点东西。首先,@tool 是一个装饰器,它让我们把一个函数变成了一个工具(tool)。
工具在 LangChain 里是一个重要的概念,它和我们说的 Agent 系统架构中的工具概念是可以对应上的,工具主要负责执行查询,或是完成一个一个的动作。
Agent在执行过程中,会获取工具的信息,传给大模型。这些信息主要就是一个工具的名称、描述和参数,这样大模型就知道该在什么情况下怎样调用这个工具了。@tool 可以提取函数名变成工具名,提取参数变成工具的参数,还有一点就是,它可以提取函数的 Docstring 作为工具的描述。这样一来,calculate 就从一个普通的函数变成了一个工具。
@tool
def calculate(what: str) -> float:
"""Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessary"""
return eval(what)
print(calculate.name)
print(calculate.description)
print(calculate.args)
提示词
接下来就是提示词,这里我们没有把上一讲的提示词直接搬过来,而是采用了一个更通用的提示词:
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}''')
如果你还记得,我们在学习提示工程的那一讲的时候,已经见过这个提示词模板了,再结合上一讲介绍过的提示词,对于这里的思考(Thought)、行动(Action)和观察(Observation),你肯定不陌生了。
作为一个模板,这里面有几个空是留给我们的,最主要的就是 tools 和 tool_names 两个变量,这就是工具的信息。tool_names 很简单,就是工具的名称。
tools 是工具格式化成一个字符串。比如,在缺省的实现中, calculate 就会格式化成下面这个样子,可以看到它包括了工具的基本属性都拼装了进去。
calculate(what: str) -> float - Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessary
input 也比较好理解,就是我们的输入。 agent_scratchpad 是在 Agent 的执行过程中,存放中间过程的,你可以把它理解成我们上一讲的聊天历史部分。
组装 Agent
有了工具,有了提示词,现在我们可以组装 Agent 了:
tools = [calculate, ask_fruit_unit_price]
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_react_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
我们调用 create_react_agent 创建了一个基于 ReAct 的 Agent。前面说过,ReAct 的 Agent 能够正常运行,需要提示词与代码配合起来使用。我前面给出的提示词就是要与 create_react_agent 函数配合在一起使用的。
create_react_agent 完成的工作就是基于这段提示词的执行过程进行处理,比如,解析返回内容中的动作(Action)与动作输入(Action Input),还有前面说的 agent_scratchpad 的处理过程,也是在这个函数中组装进去的。
站在软件设计的角度看,二者结合如此紧密,却被分开了,等于破坏了封装。实际上,二者之前确实是合在一起的,就是一个 create_react_agent 函数。现在将二者分开,是为了给使用者一个调整提示词的机会。
与之前几个基于 LangChain 的应用最大的不同在于,我们这个 Agent 的实现并没有组装成一个链。正如我们前面所说,Agent 的核心是一个循环,这其实是一个流程,而之前的应用从头到尾都是一个“链”式过程。所以,这里用到了 AgentExecutor。
即便不看它的实现,你应该也能知道,其核心实现就是一个循环:判断是不是该结束,不是的话,继续下一步,向大模型发送消息,是的话,跳出循环。
现在,我们已经组装好了所有的代码,接下来就是执行这个 Agent 了:
result = agent_executor.invoke({
"input": "What is the total price of 3 kg of apple and 2 kg of banana?"
})
print(result)
一次的执行结果输出如下:
> Entering new AgentExecutor chain...
To find the total price of 3 kg of apples and 2 kg of bananas, I need to know the unit prices of both fruits. I will first ask for the price of apples and then for the price of bananas.
Action: ask_fruit_unit_price
Action Input: "apple"
Apple unit price is 10/kg
Now that I have the unit price of apples, I need to ask for the unit price of bananas.
Action: ask_fruit_unit_price
Action Input: "banana"
Banana unit price is 6/kg
Now that I have the unit prices of both fruits (10/kg for apples and 6/kg for bananas), I can calculate the total price for 3 kg of apples and 2 kg of bananas.
Action: calculate
Action Input: "3 * 10 + 2 * 6" 42
I now know the final answer
Final Answer: The total price of 3 kg of apples and 2 kg of bananas is 42.
> Finished chain.
{'input': 'What is the total price of 3 kg of apple and 2 kg of banana?', 'output': 'The total price of 3 kg of apples and 2 kg of bananas is 42.'}
因为在 AgentExecutor 初始化的时候,我打开了 verbose 这个开关,所以,这里我们看到 Agent 内部的执行过程。我们可以看到,其过程几乎与我们上一讲的过程是一样的,先查看苹果和香蕉的单价,然后,计算总和。最终,把计算结果返回给我们。
工具(Tool)和工具包(Toolkit)
在前面的实现中,为了兼容上一讲的内容,我们自定义了自己的工具实现。实际上, LangChain 社区已经为我们提供了大量的工具,让我们可以很方便地集成各种东西。在很多情况下,这些工具我们只要直接拿过来用就好,下面是一个例子:
shell_tool = ShellTool()
tools = [shell_tool]
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_react_agent(model, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = agent_executor.invoke({
"input": "Create a file named 'test.txt' and write 'Hello, World!' to it."
})
在这个例子里,我们创建了一个可以执行自然语言命令的命令行工具。为了支持命令行的执行,我们引入了 ShellTool,它是一个命令行工具。所有的工具实际上都是 Tool 这个接口的实现,ShellTool 也是实现这个接口。前面的动作函数就是通过 @tool 这个装饰器生成了一个实现 Tool 接口的对象。
对程序员来说,命令行的行为大家都不陌生,下面就是这个 Agent 的一次执行结果,我让它创建了一个名为 test.txt 的文件,然后,在其中写入“Hello, World!”。
I need to create a file named 'test.txt' and then write the text 'Hello, World!' into it. I'll do this using shell commands in the terminal.
Action: terminal
Action Input: echo 'Hello, World!' > test.txt
Executing command:
echo 'Hello, World!' > test.txt
The file 'test.txt' has been created with the content 'Hello, World!'.
Final Answer: A file named 'test.txt' has been created with the content 'Hello, World!'.
除了工具,LangChain 还有一个 Toolkit 的概念,它的作用是把相关的一些工具集成在一起。举个例子,Github 提供了一大堆的能力,比如查询 Issue、创建 Pull Request 等等。如果一个一个列出来就会很多,所以,就有了一个 Github Toolkit 把它们放在了一起。下面是一个示例:

当然,为了这段代码能够执行,你需要找到相关的配置:

正是有了工具和工具包的概念,Agent 能做的事情就会无限放大。如果我们做的是比较通用的事情,很多时候,就是在已有的工具和工具包中进行选择。不过,我之所以把如何编写一个工具放在前头,是因为大多数情况下,我们需要编写自己的工具,无论是访问私有的数据,还是内部的接口。所以,学习编写工具几乎是一件必须要学会的事。不过,这种代码就进入到我们熟悉的范围了,对大部分程序员而言,应该不是太大的问题。
现在你已经了解了采用 LangChain 构建 Agent 的基本方法。虽然我们这里只介绍了基于 ReAct 构建的 Agent,但实际上,LangChain 里提供了大量的各种创建 Agent 的方法,比如创建基于 SQL 的 Agent、基于 JSON 的 Agent 等等,我们可以根据需要进行选择。
零基础如何高效学习大模型?
为了帮助大家打破壁垒,快速了解大模型核心技术原理,学习相关大模型技术。从原理出发真正入局大模型。在这里我和MoPaaS魔泊云联合梳理打造了系统大模型学习脉络,这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码免费领取🆓**⬇️⬇️⬇️

【大模型全套视频教程】
教程从当下的市场现状和趋势出发,分析各个岗位人才需求,带你充分了解自身情况,get 到适合自己的 AI 大模型入门学习路线。
从基础的 prompt 工程入手,逐步深入到 Agents,其中更是详细介绍了 LLM 最重要的编程框架 LangChain。最后把微调与预训练进行了对比介绍与分析。
同时课程详细介绍了AI大模型技能图谱知识树,规划属于你自己的大模型学习路线,并且专门提前收集了大家对大模型常见的疑问,集中解答所有疑惑!

深耕 AI 领域技术专家带你快速入门大模型
跟着行业技术专家免费学习的机会非常难得,相信跟着学习下来能够对大模型有更加深刻的认知和理解,也能真正利用起大模型,从而“弯道超车”,实现职业跃迁!

【精选AI大模型权威PDF书籍/教程】
精心筛选的经典与前沿并重的电子书和教程合集,包含《深度学习》等一百多本书籍和讲义精要等材料。绝对是深入理解理论、夯实基础的不二之选。

【AI 大模型面试题 】
除了 AI 入门课程,我还给大家准备了非常全面的**「AI 大模型面试题」,**包括字节、腾讯等一线大厂的 AI 岗面经分享、LLMs、Transformer、RAG 面试真题等,帮你在面试大模型工作中更快一步。
【大厂 AI 岗位面经分享(92份)】

【AI 大模型面试真题(102 道)】

【LLMs 面试真题(97 道)】

【640套 AI 大模型行业研究报告】

【AI大模型完整版学习路线图(2025版)】
明确学习方向,2025年 AI 要学什么,这一张图就够了!

👇👇点击下方卡片链接免费领取全部内容👇👇

抓住AI浪潮,重塑职业未来!
科技行业正处于深刻变革之中。英特尔等巨头近期进行结构性调整,缩减部分传统岗位,同时AI相关技术岗位(尤其是大模型方向)需求激增,已成为不争的事实。具备相关技能的人才在就业市场上正变得炙手可热。
行业趋势洞察:
- 转型加速: 传统IT岗位面临转型压力,拥抱AI技术成为关键。
- 人才争夺战: 拥有3-5年经验、扎实AI技术功底和真实项目经验的工程师,在头部大厂及明星AI企业中的薪资竞争力显著提升(部分核心岗位可达较高水平)。
- 门槛提高: “具备AI项目实操经验”正迅速成为简历筛选的重要标准,预计未来1-2年将成为普遍门槛。
与其观望,不如行动!
面对变革,主动学习、提升技能才是应对之道。掌握AI大模型核心原理、主流应用技术与项目实战经验,是抓住时代机遇、实现职业跃迁的关键一步。

01 为什么分享这份学习资料?
当前,我国在AI大模型领域的高质量人才供给仍显不足,行业亟需更多有志于此的专业力量加入。
因此,我们决定将这份精心整理的AI大模型学习资料,无偿分享给每一位真心渴望进入这个领域、愿意投入学习的伙伴!
我们希望能为你的学习之路提供一份助力。如果在学习过程中遇到技术问题,也欢迎交流探讨,我们乐于分享所知。
*02 这份资料的价值在哪里?*
专业背书,系统构建:
-
本资料由我与MoPaaS魔泊云的鲁为民博士共同整理。鲁博士拥有清华大学学士和美国加州理工学院博士学位,在人工智能领域造诣深厚:
-
- 在IEEE Transactions等顶级学术期刊及国际会议发表论文超过50篇。
- 拥有多项中美发明专利。
- 荣获吴文俊人工智能科学技术奖(中国人工智能领域重要奖项)。
-
目前,我有幸与鲁博士共同进行人工智能相关研究。

内容实用,循序渐进:
-
资料体系化覆盖了从基础概念入门到核心技术进阶的知识点。
-
包含丰富的视频教程与实战项目案例,强调动手实践能力。
-
无论你是初探AI领域的新手,还是已有一定技术基础希望深入大模型的学习者,这份资料都能为你提供系统性的学习路径和宝贵的实践参考,助力你提升技术能力,向大模型相关岗位转型发展。



抓住机遇,开启你的AI学习之旅!

更多推荐

所有评论(0)