Langchain-Chatchat Agent 天气查询工具(weather_check)原理、配置与实战指南
天气查询是智能体(Agent)应用中最常见的实时信息类工具之一。本文以 Langchain-Chatchat 仓库中内置的 weather_check(天气查询)Agent 工具为核心,系统讲解该工具如何通过"心知天气"(Seniverse)HTTP API 获取指定地点的实时天气、如何注册进 Agent 工具注册表并被 LLM 调度调用,以及它的配置方式、输入输出约束与异常处理机制。读完本文,你将掌握在 Langchain-Chatchat 中启用并自定义天气查询工具所需的完整配置项、调用链原理与排错要点。
一、工具定位:从一次"今天天气怎么样"说起
Langchain-Chatchat 是基于 Langchain 的 RAG 与 Agent 应用,其 Agent 能力依赖一组可被大模型自主调用的工具。天气查询正是其中一种典型的"单参数输入"实时查询工具:当用户问出"厦门今天天气如何"这类问题时,Agent 会识别意图并调用本工具,将实时天气数据作为上下文回传给 LLM,最终由 LLM 组织成自然语言回答。
该工具在代码仓库中的实现文件为 libs/chatchat-server/chatchat/server/agent/tools_factory/weather_check.py,对应自动生成的 API 文档为 markdown_docs/server/agent/tools/weather_check.md。需要特别说明的是:文档与实现存在历史命名差异——文档记录的是早期 weather(location, api_key) + weathercheck(location) 的两层封装设计,而当前仓库已将其重构为单一工具函数 weather_check(city)。本文以当前仓库源码为准,并指出两者的对应关系。
二、工作原理:一次天气 API 请求的完整数据流
2.1 核心函数签名
当前实现将工具函数以装饰器 @regist_tool 注册,函数本体如下(简化自 weather_check.py):
@regist_tool(title="天气查询")
def weather_check(
city: str = Field(description="City name,include city and county,like '厦门'"),
):
"""Use this tool to check the weather at a specific city"""
tool_config = get_tool_config("weather_check")
api_key = tool_config.get("api_key")
url = f"https://api.seniverse.com/v3/weather/now.json?key={api_key}&location={city}&language=zh-Hans&unit=c"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
weather = {
"temperature": data["results"][0]["now"]["temperature"],
"description": data["results"][0]["now"]["text"],
}
return BaseToolOutput(weather)
else:
raise Exception(f"Failed to retrieve weather: {response.status_code}")
一次完整的天气查询由以下环节串联而成:
- 获取配置:调用 utils.py 中的
get_tool_config("weather_check"),从全局Settings.tool_settings中取出该工具的配置字典; - 读取密钥:从配置字典中读取
api_key字段,作为心知天气 API 的访问凭证; - 构造请求 URL:向心知天气实时天气接口
https://api.seniverse.com/v3/weather/now.json发起 GET 请求,携带以下查询参数:
| 查询参数 | 值 | 含义 |
|---|---|---|
key |
配置中的 api_key |
心知天气 API 密钥 |
location |
用户输入的城市 | 查询地点,需包含城市与县区名称以精确定位 |
language |
zh-Hans |
返回语言为简体中文 |
unit |
c |
温度单位为摄氏度 |
- 解析响应:请求返回 HTTP 200 时,从 JSON 响应体中逐级取出
data["results"][0]["now"]["temperature"](当前温度)与data["results"][0]["now"]["text"](天气描述,如"多云"),组装为字典并包装成BaseToolOutput返回给 Agent 链路; - 异常兜底:状态码非 200 时抛出
Exception,异常信息直接包含失败的 HTTP 状态码。
2.2 返回值结构
无论文档记录的旧版函数还是当前实现,返回内容的核心形态一致——一个同时包含温度和天气描述的字典,典型返回值如下:
{
"temperature": "22",
"description": "多云"
}
在旧版文档 weather_check.md 中,这一返回值被描述为"包含温度和天气描述信息";在当前实现中,它被 BaseToolOutput 包装后交由 Agent 的 output parser 与回调处理,最终作为工具执行结果拼入大模型的提示上下文。也就是说:工具只负责取数,组织成"厦门当前温度 22 度,多云"这样的自然语言回答由 LLM 完成。
三、配置方法:如何让天气工具"跑起来"
天气工具默认处于关闭状态,且 api_key 为空。要让它在 Agent 中生效,必须完成两件事:填入有效的 API 密钥、打开开关。
3.1 默认配置与加载机制
工具的所有配置项定义在 settings.py 的 ToolSettings 类中:
weather_check: dict = {
"use": False,
"api_key": "",
}
'''心知天气(https://www.seniverse.com/)工具配置项'''
两个配置字段的含义:
use:布尔值,是否启用该工具,默认为False;api_key:字符串,心知天气(Seniverse)的 API 密钥,默认为空字符串,须向 心知天气官网 申请获得。
ToolSettings 在定义时指定了配置来源文件(见 settings.py):它会读取 Chatchat 根目录下的 tool_settings.yaml 或 tool_settings.json(两者都不存在时回落为代码内默认值),并且设置了 extra="allow" 允许额外字段。这意味着你只需在配置文件中覆盖需要改写的项即可,其余工具配置保持默认。
3.2 在配置文件中的写法
在运行目录下创建 tool_settings.yaml,写入:
weather_check:
use: true
api_key: "你的心知天气API密钥"
或等价地使用 JSON 格式的 tool_settings.json:
{
"weather_check": {
"use": true,
"api_key": "你的心知天气API密钥"
}
}
配置读取的底层实现位于 utils.py:get_tool_config 内部通过 Settings.tool_settings.model_dump() 将全部工具配置序列化为字典,再按工具名取对应子字典。因此 weather_check 工具运行时拿到的 api_key,正是此处配置文件的键值。
3.3 配置即代码:同一工具在不同位置的参数名
值得提醒的是:配置字段名与函数参数名并不一致。配置里通过 api_key 提供密钥,而函数内部用 tool_config.get("api_key") 读取;用户实际传入的地点则绑定在函数的 city 参数上。从源码结构看,之所以拆成两个来源,是因为"密钥"属于部署环境的静态配置,而"地点"属于每次调用时由 LLM 动态生成的入参——二者分离既避免了密钥泄露到对话上下文中,也保证了工具的可复用性。
四、注册链路:工具如何进入 Agent 的能力清单
4.1 regist_tool 装饰器与工具注册表
weather_check 工具本身不含显式的 WeatherInput 类定义,但依赖装饰器与 Pydantic 的类型注解完成 Schema 推导。regist_tool 的定义位于 tools_registry.py,它是 langchain tool 装饰器的封装,核心行为包括:
- 将装饰的工具实例写入全局字典
_TOOLS_REGISTRY,键名为工具名(对 weather_check 而言即weather_check),供get_tool按名称索引; - 若未显式提供
description,则自动提取函数 docstring 并压缩为单行描述; - 若未显式提供
title,则由工具名按首字母大写拼接生成;而 weather_check 通过@regist_tool(title="天气查询")显式指定了面向人类/前端展示的中文标题"天气查询"; - 通过
BaseTool._parse_input与BaseTool._to_args_and_kwargs的补丁(见 tools_registry.py),支持以 PydanticField定义的工具参数被正确解析为调用关键字参数。
4.2 参数 Schema:从 Pydantic Field 到 LLM 理解
虽然当前源码没有独立的 WeatherInput 类,但等价信息通过函数签名中的类型注解承载:
city: str = Field(description="City name,include city and county,like '厦门'")
这段声明对应文档中记载的 WeatherInput.location 属性描述("City name, include city and county"),且更明确地给出了示例"厦门"。其作用是双向的:
- 对 LLM:
description会随工具 Schema 一起提供给大模型,指导它把"福建厦门的天气"抽取出入参厦门; - 对运行时:pydantic 会对 LLM 生成的入参做类型校验,确保
city是合法的字符串,随后才真正发起网络请求。
从使用建议看,传入的地点应尽量"包含城市和县",例如使用"厦门"而非含糊的"那边",因为心知天气 API 依赖精确的地理位置返回准确数据。文档对此的注意点仍适用于当前实现:city 值的格式直接影响查询准确性。
4.3 工具集合的导入
libs/chatchat-server/chatchat/server/agent/tools_factory/init.py 中通过 from .weather_check import weather_check 将本工具纳入 tools_factory 包。当 Agent 加载全部工具时,即可通过 utils.py 的 get_tool() 拿到 _TOOLS_REGISTRY 中已注册的 weather_check 工具并绑定到模型。
五、文档与实现的演进对照:天气工具的两次封装
原始 API 文档 weather_check.md 描述的是更早版本的设计,与当前实现存在明显差异,读历史文档或旧代码时可对照理解:
| 维度 | 文档记载(旧版设计) | 当前仓库实现 |
|---|---|---|
| 对外函数 | weathercheck(location)(简化入口) |
weather_check(city)(唯一工具函数) |
| 底层函数 | weather(location, api_key)(实际发请求) |
请求逻辑内联在 weather_check 中 |
| 密钥来源 | 预定义常量 SENIVERSE_API_KEY |
配置项 tool_settings 中的 api_key |
| 输入模型 | WeatherInput(含 location 字段) |
函数参数 city + Pydantic Field 注解 |
| 注册方式 | 普通函数 | @regist_tool(title="天气查询") 自动注册 |
这种演进是 Langchain-Chatchat 工具框架逐步"规范化"的缩影:旧的 weather/weathercheck 双层结构把"密钥传入"与"便捷调用"分离,适合模块内部复用;新的单函数设计则将工具声明、参数描述、配置读取、HTTP 请求与结果包装收敛到一处,配合装饰器统一注册,更贴合 Agent 工具"一个函数即一个能力单元"的组织范式。从仓库当前仅保留单一 weather_check 函数即可确认,旧的两层结构已被替换。
六、注意事项与常见问题
结合文档"注意"项与当前源码,使用天气工具时应关注以下几点:
- API 密钥必须有效:无效或欠费的
api_key会导致请求失败。当前实现中,HTTP 状态码非 200 时直接抛出Exception(f"Failed to retrieve weather: {response.status_code}"),该异常会沿 Agent 回调链上报,表现为工具调用报错。排查时先确认tool_settings.yaml中的api_key已正确填写且服务可用。 - 网络状况决定时延:工具本质是一次第三方 HTTP GET 请求,执行时间受网络环境影响。文档明确指出"在网络状况不佳的情况下,响应时间可能会较长",因此在离线环境或内网部署时,该工具无法正常工作,这是由依赖公网 API 的架构决定的。
- 不要忘记开启开关:即便配置了
api_key,只要use保持False,Agent 也不会实际启用该工具。修改配置后需重启服务使ToolSettings重新加载生效。 - 地点描述要精确:请求 URL 中的
location直接拼接自入参,建议按函数注解传入"包含市、县"的完整地点(如厦门),以确保命中正确的气象站点。 - 响应解析依赖固定字段:代码按
results[0].now.temperature与results[0].now.text取数,这是心知天气/weather/now.json接口的标准返回结构;若后续切换其他天气服务商,需同步调整解析逻辑。
七、小结
weather_check 是 Langchain-Chatchat Agent 工具体系中"实时数据查询类"工具的代表:通过 @regist_tool 完成注册,以 tool_settings.yaml 注入 API 密钥并受 use 开关控制,调用时以 Pydantic 注解引导 LLM 生成精确的地点入参,最终以"温度 + 天气描述"的结构化字典向 Agent 返回结果。开发者只需三步即可在本地启用:在心知天气申请 api_key、在 tool_settings.yaml 中填写并置 use: true、重启服务后在对话中发起天气提问。若想深入调试该工具与 Agent 的交互细节,可以继续阅读 tools_registry.py 了解注册与 Schema 解析机制,并结合 settings.py 中 ToolSettings 的定义掌握全部 Agent 工具的配置组织方式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00