【大模型】8.4基于LangChain、LangGraph、Tavily实现具备自动工具调用能力的智能代理(Agent)
·
1. 代码功能简要说明
该代码基于LangChain、LangGraph框架整合OpenAI的gpt-4-turbo模型和Tavily搜索引擎,实现具备自动工具调用能力的智能代理(Agent):
- 核心逻辑:代理可自动推理用户问题是否需要调用外部工具(Tavily搜索)——无需实时数据的问题(如“中国首都是哪个城市?”)直接回答,需要实时/最新数据的问题(如“北京天气怎么样?”)自动调用Tavily搜索获取结果后整合回答;
- 关键组件:TavilySearchResults提供搜索能力,模型通过
bind_tools具备工具调用推理能力,langgraph的chat_agent_executor封装完整的代理执行流程(推理→调用工具→整合结果),最终实现“智能判断+按需工具调用+精准回答”的全流程。
2. 带逐行详细注释的完整代码
# 导入os库:1.配置网络代理(解决国内访问OpenAI/Tavily API的网络限制) 2.配置各类API密钥环境变量
import os
# 导入TavilySearchResults:LangChain封装的Tavily搜索引擎工具,用于获取实时/最新的网络搜索结果
from langchain_community.tools.tavily_search import TavilySearchResults
# 导入HumanMessage:LangChain的用户消息类型,标识用户发送的问题/指令
from langchain_core.messages import HumanMessage
# 导入OpenAI相关组件:
# - ChatOpenAI:LangChain封装的gpt-4-turbo聊天模型,支持工具调用推理
# - OpenAIEmbeddings:(本代码未使用)OpenAI文本嵌入模型,预留向量相关能力
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
# 导入chat_agent_executor:LangGraph预构建的工具调用代理执行器,封装“推理→调用工具→整合结果”的完整代理逻辑
from langgraph.prebuilt import chat_agent_executor
# 导入add_routes:(本代码未使用)将代理部署为FastAPI服务的路由函数
from langserve import add_routes
# 配置HTTP代理:127.0.0.1:7890是代理工具的本地端口,确保API请求访问OpenAI/Tavily服务器
os.environ['http_proxy'] = '127.0.0.1:7890'
# 配置HTTPS代理:OpenAI/Tavily API基于HTTPS协议,需配置该代理确保请求正常
os.environ['https_proxy'] = '127.0.0.1:7890'
# 开启LangChain Tracing V2:追踪代理的执行过程(包括模型推理、工具调用、结果整合),便于调试
os.environ["LANGCHAIN_TRACING_V2"] = "true"
# 配置LangChain项目名称:追踪数据归类到该项目,便于管理不同应用
os.environ["LANGCHAIN_PROJECT"] = "LangchainDemo"
# 配置LangChain API Key:认证LangChain Smith服务(追踪功能必需),替换为自己的密钥
os.environ["LANGCHAIN_API_KEY"] = ''
# 配置Tavily API Key:认证Tavily搜索引擎服务(调用搜索工具必需),替换为自己的密钥
os.environ["TAVILY_API_KEY"] = ''
# ===================== 核心步骤1:初始化OpenAI聊天模型 =====================
# 聊天机器人案例
# 创建ChatOpenAI模型实例:指定gpt-4-turbo模型(支持工具调用的核心模型,gpt-3.5-turbo也支持)
model = ChatOpenAI(model='gpt-4-turbo')
# ===================== 注释部分:测试无工具调用的纯模型回答 =====================
# 没有任何代理的情况下:模型仅基于自身训练数据回答,无法获取实时数据(如天气)
# result = model.invoke([HumanMessage(content='北京天气怎么样?')])
# print(result) # 输出:模型会提示无法获取实时天气,或给出过期数据
# ===================== 核心步骤2:初始化Tavily搜索工具 =====================
# LangChain内置了一个工具,可以轻松地使用Tavily搜索引擎作为工具。
# 初始化Tavily搜索工具:
# - max_results=2:指定每次搜索仅返回2条结果(减少数据量,提升回答效率)
# - Tavily特点:轻量级、免费额度充足、支持实时搜索,适合Agent工具调用场景
search = TavilySearchResults(max_results=2)
# 测试搜索工具:直接调用搜索工具获取结果(无模型推理,仅测试工具本身)
# print(search.invoke('北京的天气怎么样?')) # 输出:包含天气数据的搜索结果列表
# ===================== 注释部分:测试模型绑定工具后的推理能力 =====================
# 让模型绑定工具:将搜索工具注册到模型中,模型具备“是否调用工具”的推理能力
# tools = [search] # 定义工具列表(可包含多个工具,如搜索、计算器等)
# model_with_tools = model.bind_tools(tools) # 绑定工具到模型
# 模型可以自动推理:是否需要调用工具去完成用户的答案
# 测试无需调用工具的问题(中国首都是哪):模型判断无需调用工具,直接回答
# resp = model_with_tools.invoke([HumanMessage(content='中国的首都是哪个城市?')])
# print(f'Model_Result_Content: {resp.content}') # 输出:直接回答“北京”
# print(f'Tools_Result_Content: {resp.tool_calls}') # 输出:None(无工具调用)
# 测试需要调用工具的问题(北京天气):模型判断需要调用工具,返回工具调用指令
# resp2 = model_with_tools.invoke([HumanMessage(content='北京天气怎么样?')])
# print(f'Model_Result_Content: {resp2.content}') # 输出:模型提示将调用搜索工具
# print(f'Tools_Result_Content: {resp2.tool_calls}') # 输出:包含搜索工具调用参数的列表
# ===================== 核心步骤3:创建具备工具调用能力的智能代理 =====================
# 创建代理:使用langgraph预构建的executor封装完整的代理逻辑
# chat_agent_executor.create_tool_calling_executor:
# - 输入:模型(带推理能力)、工具列表(搜索工具)
# - 输出:具备“推理→调用工具→整合结果→回答”全流程能力的代理执行器
agent_executor = chat_agent_executor.create_tool_calling_executor(model, tools)
# ===================== 核心步骤4:测试代理的自动工具调用能力 =====================
# 测试1:无需调用工具的问题(中国首都是哪)
print('=== 测试1:无需调用工具的问题 ===')
resp = agent_executor.invoke({'messages': [HumanMessage(content='中国的首都是哪个城市?')]})
# 优化print:解析并展示代理的完整执行结果(消息列表)
print(f'用户问题:中国的首都是哪个城市?')
print(f'代理执行结果(完整消息):{resp["messages"]}')
# 提取最终回答(消息列表最后一条是Agent的回答)
print(f'代理最终回答:{resp["messages"][-1].content}\n')
# 测试2:需要调用工具的问题(北京天气)
print('=== 测试2:需要调用工具的问题 ===')
resp2 = agent_executor.invoke({'messages': [HumanMessage(content='北京天气怎么样?')]})
print(f'用户问题:北京天气怎么样?')
print(f'代理执行结果(完整消息):{resp2["messages"]}')
# 提取并打印最终回答(消息列表第3条是整合搜索结果后的回答,[-1]也可)
final_answer = resp2['messages'][2].content
print(f'代理最终回答:{final_answer}')
3. 无任何注释的代码版本
import os
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langgraph.prebuilt import chat_agent_executor
from langserve import add_routes
os.environ['http_proxy'] = '127.0.0.1:7890'
os.environ['https_proxy'] = '127.0.0.1:7890'
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "LangchainDemo"
os.environ["LANGCHAIN_API_KEY"] = ''
os.environ["TAVILY_API_KEY"] = ''
model = ChatOpenAI(model='gpt-4-turbo')
search = TavilySearchResults(max_results=2)
tools = [search]
agent_executor = chat_agent_executor.create_tool_calling_executor(model, tools)
print('=== 测试1:无需调用工具的问题 ===')
resp = agent_executor.invoke({'messages': [HumanMessage(content='中国的首都是哪个城市?')]})
print(f'用户问题:中国的首都是哪个城市?')
print(f'代理执行结果(完整消息):{resp["messages"]}')
print(f'代理最终回答:{resp["messages"][-1].content}\n')
print('=== 测试2:需要调用工具的问题 ===')
resp2 = agent_executor.invoke({'messages': [HumanMessage(content='北京天气怎么样?')]})
print(f'用户问题:北京天气怎么样?')
print(f'代理执行结果(完整消息):{resp2["messages"]}')
final_answer = resp2['messages'][2].content
print(f'代理最终回答:{final_answer}')
4. 核心知识点详解(系统梳理+表格)
4.1 核心概念梳理
| 概念 | 通俗解释 | 关键说明 |
|---|---|---|
| Agent(智能代理) | 具备“思考→决策→调用工具→完成任务”能力的智能体 | 1. 核心区别:普通模型仅能回答问题,Agent能主动调用外部工具解决模型自身无法解决的问题(如获取实时数据、计算、操作文件) 2. 本案例Agent能力:判断问题是否需要搜索→需要则调用Tavily→整合搜索结果→生成回答 3. 核心价值:解决大模型“知识过期”“无实时数据”“无计算能力”等痛点 |
| 工具调用(Tool Calling) | 模型根据问题自动决定是否调用/调用哪个外部工具的能力 | 1. 实现方式:模型需支持工具调用(如gpt-3.5-turbo/gpt-4-turbo),通过bind_tools将工具注册到模型2. 推理逻辑:模型分析问题→判断是否需要工具→若需要则生成工具调用指令(包含工具名、参数)→执行工具→整合结果 3. 关键字段: tool_calls(模型返回的工具调用指令),包含工具名称、调用参数等 |
| TavilySearchResults | LangChain封装的Tavily搜索引擎工具 | 1. 核心优势: - 轻量级:接入简单,仅需API Key - 免费额度:每月有免费搜索次数,适合学习/测试 - 实时性:返回最新的网络数据,解决模型知识过期问题 2. 核心参数: - max_results:返回搜索结果数量(默认5,建议1-3) - search_depth:搜索深度(basic/advanced,basic足够日常使用) 3. 调用方式: search.invoke(查询词),返回包含标题、内容、链接的结果列表 |
| chat_agent_executor | LangGraph预构建的工具调用代理执行器 | 1. 核心作用:封装“模型推理→工具调用→结果整合”的完整流程,无需手动实现工具调用逻辑 2. 关键方法: create_tool_calling_executor(model, tools),输入模型和工具列表,输出可直接调用的代理执行器3. 执行逻辑: - 接收用户消息→模型推理是否调用工具→调用工具(按需)→工具返回结果→模型整合结果生成回答→返回最终结果 |
| bind_tools | 模型绑定工具的核心方法 | 1. 作用:将工具列表注册到模型中,让模型具备“是否调用工具”的推理能力 2. 用法: model_with_tools = model.bind_tools(tools)3. 输出差异:绑定工具后,模型返回的响应包含 tool_calls字段(无工具调用则为None) |
| 工具列表(tools) | 代理可调用的工具集合 | 1. 格式:列表形式,可包含多个工具(如搜索、计算器、文件读写等) 2. 扩展性:LangChain支持自定义工具,只需按规范封装即可加入列表 3. 本案例:仅包含TavilySearchResults,可扩展为“搜索+计算器+地图查询”等组合工具 |
4.2 核心组件用法对照表
| 组件 | 导入路径 | 核心用法 | 作用 | 本案例应用 |
|---|---|---|---|---|
| TavilySearchResults | langchain_community.tools.tavily_search.TavilySearchResults | TavilySearchResults(max_results=2)(初始化)search.invoke(查询词)(调用) |
提供实时网络搜索能力 | 获取北京天气的最新数据 |
| chat_agent_executor | langgraph.prebuilt.chat_agent_executor | create_tool_calling_executor(model, tools)(创建代理)agent_executor.invoke(输入)(调用代理) |
封装完整的Agent执行流程 | 实现“推理→调用工具→整合结果”全流程 |
| bind_tools | ChatOpenAI实例方法 | model.bind_tools(tools) |
让模型具备工具调用推理能力 | (注释部分)测试模型的工具调用推理逻辑 |
| HumanMessage | langchain_core.messages.HumanMessage | HumanMessage(content=用户问题) |
封装用户输入,适配Agent的输入格式 | 传递“中国首都是哪”“北京天气”等问题 |
| agent_executor.invoke | 代理执行器方法 | agent_executor.invoke({'messages': [HumanMessage]}) |
调用Agent处理用户问题 | 触发Agent的完整执行流程 |
4.3 Agent执行流程(可视化)
5. Print函数优化与说明
5.1 优化对比与核心改进
| 优化前代码 | 优化后代码 | 核心改进 |
|---|---|---|
print(resp['messages'])print(resp2['messages'])print(resp2['messages'][2].content) |
print('=== 测试1:无需调用工具的问题 ===')print(f'用户问题:xxx')print(f'代理执行结果(完整消息):xxx')print(f'代理最终回答:xxx')测试2同理 |
1. 增加测试场景说明(是否调用工具),小白能清晰区分两种不同的处理逻辑 2. 明确标注“用户问题”“完整消息”“最终回答”,避免输出内容混乱 3. 提取最终回答字段,无需小白手动解析消息列表 |
5.2 输出示例(参考)
=== 测试1:无需调用工具的问题 ===
用户问题:中国的首都是哪个城市?
代理执行结果(完整消息):[HumanMessage(content='中国的首都是哪个城市?'), AIMessage(content='中国的首都是北京。')]
代理最终回答:中国的首都是北京。
=== 测试2:需要调用工具的问题 ===
用户问题:北京天气怎么样?
代理执行结果(完整消息):[HumanMessage(content='北京天气怎么样?'), ToolCallMessage(...), AIMessage(content='截至当前,北京的天气为晴,气温25℃,微风,空气质量优。')]
代理最终回答:截至当前,北京的天气为晴,气温25℃,微风,空气质量优。
5.3 关键说明
- 消息列表解析:
- 无需调用工具:消息列表包含
HumanMessage(用户问题)+AIMessage(模型回答); - 需要调用工具:消息列表包含
HumanMessage+ToolCallMessage(工具调用指令)+AIMessage(整合结果后的回答);
- 无需调用工具:消息列表包含
- API Key注意:Tavily API Key需自行申请(https://tavily.com/),替换代码中的密钥才能正常使用;
- 代理扩展性:可在
tools列表中添加更多工具(如CalculatorTool计算器、FileWriteTool文件写入),实现更复杂的任务(如“计算1+2+3并写入文件”)。
总结(关键点回顾)
- Agent核心价值:解决大模型“知识过期”“无实时数据”痛点,能自动判断并调用外部工具(如Tavily搜索)获取最新数据;
- 关键组件:
- TavilySearchResults提供实时搜索能力,需配置API Key;
- chat_agent_executor封装完整的Agent执行流程,无需手动实现工具调用逻辑;
- bind_tools让模型具备“是否调用工具”的推理能力(底层逻辑);
- 执行逻辑:
- 无需工具的问题→模型直接回答;
- 需要工具的问题→模型调用工具→整合结果→回答;
- 实用技巧:
- 控制Tavily的
max_results为1-3,减少数据量提升回答效率; - 通过LangChain Tracing查看Agent的完整执行流程,便于调试工具调用问题;
- 可扩展工具列表,实现“搜索+计算+文件操作”等组合能力。
- 控制Tavily的
更多推荐

所有评论(0)