diff --git a/docs/API_ZH.md b/docs/API_ZH.md index b6ae140e..0f7008b2 100644 --- a/docs/API_ZH.md +++ b/docs/API_ZH.md @@ -126,18 +126,14 @@ SSE 事件: #### 2. `probabilities` -概率层现在按“校准模型概率”对外解释,而不是直接把模型票数或市场价格当成概率。 +概率层基于 legacy 高斯分桶,以 DEB 融合预测 μ 和 ensemble spread σ 生成 1°C 粒度概率分布。 -新增 / 重点字段: +概率字段: -- `engine`:概率引擎名称,例如 `lgbm_calibrated`、`emos`、`legacy` -- `calibration_mode`:校准运行模式 -- `calibration_version`:校准产物版本 -- `raw_mu` / `raw_sigma`:原始分布参数 -- `calibrated_mu` / `calibrated_sigma`:校准后分布参数 -- `shadow_distribution`:shadow / 对照分布,供回归与灰度验证 - -当前前端展示 `probabilities.engine` 对应的生产概率分布;`EMOS` / `LGBM` 只有在评估通过、显式启用或 shadow 对照时才进入展示/解释层。模型共识与市场价格只作为辅助参考,不再作为主结论。 +- `engine`:固定为 `legacy` +- `mu`:DEB 融合预测中心值 +- `distribution`:当天合约桶概率分布 +- `distribution_all`:包含外围桶的完整分布 #### 3. `detail_depth` diff --git a/docs/COMMERCIALIZATION.md b/docs/COMMERCIALIZATION.md index 6638bfb6..55d93e0f 100644 --- a/docs/COMMERCIALIZATION.md +++ b/docs/COMMERCIALIZATION.md @@ -32,7 +32,7 @@ PolyWeather 是面向温度结算场景的气象决策层,不是通用天气 - Pro 用户: - 今日日内深度分析(含高温时段) - 专业气象结论条、证据链、失效条件、确认条件 - - LGBM / EMOS 等校准概率层 + - 概率分布层(基于 DEB 融合 + 高斯分桶) - 历史对账 + 未来日期分析 - 全平台智能气象推送 diff --git a/docs/CONFIGURATION_ZH.md b/docs/CONFIGURATION_ZH.md index c4001a08..ff7b0d2c 100644 --- a/docs/CONFIGURATION_ZH.md +++ b/docs/CONFIGURATION_ZH.md @@ -111,7 +111,6 @@ PolyWeather 的环境变量很多,但不是所有变量都属于同一层级 - `TELEGRAM_MARKET_FOCUS_DIGEST_ENABLED` - `POLYMARKET_WALLET_ACTIVITY_ENABLED`(已退役,建议保持 `false`) - `POLYWEATHER_DASHBOARD_PREWARM_ENABLED` -- `POLYWEATHER_GROQ_COMMENTARY_ENABLED` ### 4.3 L3:运行调优项 @@ -137,9 +136,6 @@ PolyWeather 的环境变量很多,但不是所有变量都属于同一层级 - `POLYWEATHER_PREWARM_INCLUDE_DETAIL` - `POLYWEATHER_PREWARM_INCLUDE_MARKET` - `POLYWEATHER_PREWARM_FORCE_REFRESH` -- `POLYWEATHER_GROQ_COMMENTARY_MODEL` -- `POLYWEATHER_GROQ_COMMENTARY_TIMEOUT_SEC` -- `POLYWEATHER_GROQ_COMMENTARY_CACHE_TTL_SEC` 策略: @@ -167,7 +163,6 @@ PolyWeather 的环境变量很多,但不是所有变量都属于同一层级 - `METEOBLUE_API_KEY` - `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` - `POLYMARKET_SECRET_KEY` -- `GROQ_API_KEY` ## 5. 推荐部署矩阵 @@ -266,10 +261,6 @@ POLYWEATHER_PREWARM_JITTER_SEC=20 POLYWEATHER_PREWARM_INCLUDE_DETAIL=true POLYWEATHER_PREWARM_INCLUDE_MARKET=true POLYWEATHER_BACKEND_URL=http://polyweather_web:8000 -POLYWEATHER_GROQ_COMMENTARY_ENABLED=false -POLYWEATHER_GROQ_COMMENTARY_MODEL=openai/gpt-oss-20b -POLYWEATHER_GROQ_COMMENTARY_TIMEOUT_SEC=8 -POLYWEATHER_GROQ_COMMENTARY_CACHE_TTL_SEC=1800 POLYWEATHER_SCAN_AI_ENABLED=false POLYWEATHER_SCAN_AI_API_KEY=... POLYWEATHER_SCAN_AI_PROVIDER=mimo @@ -292,8 +283,6 @@ POLYWEATHER_SCAN_CITY_AI_MODEL=mimo-v2.5-pro - `TELEGRAM_MARKET_FOCUS_DIGEST_INTERVAL_SEC` 表示主动推送间隔,默认 `1800` 秒(30 分钟)。 - `POLYMARKET_WALLET_ACTIVITY_ENABLED` 已退役,保留为 `false` 即可,不建议再启用钱包异动监听。 - `POLYWEATHER_DASHBOARD_PREWARM_ENABLED=true` 时,建议同时启用独立 worker 或 bot 内嵌预热线程。 -- `POLYWEATHER_BACKEND_URL` 仅在独立 `polyweather_prewarm` worker 容器中使用,建议设为 `http://polyweather_web:8000`,不要写 `127.0.0.1`。 -- `POLYWEATHER_GROQ_COMMENTARY_ENABLED=false` 表示默认仍走规则文案;只有在确实配置了 `GROQ_API_KEY` 时才建议开启。 ### 6.3 Dashboard 预热 worker 推荐变量 @@ -311,22 +300,14 @@ POLYWEATHER_BACKEND_URL=http://polyweather_web:8000 说明: - 这组变量用于后台定向预热热点城市,避免用户点击城市时才冷启动拉 detail。 -- 如果使用独立 `polyweather_prewarm` 容器,`POLYWEATHER_BACKEND_URL` 必须指向容器网络中的 `polyweather_web`。 -### 6.4 Groq 解读增强层 ```env -POLYWEATHER_GROQ_COMMENTARY_ENABLED=true -GROQ_API_KEY=... -POLYWEATHER_GROQ_COMMENTARY_MODEL=openai/gpt-oss-20b -POLYWEATHER_GROQ_COMMENTARY_TIMEOUT_SEC=8 -POLYWEATHER_GROQ_COMMENTARY_CACHE_TTL_SEC=1800 ``` 说明: - 这层只负责把结构化信号改写成短摘要,不替代真实模型、机场锚点和结算逻辑。 -- Groq 调用失败时,系统会自动回退到规则文案。 ### 6.5 机器人市场监控建议配置 diff --git a/docs/EMOS_LGBM_SYSTEM_ZH.md b/docs/EMOS_LGBM_SYSTEM_ZH.md deleted file mode 100644 index ad3d37cb..00000000 --- a/docs/EMOS_LGBM_SYSTEM_ZH.md +++ /dev/null @@ -1,685 +0,0 @@ -# EMOS + LGBM 系统说明(中文) - -最后更新:`2026-04-19` - -本文档用于完整说明 PolyWeather 当前的两条统计/机器学习链路: - -- `EMOS`:概率后处理与校准链路 -- `LGBM`:日最高温点预测辅助模型 - -重点不只是“模型怎么训练”,还包括: - -- 这些模型依赖什么历史数据 -- 真值和训练特征现在如何长期保存 -- 为什么过去样本一直不够 -- 当前线上到底运行在哪个模式 -- 现在能做什么,不能做什么 - -本文档基于仓库当前实现与最近一轮重建结果,适合作为: - -- 项目内部模型说明 -- 运维与数据治理说明 -- 未来继续扩展 EMOS/LGBM 的基线文档 - ---- - -## 1. 总览 - -PolyWeather 当前不是“用一个模型替代所有东西”,而是多层结构: - -1. 多源天气采集层 -2. `DEB` 业务主预测层 -3. `LGBM` 轻量点预测辅助层 -4. `EMOS` 概率校准层 -5. 市场概率/桶命中评估层 - -可以简化理解为: - -```text -天气源 / 观测 / 历史真值 - ↓ - DEB 主预测 - ↓ - LGBM 辅助点预测 - ↓ -EMOS 对概率分布做后处理 - ↓ -市场概率 / shadow / rollout 门禁 -``` - -其中: - -- `DEB` 仍然是当前业务主路径 -- `LGBM` 是辅助预测源,不是主路径 -- `EMOS` 是概率后处理,不是基础天气模型 - ---- - -## 2. 两条链路各自负责什么 - -### 2.1 EMOS 负责什么 - -`EMOS` 的全称通常指 Ensemble Model Output Statistics。 - -在本项目里,它的角色不是重新预测温度,而是: - -- 把已有的预测结果做概率后处理 -- 让输出分布更“可校准” -- 让桶概率和市场评估更稳定 - -EMOS 关注的是: - -- `raw_mu` -- `raw_sigma` -- `deb_prediction` -- `ens_median` -- `ensemble_spread` -- `max_so_far_gap` -- `peak_flag` -- 最终真实 `actual_high` - -它最终输出的是一套“经过校准的概率分布”,而不是单一温度值。 - -所以 EMOS 的核心衡量指标不是单纯 MAE,而更看重: - -- `CRPS` -- `bucket_hit_rate` -- `bucket_brier` - -### 2.2 LGBM 负责什么 - -`LGBM` 是一个轻量级的回归模型,用来预测: - -- `actual_high`(日最高温) - -它吃的是: - -- 历史真值 lag 特征 -- 多模型 forecast -- `deb_prediction` -- 当前观测特征 -- 时间特征 - -它输出的是: - -- 一个点预测 `actual_high` - -然后这个点预测可以作为: - -- 额外 forecast 源 -- 供 DEB / 运营 / 研究参考 - -所以它和 EMOS 的区别非常重要: - -- `LGBM`:做点预测 -- `EMOS`:做概率校准 - ---- - -## 3. 当前代码结构 - -### 3.1 EMOS 相关 - -核心文件: - -- [probability_calibration.py](/E:/web/PolyWeather/src/analysis/probability_calibration.py) -- [probability_rollout.py](/E:/web/PolyWeather/src/analysis/probability_rollout.py) -- [fit_probability_calibration.py](/E:/web/PolyWeather/scripts/fit_probability_calibration.py) -- [evaluate_probability_calibration.py](/E:/web/PolyWeather/scripts/evaluate_probability_calibration.py) -- [build_probability_shadow_report.py](/E:/web/PolyWeather/scripts/build_probability_shadow_report.py) -- [judge_probability_rollout.py](/E:/web/PolyWeather/scripts/judge_probability_rollout.py) - -核心产物: - -- [default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json) -- [evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.json) -- [shadow_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/shadow_report.json) -- [rollout_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/rollout_report.json) -- [training_samples.json](/E:/web/PolyWeather/artifacts/probability_calibration/training_samples.json) - -### 3.2 LGBM 相关 - -核心文件: - -- [lgbm_daily_high.py](/E:/web/PolyWeather/src/models/lgbm_daily_high.py) -- [lgbm_features.py](/E:/web/PolyWeather/src/models/lgbm_features.py) -- [train_lgbm_daily_high.py](/E:/web/PolyWeather/scripts/train_lgbm_daily_high.py) -- [report_lgbm_daily_high.py](/E:/web/PolyWeather/scripts/report_lgbm_daily_high.py) - -核心产物: - -- [lgbm_daily_high.txt](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high.txt) -- [lgbm_daily_high_schema.json](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high_schema.json) - ---- - -## 4. 为什么之前样本总是上不去 - -这件事是理解当前状态的关键。 - -过去项目里有一个结构性问题: - -- `daily_records_store` 同时承担了 - - 运行态缓存 - - 历史训练数据来源 - -但运行态层会把 `daily_records` 硬裁成最近 14 天。 - -这意味着: - -- 对线上运行来说没问题 -- 对训练来说,历史监督样本会不断被删掉 - -结果就是: - -- 城市越来越多 -- 训练历史反而越来越稀 -- `LGBM` 很容易只有二十几条样本 -- `EMOS` 也只能靠有限 snapshot/daily_record 拼起来 - -这不是“模型太差”,而是“数据主存设计不对”。 - ---- - -## 5. 这次历史真值治理做了什么 - -现在已经把“运行态缓存”和“长期训练主存”拆开了。 - -### 5.1 `daily_records_store` - -继续保留,但只作为: - -- 最近 14 天运行态缓存 - -它不再承担长期训练历史职责。 - -### 5.2 `truth_records_store` - -新增永久真值表,作为长期训练真值主存。 - -当前核心字段包括: - -- `city` -- `target_date` -- `actual_high` -- `settlement_source` -- `settlement_station_code` -- `settlement_station_label` -- `truth_version` -- `updated_by` -- `updated_at` -- `source_payload_json` -- `is_final` - -这张表的意义是: - -- 长期保存监督真值 -- 不再被 14 天缓存裁剪 -- 真值来源变得可追溯 - -### 5.3 `truth_revisions_store` - -新增真值修订审计表。 - -它记录: - -- 老值是什么 -- 新值是什么 -- 来源怎么变了 -- 谁改的 -- 为什么改 -- 什么时候改 - -所以现在回填不会再是“静默覆盖”。 - -### 5.4 `training_feature_records_store` - -新增长期训练特征表。 - -它长期留存: - -- forecasts -- deb_prediction -- mu -- probability_features -- prob_snapshot -- shadow_prob_snapshot -- calibration 摘要 - -它的作用是: - -- 从现在开始,不再继续丢失历史训练特征 -- 让未来 EMOS/LGBM 样本自然累积 - ---- - -## 6. 训练数据现在怎么来 - -### 6.1 EMOS 训练样本 - -EMOS 训练不只是需要真值,还要有“当时那一刻的预测快照”。 - -所以一条 EMOS 样本,本质上需要两部分: - -1. 历史预测特征 -2. 对应日期最终真值 - -当前导出的 EMOS 样本里,核心字段包括: - -- `city` -- `date` -- `actual_high` -- `raw_mu` -- `raw_sigma` -- `deb_prediction` -- `ens_median` -- `ensemble_spread` -- `max_so_far_gap` -- `peak_flag` -- `sample_source` -- `settlement_source` -- `settlement_station_code` -- `truth_version` -- `truth_updated_by` -- `truth_updated_at` - -也就是说,EMOS 训练样本现在已经带了真值 provenance。 - -### 6.2 LGBM 训练样本 - -LGBM 训练样本会优先从: - -1. 永久真值表取监督目标 -2. 长期训练特征表取历史特征 -3. 再回退到必要的运行态/快照补充 - -当前 LGBM 样本会用到: - -- 历史 `actual_high` lag -- 历史均值/趋势 -- 多模型 forecast -- `deb_prediction` -- 当前观测 -- 时间特征 - ---- - -## 7. Wunderground 历史回填为什么重要 - -这次治理里一个重点是: - -- `Taipei` -- `Shenzhen` - -这两个城市配置了 `Wunderground` 历史页面作为历史观测取数入口。 - -这里要注意产品文案口径: - -- `Wunderground` 不是物理观测站 -- 它只是历史页面 / 数据入口 -- 机场类市场仍应以 METAR / 机场主站作为结算锚点 -- 明确官方站点市场才以规则指定的官方站点作为最终结算锚点 - -之前的问题是: - -- 城市注册表已经写成 `wunderground` -- 但历史回填链路还没有真正支持按指定历史日期抓 WU 历史页 - -所以过去它们的 `actual_high` 可能: - -- 没有被正确回填 -- 或者被错误来源污染 - -现在已经补了正式历史回填函数: - -- [wunderground_sources.py](/E:/web/PolyWeather/src/data_collection/wunderground_sources.py) - -它会: - -1. 按 `city + target_date` 拼出对应历史页 -2. 解析该日观测序列 -3. 取当日最高温 -4. 按市场规则做整度结算 -5. 写入永久真值表 -6. 记录来源与审计信息 - -这一步对 `Taipei/Shenzhen` 尤其关键,因为它们的历史页面取数和普通 METAR bootstrap 不同。 - ---- - -## 8. 当前线上/离线运行模式 - -### 8.1 概率引擎模式 - -当前生产主概率应保持: - -- `legacy` - -如果需要观察 EMOS 对照,可切: - -- `emos_shadow` - -而不是: - -- `emos_primary` - -原因不是工程没接好,而是主概率发布必须由离线评估结果决定。VPS 轻量训练候选未通过门禁;本地训练候选虽通过门禁,但仍建议先 shadow 观察,再人工决定是否切主。 - -### 8.2 LGBM 角色 - -当前 `LGBM` 仍然只能算: - -- 辅助预测源 -- 研究/观测链路 -- 校准概率层的一个可用引擎输入 - -不适合替代 `DEB` 主路径。 - -前端展示上,`LGBM 校准概率` 代表概率层已使用 LGBM 上下文生成桶分布;它不是把模型四舍五入票数直接当成概率。模型共识仍只是解释层,市场价格也只作为参考层。 - ---- - -## 9. 当前最新状态 - -以下状态来自最近一轮恢复、回填和重训产物。 - -### 9.1 永久真值 - -当前永久真值表已恢复到长期历史: - -- `truth_records_store` - - 最早:`2023-01-01` - - 最晚:`2026-04-02` - - 行数:约 `35138` - - 城市数:`30` - -运行态缓存仍然只有近 14 天: - -- `daily_records_store` - - 仍然是近两周范围 - -这说明: - -- 长期真值主存已经从运行态缓存里分离出来了 - -### 9.2 真值修订 - -当前已有 revision 审计记录: - -- `truth_revisions_store` - - 行数:`2` - -这说明审计链路已经在工作。 - -### 9.3 Wunderground 回填 - -`Taipei` 与 `Shenzhen` 已按 WU 历史页完成回填。 - -当前这两城已经补到: - -- `2026-04-02` - -### 9.4 长期训练特征 - -当前 `training_feature_records_store` 已经接通,但历史上真正留存下来的特征仍然很少。 - -这意味着: - -- 从现在开始不会继续丢 -- 但过去没留下的那部分特征,不会凭空恢复 - -这也是为什么: - -- 真值恢复了 -- `EMOS` 样本量却没有同步大幅增长 - ---- - -## 10. 当前 EMOS 结果怎么理解 - -最近两轮评估给出了更清晰的结论。 - -VPS 轻量训练候选: - -- 版本:`emos-auto-20260418204203` -- `sample_count = 791` -- `delta_crps = +0.004652` -- `delta_mae = +0.102623` -- `delta_bucket_hit_rate = -0.137800` -- 结论:`hold` - -本地训练候选: - -- 版本:`emos-auto-20260418212046` -- `sample_count = 847` -- `delta_crps = -0.036170` -- `delta_mae = -0.007896` -- `delta_bucket_hit_rate = -0.009445` -- 结论:`promote` - -这说明: - -- EMOS 工程链路有效,本地用更多 snapshot 训练时可以超过 legacy 的 CRPS/MAE。 -- 低配 VPS 不适合做主训练环境。 -- 通过门禁不等于立即默认主用,仍应先 `emos_shadow` 观察。 - -当前生产策略仍然是: - -- 用户主概率默认 `legacy` -- EMOS 通过本地训练产生候选 -- 通过门禁后先以 `emos_shadow` 灰度 -- 连续稳定后才考虑 `emos_primary` - -这不是“EMOS 无效”,而是: - -- 它还没有稳定到能切主路径 - -### 10.1 当前阻塞点 - -主要阻塞仍然是: - -- 有效样本仍然不大,城市级样本分布不均 -- 桶概率容易受结算边界影响 -- 需要避免 VPS 训练消耗线上资源 -- `emos_primary` 发布需要明确人工门禁 - -也就是说,当前 EMOS 状态可以总结成: - -- 工程链路完整 -- 数据治理大幅改善 -- 本地训练可通过门禁 -- 生产主用仍需 shadow 观察与人工发布 - ---- - -## 11. 当前 LGBM 结果怎么理解 - -最近一轮 LGBM 训练后,样本数已经从以前更少的状态提升到: - -- `sample_count = 54` -- `train_count = 42` -- `validation_count = 12` - -验证集指标大致为: - -- `lgbm_mae = 1.349` -- `deb_mae = 0.875` - -这说明: - -- LGBM 比以前样本更充足了 -- 但在验证集上仍然不如 DEB - -所以当前它的定位仍然应该是: - -- 辅助参考 -- 不替代 DEB - ---- - -## 12. 为什么现在 EMOS 没有像 LGBM 那样明显涨样本 - -这点很容易误解。 - -答案不是“恢复失败”,而是两条链路对数据要求不一样。 - -### 12.1 LGBM - -LGBM 更依赖: - -- 长期真值 -- 基础 forecast 特征 - -这部分通过: - -- `truth_records_store` -- `training_feature_records_store` - -已经改善很多。 - -### 12.2 EMOS - -EMOS 更依赖: - -- 某一时刻的概率快照/分布特征 - -如果过去那些 snapshot 没有长期保存下来,那么即使今天把真值补齐了: - -- 也无法凭空重建完整 EMOS 样本 - -所以当前现实是: - -- 真值问题已经大幅改善 -- 未来特征不会再继续丢 -- 但过去缺失的 EMOS 快照历史仍然限制样本增长 - ---- - -## 13. 当前最重要的工程判断 - -### 13.1 已经完成的 - -这些现在可以认为已经完成: - -- 真值主存从运行态缓存里拆出 -- 真值 provenance 落库 -- revision 审计表落地 -- Wunderground 历史回填接通 -- `Taipei/Shenzhen` 真值口径修正 -- 长期训练特征表接通 -- `/ops` 已能可视化 truth / feature / EMOS / LGBM 覆盖情况 - -### 13.2 还没完成的 - -这些仍然是后续重点: - -- EMOS 样本继续自然积累 -- shadow bucket brier 稳定下来 -- LGBM 验证效果超过 DEB -- 让更多城市开始持续积累训练特征 - ---- - -## 14. 运维怎么看当前状态 - -现在最直接的入口是: - -- `/ops` - -这页已经能看到: - -- 历史真值主表统计 -- 真值来源分布 -- 真值修订数量 -- 长期训练特征统计 -- `Taipei/Shenzhen` 的 WU 回填状态 -- 城市覆盖缺口 -- 模型城市覆盖 -- 城市覆盖矩阵 - -因此,运维现在可以快速回答: - -- 哪些城市真值已经长期化 -- 哪些城市还没有特征积累 -- 哪些城市已经能支撑 EMOS/LGBM -- 哪些城市目前仍然只能主要依赖 DEB - ---- - -## 15. 推荐工作流 - -### 15.1 日常 - -1. 查看 `/ops` -2. 看 `truth / feature / EMOS / LGBM` 覆盖有没有继续增长 -3. 看 `Taipei/Shenzhen` 的 WU 行数是否继续更新 -4. 看本地 EMOS 候选是否通过门禁 -5. 看 VPS 是否只加载已批准参数,不在低配机器上训练 - -### 15.2 周期性重训 - -建议在本地开发机执行,不建议在低配 VPS 上执行: - -```powershell -scp root@38.54.27.70:/var/lib/polyweather/polyweather.db E:\web\PolyWeather\data\polyweather-prod.db -$env:POLYWEATHER_DB_PATH="E:\web\PolyWeather\data\polyweather-prod.db" -$env:POLYWEATHER_RUNTIME_DATA_DIR="E:\web\PolyWeather\artifacts\local_runtime" -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 -``` - -只有 `auto_retrain_report.json` 里 `ready_for_promotion=true` 时,才允许把候选 `default.json` 传回 VPS。 - -### 15.3 真值恢复/补数 - -当有新的历史真值补数或回填需要时: - -```bash -./venv/Scripts/python.exe scripts/restore_training_truth_history.py -./venv/Scripts/python.exe scripts/restore_training_feature_history.py -./venv/Scripts/python.exe scripts/backfill_recent_daily_actuals_from_metar.py --cities taipei shenzhen --lookback-days 14 -``` - -说明: - -- 脚本名里虽然还保留 `from_metar` -- 但当前实现已经会按 `settlement_source` 自动分发 -- `wunderground` 会走 WU 历史回填分支 - ---- - -## 16. 当前最务实的结论 - -如果只用一句话概括当前状态: - -**EMOS 和 LGBM 的工程基础已经补齐,但生产主概率仍必须由评估门禁控制;当前最正确的策略是继续以 `DEB/legacy` 为主路径,在本地训练 EMOS 候选,VPS 只加载已批准参数。** - -更具体一点: - -- `EMOS` - - 已接好 - - 可训练 - - 可评估 - - 可 shadow - - 通过门禁后可灰度 - - 不应在低配 VPS 上自动训练或自动主用 - -- `LGBM` - - 已接好 - - 样本比以前更多 - - 但验证集还不如 DEB - - 目前只能做辅助参考 - -- 数据层 - - 这次治理的真正价值,是防止未来继续丢历史 - - 这对两条模型链路都比继续“微调参数”更关键 - ---- - -## 17. 相关文档 - -若需要看更细分的历史说明,可继续参考: - -- [EMOS_TRAINING_REPORT_ZH.md](/E:/web/PolyWeather/docs/EMOS_TRAINING_REPORT_ZH.md) -- [LGBM_DAILY_HIGH_ZH.md](/E:/web/PolyWeather/docs/LGBM_DAILY_HIGH_ZH.md) -- [PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md](/E:/web/PolyWeather/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md) -- [deep-research-report.md](/E:/web/PolyWeather/docs/deep-research-report.md) diff --git a/docs/EMOS_TRAINING_REPORT_ZH.md b/docs/EMOS_TRAINING_REPORT_ZH.md deleted file mode 100644 index cc9e0bdd..00000000 --- a/docs/EMOS_TRAINING_REPORT_ZH.md +++ /dev/null @@ -1,263 +0,0 @@ -# EMOS 训练与发布报告(2026-04-19) - -## 1. 当前结论 - -- `EMOS` 工程链路已经接通:可以训练、评估、生成候选参数,并在前端以校准概率层展示。 -- 生产主概率当前不应默认使用 `emos_primary`。默认建议为 `legacy`;需要观察时使用 `emos_shadow`。 -- `emos_primary` 只允许在本地离线训练通过门禁、人工复核后手动灰度。 -- 低配 VPS(例如 1 vCPU / 2GB RAM)不适合做 EMOS 全量训练;VPS 只负责采集、服务和加载已批准的参数文件。 -- `LGBM` 当前仍不建议作为主路径,继续保持 `POLYWEATHER_LGBM_ENABLED=false`。 - -## 2. 最近两次训练结果 - -### 2.1 VPS 轻量训练:不通过 - -VPS 使用最近 `5000` 条 snapshot 训练的候选: - -- 版本:`emos-auto-20260418204203` -- 样本数:`791` -- 结论:`hold` - -| 指标 | 变化 | -| :-- | --: | -| `delta_crps` | `+0.004652` | -| `delta_mae` | `+0.102623` | -| `delta_bucket_hit_rate` | `-0.137800` | - -解读:CRPS、MAE、桶命中全部弱于 legacy,因此不能晋级。 - -### 2.2 本地训练:通过门禁,但仍需灰度 - -本地电脑使用生产 SQLite 副本与最近 `50000` 条 snapshot 训练的候选: - -- 版本:`emos-auto-20260418212046` -- 样本数:`847` -- 结论:`promote` - -| 指标 | 变化 | -| :-- | --: | -| `delta_crps` | `-0.036170` | -| `delta_mae` | `-0.007896` | -| `delta_bucket_hit_rate` | `-0.009445` | - -解读: - -- CRPS 与 MAE 有改善,候选通过当前门禁。 -- 桶命中率轻微下降,虽然在门禁允许范围内,但仍建议先以 `emos_shadow` 观察,再决定是否切 `emos_primary`。 - -## 3. 生产运行策略 - -推荐生产 `.env`: - -```env -POLYWEATHER_PROBABILITY_ENGINE=legacy -POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json -``` - -观察 EMOS 时: - -```env -POLYWEATHER_PROBABILITY_ENGINE=emos_shadow -POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json -``` - -只有在候选连续通过评估、前端展示稳定、业务侧确认后,才切: - -```env -POLYWEATHER_PROBABILITY_ENGINE=emos_primary -POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json -``` - -验证线上加载状态: - -```bash -docker compose exec -T polyweather_web python - <<'PY' -from src.analysis.probability_calibration import load_calibration, resolve_probability_engine_mode -cal = load_calibration() -print("engine_mode =", resolve_probability_engine_mode()) -print("loaded_version =", cal.get("version")) -print("sample_count =", (cal.get("metrics") or {}).get("sample_count")) -print("has_global =", bool(cal.get("global"))) -PY -``` - -## 4. 本地训练 SOP - -### 4.1 拉取生产 SQLite 副本 - -推荐先在 VPS 上用 SQLite 在线备份生成快照: - -```bash -sqlite3 /var/lib/polyweather/polyweather.db ".backup '/var/lib/polyweather/polyweather-train-copy.db'" -``` - -本地 PowerShell 拉取: - -```powershell -cd E:\web\PolyWeather -scp root@38.54.27.70:/var/lib/polyweather/polyweather-train-copy.db E:\web\PolyWeather\data\polyweather-prod.db -``` - -如果生产库写入压力很低,也可以直接拉主库副本: - -```powershell -scp root@38.54.27.70:/var/lib/polyweather/polyweather.db E:\web\PolyWeather\data\polyweather-prod.db -``` - -### 4.2 本地训练 - -```powershell -cd E:\web\PolyWeather -$env:POLYWEATHER_DB_PATH="E:\web\PolyWeather\data\polyweather-prod.db" -$env:POLYWEATHER_RUNTIME_DATA_DIR="E:\web\PolyWeather\artifacts\local_runtime" -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 -``` - -如果本地机器仍然较慢,可先降到: - -```powershell -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 20000 -``` - -训练报告: - -```powershell -Get-Content E:\web\PolyWeather\artifacts\local_runtime\probability_calibration\auto_retrain_report.json -``` - -候选目录: - -```text -E:\web\PolyWeather\artifacts\local_runtime\probability_calibration\candidates\\ -``` - -### 4.3 晋级判断 - -只有报告满足以下条件时,候选才可进入部署流程: - -```json -"ready_for_promotion": true -``` - -同时人工检查: - -- `delta_crps <= 0` -- `delta_mae <= 0.05` -- `delta_bucket_hit_rate >= -0.05` -- 城市级结果没有出现关键城市大幅退化 -- 前端概率分布没有明显过度摊平或异常偏桶 - -## 5. 部署通过的候选 - -把本地候选上传到 VPS: - -```powershell -scp E:\web\PolyWeather\artifacts\local_runtime\probability_calibration\candidates\\default.json root@38.54.27.70:/var/lib/polyweather/probability_calibration/default.json -``` - -VPS 上优先设置为 `emos_shadow`: - -```env -POLYWEATHER_PROBABILITY_ENGINE=emos_shadow -POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json -``` - -重启: - -```bash -cd /root/PolyWeather -docker compose up -d polyweather_web -``` - -观察稳定后再考虑 `emos_primary`。 - -## 6. VPS 定时训练策略 - -当前策略:**不在 VPS 上做 EMOS 定时训练**。 - -原因: - -- 生产 SQLite 的 `probability_training_snapshots_store` 会持续增长。 -- 低配 VPS 全量扫描会造成 CPU/IO 飙升,严重时影响 SSH 和线上服务。 -- VPS 训练用较小 `--snapshot-limit` 虽然安全,但训练效果可能弱于本地。 - -如果曾经加过 cron,应删除: - -```bash -crontab -l | grep -v 'auto_retrain_probability_calibration.py' | crontab - -``` - -确认: - -```bash -crontab -l -``` - -## 7. 自动重训脚本说明 - -脚本: - -```text -python scripts\auto_retrain_probability_calibration.py -``` - -默认行为: - -- 生成新的 EMOS candidate。 -- 对 candidate 跑离线评估。 -- 写入候选目录和门禁报告。 -- 不覆盖线上 `default.json`。 - -重要参数: - -- `--verbose`:输出训练/评估进度。 -- `--snapshot-limit N`:只使用最近 N 条 snapshot。 -- `--promote-if-passed`:门禁通过后覆盖目标参数文件。 -- `--run-tests`:晋级前跑测试。 - -当前不建议在 VPS 使用 `--promote-if-passed`。本地训练通过后,仍优先人工上传并使用 `emos_shadow`。 - -## 8. 门禁阈值 - -默认阈值: - -- `POLYWEATHER_EMOS_AUTO_MIN_SAMPLES=50` -- `POLYWEATHER_EMOS_AUTO_MAX_DELTA_CRPS=0` -- `POLYWEATHER_EMOS_AUTO_MAX_DELTA_MAE=0.05` -- `POLYWEATHER_EMOS_AUTO_MIN_DELTA_BUCKET_HIT_RATE=-0.05` - -解释: - -- `CRPS` 不允许比 legacy 更差。 -- `MAE` 最多允许轻微退化 `0.05`。 -- `bucket_hit_rate` 是业务参考指标,但对结算边界敏感,不单独作为唯一判断。 - -## 9. 前端说明 - -今日日内分析中的概率区展示的是当前生产概率引擎输出: - -- `legacy`:展示现有动态概率。 -- `emos_shadow`:用户主概率仍为 legacy,EMOS 仅用于对照和评估。 -- `emos_primary`:用户主概率使用 EMOS 校准分布。 - -对外文案应避免暗示“EMOS 一定更准”。推荐解释为: - -> EMOS 是 PolyWeather 基于 DEB 路径、多模型集合、METAR 实测进度和历史误差结构生成的统计校准概率,不是外部天气模型,也不是直接 API 结果。 - -## 10. 已验证 - -本地训练链路已验证: - -```text -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 -``` - -测试链路已验证: - -```text -python -m pytest tests\test_auto_retrain_probability_calibration.py tests\test_probability_calibration.py tests\test_probability_rollout.py -``` - -当前工程结论: - -**EMOS 可以继续本地训练与 shadow 观察,但生产主概率不应因为“机制接好”而默认切到 `emos_primary`。** diff --git a/docs/LGBM_DAILY_HIGH_ZH.md b/docs/LGBM_DAILY_HIGH_ZH.md deleted file mode 100644 index 9a9c8dc7..00000000 --- a/docs/LGBM_DAILY_HIGH_ZH.md +++ /dev/null @@ -1,325 +0,0 @@ -# LightGBM 日最高温模型(中文) - -最后更新:`2026-04-18` - -## 1. 目标 - -这套 `LightGBM` 模型是给 PolyWeather 增加一个轻量级的统计学习预测源。 - -它的定位不是替代: - -- `DEB` -- `EMOS` -- `ECMWF / GFS / GEM / JMA / ICON / Open-Meteo / MGM / NWS` - -而是作为一个新的点预测源: - -`现有模型 + 观测特征 -> LGBM -> 并入 current_forecasts -> DEB -> EMOS` - -第一版只做: - -- `D0` 当日最高温预测 - -不做: - -- `D1-D3` -- 小时级曲线 -- 原始独立概率分布 -- 独立结算源 - -注意:前端出现的“LGBM 校准概率”不是把 LGBM 模型票数直接当成概率,而是概率层基于 LGBM / DEB / 观测上下文输出的校准分布。模型共识只保留为解释性参考。 - -## 2. 适用场景 - -这条链路是为低资源 VPS 准备的。 - -当前项目线上环境只有 `2GB RAM` 时,不适合引入 `TimesFM` 这类大模型,但适合用 `LightGBM` 做轻量推理。 - -当前方案是: - -1. 训练离线完成 -2. 训练产物直接提交到仓库 -3. VPS 线上只加载模型文件并推理 -4. VPS 不训练,不起额外服务 - -## 3. 文件结构 - -核心文件如下: - -- 运行时推理: - - [src/models/lgbm_daily_high.py](/E:/web/PolyWeather/src/models/lgbm_daily_high.py) -- 特征构建: - - [src/models/lgbm_features.py](/E:/web/PolyWeather/src/models/lgbm_features.py) -- 训练脚本: - - [scripts/train_lgbm_daily_high.py](/E:/web/PolyWeather/scripts/train_lgbm_daily_high.py) -- 训练报告脚本: - - [scripts/report_lgbm_daily_high.py](/E:/web/PolyWeather/scripts/report_lgbm_daily_high.py) -- 模型文件: - - [artifacts/models/lgbm_daily_high.txt](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high.txt) -- 模型 schema / 指标: - - [artifacts/models/lgbm_daily_high_schema.json](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high_schema.json) - -接入链路位置: - -- Web API 聚合: - - [web/analysis_service.py](/E:/web/PolyWeather/web/analysis_service.py) -- 共享趋势引擎: - - [src/analysis/trend_engine.py](/E:/web/PolyWeather/src/analysis/trend_engine.py) - -## 4. 特征说明 - -第一版特征固定为以下几组。 - -### 4.1 历史日高温特征 - -- `actual_high_lag_1` -- `actual_high_lag_2` -- `actual_high_lag_3` -- `actual_high_lag_7` -- `actual_high_mean_7` -- `actual_high_mean_14` -- `actual_high_trend_3` - -### 4.2 当天模型特征 - -- `Open-Meteo` -- `ECMWF` -- `GFS` -- `GEM` -- `JMA` -- `ICON` -- `MGM` -- `NWS` -- `deb_prediction` -- `model_median` -- `model_spread` - -### 4.3 当前观测特征 - -- `current_temp` -- `max_so_far` -- `humidity` -- `wind_speed_kt` -- `visibility_mi` - -### 4.4 时间与状态特征 - -- `local_hour` -- `month` -- `weekday` -- `peak_status_code` - -其中: - -- `before = 0` -- `in_window = 1` -- `past = 2` - -## 5. 训练数据来源 - -训练数据主要来自两份运行时历史文件: - -- [data/daily_records.json](/E:/web/PolyWeather/data/daily_records.json) -- [data/probability_training_snapshots.jsonl](/E:/web/PolyWeather/data/probability_training_snapshots.jsonl) - -作用分工: - -- `daily_records.json` - - 提供 `actual_high` - - 提供当天各模型 forecast - - 提供历史 `deb_prediction` - -- `probability_training_snapshots.jsonl` - - 提供 `max_so_far` - - 提供 `peak_status` - - 提供观测特征快照 - -为后续重训,概率快照归档现在还会额外写入: - -- `current_temp` -- `humidity` -- `wind_speed_kt` -- `visibility_mi` -- `local_hour` - -对应代码: - -- [src/analysis/probability_snapshot_archive.py](/E:/web/PolyWeather/src/analysis/probability_snapshot_archive.py) - -## 6. 训练流程 - -训练脚本: - -```bash -./venv/Scripts/python.exe scripts/train_lgbm_daily_high.py -``` - -训练流程如下: - -1. 从历史文件构造监督样本 -2. 目标值固定为 `actual_high` -3. 按日期做简单的时间顺序切分 -4. 最后约 20% 做验证集 -5. 先训练并评估验证集 -6. 再用全量样本训练最终模型 -7. 输出模型文件和 schema 文件 - -输出产物: - -- [artifacts/models/lgbm_daily_high.txt](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high.txt) -- [artifacts/models/lgbm_daily_high_schema.json](/E:/web/PolyWeather/artifacts/models/lgbm_daily_high_schema.json) - -## 7. 如何看训练结果 - -查看训练报告: - -```bash -./venv/Scripts/python.exe scripts/report_lgbm_daily_high.py -``` - -这个脚本会读取 schema,并打印: - -- `Sample Count` -- `Train Count` -- `Valid Count` -- `LGBM MAE` -- `DEB MAE` -- `Best Single MAE` -- `Median MAE` -- `Winner` - -当前这版训练结果是: - -- `sample_count = 29` -- `validation_count = 12` -- `validation.lgbm_mae = 2.975` -- `validation.deb_mae = 2.267` -- `validation.best_single_mae = 1.167` - -这说明: - -- 当前 `LGBM` 链路已经可用 -- 但现阶段验证集表现还没有超过 `DEB` -- 所以默认配置仍建议保持关闭 - -## 8. 线上运行逻辑 - -运行时推理逻辑不是“直接替代 DEB”,而是: - -1. 先收集现有模型 forecast -2. 先算一版基线 `DEB` -3. 把这版 `DEB` 当作 `LGBM` 的一个输入特征 -4. 输出 `LGBM` 点预测 -5. 把 `LGBM` 注入 `current_forecasts` -6. 重新计算最终 `DEB` - -这样做的原因是: - -- `LGBM` 需要吃到 `deb_prediction` 特征 -- 但最终 `DEB` 又要把 `LGBM` 当成一个新的输入模型 - -## 8.1 前端概率展示口径 - -当前网页的概率区按以下顺序解释: - -1. 如果后端 `probabilities.engine` 表示 LGBM 校准概率可用,则标题显示为 `LGBM 校准概率`。 -2. 如果 LGBM 不可用,但 EMOS / legacy 概率可用,则显示为 `校准模型概率`。 -3. 模型舍入票数只保留为“模型共识参考”,用于说明哪些模型四舍五入后落在同一温度档,不作为最终命中概率。 -4. 市场价格只保留为“市场参考”,不和校准概率混成同一结论。 - -这能避免用户把 `4/8 模型支持 82°F` 误读成 `82°F 有 50% 概率`。模型共识是解释层,概率引擎才是结论层。 - -## 9. 环境变量 - -示例配置见: - -- [.env.example](/E:/web/PolyWeather/.env.example) - -相关变量: - -```env -POLYWEATHER_LGBM_ENABLED=false -POLYWEATHER_LGBM_MODEL_PATH=/app/artifacts/models/lgbm_daily_high.txt -POLYWEATHER_LGBM_SCHEMA_PATH=/app/artifacts/models/lgbm_daily_high_schema.json -POLYWEATHER_LGBM_MIN_HISTORY_POINTS=3 -``` - -说明: - -- `POLYWEATHER_LGBM_ENABLED` - - 是否启用运行时推理 -- `POLYWEATHER_LGBM_MODEL_PATH` - - 模型文件路径 -- `POLYWEATHER_LGBM_SCHEMA_PATH` - - schema 文件路径 -- `POLYWEATHER_LGBM_MIN_HISTORY_POINTS` - - 某城市最低历史样本门槛 - -默认是 `3`,原因不是最理想,而是当前整体样本仍然偏少。 - -如果门槛设太高,很多城市现在根本不会触发 `LGBM`。 - -## 10. VPS 部署建议 - -如果你的 VPS 只有 `2GB RAM`: - -- 可以跑这套 `LightGBM` -- 不要在 VPS 上训练 -- 不要起额外模型服务 - -推荐方式: - -1. 在本地或开发环境训练 -2. 提交模型产物 -3. VPS 拉代码 -4. 开启 `POLYWEATHER_LGBM_ENABLED=true` -5. 重启主服务 - -不推荐: - -- 在 VPS 上跑训练脚本 -- 把 `LightGBM` 当成长任务服务单独部署 -- 同时引入大模型推理 - -## 11. 当前结论 - -这条链路已经完成了: - -- 离线训练 -- 模型产物固化 -- 运行时懒加载 -- Web / 共享分析链路注入 -- 前端模型类型兼容 - -但当前样本量仍偏少,所以建议运营策略是: - -1. 先继续积累历史 `actual_high` -2. 继续积累概率快照观测字段 -3. 定期重训 -4. 只有当验证集 `MAE` 持续接近或优于 `DEB` 时,再考虑默认线上开启 - -## 12. 常用命令 - -### 训练 - -```bash -./venv/Scripts/python.exe scripts/train_lgbm_daily_high.py -``` - -### 查看训练报告 - -```bash -./venv/Scripts/python.exe scripts/report_lgbm_daily_high.py -``` - -### 本地测试 - -```bash -./venv/Scripts/python.exe -m pytest tests/test_lgbm_features.py tests/test_lgbm_daily_high.py -``` - -### 编译检查 - -```bash -./venv/Scripts/python.exe -m compileall src web scripts tests -``` diff --git a/docs/MODEL_STACK_AND_DEB_ZH.md b/docs/MODEL_STACK_AND_DEB_ZH.md index b37ec6a1..04db8c10 100644 --- a/docs/MODEL_STACK_AND_DEB_ZH.md +++ b/docs/MODEL_STACK_AND_DEB_ZH.md @@ -151,7 +151,6 @@ HRDPS > RDPS > GDPS > GEM - MGM - NWS - HKO -- LGBM - Open-Meteo ECMWF IFS 与 ECMWF AIFS 分开保留,因为前者是传统 NWP,后者是 AIFS 模型。 @@ -219,7 +218,6 @@ raw current_forecasts 当前前端把三层拆开展示: - `模型区间与分歧`:解释不同模型当前给出的最高温范围和分歧,不直接等于命中概率。 -- `校准模型概率`:由当前生产概率引擎输出温度桶概率;默认可保持 legacy,EMOS / LGBM 只在评估通过、显式启用或 shadow 对照时进入展示。 - `市场参考`:只展示市场价格和错价背景,不再作为主判断,也不默认输出 BUY YES / BUY NO。 模型票数只用于解释“哪些模型支持某个档位”,不等于最终概率。最终概率应优先读取 `probabilities.engine` 对应的校准分布。 @@ -230,7 +228,6 @@ raw current_forecasts - `tests/test_multi_model_sources.py` - `tests/test_deb_model_family.py` -- `tests/test_lgbm_features.py` 重点覆盖: diff --git a/docs/OPS_ADMIN_ZH.md b/docs/OPS_ADMIN_ZH.md index c17e58ae..07782bea 100644 --- a/docs/OPS_ADMIN_ZH.md +++ b/docs/OPS_ADMIN_ZH.md @@ -25,7 +25,6 @@ POLYWEATHER_OPS_ADMIN_EMAILS=yhrsc30@gmail.com - 系统健康 - SQLite / rollout / metrics 摘要 - 支付运行态 -- prewarm worker 运行态 - 缓存桶状态与 summary cache hit/miss - 当前会员 - 周榜 @@ -101,11 +100,9 @@ python scripts/reconcile_subscription_by_email.py --email ## 7. 备注 -### 7.1 当前 prewarm / 缓存观测项 `/ops` 里的系统状态卡目前已额外展示: -- `prewarm` 是否启用 - `thread_alive` / `heartbeat_age_sec` - 最近一轮: - `cycle_count` diff --git a/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md b/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md deleted file mode 100644 index e47c7cff..00000000 --- a/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md +++ /dev/null @@ -1,347 +0,0 @@ -# 概率训练样本归档说明(中文) - -最后更新:`2026-04-19` - -## 1. 目的 - -这份文档说明两件事: - -1. 为什么 `EMOS` 训练不能只依赖历史实测天气 -2. 未来如何持续沉淀“历史预测记录”,让概率引擎越训越稳 - -一句话结论: - -- 历史实测天气只能补 `actual_high` -- 真正决定 `EMOS` 训练质量的是“当时那一刻的预测快照” - -## 2. 什么是“历史预测记录” - -对 PolyWeather 来说,一条可训练的历史预测记录,至少应该包含这些字段: - -- `city` -- `timestamp` -- `date` -- `raw_mu` -- `raw_sigma` -- `deb_prediction` -- `ensemble p10 / p50 / p90` -- `multi-model forecasts` -- `max_so_far` -- `peak_status` -- `prob_snapshot` -- `probability_engine` -- `calibration_mode` -- `calibration_version` -- `raw_mu / raw_sigma` -- `calibrated_mu / calibrated_sigma` -- `shadow_distribution` -- 当天最终 `actual_high` -- 当天最终 `settlement bucket` - -这类记录的核心价值是: - -- 还原“当时系统实际看到什么” -- 再对照“后来真实发生了什么” - -只有这两者成对,`EMOS` 才能学习偏差。 - -## 3. 为什么不能只用历史天气实测 - -历史天气 CSV 只能告诉你: - -- 当天最高温是多少 -- 某小时温度是多少 - -但它不能告诉你: - -- 当天早上 09:00 时,系统的 `mu` 是多少 -- 当时的 `ensemble spread` 是多少 -- 当时 `DEB` 怎么看 -- 当时的 top bucket 是什么 - -所以: - -- 历史实测天气是标签 -- 历史预测记录才是训练输入 - -缺少后者,EMOS 只能学到很有限的东西。 - -## 4. 当前项目里已经有的基础 - -### 4.1 已有历史日记录 - -文件: - -- [daily_records.json](/E:/web/PolyWeather/data/daily_records.json) - -当前已经保存了一部分训练相关字段,例如: - -- `forecasts` -- `actual_high` -- `deb_prediction` -- `mu` -- `prob_snapshot` -- `shadow_prob_snapshot` -- `probability_calibration` -- `probability_features` - -这已经是“历史预测记录”的雏形。 - -### 4.2 已有历史天气 CSV - -目录: - -- [data/historical](/E:/web/PolyWeather/data/historical) - -它们可以帮助补: - -- `actual_high` -- `settlement history` - -但不能替代预测快照归档。 - -## 5. 未来应该怎么存历史预测记录 - -推荐做法是: - -### 5.1 固定时点归档 - -每天为每个重点城市固定存几次快照,例如: - -- 当地 `09:00` -- 当地 `12:00` -- 当地 `15:00` - -这样能确保每个交易日都有稳定可比样本。 - -### 5.2 关键变化时补充归档 - -除了固定时点,还应该在以下情况额外存一次: - -- `max_so_far` 创新高 -- `mu` 变化超过阈值 -- `top bucket` 发生变化 -- `shadow top bucket` 发生变化 - -这样能捕捉真正有训练价值的转折点。 - -### 5.3 建议的存储格式 - -建议新增一个文件,例如: - -- `data/probability_training_snapshots.jsonl` - -每一行保存一条 JSON 记录。 - -优点: - -- 追加写入简单 -- 后续导出训练集方便 -- 不容易因为单个大 JSON 文件损坏而全盘受影响 - -## 6. 一条建议的快照结构 - -示例: - -```json -{ - "city": "ankara", - "timestamp": "2026-03-20T12:00:00+03:00", - "date": "2026-03-20", - "raw_mu": 15.2, - "raw_sigma": 1.2, - "deb_prediction": 15.4, - "ensemble": { - "p10": 14.8, - "median": 15.8, - "p90": 17.9 - }, - "multi_model": { - "ECMWF": 15.8, - "GFS": 14.1, - "ICON": 15.9, - "GEM": 16.5, - "JMA": 14.5 - }, - "max_so_far": 15.0, - "peak_status": "before", - "prob_snapshot": [ - {"v": 15, "p": 0.552}, - {"v": 16, "p": 0.377} - ], - "shadow_prob_snapshot": [ - {"v": 15, "p": 0.324}, - {"v": 16, "p": 0.238} - ], - "probability_engine": "legacy", - "probability_mode": "emos_shadow", - "calibration_mode": "emos_shadow", - "calibration_version": "emos-20260320130245", - "calibrated_mu": 15.4, - "calibrated_sigma": 1.1 -} -``` - -当天结束后,再由后处理脚本回填: - -- `actual_high` -- `settlement_bucket` - -当前前端把这类快照解释为“校准模型概率”。如果 `probability_engine` 为 LGBM 相关值,则显示为 LGBM 校准概率;模型舍入票数和市场价格只用于解释,不直接作为最终概率。 - -## 7. 现阶段你可以执行的命令 - -### 7.1 回填历史天气 CSV - -```bash -python scripts/backfill_historical_weather.py -``` - -作用: - -- 补全 30 城市历史天气时序 CSV - -### 7.2 从历史 CSV 构建日级结算标签 - -```bash -python scripts/build_settlement_history_from_csv.py -``` - -作用: - -- 生成 [settlement_history.json](/E:/web/PolyWeather/artifacts/probability_calibration/settlement_history.json) - -### 7.3 导出当前训练样本 - -```bash -python scripts/export_probability_training_dataset.py -``` - -作用: - -- 生成 [training_samples.json](/E:/web/PolyWeather/artifacts/probability_calibration/training_samples.json) - -### 7.4 重训 EMOS - -推荐在本地电脑使用生产 SQLite 副本训练,不建议在低配 VPS 上训练: - -```powershell -scp root@38.54.27.70:/var/lib/polyweather/polyweather.db E:\web\PolyWeather\data\polyweather-prod.db -$env:POLYWEATHER_DB_PATH="E:\web\PolyWeather\data\polyweather-prod.db" -$env:POLYWEATHER_RUNTIME_DATA_DIR="E:\web\PolyWeather\artifacts\local_runtime" -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 -``` - -作用: - -- 生成新的候选 `default.json` -- 同时生成 `evaluation_report.json` 与 `auto_retrain_report.json` -- 不自动覆盖线上参数 - -### 7.5 离线评估训练效果 - -```bash -python scripts/evaluate_probability_calibration.py -``` - -作用: - -- 生成 [evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.json) - -### 7.6 回填 shadow 结果到历史记录 - -```bash -python scripts/backfill_probability_shadow_history.py -``` - -作用: - -- 把 `shadow_prob_snapshot` 和 `probability_calibration` 回填到 [daily_records.json](/E:/web/PolyWeather/data/daily_records.json) - -### 7.7 生成线上 shadow 滚动报表 - -```bash -python scripts/build_probability_shadow_report.py -``` - -作用: - -- 生成 [shadow_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/shadow_report.json) - -## 8. 推荐的一整套重训流程 - -如果过了十天、半个月,想重新训练一次,当前推荐流程是: - -```powershell -scp root@38.54.27.70:/var/lib/polyweather/polyweather.db E:\web\PolyWeather\data\polyweather-prod.db -$env:POLYWEATHER_DB_PATH="E:\web\PolyWeather\data\polyweather-prod.db" -$env:POLYWEATHER_RUNTIME_DATA_DIR="E:\web\PolyWeather\artifacts\local_runtime" -python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 -``` - -只有 `auto_retrain_report.json` 中 `ready_for_promotion=true`,才把候选参数传回 VPS,并优先用 `emos_shadow` 观察。 - -如果只是做历史真值补数,才需要额外执行: - -```bash -python scripts/backfill_historical_weather.py -python scripts/build_settlement_history_from_csv.py -``` - -## 9. 怎么判断这次训练有没有进步 - -重训后,不要只看一个指标。 - -至少看这 4 个: - -1. `CRPS` -- 越低越好 - -2. `MAE` -- 越低越好 -- 至少不要明显变差 - -3. `Bucket Hit Rate` -- 越高越好 -- 这是业务上非常关键的指标 - -4. `Bucket Brier` -- 越低越好 -- 反映概率分布质量 - -当前自动门禁至少要求: - -- `CRPS` 下降 -- `MAE` 最多轻微退化 `0.05` -- `Bucket Hit Rate` 退化不超过 `0.05` - -人工复核还应看城市级结果,避免少数关键城市大幅退化。`Bucket Hit Rate` 受整数结算边界影响大,不能单独作为唯一判断。 - -## 10. 当前最重要的现实判断 - -过去的“完整历史预测记录”通常没法完全补出来,除非: - -1. 你之前就存过 -2. 你接入了支持 forecast archive 的商业数据源 - -所以现实里最重要的不是“把过去全补齐”,而是: - -- 从现在开始系统化归档 -- 每天稳定沉淀可训练样本 -- 定期离线重训 - -## 11. 推荐的下一步 - -最值得做的改造是: - -1. 新增 `probability_training_snapshots.jsonl` -2. 每次分析时自动追加一条快照 -3. 当天结束后自动回填 `actual_high` -4. 每 1-2 周在本地电脑重新训练一次 -5. VPS 只加载通过评估的参数文件,不做全量训练 - -## 12. 总结 - -如果只记住一句话,就记这个: - -**EMOS 要想越训越好,关键不是多下载一点历史天气,而是持续保存“当时系统看到的预测快照”。** diff --git a/docs/TECH_DEBT_ZH.md b/docs/TECH_DEBT_ZH.md index da628c4b..02bc3a9d 100644 --- a/docs/TECH_DEBT_ZH.md +++ b/docs/TECH_DEBT_ZH.md @@ -29,7 +29,6 @@ flowchart TD end subgraph S["状态与概率"] - S1["EMOS 本地训练与 shadow 发布门禁"] end A --> P @@ -50,13 +49,11 @@ flowchart TD - 钱包异动支持独立频道路由。 - 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。 - 轻量可观测性已上线(`/healthz`、`/api/system/status`、`/metrics`)。 -- EMOS/CRPS 校准链路已接通;生产主概率保持 `legacy` 或 `emos_shadow`,`emos_primary` 只允许本地训练通过门禁后人工灰度。 ## 3. 高优先级技术债 | 项目 | 影响 | 建议动作 | | :-- | :-- | :-- | -| EMOS 发布门禁 | 低配 VPS 不适合训练,主概率不能绕过评估 | 本地拉生产 SQLite 训练,`ready_for_promotion=true` 后先 `emos_shadow` | | 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 | | 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 | @@ -77,6 +74,5 @@ flowchart TD ## 6. 下阶段里程碑 -1. 固化 EMOS 本地训练流程,禁止低配 VPS 自动训练和自动主用。 2. 补外部监控抓取与告警阈值。 3. 评估并推进支付合约 V2 升级。 diff --git a/docs/data-architecture-review.md b/docs/data-architecture-review.md index bf0e8f1a..1e7f5421 100644 --- a/docs/data-architecture-review.md +++ b/docs/data-architecture-review.md @@ -21,8 +21,6 @@ Polymarket Gamma/CLOB ─┤ │ │ ├─ _analyze() ├─ useDashboardStore │ ├─ DEB 融合 (11模型加权) │ (双Context拆分) - │ ├─ LGBM 独立预测 │ - │ ├─ EMOS 概率校准 ├─ ScanTerminalDashboard │ └─ 趋势引擎 │ (扫描数据预加载) │ │ ├─ scan_terminal_service.py ├─ 扫描终端查询 @@ -64,11 +62,9 @@ Polymarket Gamma/CLOB ─┤ 自适应加权:11 模型按过去 7 天 MAE 动态分配权重。回退链完善。 -**已修复:LGBM 循环依赖解除** — LGBM 预测值不再参与 DEB 权重计算,保留为独立参考字段 `lgbm.prediction`。 ### 概率校准 -EMOS 线性回归校准 raw distribution,支持 `legacy` / `emos_shadow` / `emos_primary` 三种模式。 **已修复:校准漂移检测** — `check_calibration_drift()` 对比最近 CRPS 与基线,漂移 >15% 时告警,集成在 `/api/system/status` 的 `probability.drift` 字段。 diff --git a/docs/deep-research-report.md b/docs/deep-research-report.md index 0b9d4d02..08007fcb 100644 --- a/docs/deep-research-report.md +++ b/docs/deep-research-report.md @@ -3,10 +3,6 @@ ## 执行摘要 PolyWeather(仓库:`yangyuan-zhen/PolyWeather`)定位为**面向温度类结算预测市场(如 Polymarket 的温度结算合约)**的“生产级气象情报系统”,核心在于把多源天气观测/预报转化为**结算导向的概率桶(μ + bucket distribution)**,并进一步映射到市场报价完成**错价扫描**;同时提供 Web 仪表盘与 Telegram Bot 两套交互入口,并包含 Polygon 链上 USDC/USDC.e 支付、自动补单与订阅/积分体系。项目 README 现明确仓库代码采用 `AGPL-3.0-only`,同时将品牌、商标、生产私有数据与运营阈值保留在代码许可证之外。 -从工程实现看,截至 `2026-05-11`,项目已经完成一轮更明确的工程化收口:多源天气采集仍保持现有业务能力,同时已完成采集层与 Web API 大文件拆分、CI 质量门禁、配置分级(`.env.example` / `.env.secrets.example` / 中文部署文档)、EMOS/CRPS 校准链路、运行态状态与缓存迁移到 SQLite 主路径,以及最小外部监控链路(`/healthz`、`/api/system/status`、`/metrics` + Prometheus + Alertmanager + Grafana + Telegram relay)。除此之外,项目还补上了**历史真值治理**:`daily_records` 继续只保留近 14 天运行态缓存,但新增了永久真值表、真值 revision 审计表和长期训练特征表,并开始把监督真值与训练特征从“短期缓存”正式拆到“长期可追溯存储”。2026-04 下旬新增的前端城市决策卡把“多模型 + METAR + 市场桶”进一步组合成面向单城点击的解释层:AI 机场报文解读、最高温中枢、完整市场桶匹配与“模型-市场差”已成为 Scan Terminal 的核心决策入口。 -这意味着报告里最初最突出的“工程地基缺失”问题,已经有一部分被关闭:`src/data_collection/weather_sources.py` 与 `web/app.py` 不再是原来的超大单文件;GitHub Actions 已覆盖 Python、前端和 Docker build;配置与密钥治理已成体系;运行态状态不再只能依赖 JSON/JSONL 文件;EMOS 也不再只是概念,而是进入了可训练、可评估、可 shadow、可门禁判断的阶段;更重要的是,监督真值与训练特征不再只能附着在 14 天运行态缓存上。 -但项目仍处在“从可用走向稳态”的中段,而不是终局。当前真正的高优先级问题已进一步收敛:**EMOS 仍未达到生产切换标准**,当前门禁结论明确为 `hold`,阻塞原因是 shadow bucket brier 明显退化,同时历史长期特征仍处在“刚开始积累”的阶段。SQLite 迁移方面,运行态主读切换和核心离线训练/回填链路已经完成验收:在移除 `data/*.json` / `data/*.jsonl` 后,训练、评估、shadow report 与关键 backfill 脚本仍可仅依赖运行时数据库正常执行;当前保留的 legacy 文件路径主要用于迁移、导出、校验和显式回退输入。历史真值治理方面,新增的永久真值表、revision 审计表与长期训练特征表已经落地,`Taipei` / `Shenzhen` 的历史页面回填也已接通,因此当前缺口已从“历史真值是否会继续丢失”转为“历史特征是否能持续增长并支撑 EMOS/LGBM 评估”。可观测性方面,最小外部监控链路已经补齐:Prometheus 抓取、Alertmanager 规则、Grafana 面板、Telegram 告警 relay 与巡检脚本均已落地;当前剩余缺口已从“有没有外部监控”转为“监控覆盖深度是否足够”,例如节点级资源、数据库体积趋势、支付细粒度指标、按城市/来源拆分的业务 SLA。支付链路方面,链下审计与容灾已明显增强:事件重放、SQLite 审计事件、RPC 多节点容灾、合约静态检查、`/ops` 支付异常单都已补齐;当前剩余风险主要集中在**链上合约本身仍是最小实现**,尚未升级到 SafeERC20、Pausable、链上套餐绑定等更强防护版本。 -因此,当前阶段最正确的策略已经不是继续做“大范围基础重构”,而是围绕**EMOS 上线门禁稳定化、长期训练特征持续积累、监控覆盖深挖、城市决策卡可观测性、支付合约防护升级**这五条线持续收口。短中期内更高 ROI 的方向依然不是引入新的大模型,而是把现有“采集→后处理→市场映射→前端决策→支付/订阅”的链路做成**状态一致、指标可见、发布可控、回退明确**的生产平台。 ## 项目概览 PolyWeather 的目标与范围在 README/README_ZH 中定义得较清楚:为温度结算市场提供气象情报(多源采集→融合→概率→对照市场报价),并提供“官方看板(Vercel 前端)+ VPS 后端 + Telegram Bot”。 @@ -35,7 +31,6 @@ DEB(Dynamic Error Balancing)基于过去 N 天模型误差(MAE)倒数加 | 运行时组件 | `bot_listener.py` + `src/bot/*` | Telegram Bot | 入口 `bot_listener.py` 调 `start_bot()`,并由 `StartupCoordinator` 启动多个后台 loop。 | | Python 域模块 | `src/data_collection/*` | 天气采集 + 城市注册 + 市场读取 | 采集层已拆为 `weather_sources.py` 编排层 + `open_meteo_cache.py`、`settlement_sources.py`、`metar_sources.py`、`mgm_sources.py`、`amos_station_sources.py`、`jma_amedas_sources.py`、`nws_open_meteo_sources.py`。 | | Python 域模块 | `src/analysis/*` | DEB/趋势/概率/结算口径 | `deb_algorithm.py`、`trend_engine.py`、`settlement_rounding.py`。 | -| Python 域模块 | `src/analysis/probability_calibration.py` + `src/analysis/probability_rollout.py` | 概率校准与上线门禁 | 已支持 `legacy / emos_shadow / emos_primary`,并可产出 rollout 判断。 | | Python 域模块 | `src/payments/*` + `contracts/*` | 支付合约 + 事件监听/补单 | Solidity 合约 + Python 侧事件扫描/确认循环 + SQLite 审计事件 + RPC 多节点容灾 + 合约静态检查。 | | Python 域模块 | `src/auth/*`、`docs/SUPABASE_SETUP_ZH.md`、`scripts/supabase/schema.sql` | Supabase 鉴权/订阅/积分 | 使用 `/auth/v1/user` 校验 JWT、`/rest/v1/subscriptions` 查订阅(服务端角色 key 必须保密)。 | | Python 域模块 | `src/database/runtime_state.py` | 运行态状态、永久真值与训练特征仓储 | 已接入 `daily_records`、`telegram_alert_state`、`probability_training_snapshots`、`open_meteo` 持久缓存,并新增永久真值表、真值修订审计表、长期训练特征表。 | @@ -150,7 +145,6 @@ Web/Telegram 请求 → FastAPI 调用采集器抓取/复用缓存 → 分析引 **测试**:仓库存在 `tests/test_trend_engine.py`,覆盖 μ 计算、死盘判定、预报崩盘提示、趋势方向等核心逻辑(通过 patch 隔离外部依赖)。前端侧已通过 `npm run build` 验证 Scan Terminal 改动可以编译;后续仍建议为城市决策卡补固定 fixture,覆盖 `all_buckets` 匹配、温度单位渲染、AI 缓存 key 与 stream 队列行为。 **CI/CD**:已补齐 GitHub Actions 工作流,至少覆盖 Python lint/test、前端 build、Docker build 三条门禁;当前缺口不再是“有没有 CI”,而是“是否已在 GitHub 分支保护中强制执行”。 -**运维验收**:除 `scripts/validate_frontend_cache.sh` 外,现已新增配置校验、运行态迁移/核验、EMOS rollout 判断等脚本,并提供 `/healthz`、`/api/system/status`、`/metrics` 作为基础观测入口。 **部署/更新**:Compose 用于启动服务;另有 `update.sh` 通过 `pkill` + `nohup` 重启 bot 与 web。 ## 优势与薄弱点 @@ -166,27 +160,21 @@ Web/Telegram 请求 → FastAPI 调用采集器抓取/复用缓存 → 分析引 **可复现性已从“缺模板”进入“模板与生产对齐”的阶段**:`.env.example`、`.env.secrets.example`、中文配置文档、前端部署文档、运行时配置校验器都已存在;当前风险主要在于线上历史 `.env` 与新模板并存、旧变量命名残留、以及密钥轮换与分层是否真正落实。 **CI 已建立,但组织级质量门禁未必完全收口**:CI 现已覆盖 Python、前端与 Docker build。当前问题不再是“缺 CI”,而是是否把这些 status check 绑定到 `main` 保护策略,以及是否逐步引入更严格的 pre-merge 审查。 **运行态状态/缓存与核心离线链路的 SQLite 收口已完成**:`daily_records`、`telegram_alert_state`、`probability_training_snapshots`、`open_meteo` 缓存已经支持并在生产中主读 SQLite,迁移/校验脚本可用;进一步地,在临时移除 `data/*.json` / `data/*.jsonl` 后,训练集导出、概率拟合、评估报告、shadow report 和关键 backfill 脚本已验证仍可运行。当前 legacy 文件路径主要是显式回退入口,而不再是默认主输入。 -**历史真值治理已从设计缺陷修复到可追溯运行**:`daily_records` 继续作为近 14 天运行态缓存,但已经不再承担长期监督真值职责;项目新增了永久真值表、真值 revision 审计表和长期训练特征表,并为 `Taipei` / `Shenzhen` 补上了历史页面回填链路。当前风险已不再是“监督真值会不会继续被 14 天裁剪吞掉”,而是“历史长期特征能否持续积累到足够支撑 EMOS/LGBM 重新评估”。 **第三方服务合规与稳定性风险**: 项目强依赖外部 API(Open-Meteo、AviationWeather、global.amo.go.kr AMOS、NWS、HKO、CWA、Polymarket、Supabase)以及城市 AI provider(OpenAI-compatible stream,当前临时 MiMo)。其中 AviationWeather Data API 有明确速率限制;Polymarket 官方说明 Gamma/Data/CLOB 三套 API 分属不同域,CLOB 交易端点需鉴权且策略可能变化;Supabase 明确强调 `service_role`/secret keys 绝不可暴露。若缺乏集中治理(重试/退避/熔断/降级/配额监控/密钥轮换),稳定性与合规不可控。城市 AI 解读已经通过前端 2 并发队列、30s timeout、stream parse retry 与缓存 key 稳定化降低第三/第四城市失败概率,但仍需持续记录 stream duration、cache hit、retry、degraded 与 queue depth。 -**可观测性最小闭环已完成,但监控深度仍待加强**:项目现在已有 `/healthz`、`/api/system/status`、`/metrics`,并已补齐 Prometheus 抓取、Alertmanager 规则、Grafana 面板、Telegram relay 与巡检脚本。与此同时,`/ops` 已经逐步演进为后台管理台而不只是状态页:除支付、会员、用户与 EMOS 门禁外,还新增了训练数据治理卡片、城市覆盖矩阵,以及 `/ops/truth-history` 这种可直接查询 `actual_high / settlement_source / station_code / truth_version / updated_by / updated_at` 的真值表浏览页。当前缺口不再是“有没有外部监控”,而是节点级资源、数据库体积趋势、更细粒度支付指标、按城市/来源拆分的业务 SLA,以及是否需要进一步补 `truth revision` 明细页、趋势图和运营日报。 -**EMOS 已完成工程接入,但未完成生产发布**:EMOS/CRPS 校准、shadow 观测、rollout report、上线门禁都已实现;当前真实门禁结果为 `hold`,阻塞原因是 shadow bucket brier 明显退化。因此概率引擎标准化并非未做,而是“工程完成、发布未通过”。 **许可证/商业使用的潜在冲突点**:仓库自身现为 `AGPL-3.0-only`,但如果未来尝试引入外部神经天气模型,仍需单独核验第三方代码与权重的商用条件:GraphCast 仓库代码 Apache-2.0,但权重使用 CC BY-NC-SA 4.0(非商业),Pangu-Weather 权重同样 BY-NC-SA 且明确禁止商业用途;不加区分地把这些模型用于付费产品会留下法律风险。 ## 对标分析 为满足“至少 3 个相似开源项目或近期论文”对标,本报告选择三类代表: 1)**AI 气象预报模型**(GraphCast / FourCastNet / Pangu-Weather):用于评估“若 PolyWeather 未来扩展到更强预测能力”的技术与许可边界; -2)**概率后处理方法**(EMOS):作为 PolyWeather 概率引擎的更标准化替代/对照; 3)**预测市场 API 客户端生态**(Polymarket/py-clob-client、aiopolymarket):用于评估市场层的工程选型。 ### 关键对比表 | 项目/论文 | 解决的问题 | 输出形态 | 性能/效果(公开描述) | 易用性与依赖 | 许可证要点 | | --------------------------------------------------------- | ---------------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -| **PolyWeather**(本仓库) | 温度结算市场气象情报:多源→校准概率桶→错价扫描→城市决策卡→订阅/支付 | 生产级应用(Web+Bot+API+支付) | 以工程能力为主;内置 DEB、LGBM/EMOS 校准概率、死盘判定、市场扫描;当前覆盖 51 城市,并已补齐韩国 AMOS 跑道级观测、积分制度改造(免费查询/普惠周奖励)、真值治理、后台运维视图、AI 机场报文解读与 full bucket 决策映射。 | 主要依赖外部 API 与城市 AI provider;Docker Compose 一键启动。 | 仓库 `AGPL-3.0-only`;品牌、生产私有数据与运营规则不随代码许可证授权。 | | **GraphCast**(google-deepmind/graphcast) | 10 天全球中期预报(ML 替代/增强 NWP) | 模型代码+权重+notebooks | 论文与介绍提到在大量指标上优于主流确定性系统;仓库提供预训练权重与示例数据入口,并提示 ERA5/HRES 数据条款需另行遵守。 | 完整训练需 ERA5 等;更适合科研/平台级推理,不是产品级 BFF。 | 代码 Apache-2.0;权重 CC BY-NC-SA 4.0(商业限制)。 | | **FourCastNet**(NVlabs/FourCastNet) | 高分辨率 data-driven 全球预报(AFNO/ViT) | 模型训练/推理代码+数据/权重链接 | README 描述:0.25° 分辨率、周尺度推理非常快,并可做大规模集合;适合平台型预报。 | 训练/数据依赖大(ERA5 子集 TB 级);工程集成成本高。 | BSD 3-Clause(代码)。 | | **Pangu-Weather**(198808xc/Pangu-Weather + Nature 论文) | 3D Transformer 架构的中期全球预报 | ONNX 推理代码+预训练模型 | Nature 论文称在 reanalysis 上对比 IFS 有更强确定性预报表现,并强调速度优势;仓库提供 ONNX 推理与 lite 版训练说明。 | 模型文件大(多份 ~GB 级),训练资源需求高;更适合科研推理或内部平台。 | 权重 BY-NC-SA 4.0、明确禁止商业用途。 | -| **EMOS**(Gneiting & Raftery 等) | 集合预报校准:纠偏与解决 underdispersion | 统计后处理方法 | 提出用回归形式输出概率分布(常见为高斯),并以 CRPS 等指标拟合,属于成熟的气象概率校准路线。 | 易落地:对 PolyWeather 而言只需“历史库+拟合器”。 | 方法论(论文);可自行实现,无额外许可约束(注意论文版权)。 | | **Polymarket/py-clob-client** | Polymarket CLOB 读写 SDK | Python SDK | 官方 SDK,支持 read-only 与交易接口;协议与端点在官方文档中给出。 | 易用,适合增强 PolyWeather 市场层。 | MIT。 | | **aiopolymarket** | Polymarket APIs 的 async 客户端 | Python async 客户端 | 强调类型安全(Pydantic)、自动分页、重试与 backoff,适合高并发与健壮性诉求。 | 适合替换/补强当前同步 requests 与自定义缓存。 | 以仓库许可为准(此处建议上线前核验)。 | @@ -196,8 +184,6 @@ Web/Telegram 请求 → FastAPI 调用采集器抓取/复用缓存 → 分析引 下表按截至 `2026-05-11` 的真实状态重排优先级。已完成项不再继续列为“待做”,只保留当前仍需推进的事项。 | 优先级 | 改进项 | 预估工作量 | 主要收益 | 主要风险 | 可执行步骤(建议顺序) | | ------ | --------------------------------------------------------------------------------------------------------------------------------- | -------------------: | ------------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 高 | **稳定 EMOS shadow 并收紧上线门禁** | 1–2 周 | 让概率引擎升级具备明确发布条件,避免拍脑袋切换 | 当前 shadow bucket brier 退化明显,存在误上线风险 | 1) 持续积累 snapshot 样本 → 2) 定期重训与生成 `evaluation_report` / `shadow_report` / `rollout_report` → 3) 重点压 `bucket_brier` 退化 → 4) 只有门禁从 `hold` 进入 `observe/promote` 后才考虑上线 | -| 高 | **持续积累长期训练特征,验证 SQLite 真值治理后的样本增长** | 1–2 周 | 让 EMOS/LGBM 的重训真正建立在长期可信样本上,而不是继续被短期特征缺口卡住 | 当前真值已长期化,但历史长期特征仍偏少,EMOS/LGBM 样本增长会滞后 | 1) 持续写入 `training_feature_records_store` → 2) 每日检查 `/ops` 训练数据与 `/ops/truth-history` → 3) 定期对 `Taipei` / `Shenzhen` 的历史页面回填做抽查 → 4) 观察样本是否自然增长后再重训 | | 中 | **把最小外部监控继续补深**:从“可告警”提升到“可运营” | 3–7 天 | 不再只知道服务坏没坏,还能看资源趋势、来源 SLA 和支付波动 | 指标过多会带来维护噪音 | 1) 增加节点 CPU/内存/磁盘 → 2) 增加 SQLite/支付体积与事件趋势 → 3) 把 HTTP/来源指标细分到城市/来源维度 → 4) 增加日报或异常摘要 | | 中 | **城市决策卡 AI 解读可观测性与回放测试** | 3–5 天 | 降低第三/第四/第五城市 AI 解读失败,验证缓存与队列是否真正生效 | 外部 AI stream 仍可能超时或输出截断,若无指标很难复盘 | 1) 记录 city-ai stream status/duration/retry/degraded/cache-hit/queue-depth → 2) 增加固定 METAR + detail + all_buckets fixture → 3) 回归断言 bucket 匹配、模型-市场差、温度单位与缓存 key → 4) 将生产 env 建议同步进部署文档 | | 中 | **市场层升级为 async + 类型安全**:引入 `aiopolymarket` 或在现有层加重试/backoff/连接池 | 4–7 天 | 行情层更稳,减少短时网络抖动;更易扩展更多市场/分页 | 依赖升级带来的行为差异 | 1) 把 requests.Session 替换为 aiohttp/httpx → 2) 在 Gamma/CLOB 调用侧实现指数退避 → 3) 引入 typed models,减少解析失败 | @@ -223,18 +209,15 @@ PolyWeather 的评测应围绕“结算场景”而非传统数值天气预报 **指标** 1)确定性误差:MAE、RMSE(按城市、按季节、按风险等级分组); 2)结算命中率:`WU_round(pred) == WU_round(actual)`(项目已有统计口径); -3)概率质量:Brier Score(对离散温度桶),以及建议补充 CRPS(连续变量概率评分,EMOS 体系常用)。 4)校准曲线:预测概率分箱的可靠性图(reliability diagram)与 Sharpness(分布集中度)。 **基线** - Baseline A:Open-Meteo 当日最高温(或 forecast median)作为点预测; - Baseline B:等权平均(DEB 在历史少时也会回退此策略); - Baseline C:当前 DEB; -- Baseline D:EMOS(以 ensemble 均值/方差为输入,拟合 μ 与 σ,优化 CRPS)。 **预期结果(定性)** - 若历史样本足够,DEB 应在“系统性偏差明显”的城市提升 MAE; -- EMOS 类方法通常能在概率校准(可靠性与 CRPS)上更稳定,尤其当 ensemble 信息可用(项目已接入 Open-Meteo ensemble/p10/p90)。 **算力**:以上评测全部可在 CPU 上完成;数据量按“51 城市 × 180 天”级别,pandas/duckdb 即可。若引入更复杂拟合(如分层贝叶斯/分位数回归),也通常不需要 GPU。 ### 错价信号与市场有效性基准 @@ -259,7 +242,6 @@ PolyWeather 的评测应围绕“结算场景”而非传统数值天气预报 | ----------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | | 第 1 周 | 城市决策卡稳定性补强 | city-ai stream/cache/queue 指标;固定 METAR + `all_buckets` fixture;温度桶匹配与模型-市场差回归测试;生产 env 文档化 | 前端为主,后端补指标 | | 第 2 周 | 市场层与 Scan Terminal 数据回放 | 保存 `bucket_label/bucket_direction/model_market_diff/matching_reason`;支持回放第三/第四/第五城市 AI 解读失败案例 | 用真实失败样本压回归 | -| 第 3–4 周 | EMOS 与长期特征继续收口 | 持续积累 `training_feature_records_store`;定期生成 evaluation/shadow/rollout report;继续观察 `bucket_brier` 是否退出 hold | 数据工程为主 | | 第 4–5 周 | 监控深挖与运维日报 | 来源 SLA、城市维度延迟、AI stream 状态、SQLite 体积、支付事件趋势、异常摘要 | 避免指标过多,先覆盖高频故障 | | 第 6 周 | 支付合约与发布门禁升级 | SafeERC20/Pausable 方案评审;CI required checks 与 release/tag 流程绑定;热修例外流程 | 合约升级需单独部署验证 |