LangChain 自定义工具 + 自定义链(附天气查询工具 + Agent 完整代码)
·
LangChain 最核心的扩展能力:
- 自定义工具:把任意 Python 函数包装成 LLM 能调用的工具
- 自定义链:灵活组装你的业务逻辑,不是简单的
Prompt | LLM
一、自定义工具(Custom Tools)
1. 什么是自定义工具?
简单来说,自定义工具就是把你的 Python 函数包装成 LLM 能理解、能自主调用的工具。
比如:
- 你写一个天气查询函数 → 包装成工具 → LLM 能自主调用查天气
- 你写一个数据库查询函数 → 包装成工具 → LLM 能自主查数据库
- 你写一个文件读写函数 → 包装成工具 → LLM 能自主读写文件
2. 自定义工具的 3 个核心要素
(1)@tool 装饰器
把普通 Python 函数变成 LangChain 工具的 “魔法装饰器”。
(2)清晰的 docstring(最重要!)
这是 LLM 的 “工具使用说明书”,LLM 完全靠看 docstring 来判断:
- 这个工具是做什么的
- 什么时候用这个工具
- 参数是什么
- 返回什么
docstring 写得越清楚,LLM 越会正确调用工具!
(3)正确的参数和返回值
参数要明确类型,返回值要是字符串(方便 LLM 理解)。
二、实战:自定义天气查询工具
我们用 OpenWeatherMap 免费 API 来做天气查询工具,稳定、免费、国内可访问。
1. 准备工作
(1)获取 OpenWeatherMap API Key
- 访问 OpenWeatherMap 官网
- 注册账号(免费)
- 登录后进入「My API Keys」,复制你的 API Key
(2)安装依赖
pip install -U langchain langchain-openai langchain-community python-dotenv requests
三、完整代码:自定义天气工具 + 自定义链 + ReAct Agent
import os
import requests
from dotenv import load_dotenv
# langchain 相关的模块
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_react_agent, AgentExecutor, create_tool_calling_agent
from langchain_core.output_parsers import StrOutputParser
from langchain_core.callbacks import BaseCallbackHandler, StdOutCallbackHandler
# 加载环境变量
load_dotenv()
# 配置
OPEN_WEATHER_API_KEY = os.getenv("OPEN_WEATHER_API_KEY")
ZHIPU_API_KEY = os.getenv("ZHIPU_API_KEY")
# 初始化LLM
llm = ChatOpenAI(
api_key=ZHIPU_API_KEY,
base_url="https://open.bigmodel.cn/api/paas/v4",
model='glm-4.6',
temperature=0.01
)
# 自定义天气查询工具
@tool
def get_weather(city: str) -> str:
"""
【天气查询专用工具】查询指定城市的实时天气信息
当用户询问天气、温度、湿度、风速等气象信息时,必须调用此工具
:param city: 城市名称,支持中文(如“北京”)或英文(如“Beijing”)
:return: 实时天气信息的字符串,包括温度、湿度、天气描述、风速
"""
base_url = "https://api.openweathermap.org/data/2.5/weather"
params = {
"lon": 116.40, # 经度
"lat": 39.90, # 纬度
# "q": city,
"appid": OPEN_WEATHER_API_KEY,
"units": "metric", # 摄氏度
"lang": "zh-CN", # 中文秒速
}
try:
response = requests.get(url=base_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
# 解析天气数据
weather_desc = data["weather"][0]["description"]
temp = data["main"]["temp"]
humidity = data["main"]["humidity"]
wind_speed = data["wind"]["speed"]
city_name = data["name"]
return (
f"【{city_name} 实时天气】\n"
f"天气:{weather_desc}\n"
f"温度:{temp}℃\n"
f"湿度:{humidity}%\n"
f"风速:{wind_speed} m/s"
)
except requests.exceptions.RequestException as e:
return f'天气查询失败:{str(e)}'
except KeyError:
return "未找到该城市的天气信息,请检查城市名称是否正确"
# 自定义链 Custom Chain
# 自定义链的两种方式:
# 1. RunnableLambda 最简单 适合简答的
# 2. 继承Runnable 最灵活 适合复杂的逻辑
# 例子1: 用 RunnableLambda 做一个简单的文本长度统计链
def count_text_length(text: str) -> str:
"""统计文本长度的自定义函数"""
return f"文本长度: {len(text)}个字符"
# 包装成 Runnable
length_counter = RunnableLambda(count_text_length)
# 例子2:组装一个完整的自定义链(翻译 + 长度统计)
translation_prompt = ChatPromptTemplate.from_template(("""把下面的文本翻译成英文:{text}"""))
translation_chain = translation_prompt | llm | StrOutputParser()
# 自定义链: 先翻译 在统计长度
custom_chain = (
{"text": RunnablePassthrough()}
| translation_chain
| (lambda x: {"original": x, "length": count_text_length(x)})
)
# 把自定义工具加入ReAct Agent
# 工具列表 把查询天气的工具加进去
tools = [get_weather]
# ReAct 提示词
prompt = ChatPromptTemplate.from_messages([
("system", """
你是一个强大的智能助手,能通过调用工具解决问题,会调用工具查天气。
核心规则:
1. 严格按照「Thought → Action → Observation」的格式执行
2. 当用户询问天气时,必须调用 get_weather 工具
3. 只有获取了足够的信息,才能输出 Final Answer
4. 禁止编造信息
"""),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# 创建 ReAct Agent
# agent = create_react_agent(llm, tools, prompt)
# 【关键修复】用新版 create_tool_calling_agent,兼容性更好
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, #开启详细日志
handle_parsing_errors=True,
callbacks=[StdOutCallbackHandler()]
)
# 主程序
def main():
print("=== 🚀 Langchain 自定义工具 + 自定义链 + Agent ===")
print("1. 测试自定义天气工具")
print("2. 测试自定义链(翻译+长度统计)")
print("3. 测试 ReAct Agent (自助调用天气工具)")
print("输入 q 退出\n")
while True:
choice = input("请选择功能 (1/2/3/q): ").strip()
if choice.lower() == "q":
print("👋 再见!")
break
# 测试1: 自定义天气工具
if choice == "1":
city = input("请输入城市名称:").strip()
result = get_weather.invoke(city)
print(f"\n 🌤️ 天气查询结果:\n {result}\n")
# 测试2: 自定义链
elif choice == "2":
text = input("请输入要翻译的中文文本:").strip()
result = custom_chain.invoke(text)
print(f"\n 📄 翻译结果:{result["original"]}")
print(f"📏 {result["length"]}\n")
# 测试3:ReAct Agent
elif choice == "3":
query = input("请输入你的问题 (比如:北京今天天气怎么样?)").strip()
result = agent_executor.invoke({"input":query})
print(f"\n 🤖 Agent最终回答:{result["output"]} ")
else:
print("⚠️ 无效选择,请重新输入! \n")
if __name__ == "__main__":
main()
四、.env 文件配置
DOUBAO_API_KEY=你的豆包APIKey
OPENWEATHER_API_KEY=你的OpenWeatherMapAPIKey
五、代码核心部分详解
1. 自定义天气工具:@tool 装饰器
@tool
def get_weather(city: str) -> str:
"""
【天气查询专用工具】查询指定城市的实时天气信息
当用户询问天气、温度、湿度、风速等气象信息时,必须调用此工具
:param city: 城市名称,支持中文(如“北京”)或英文(如“Beijing”)
:return: 实时天气信息的字符串,包括温度、湿度、天气描述、风速
"""
# ... 具体实现
@tool:把函数变成工具- docstring 极其重要:LLM 完全靠它判断什么时候用工具
- 参数和返回值明确:方便 LLM 理解
2. 自定义链:RunnableLambda
def count_text_length(text: str) -> str:
return f"文本长度:{len(text)} 个字符"
# 包装成 Runnable
length_counter = RunnableLambda(count_text_length)
RunnableLambda:把普通 Python 函数变成 LangChain 可调用的链- 可以和其他链用
|操作符串联
3. 把工具加入 Agent
tools = [get_weather]
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
- 把自定义工具加入
tools列表 - Agent 就能自主判断什么时候调用工具了
六、运行效果演示
测试 1:自定义天气工具
plaintext
请选择功能 (1/2/3/q): 1
请输入城市名称:北京
🌤️ 天气查询结果:
【Beijing 实时天气】
天气:clear sky
温度:15.23℃
湿度:12%
风速:1.84 m/s
测试 2:自定义链
请选择功能 (1/2/3/q): 2
请输入要翻译的中文文本:七里香
📄 翻译结果:“七里香”根据上下文不同,可以翻译为:
1. **Seven Mile Fragrance** (直译,最通用的翻译)
2. **Orange Jasmine** 或 **Chinese Box** (植物学名称,指九里香/月橘)
3. **Common Jasmine Orange** (周杰伦同名专辑及歌曲的官方英文译名)
📏 文本长度: 168个字符
测试 3:ReAct Agent
=== 🚀 Langchain 自定义工具 + 自定义链 + Agent ===
1. 测试自定义天气工具
2. 测试自定义链(翻译+长度统计)
3. 测试 ReAct Agent (自助调用天气工具)
输入 q 退出
请选择功能 (1/2/3/q): 3
请输入你的问题 (比如:北京今天天气怎么样?)北京天气怎么样?
> Entering new AgentExecutor chain...
Invoking: `get_weather` with `{'city': '北京'}`
responded: 我来帮您查询北京的天气情况。
【Beijing 实时天气】
天气:clear sky
温度:15.23℃
湿度:12%
风速:1.84 m/s根据查询结果,北京目前的天气情况如下:
🌤️ **天气状况**:晴朗(clear sky)
🌡️ **温度**:15.23℃
💧 **湿度**:12%
💨 **风速**:1.84 m/s
今天北京天气不错,晴朗的天空,温度适宜,湿度较低,微风轻拂,是个比较舒适的天气。
> Finished chain.
七、总结
- 自定义工具的核心:
@tool装饰器 + 清晰的 docstring - 自定义链的核心:
RunnableLambda或继承Runnable - Agent 调用工具的核心:把工具加入
tools列表,LLM 会自主判断
更多推荐
所有评论(0)