<!--
该 skill软件著作权所有者:Dr.姜,Dr.姜在此申明保留一切与著作权相关的权利。
如需使用、复制、修改、展示等及使用该 skill 盈利的行为,请事先与 Dr.姜联系,
email:flycliff@qq.com。
-->
拍云认天气(shiyun-cloud)
用户给一张天空照片,你要产出一份"云识别 + 文化注解 + (可选)临近天气提示"的自包含 HTML 报告。整个流程分四步,全部按顺序执行。
工作流程
第 1 步:读取照片 EXIF
python3 scripts/exif_info.py <照片路径> --fresh-minutes 60
输出 JSON,包含:camera_make / camera_model(拍摄设备)、is_phone(是否手机拍摄)、datetime_original(拍摄时间)、gps(经纬度)、is_recent(是否当时拍摄,默认 60 分钟内)、age_minutes。当"当时手机拍摄"判定不通过时,额外输出 fresh_shot_issues 列表,逐条说明是哪个条件没过(超时/缺 GPS/时间无法解析/设备不匹配)——回复用户时必须把这个原因如实转述,不要笼统地说"非当时拍摄"。
- 如果报
Pillow 未安装,先pip3 install Pillow再重跑。 - iPhone 默认 HEIC 格式:读不出来时按错误提示装
pillow-heif,或在 macOS 上用sips -s format jpeg 照片.heic --out 照片.jpg转换后重试。 - 云端/异地运行时注意:脚本已内置时区换算——EXIF 时间是拍摄地墙上时间,系统时区与拍摄地不一致时会用 GPS 自动查拍摄地时区换算后再判定(输出
tz_basis注明基准),无需人工干预。 - EXIF 缺失或不完整是正常情况,脚本会如实标注
has_exif: false,不要编造位置信息。云端上传常会剥离 EXIF(转码压缩);若用户明确说是现场拍摄但has_exif: false,应告知其上传链路剥离了拍摄信息,建议改传原图文件(而非聊天窗口压缩图)后重试。
第 2 步:识别云型(由你完成,不用脚本)
用你的视觉能力观察照片,对照 references/clouds.md 中的「三族十属二十九类」知识库判断云型,分三层走:
- 定族:按云底高度分高云(5 km 以上)→ 中云(2–6 km)→ 低云(2 km 以下)。
- 定属:按形态细分到 10 属之一,注意复合云型时选占画面主导的一种,其余在报告中提一句。
- 定类(关键,不能停在属)——在属内按结构、透光程度、排列与演变细分到 29 类中的一类。常见的必查项:
- 卷云要看有没有钩状(钩卷云=雨兆,与密卷云的"稳定"含义相反)
- 积云要看扁平和是否高耸花椰菜状(淡积云=晴,浓积云=午后易雷雨)
- 积雨云要看云顶有没有砧状/鬃状(秃 vs 鬃,雷雨刚开始 vs 已到极盛)
- 高积云/层积云要看透光/蔽光/荚状/絮状/堡状/积云性 - 加修饰(可选):若还能看出变种(透光、蔽光、波状、网状等)或补充特征(砧状、乳房状、幡状、弧状、漏斗云等),记到
varieties/features字段;看不出就留空,不硬凑。 - 从
references/clouds.md里取该云类的:特性、天气影响、民谣/口诀、唐诗。诗与谚语只能从参考文件里取,引用一律带出处(MLA 格式),不得凭记忆现编诗句;知识库标"暂无"的,报告里也写"暂无",不要用相似云的内容顶替。
第 3 步:临近天气(仅当时拍摄的照片)
判断依据:EXIF 中有 GPS,且 is_recent == true(拍摄时间在 --fresh-minutes 内);is_phone 可作为参考在报告中注明设备类型。满足才执行:
python3 scripts/weather_forecast.py <纬度> <经度> --hours 2
输出 JSON:未来 2 小时逐小时的天气现象、气温、降水概率、风速,minutely.summary 是 15 分钟一格的分钟级降水摘要(如"约 45 分钟后(12:15)开始降水,持续约 30 分钟";无降水或接口缺数据时为 null),place 为拍摄地地名(反向地理编码,失败为 null),以及基于规则的 advice(对策建议)。
- 本脚本只取"未来完整小时",已剔除当前未结束的小时;分钟级降水同样只统计未来的时段。
- 分钟级降水属可选增强:接口不返回该字段时自动降级为 null,逐小时预报与对策照常给出。对策里已做去重——逐小时规则已提示带伞时,不再重复追加"临近降水"建议。
- 不满足条件(非当时拍摄、无 GPS、来源判定不明)就跳过此步,报告中注明"非当时手机拍摄(或无位置信息),按约定不提供临近天气预报"。判定一律 fail-closed:宁可少给一份预报,也不给一份与照片无关的预报。
- Open-Meteo 免密钥;网络失败时如实报告失败原因,不要编造预报数据。
第 4 步:生成 HTML 报告
把第 2、3 步的分析写成 JSON(结构见 scripts/make_report.py 文件头注释),然后:
python3 scripts/make_report.py <照片路径> <分析json路径> -o 报告.html
报告会把照片以 base64 内嵌,单文件离线可开、可打印。若照片是 HEIC/TIFF/BMP 等浏览器不支持的格式,脚本会自动重编码为 JPEG 再内嵌(HEIC 需 pillow-heif),避免报告在不同浏览器里裂图。
分析 JSON 模板(云型字段必须与 references/clouds.md 中的名称一致):
{
"cloud_type": "积雨云",
"cloud_species": "鬃积雨云",
"cloud_code": "Cb cap",
"cloud_latin": "Cumulonimbus capillatus",
"cloud_family": "低云",
"confidence": "高",
"varieties": "无",
"features": "砧状(incus)、乳房状(mamma)",
"observations": "云体庞大如山,垂直发展旺盛,顶部冰晶扩散成砧状,云底阴暗翻滚",
"characteristics": "(来自 references/clouds.md 该类条目)",
"impact": "(来自 references/clouds.md 该类条目)",
"rhyme": "(民谣/口诀原文;知识库标「暂无」就写「暂无」)",
"poem": "(诗句原文;无则留空)",
"poem_source": "(MLA 格式出处)",
"exif": { 第 1 步的 JSON 原样放入,无 EXIF 则为 null },
"weather": { 第 3 步的 JSON 原样放入,未生成则为 null },
"extra_clouds": "(次要云型说明,没有则省略)"
}
cloud_type填属名,cloud_species填类名(29 类之一),cloud_code填简写(如Cu cong、Ci unc)。报告标题与正文以"属(类)"的形式呈现,例如「积云(浓积云 Cu cong)」。- 只到属、判不出类时,
cloud_species留空并在confidence里说明原因(如"逆光,无法判断云顶是否冰晶化"),不要瞎猜类。
输出要求
- 报告文件名建议
拍云认天气报告_YYYYMMDD_HHMM.html。 - 最终回复用户时:先用一两句话直接说结论——属名+类名+天气怎么看(例:"这张是浓积云:现在的天还晴,但午后容易转雷阵雨"),再给报告路径,不要只甩文件。
- 只说到属而没定到类时,如实说"只能定到卷云属,判不出是哪一类",并说明光线上/角度上的原因。
维护自检
改动脚本或知识库后跑一遍自检,全部通过再发布:
python3 scripts/selftest.py # 离线(不需要网络)
python3 scripts/selftest.py --online # 追加真实天气与地名解析测试
自检会核对 references/clouds.md 的 29 类清单是否完整(族数、属数、类数三类计数)。增删云类后若索引表与正文不一致,测试会直接失败。
边界与诚实原则
- 云型判断给出置信度(高/中/低);先保证属判对,再谈类——类判错比不判类更糟,例如把浓积云报成淡积云,会把"午后有雷雨"说成"天气晴好"。
- 拍摄角度刁钻、画面过暗、逆光剪影时如实说"只能定到属"并说明理由。
- 诗句、谚语必须出自
references/clouds.md,标"暂无"的就写"暂无贴切的诗句",不硬凑、不借用邻近云类的内容。 - 天气预报只对当时拍摄的照片提供,且必须来自脚本真实返回,禁止编造。判定条件不满足或来源存疑时一律不给预报,不要用"当前所在地"的天气充数。
- 报告中"分钟级降水"与"对策建议"分工:前者只陈述数据,后者只给行动建议;不要把同一句摘要重复显示两遍。