基于LangChain的天气查询插件开发与实践
一、插件设计背景
在智能对话系统中,天气查询是高频需求。本文将演示如何开发一个支持自然语言解析和异步API调用的天气插件,实现以下功能:
- 支持城市名称/行政编码双重输入
- 自动识别用户关注的天气要素
- 基于高德地图API获取实时天气数据
二、准备工作
1. 环境依赖
pip install langchain langchain-ollama aiohttp python-dotenv
2. 高德API配置
- 注册高德开放平台获取API Key
- 创建
.env
文件:
GAODE_API_KEY=your_api_key_here
三、核心代码实现
1. 天气工具类设计
class WeatherTool(BaseTool):
name: str = "get_current_weather"
description: str = (
"获取指定地点的当前天气信息。"
"参数应为包含'location'键的字典,"
"location可以是城市名称或行政编码"
)
api_key: str = GAODE_API_KEY
session: aiohttp.ClientSession = None
关键特性:
- 异步支持:使用
aiohttp
实现非阻塞IO - 会话复用:通过
create()
方法共享HTTP会话 - 错误处理:自定义
GeoAPIError
异常体系
2. 核心功能模块
(1)地理编码解析
async def _get_city_code(self, location: str) -> str:
"""自动识别城市名称/编码"""
params = {"key": self.api_key, "address": location}
async with self.session.get(GEOCODE_URL, params=params) as response:
data = await response.json()
return geocodes[0]["adcode"] # 返回行政编码
(2)天气数据获取
async def _arun(self, location: str) -> str:
"""异步执行主逻辑"""
city_code = location if location.isdigit() else await self._get_city_code(location)
params = {"city": city_code, "key": self.api_key}
async with self.session.get(WEATHER_URL, params=params) as response:
return self._format_weather_data(await response.json())
(3)数据格式化
@staticmethod
def _format_weather_data(data: Dict) -> str:
"""人性化输出设计"""
return (
f"📍地区:{weather.get('province')} {weather.get('city')}\n"
f"🌤天气:{weather.get('weather')}\n"
f"🌡温度:{weather.get('temperature')}℃"
)
3. 智能解析模块
tool_prompt = ChatPromptTemplate.from_messages([
SystemMessage(content=(
"请从用户输入中识别:"
"1. 地理位置(支持中文名称/行政编码)"
"2. 用户关心的天气要素"
"请用JSON返回{location}"
)),
HumanMessage(content=message)
])
四、插件集成与测试
1. 完整调用链
async def get_weather_info(message: str) -> List[ToolMessage]:
weather_tool = await WeatherTool.create()
try:
tool_llm = ChatOllama( # 使用本地部署的Qwen模型
model="qwen2.5:32b",
base_url="http://192.168.1.237:11434"
).bind_tools([weather_tool])
chain = tool_prompt | tool_llm # 组合提示模板和模型
response = await chain.ainvoke({"input": message})
# 处理工具调用结果
return [await _handle_tool_call(call, weather_tool) for call in response.tool_calls]
finally:
await weather_tool.close()
2. 测试用例与结果
测试输入 | 处理逻辑 | 输出示例 |
---|---|---|
“北京海淀区天气怎么样?” | 解析为城市名称 | 🌡温度:18℃ 🌤天气:多云 |
“110101的天气” | 直接使用行政编码 | 📍地区:北京市 东城区 |
“上海浦东风力” | 提取关注要素 | 💨风力:3级 |
五、扩展与优化建议
1. 功能增强方向
# 建议扩展点示例
def _format_weather_data(data: Dict) -> str:
# 添加空气质量数据
if (forecasts := data.get("forecasts")):
return f"🌬空气质量:{forecasts[0]['aqi']}"
# 支持多日预报
if len(lives) > 1:
return "\n".join([format_day(day) for day in lives])
2. 部署建议
- 使用
uvicorn
部署为HTTP服务:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.post("/weather")
async def get_weather(message: str):
return await get_weather_info(message)
- 配置Nginx反向代理提升安全性
六、总结
本文通过实际代码演示了:
- 基于LangChain工具链的插件开发规范
- 异步API调用的最佳实践
- 自然语言到结构化参数的解析方法
- 异常处理与用户体验优化
该插件可无缝集成到各类对话系统中,通过扩展_format_weather_data
方法,可轻松支持空气质量、生活指数等更多天气相关功能。