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执行流程(可视化)

无需调用(如中国首都是哪)

需要调用(如北京天气)

用户输入问题

Agent执行器接收消息

模型推理:是否需要调用工具?

模型直接生成回答

模型生成工具调用指令

调用TavilySearchResults工具

工具返回搜索结果

模型整合搜索结果生成回答

返回最终回答给用户

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并写入文件”)。

总结(关键点回顾)

  1. Agent核心价值:解决大模型“知识过期”“无实时数据”痛点,能自动判断并调用外部工具(如Tavily搜索)获取最新数据;
  2. 关键组件
    • TavilySearchResults提供实时搜索能力,需配置API Key;
    • chat_agent_executor封装完整的Agent执行流程,无需手动实现工具调用逻辑;
    • bind_tools让模型具备“是否调用工具”的推理能力(底层逻辑);
  3. 执行逻辑
    • 无需工具的问题→模型直接回答;
    • 需要工具的问题→模型调用工具→整合结果→回答;
  4. 实用技巧
    • 控制Tavily的max_results为1-3,减少数据量提升回答效率;
    • 通过LangChain Tracing查看Agent的完整执行流程,便于调试工具调用问题;
    • 可扩展工具列表,实现“搜索+计算+文件操作”等组合能力。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐