Langchain(十一)tools 使用案例详解
本文通过三个案例详细介绍了如何利用LangChain框架扩展大语言模型(LLM)的功能,使其具备调用外部工具的能力。案例一展示了基本的天气查询工具实现;案例二演示了网络搜索工具集成;案例三则完整实现了"天气查询+本地文件写入"的复合功能。文章重点讲解了@tool装饰器的使用、工具文档字符串规范、异常处理、Agent配置等核心知识点,并提供了生产环境优化建议。通过灵活组合自定义工
介绍
LangChain 的核心优势之一是支持灵活扩展外部工具(Tools),让大语言模型(LLM)突破纯文本交互的限制,具备调用 API、操作文件、执行计算等实际业务能力。本文将以「天气查询 + 本地文件写入」为例,详解如何自定义 Tools、绑定到 Agent 并实现智能调用,完整覆盖工具开发、参数定义、异常处理和 Agent 集成的全流程。
案例一,自定义天气工具使用
from dotenv import load_dotenv
load_dotenv()
import os
from pydantic import SecretStr
from langchain.tools import tool
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
model="qwen-plus",
api_key=SecretStr(os.environ["DASHSCOPE_API_KEY"]),
)
from langchain.agents import create_agent
# 1. 定义工具 (Tools)
#编写问题"北京天气怎么样"来测试智能体,并使用 agent.stream 方法实现流式输出,通过 pretty_print() 方法格式化显示每次的输出结果
@tool
def get_weather(city: str) -> str:
"""获取给定城市的当前天气信息。"""
return f"总是晴天,温度为 25 度 in {city}!"
SYSTEM_PROMPT = "你是一个天气助手,具备调用get_weather天气函数获取指定地点天气的能力"
# 3. 创建代理
agent = create_agent(
model=llm,
tools=[get_weather],
system_prompt=SYSTEM_PROMPT,
)
question="北京的天气怎么样?"
for step in agent.stream(
{'messages': question},
stream_mode="values"
):
step["messages"][-1].pretty_print()
#运行上述代码后,我们可以清晰地观察到
#LangChain1.0
#智能体的完整执行流程:
#用户提问:接收到问题
#"北京天气怎么样"
#模型分析:大语言模型识别出自身无法直接回答,决定调用工具函数
#get_weather,并自动生成调用参数
#{loc: 北京}
#工具执行:执行工具函数并获取返回结果
#结果整合:大语言模型根据工具函数的执行结果,生成格式化的最终回答
案例二,网络搜索工具使用
Tavily API Platform 注册获取api key
from dotenv import load_dotenv
load_dotenv()
import os
from pydantic import SecretStr
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
model="qwen-plus",
api_key=SecretStr(os.environ["DASHSCOPE_API_KEY"]),
)
from langchain.agents import create_agent
from langchain_tavily import TavilySearch
# 3. 初始化Tavily搜索工具(配置API密钥)
web_search = TavilySearch(
api_key=os.environ["TAVILY_API_KEY"], # 配置Tavily密钥
max_results=2, # 限制搜索结果数量
search_depth="basic" # 基础搜索,速度更快
)
# 3.创建Agent
agent = create_agent(
model=llm,
tools=[web_search],
system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)
from langchain_core.tools import tool
# 4.运行Agent获得结果
result = agent.invoke(
{"messages": [{"role": "user", "content": "请帮我查询2023年诺贝尔物理学奖得主是谁?"}]}
)
finalAnswer = result['messages'][-1].content
print(finalAnswer)
案例三
一、案例背景与核心目标
本案例将实现一个具备两大核心能力的智能 Agent:
- 调用 OpenWeather API 查询指定城市的实时天气;
- 将查询到的天气信息自动写入本地文本文件;
- Agent 能根据用户指令(如 “查询天津、石家庄、上海天气并写入文件”),自动判断并依次调用上述两个工具完成任务。
二、环境准备
1. 安装依赖
pip install langchain langchain-openai langchain-tavily python-dotenv pydantic requests
2. 配置环境变量(.env 文件)
在项目根目录创建.env文件,填入所需 API 密钥(需提前申请):
# 阿里云通义千问API密钥(灵积平台获取)
DASHSCOPE_API_KEY=your_dashscope_api_key
# OpenWeather天气API密钥(官网免费申请)
OPENWEATHER_API_KEY=your_openweather_api_key
3.openweather官网获取API-KEY
这里需要先登录openweather官网获取API-KEY:https://home.openweathermap.org/ ,然后将其写入.env中的OPENWEATHER_API_KEY变量中。
三、完整实战代码(含详细注释)
from datetime import datetime
from dotenv import load_dotenv
load_dotenv() # 加载.env环境变量
import os
import requests
import json
from pydantic import SecretStr
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.tools import tool # 自定义工具装饰器
# ====================== 1. 初始化大语言模型 ======================
llm = ChatOpenAI(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
model="qwen-plus", # 通义千问增强版
api_key=SecretStr(os.environ["DASHSCOPE_API_KEY"]),
)
# ====================== 2. 自定义工具开发 ======================
# 工具1:查询即时天气(调用OpenWeather API)
@tool # 核心装饰器:将普通函数转为LangChain可调用的Tool
def get_weather(loc: str) -> str:
"""
查询指定城市的即时天气(核心文档字符串,Agent依赖此理解工具功能)
:param loc: 必要参数,字符串类型,城市英文名称(如北京=Beijing);
:return: JSON格式的天气信息字符串(包含温度、湿度、天气状况等)。
"""
# 1. 构建API请求参数
url = "https://api.openweathermap.org/data/2.5/weather"
params = {
"q": loc,
"appid": os.getenv("OPENWEATHER_API_KEY"),
"units": "metric", # 摄氏度(默认华氏度)
"lang": "zh_cn" # 中文返回结果
}
# 2. 发送请求并处理响应
try:
response = requests.get(url, params=params)
response.raise_for_status() # 捕获HTTP错误(如404/500)
return json.dumps(response.json(), ensure_ascii=False, indent=2)
except Exception as e:
return f"天气查询失败:{str(e)}"
# 工具2:将内容写入本地文件(带时间戳命名)
@tool
def write_file(content: str) -> str:
"""
将指定内容写入本地文件(自动生成带时间戳的文件名)
:param content: 必要参数,字符串类型,需写入文件的内容;
:return: 写入成功/失败的提示信息(含文件绝对路径)。
"""
try:
# 生成唯一文件名(避免覆盖)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"weather_{timestamp}.txt"
# 写入文件(指定UTF-8编码,避免中文乱码)
with open(filename, "w", encoding="utf-8") as f:
f.write(content)
# 返回绝对路径,方便用户查找
abs_path = os.path.abspath(filename)
return f"✅ 文件写入成功:{abs_path}"
except Exception as e:
return f"❌ 文件写入失败:{str(e)}"
# ====================== 3. 创建Agent并绑定工具 ======================
agent = create_agent(
model=llm, # 核心LLM模型
tools=[get_weather, write_file], # 绑定自定义工具列表
system_prompt="""
你是专业的天气助手,需按以下规则执行任务:
1. 查询多个城市天气时,需逐个调用get_weather工具(城市名转英文);
2. 将所有城市天气信息整理为清晰格式后,调用write_file工具写入本地;
3. 最终返回文件路径和简要的天气总结。
"""
)
# ====================== 4. 执行Agent并输出结果 ======================
result = agent.invoke({
"messages": [{"role": "user", "content": "请帮我查询天津、石家庄、上海等地天气,并写入本地文件。"}]
})
# 提取最终回答并打印
final_answer = result['messages'][-1].content
print("Agent执行结果:")
print(final_answer)
四、核心知识点深度解析
1. 自定义 Tool 的核心:@tool装饰器
@tool是 LangChain 将普通 Python 函数转为可被 Agent 调用的工具的核心装饰器,其工作原理是:
- 解析函数的文档字符串(docstring):Agent 通过这段文字理解工具的功能、参数要求,这是工具能被正确调用的关键;
- 封装函数入参 / 出参:自动适配 Agent 的调用格式,无需手动处理参数转换;
- 生成工具标识:为每个工具生成唯一名称(默认是函数名),方便 Agent 选择调用。
文档字符串编写规范(关键!)
@tool
def get_weather(loc: str) -> str:
"""
查询指定城市的即时天气(工具功能描述)
:param loc: 必要参数,字符串类型,城市英文名称(如北京=Beijing);(参数说明)
:return: JSON格式的天气信息字符串;(返回值说明)
"""
⚠️ 注意:文档字符串必须清晰说明参数类型、取值要求、返回格式,否则 Agent 可能传错参数(比如用 “天津” 而非 “Tianjin”)。
2. 天气查询工具(get_weather)核心逻辑
关键步骤:
- API 参数配置:
units="metric":将温度单位从华氏度转为摄氏度(符合中文用户习惯);lang="zh_cn":让返回的天气描述(如 “晴”“多云”)为中文;q=loc:接收城市英文名称(OpenWeather API 要求)。
- 异常处理:
- 用
response.raise_for_status()捕获 401(密钥错误)、404(城市不存在)等 HTTP 错误; - 外层
try-except确保工具不会因异常崩溃,而是返回错误提示(Agent 能识别并调整策略)。
- 用
- 结果格式化:
- 用
json.dumps(..., ensure_ascii=False, indent=2)让返回的 JSON 字符串带缩进、中文正常显示,方便后续写入文件。
- 用
3. 文件写入工具(write_file)核心优化
新手避坑点:
- 唯一文件名生成:
- 用
datetime.now().strftime("%Y%m%d_%H%M%S")生成时间戳,避免多次运行覆盖文件;
- 用
- 编码设置:
- 写入文件时指定
encoding="utf-8",解决中文乱码问题(Windows 默认 GBK 编码);
- 写入文件时指定
- 绝对路径返回:
- 用
os.path.abspath(filename)返回文件绝对路径,用户无需手动找文件位置;
- 用
- 异常捕获:
- 捕获所有可能的异常(如权限不足、磁盘满),返回友好提示,而非直接抛出错误。
4. Agent 绑定工具与系统提示优化
核心配置:
agent = create_agent(
model=llm,
tools=[get_weather, write_file], # 支持多个工具同时绑定
system_prompt="""
你是专业的天气助手,需按以下规则执行任务:
1. 查询多个城市天气时,需逐个调用get_weather工具(城市名转英文);
2. 将所有城市天气信息整理为清晰格式后,调用write_file工具写入本地;
3. 最终返回文件路径和简要的天气总结。
"""
)
系统提示的关键作用:
- 无约束的系统提示(如 “你是智能助手”)可能导致 Agent 只查询天气但不写入文件,或直接返回原始 JSON 数据;
- 明确的规则指引(如 “逐个调用工具”“整理格式后写入”)能大幅提升 Agent 的任务完成率。
五、执行效果与结果示例
用户输入:
请帮我查询天津、石家庄、上海等地天气,并写入本地文件。
Agent 执行流程(内部逻辑):
- 解析用户需求:需要查询 3 个城市天气 → 写入文件;
- 转换城市名称:天津→Tianjin、石家庄→Shijiazhuang、上海→Shanghai;
- 逐个调用
get_weather工具,获取每个城市的天气数据; - 整理数据为易读格式(如下);
- 调用
write_file工具写入本地; - 返回最终结果(含文件路径 + 天气总结)。
最终输出示例:
plaintext
Agent执行结果:
✅ 已完成天气查询并写入文件,详情如下:
1. 天津(Tianjin):
{
"coord": {"lon": 117.2, "lat": 39.13},
"weather": [{"id": 800, "main": "Clear", "description": "晴", "icon": "01d"}],
"main": {"temp": 22.5, "feels_like": 22.8, "humidity": 65},
"name": "Tianjin"
}
2. 石家庄(Shijiazhuang):
{
"coord": {"lon": 114.48, "lat": 38.03},
"weather": [{"id": 801, "main": "Clouds", "description": "多云", "icon": "02d"}],
"main": {"temp": 24.1, "feels_like": 24.5, "humidity": 58},
"name": "Shijiazhuang"
}
3. 上海(Shanghai):
{
"coord": {"lon": 121.47, "lat": 31.23},
"weather": [{"id": 500, "main": "Rain", "description": "小雨", "icon": "10d"}],
"main": {"temp": 28.3, "feels_like": 30.5, "humidity": 78},
"name": "Shanghai"
}
📁 天气信息已写入文件:/Users/xxx/weather_20260107_153022.txt
💡 总结:天津晴(22.5℃)、石家庄多云(24.1℃)、上海小雨(28.3℃)。
六、扩展与优化建议
1. 工具增强
- 参数校验:在
get_weather中添加城市名称校验(如判断是否为有效英文名称); - 批量查询:优化
get_weather支持多城市批量查询,减少 API 调用次数; - 结果解析:将原始 JSON 数据解析为自然语言(如 “天津当前温度 22.5℃,晴,湿度 65%”),提升可读性。
2. Agent 能力优化
- 工具优先级:通过
tool_selection参数指定工具调用优先级; - 多轮对话:支持用户追问(如 “文件里的上海温度是多少?”);
- 重试机制:工具调用失败时(如 API 超时),让 Agent 自动重试。
3. 生产环境适配
- 日志记录:添加日志模块,记录工具调用过程和参数;
- 权限控制:限制文件写入路径(避免 Agent 写入敏感目录);
- 性能监控:统计工具调用耗时,优化慢接口(如天气 API)。
总结
- LangChain 自定义 Tool 的核心是
@tool装饰器 + 清晰的文档字符串,Agent 依赖文档字符串理解工具功能和参数; - 工具开发需注重异常处理和用户体验(如唯一文件名、中文编码、绝对路径),避免崩溃或乱码;
- 系统提示是 Agent 正确调用工具的关键,需明确任务步骤和规则,而非仅泛化描述。
通过本案例,你不仅能掌握自定义 Tool 的开发方法,还能理解 Agent 如何 “思考” 并调用工具完成复杂任务,为后续开发更复杂的智能体(如数据分析助手、自动化办公机器人)打下基础。

更多推荐



所有评论(0)