心知天气通知 Skill (seniverse-weather)
基于心知天气 (Seniverse) API 的天气查询与通知技能。支持实时天气查询、逐日/逐时预报、天气预警、生活指数等,并可结合定时任务实现每日天气推送通知。
触发条件
用户提到以下意图时触发:
- "天气查询"、"今天天气"、"明天天气"、"天气预报"
- "心知天气"、"Seniverse"、"seniverse weather"
- "天气通知"、"每日天气推送"、"天气提醒"
- "气温"、"下雨"、"紫外线"、"穿衣指数"、"空气质量"
- "XX市天气"、"XX区天气"
API 信息
- API 基础地址:
https://api.seniverse.com/v3/ - API Key: 用户首次使用时需提供自己的心知天气 API 私钥(key)
- 免费版限制: 400次/小时,支持天气实况、逐日预报、逐时预报、生活指数
- 注册地址: https://www.seniverse.com 注册后可在控制台获取 API 密钥
- 安全验证: 使用私钥直接请求方式,将 key 参数附加到 URL
核心接口
1. 天气实况
GET https://api.seniverse.com/v3/weather/now.json
参数:
key: API 私钥
location: 城市名/拼音/IP/经纬度
language: zh-Hans (中文简体)
unit: c (摄氏度)
返回:温度、天气现象、风力风向、湿度、体感温度等
2. 逐日预报(3天)
GET https://api.seniverse.com/v3/weather/daily.json
参数:
key: API 私钥
location: 城市名/拼音/IP/经纬度
language: zh-Hans
unit: c
start: 起始天数 (0=今天, 1=明天, 默认0)
days: 预报天数 (默认3, 最大3)
返回:每日最高/最低温度、白天/夜间天气现象、风向风力、日出日落
3. 逐时预报(24小时)
GET https://api.seniverse.com/v3/weather/hourly.json
参数:
key: API 私钥
location: 城市名/拼音/IP/经纬度
language: zh-Hans
unit: c
hours: 小时数 (默认24)
返回:逐小时温度、天气现象、风力风向、湿度
4. 生活指数
GET https://api.seniverse.com/v3/life/suggestion.json
参数:
key: API 私钥
location: 城市名/拼音/IP/经纬度
language: zh-Hans
返回:穿衣、紫外线、洗车、旅游、运动、感冒等生活建议指数
5. 天气预警(免费版不支持)
GET https://api.seniverse.com/v3/weather/alarm.json
参数:
key, location, language
注意:天气预警需要付费版 API Key
使用前准备
用户必须先在心知天气官网注册并获取 API Key。 如果用户未提供 API Key,应提醒用户:
> 请先前往 心知天气官网 注册账号,在控制台中获取你的 API 私钥(key)。注册免费,免费版每日可调用天气实况、逐日预报、逐时预报和生活指数接口。
获取 API Key 后,用户可告知 Agent 存储以便后续使用(注意:出于安全考虑,API Key 不应持久化存储到 user 记忆中,仅在本次会话中使用)。
执行流程
场景一:即时天气查询
- 确认用户要查询的城市(默认根据用户常用城市或 IP 定位)
- 确认用户已有 API Key(如无则提示注册)
- 调用对应接口获取天气数据
- 格式化输出天气信息
Python 示例代码:
import requests
def query_weather_now(api_key, location="北京", language="zh-Hans", unit="c"):
"""查询天气实况"""
url = "https://api.seniverse.com/v3/weather/now.json"
params = {
"key": api_key,
"location": location,
"language": language,
"unit": unit
}
resp = requests.get(url, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
return data
def query_weather_daily(api_key, location="北京", days=3):
"""查询逐日预报"""
url = "https://api.seniverse.com/v3/weather/daily.json"
params = {
"key": api_key,
"location": location,
"language": "zh-Hans",
"unit": "c",
"days": days
}
resp = requests.get(url, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
return data
def query_life_suggestion(api_key, location="北京"):
"""查询生活指数"""
url = "https://api.seniverse.com/v3/life/suggestion.json"
params = {
"key": api_key,
"location": location,
"language": "zh-Hans"
}
resp = requests.get(url, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
return data
def format_weather_now(data):
"""格式化天气实况为可读文本"""
try:
result = data["results"][0]
loc = result["location"]
now = result["now"]
lines = [
f"📍 {loc['name']},{loc['country']}",
f"🌤 天气: {now['text']}",
f"🌡 温度: {now['temperature']}°C",
f"🤗 体感: {now['feels_like']}°C",
f"💨 风力: {now['wind_direction']} {now['wind_scale']}级",
f"💧 湿度: {now['humidity']}%",
f"👁 能见度: {now['visibility']}km",
f"📊 更新时间: {now['last_update']}",
]
return "\n".join(lines)
except (KeyError, IndexError) as e:
return f"解析天气数据失败: {e}\n原始数据: {data}"
def format_weather_daily(data):
"""格式化逐日预报为可读文本"""
try:
result = data["results"][0]
loc = result["location"]
lines = [f"📍 {loc['name']} 未来天气预报\n"]
for day in result["daily"]:
lines.append(
f"📅 {day['date']} ({day['week']})\n"
f" 白天: {day['text_day']} / 夜间: {day['text_night']}\n"
f" 🌡 {day['high']}°C ~ {day['low']}°C\n"
f" 💨 {day['wind_direction']} {day['wind_scale']}级\n"
f" 🌅 日出 {day['sunrise']} / 🌇 日落 {day['sunset']}"
)
return "\n".join(lines)
except (KeyError, IndexError) as e:
return f"解析天气数据失败: {e}\n原始数据: {data}"
def format_life_suggestion(data):
"""格式化生活指数为可读文本"""
try:
result = data["results"][0]
loc = result["location"]
lines = [f"📍 {loc['name']} 生活指数建议\n"]
suggestions = result.get("suggestion", {})
name_map = {
"dressing": "👕 穿衣",
"uv": "☀️ 紫外线",
"car_washing": "🚗 洗车",
"travel": "✈️ 旅行",
"sport": "🏃 运动",
"flu": "🤒 感冒",
"comfort": "😊 舒适度",
"air": "🌬 空气",
"rain": "🌧 雨伞",
}
for key, label in name_map.items():
if key in suggestions:
s = suggestions[key]
lines.append(f"{label}: {s['brief']}")
return "\n".join(lines)
except (KeyError, IndexError) as e:
return f"解析数据失败: {e}\n原始数据: {data}"
场景二:每日天气通知(定时任务)
结合 timer_task 工具,创建每日定时天气推送。
- 确认用户的城市和通知时间
- 确认用户已有 API Key
- 使用
timer_task(action="add")创建定时任务 - 定时任务 prompt 示例(不要包含"定时"等暗示词汇):
查询北京的今日天气实况和未来3天预报,包括生活指数建议,汇总成简洁的天气日报发送给我。
注意: 定时任务的 prompt 必须是纯粹的任务指令,不能包含"每天"、"定时"等词汇。
场景三:多城市对比
用户要求对比多个城市的天气时,分别查询各城市并生成对比表格。
输出格式规范
- 天气信息应结构化呈现,包含城市、温度、天气现象、风力等关键要素
- 推荐使用 emoji 增加可读性(但不是必须)
- 温度统一使用摄氏度(°C)
- 如数据解析失败,展示原始 JSON 供用户排查
注意事项
- API Key 安全: 不应将用户的 API Key 写入持久化记忆(user memory),仅在会话中临时使用
- 调用频率: 免费版限制 400次/小时,批量查询时注意控制频率
- 城市定位: location 参数支持城市中文名、拼音、城市ID、经纬度坐标、IP地址
- 错误处理: API 返回错误时(如 key 无效、超频),应友好提示并建议解决方案
- 免费版限制: 天气预警(alarm)接口免费版不可用,如用户需要应提示升级付费版