From 658689bc9210ab3abe3cd0c5057c4ae5353645fc Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Sun, 19 Apr 2026 06:11:21 +0800 Subject: [PATCH] Clarify EMOS local training and rollout docs --- .env.example | 14 +- README.md | 19 +- README_ZH.md | 24 +- docs/API_ZH.md | 2 +- docs/EMOS_LGBM_SYSTEM_ZH.md | 83 ++++-- docs/EMOS_TRAINING_REPORT_ZH.md | 359 ++++++++++++++---------- docs/MODEL_STACK_AND_DEB_ZH.md | 2 +- docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md | 46 +-- docs/TECH_DEBT.md | 8 +- docs/TECH_DEBT_ZH.md | 8 +- frontend/README.md | 4 +- frontend/content/docs/docs.ts | 2 +- 12 files changed, 342 insertions(+), 229 deletions(-) diff --git a/.env.example b/.env.example index 4c5b07e1..98e226cf 100644 --- a/.env.example +++ b/.env.example @@ -55,16 +55,20 @@ POLYWEATHER_METAR_CLUSTER_TIMEOUT_SEC=3.5 METAR_CACHE_TTL_SEC=600 JMA_AMEDAS_CACHE_TTL_SEC=120 METEOBLUE_CACHE_TTL_SEC=7200 -POLYWEATHER_PROBABILITY_ENGINE=emos_primary +# Probability engine modes: +# - legacy: production-safe primary path. +# - emos_shadow: user-facing probability stays legacy, EMOS is generated for comparison. +# - emos_primary: only after offline evaluation passes and manual rollout is approved. +POLYWEATHER_PROBABILITY_ENGINE=legacy 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 -# Optional: cap recent probability snapshots used by EMOS retraining if the -# runtime SQLite snapshot table grows too large. +# Optional: cap recent probability snapshots used by EMOS retraining. +# Recommended on VPS: do not train there; pull the SQLite DB to a local machine. # POLYWEATHER_EMOS_TRAINING_SNAPSHOT_LIMIT=20000 -# Optional: set this to a writable runtime path if you want auto retrain to -# promote new EMOS parameters without rebuilding the image. +# Optional: set this to a writable runtime path if you manually deploy a +# locally trained EMOS calibration file. # POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json POLYWEATHER_LGBM_ENABLED=false POLYWEATHER_LGBM_MODEL_PATH=/app/artifacts/models/lgbm_daily_high.txt diff --git a/README.md b/README.md index 12cb8736..7bf7fa8c 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ Public docs center: `/docs/intro` on the main site (bilingual product documentat - Ops dashboard live: `/ops` for memberships, leaderboard, manual point grants, and payment incident triage. - Lightweight observability live: `/healthz`, `/api/system/status`, `/metrics`. - Runtime state, cache, and core offline training/backfill flows now use SQLite as the primary path; legacy JSON/JSONL files remain only for migration, export, and explicit fallback input. -- EMOS/CRPS calibrated probability is now the default primary probability engine (`emos_primary`); set `POLYWEATHER_PROBABILITY_ENGINE=emos_shadow` or `legacy` to roll back. +- EMOS/CRPS calibration is wired and trainable, but production should stay on `legacy` or `emos_shadow`; `emos_primary` is only for candidates that pass local offline evaluation and manual rollout. - Intraday analysis is now positioned as a professional meteorology read: headline, confidence, base/upside/downside paths, next observation point, evidence chain, failure modes, and confirmation rules. - Intraday modal now blocks stale cached detail during refresh, so users do not briefly trade off old city/date data before full detail arrives. -- Calibrated model probability is now the primary probability panel. `LGBM` is shown as a calibrated probability engine when available; model consensus and market prices are secondary references. +- Calibrated model probability is now the primary probability panel. It shows the active production probability engine; EMOS/LGBM are surfaced only when evaluated or shadowed, while model consensus and market prices remain secondary references. - Non-Hong Kong airport cities now ingest `TAF` and parse `FM / TEMPO / BECMG / PROB30/40`. - Temperature chart now overlays `TAF Timing` markers near the expected peak window. - Trade cue now combines upper-air structure, `TAF`, market crowding, and `edge_percent`. @@ -132,6 +132,19 @@ POLYWEATHER_DB_PATH=/var/lib/polyweather/polyweather.db POLYWEATHER_STATE_STORAGE_MODE=sqlite ``` +## EMOS Local Training + +Do not run full EMOS retraining on a small VPS. The VPS should collect data and load approved calibration files; training should run on a local/dev machine using a copied production SQLite database: + +```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 +``` + +Promote a generated `default.json` only when `auto_retrain_report.json` has `ready_for_promotion=true`, and prefer `emos_shadow` before enabling `emos_primary`. + ## Ops Verification ### Health / system status / metrics @@ -219,4 +232,4 @@ docker compose logs -f polyweather | egrep "polymarket wallet activity watcher s ## Version - Version: `v1.5.4` -- Last Updated: `2026-04-18` +- Last Updated: `2026-04-19` diff --git a/README_ZH.md b/README_ZH.md index 08de7fb9..b3ad3de3 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -25,7 +25,7 @@ - 已上线轻量可观测性:`/healthz`、`/api/system/status`、`/metrics`。 - 已补最小外部监控栈:Prometheus + Alertmanager + Grafana + Telegram 告警 relay。 - 运行态状态、缓存与核心离线训练/回填链路已完成 SQLite 主路径收口;legacy JSON/JSONL 仅保留给迁移、导出与显式回退输入。 -- EMOS/CRPS 校准概率已切为默认主路径(`emos_primary`);如需回滚可设置 `POLYWEATHER_PROBABILITY_ENGINE=emos_shadow` 或 `legacy`。 +- EMOS/CRPS 校准链路已接通,但生产主概率保持 `legacy` 或 `emos_shadow`;`emos_primary` 只在本地离线评估通过并手动灰度后启用。 - 官方增强站网已统一接入: - `MGM`(土耳其) - `CMA/NMC`(中国内地) @@ -38,7 +38,7 @@ - `/ops` 现已展示缓存桶数量、summary cache hit/miss 与 prewarm heartbeat。 - 今日日内分析已改为“专业气象判断台”:顶部先给气象主判断、置信度、基准/上修/下修路径、下一观测点,再展示证据链、失效条件、确认条件和模型层。 - 日内分析弹窗在 full detail / market detail 同步完成前会锁住旧内容并显示刷新状态,避免用户短暂看到上一轮缓存数据后误判。 -- 概率区已改为“校准模型概率”,有 LGBM 时展示 LGBM 校准概率;模型共识和市场价格只作为辅助参考。 +- 概率区已改为“校准模型概率”;默认展示生产概率引擎输出,EMOS/LGBM 只在通过评估或作为 shadow 时进入解释层。 - 今日日内结构解读已支持可选 `Groq` 改写层,失败时自动回退规则文案。 - 前端部署文档已补充 Vercel 节流建议,包括 analytics 关闭、eager fetch 开关与扫描流量防火墙规则。 @@ -122,6 +122,24 @@ POLYWEATHER_DB_PATH=/var/lib/polyweather/polyweather.db POLYWEATHER_STATE_STORAGE_MODE=sqlite ``` +## EMOS 本地训练流程 + +低配 VPS 只负责采集、服务和加载已通过评估的参数,不建议在 VPS 上跑 EMOS 全量训练。训练前先从 VPS 拉 SQLite 副本到本地: + +```powershell +scp root@38.54.27.70:/var/lib/polyweather/polyweather.db E:\web\PolyWeather\data\polyweather-prod.db +``` + +本地训练: + +```powershell +$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,并优先以 `emos_shadow` 观察。 + ## 运维验收 ### 健康与系统状态 @@ -235,4 +253,4 @@ docker compose logs -f polyweather | egrep "polymarket wallet activity watcher s ## 当前版本 - 版本:`v1.5.4` -- 文档最后更新:`2026-04-18` +- 文档最后更新:`2026-04-19` diff --git a/docs/API_ZH.md b/docs/API_ZH.md index e9297cb2..157ce211 100644 --- a/docs/API_ZH.md +++ b/docs/API_ZH.md @@ -94,7 +94,7 @@ flowchart LR - `calibrated_mu` / `calibrated_sigma`:校准后分布参数 - `shadow_distribution`:shadow / 对照分布,供回归与灰度验证 -当前前端会优先展示 LGBM / EMOS 等校准概率;模型共识与市场价格只作为辅助参考,不再作为主结论。 +当前前端展示 `probabilities.engine` 对应的生产概率分布;`EMOS` / `LGBM` 只有在评估通过、显式启用或 shadow 对照时才进入展示/解释层。模型共识与市场价格只作为辅助参考,不再作为主结论。 #### 3. `detail_depth` diff --git a/docs/EMOS_LGBM_SYSTEM_ZH.md b/docs/EMOS_LGBM_SYSTEM_ZH.md index aa05af8a..ad3d37cb 100644 --- a/docs/EMOS_LGBM_SYSTEM_ZH.md +++ b/docs/EMOS_LGBM_SYSTEM_ZH.md @@ -1,6 +1,6 @@ # EMOS + LGBM 系统说明(中文) -最后更新:`2026-04-18` +最后更新:`2026-04-19` 本文档用于完整说明 PolyWeather 当前的两条统计/机器学习链路: @@ -351,7 +351,11 @@ LGBM 训练样本会优先从: ### 8.1 概率引擎模式 -当前项目仍然应该保持: +当前生产主概率应保持: + +- `legacy` + +如果需要观察 EMOS 对照,可切: - `emos_shadow` @@ -359,7 +363,7 @@ LGBM 训练样本会优先从: - `emos_primary` -原因不是工程没接好,而是门禁还没过。 +原因不是工程没接好,而是主概率发布必须由离线评估结果决定。VPS 轻量训练候选未通过门禁;本地训练候选虽通过门禁,但仍建议先 shadow 观察,再人工决定是否切主。 ### 8.2 LGBM 角色 @@ -433,26 +437,38 @@ LGBM 训练样本会优先从: ## 10. 当前 EMOS 结果怎么理解 -最近一轮离线评估大致是: +最近两轮评估给出了更清晰的结论。 -- `sample_count = 54` -- `delta_crps ≈ -0.0867` -- `delta_mae = 0` -- `delta_bucket_hit_rate = 0` +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` 这说明: -- 从 `CRPS` 看,EMOS 有改善 -- 但从 `MAE` 和 `top bucket hit` 看,没有明显进步 +- EMOS 工程链路有效,本地用更多 snapshot 训练时可以超过 legacy 的 CRPS/MAE。 +- 低配 VPS 不适合做主训练环境。 +- 通过门禁不等于立即默认主用,仍应先 `emos_shadow` 观察。 -shadow 报告里更关键的问题是: +当前生产策略仍然是: -- `shadow sample_count = 48` -- `delta_bucket_brier` 仍然明显偏坏 - -所以 rollout 结论仍然是: - -- `hold` +- 用户主概率默认 `legacy` +- EMOS 通过本地训练产生候选 +- 通过门禁后先以 `emos_shadow` 灰度 +- 连续稳定后才考虑 `emos_primary` 这不是“EMOS 无效”,而是: @@ -462,14 +478,17 @@ shadow 报告里更关键的问题是: 主要阻塞仍然是: -- 样本数不够 -- shadow bucket brier 退化 +- 有效样本仍然不大,城市级样本分布不均 +- 桶概率容易受结算边界影响 +- 需要避免 VPS 训练消耗线上资源 +- `emos_primary` 发布需要明确人工门禁 也就是说,当前 EMOS 状态可以总结成: - 工程链路完整 - 数据治理大幅改善 -- 发布门禁仍未通过 +- 本地训练可通过门禁 +- 生产主用仍需 shadow 观察与人工发布 --- @@ -594,21 +613,22 @@ EMOS 更依赖: 1. 查看 `/ops` 2. 看 `truth / feature / EMOS / LGBM` 覆盖有没有继续增长 3. 看 `Taipei/Shenzhen` 的 WU 行数是否继续更新 -4. 看 rollout 仍然是 `hold` 还是有改善 +4. 看本地 EMOS 候选是否通过门禁 +5. 看 VPS 是否只加载已批准参数,不在低配机器上训练 ### 15.2 周期性重训 -建议周期性执行: +建议在本地开发机执行,不建议在低配 VPS 上执行: -```bash -./venv/Scripts/python.exe scripts/export_probability_training_dataset.py -./venv/Scripts/python.exe scripts/fit_probability_calibration.py -./venv/Scripts/python.exe scripts/evaluate_probability_calibration.py -./venv/Scripts/python.exe scripts/build_probability_shadow_report.py -./venv/Scripts/python.exe scripts/judge_probability_rollout.py -./venv/Scripts/python.exe scripts/train_lgbm_daily_high.py +```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 真值恢复/补数 当有新的历史真值补数或回填需要时: @@ -631,7 +651,7 @@ EMOS 更依赖: 如果只用一句话概括当前状态: -**EMOS 和 LGBM 的工程基础已经补齐,但数据积累还在恢复期;当前最正确的策略仍然是继续以 `DEB` 为主路径,让长期真值和训练特征继续沉淀,再观察 EMOS/LGBM 是否自然变强。** +**EMOS 和 LGBM 的工程基础已经补齐,但生产主概率仍必须由评估门禁控制;当前最正确的策略是继续以 `DEB/legacy` 为主路径,在本地训练 EMOS 候选,VPS 只加载已批准参数。** 更具体一点: @@ -640,7 +660,8 @@ EMOS 更依赖: - 可训练 - 可评估 - 可 shadow - - 但暂时不能切主路径 + - 通过门禁后可灰度 + - 不应在低配 VPS 上自动训练或自动主用 - `LGBM` - 已接好 diff --git a/docs/EMOS_TRAINING_REPORT_ZH.md b/docs/EMOS_TRAINING_REPORT_ZH.md index 6647dcf2..cc9e0bdd 100644 --- a/docs/EMOS_TRAINING_REPORT_ZH.md +++ b/docs/EMOS_TRAINING_REPORT_ZH.md @@ -1,107 +1,201 @@ -# EMOS 训练报告(2026-04-19) +# EMOS 训练与发布报告(2026-04-19) ## 1. 当前结论 -- `EMOS` 已切为默认主概率路径:`emos_primary`。 -- 本次切换只影响概率分布校准层,不改变 `DEB`、多模型预报、METAR 结算口径、订阅权限或缓存路由。 -- 线上回滚开关保留:`POLYWEATHER_PROBABILITY_ENGINE=emos_shadow` 或 `legacy`。 -- `LGBM` 本轮重新训练后仍不建议上线,继续保持 `POLYWEATHER_LGBM_ENABLED=false`。 +- `EMOS` 工程链路已经接通:可以训练、评估、生成候选参数,并在前端以校准概率层展示。 +- 生产主概率当前不应默认使用 `emos_primary`。默认建议为 `legacy`;需要观察时使用 `emos_shadow`。 +- `emos_primary` 只允许在本地离线训练通过门禁、人工复核后手动灰度。 +- 低配 VPS(例如 1 vCPU / 2GB RAM)不适合做 EMOS 全量训练;VPS 只负责采集、服务和加载已批准的参数文件。 +- `LGBM` 当前仍不建议作为主路径,继续保持 `POLYWEATHER_LGBM_ENABLED=false`。 -## 2. 本次 EMOS 版本 +## 2. 最近两次训练结果 -- 校准版本:`emos-20260418192717` -- 训练时间:`2026-04-18T19:27:17Z` -- 样本数:`74` -- 参数文件:[default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json) -- 离线评估报告:[evaluation_report.json](/E:/web/PolyWeather/artifacts/probability_calibration/evaluation_report.json) +### 2.1 VPS 轻量训练:不通过 -## 3. 离线评估摘要 +VPS 使用最近 `5000` 条 snapshot 训练的候选: -本次评估对比 legacy 概率和强制 EMOS primary 概率: +- 版本:`emos-auto-20260418204203` +- 样本数:`791` +- 结论:`hold` -| 指标 | Legacy | EMOS | 变化 | -| :-- | --: | --: | --: | -| CRPS | `3.474108` | `3.331240` | `-0.142868` | -| MAE | `3.679324` | `3.622584` | `-0.056741` | -| Bucket hit rate | `0.500000` | `0.500000` | `0.000000` | +| 指标 | 变化 | +| :-- | --: | +| `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` 小幅改善,不再出现上一版“误差持平或略差”的问题。 -- `bucket_hit_rate` 持平,没有牺牲结算桶命中率。 +- CRPS 与 MAE 有改善,候选通过当前门禁。 +- 桶命中率轻微下降,虽然在门禁允许范围内,但仍建议先以 `emos_shadow` 观察,再决定是否切 `emos_primary`。 -因此本轮可以先把 EMOS 作为主概率路径上线,但仍需要线上持续观察。 +## 3. 生产运行策略 -## 4. LGBM 本轮结果 +推荐生产 `.env`: -本轮 LGBM 训练完成,但验证集表现不足: - -| 指标 | Validation | -| :-- | --: | -| LGBM MAE | `5.867` | -| DEB MAE | `1.825` | -| Best-single MAE | `0.567` | -| Median MAE | `1.700` | - -结论: - -- LGBM 当前样本量和泛化质量不足。 -- 不能替代“校准模型概率”板块。 -- 线上继续关闭:`POLYWEATHER_LGBM_ENABLED=false`。 -- 可以保留模型文件用于离线跟踪,不进入前端主路径。 - -## 5. 上线方式 - -默认代码路径已改为: - -```text -POLYWEATHER_PROBABILITY_ENGINE=emos_primary -``` - -未设置环境变量时,系统默认走 `emos_primary`。 - -显式回滚方式: - -```text -POLYWEATHER_PROBABILITY_ENGINE=emos_shadow -``` - -或: - -```text +```env POLYWEATHER_PROBABILITY_ENGINE=legacy +POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json ``` -`.env.example` 已同步暴露该配置项。 +观察 EMOS 时: -## 6. 前端表现 +```env +POLYWEATHER_PROBABILITY_ENGINE=emos_shadow +POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json +``` -今日日内分析中的“校准模型概率”会优先展示 EMOS 校准后的温度桶分布。 +只有在候选连续通过评估、前端展示稳定、业务侧确认后,才切: -用户看到的含义应该是: +```env +POLYWEATHER_PROBABILITY_ENGINE=emos_primary +POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json +``` -- 这是经过历史误差校准后的概率分布; -- 不是简单模型投票; -- 不直接等于最终结算概率; -- 仍应结合 METAR 实测、峰值窗口、失效条件和模型层分歧。 +验证线上加载状态: -## 7. 监控要求 +```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 -- `CRPS` -- `MAE` -- `bucket_hit_rate` -- 城市级样本分布 -- 概率是否过度摊平 -- 高温/低温尾部桶是否系统性低估 +### 4.1 拉取生产 SQLite 副本 -如果连续回归显示 EMOS 退化,应先切回 `emos_shadow`,保留 shadow 观测,再决定是否回退到 `legacy`。 +推荐先在 VPS 上用 SQLite 在线备份生成快照: -## 8. 自动重训 +```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 @@ -109,108 +203,61 @@ python scripts\auto_retrain_probability_calibration.py 默认行为: -- 生成一个新的 EMOS candidate。 +- 生成新的 EMOS candidate。 - 对 candidate 跑离线评估。 - 写入候选目录和门禁报告。 -- 不覆盖线上 [default.json](/E:/web/PolyWeather/artifacts/probability_calibration/default.json)。 +- 不覆盖线上 `default.json`。 -候选产物默认写入: +重要参数: -```text -/var/lib/polyweather/probability_calibration/candidates// -``` +- `--verbose`:输出训练/评估进度。 +- `--snapshot-limit N`:只使用最近 N 条 snapshot。 +- `--promote-if-passed`:门禁通过后覆盖目标参数文件。 +- `--run-tests`:晋级前跑测试。 -最新自动训练报告默认写入: +当前不建议在 VPS 使用 `--promote-if-passed`。本地训练通过后,仍优先人工上传并使用 `emos_shadow`。 -```text -/var/lib/polyweather/probability_calibration/auto_retrain_report.json -``` +## 8. 门禁阈值 -允许门禁通过后自动发布: - -```text -python scripts\auto_retrain_probability_calibration.py --promote-if-passed --run-tests -``` - -门禁默认阈值: +默认阈值: - `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` 只做软门槛,因为它对结算边界过于敏感。 -- 如果发布,会先备份旧版 `default.json`。 +- `bucket_hit_rate` 是业务参考指标,但对结算边界敏感,不单独作为唯一判断。 -Docker 手动触发: +## 9. 前端说明 + +今日日内分析中的概率区展示的是当前生产概率引擎输出: + +- `legacy`:展示现有动态概率。 +- `emos_shadow`:用户主概率仍为 legacy,EMOS 仅用于对照和评估。 +- `emos_primary`:用户主概率使用 EMOS 校准分布。 + +对外文案应避免暗示“EMOS 一定更准”。推荐解释为: + +> EMOS 是 PolyWeather 基于 DEB 路径、多模型集合、METAR 实测进度和历史误差结构生成的统计校准概率,不是外部天气模型,也不是直接 API 结果。 + +## 10. 已验证 + +本地训练链路已验证: ```text -docker compose exec -T polyweather_web python scripts/auto_retrain_probability_calibration.py --verbose +python scripts\auto_retrain_probability_calibration.py --verbose --snapshot-limit 50000 ``` -查看最新报告: +测试链路已验证: ```text -docker compose exec -T polyweather_web cat /var/lib/polyweather/probability_calibration/auto_retrain_report.json +python -m pytest tests\test_auto_retrain_probability_calibration.py tests\test_probability_calibration.py tests\test_probability_rollout.py ``` -Docker 允许门禁发布: +当前工程结论: -```text -docker compose exec -T polyweather_web python scripts/auto_retrain_probability_calibration.py --verbose --promote-if-passed --run-tests -``` - -如果线上 SQLite 的 `probability_training_snapshots_store` 已经很大,可以先限制最近 N 条快照: - -```text -docker compose exec -T polyweather_web python scripts/auto_retrain_probability_calibration.py --verbose --snapshot-limit 20000 -``` - -也可以放到 `.env`: - -```text -POLYWEATHER_EMOS_TRAINING_SNAPSHOT_LIMIT=20000 -``` - -如果希望自动发布不需要重建镜像,需要在 `.env` 中指定可写参数文件: - -```text -POLYWEATHER_PROBABILITY_CALIBRATION_FILE=/var/lib/polyweather/probability_calibration/default.json -``` - -首次启用该路径前,先用当前镜像内置参数初始化一次: - -```text -docker compose exec -T polyweather_web mkdir -p /var/lib/polyweather/probability_calibration -docker compose exec -T polyweather_web cp /app/artifacts/probability_calibration/default.json /var/lib/polyweather/probability_calibration/default.json -``` - -建议后续挂到宿主机 `cron` 或 systemd timer: - -```text -0 3 * * * cd /root/PolyWeather && docker compose exec -T polyweather_web python scripts/auto_retrain_probability_calibration.py --promote-if-passed --run-tests -``` - -## 9. 已验证 - -本次上线前已执行: - -```text -python scripts\fit_probability_calibration.py -python scripts\evaluate_probability_calibration.py -python scripts\train_lgbm_daily_high.py -python scripts\report_lgbm_daily_high.py -python -m pytest tests\test_probability_calibration.py tests\test_probability_rollout.py tests\test_lgbm_daily_high.py tests\test_lgbm_features.py -``` - -代码切换后补充执行: - -```text -python -m pytest tests\test_probability_calibration.py tests\test_probability_rollout.py -``` - -结果:通过。 +**EMOS 可以继续本地训练与 shadow 观察,但生产主概率不应因为“机制接好”而默认切到 `emos_primary`。** diff --git a/docs/MODEL_STACK_AND_DEB_ZH.md b/docs/MODEL_STACK_AND_DEB_ZH.md index 13d96647..c14d2aa7 100644 --- a/docs/MODEL_STACK_AND_DEB_ZH.md +++ b/docs/MODEL_STACK_AND_DEB_ZH.md @@ -219,7 +219,7 @@ raw current_forecasts 当前前端把三层拆开展示: - `模型区间与分歧`:解释不同模型当前给出的最高温范围和分歧,不直接等于命中概率。 -- `校准模型概率`:由概率引擎输出温度桶概率;有 LGBM 时展示 LGBM 校准概率,缺失时降级到 EMOS / legacy 概率。 +- `校准模型概率`:由当前生产概率引擎输出温度桶概率;默认可保持 legacy,EMOS / LGBM 只在评估通过、显式启用或 shadow 对照时进入展示。 - `市场参考`:只展示市场价格和错价背景,不再作为主判断,也不默认输出 BUY YES / BUY NO。 模型票数只用于解释“哪些模型支持某个档位”,不等于最终概率。最终概率应优先读取 `probabilities.engine` 对应的校准分布。 diff --git a/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md b/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md index d314884f..e47c7cff 100644 --- a/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md +++ b/docs/PROBABILITY_SNAPSHOT_ARCHIVE_ZH.md @@ -1,6 +1,6 @@ # 概率训练样本归档说明(中文) -最后更新:`2026-04-18` +最后更新:`2026-04-19` ## 1. 目的 @@ -223,13 +223,20 @@ python scripts/export_probability_training_dataset.py ### 7.4 重训 EMOS -```bash -python scripts/fit_probability_calibration.py +推荐在本地电脑使用生产 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](/E:/web/PolyWeather/artifacts/probability_calibration/default.json) +- 生成新的候选 `default.json` +- 同时生成 `evaluation_report.json` 与 `auto_retrain_report.json` +- 不自动覆盖线上参数 ### 7.5 离线评估训练效果 @@ -263,21 +270,22 @@ python scripts/build_probability_shadow_report.py ## 8. 推荐的一整套重训流程 -如果过了十天、半个月,想重新训练一次,建议按这个顺序执行: +如果过了十天、半个月,想重新训练一次,当前推荐流程是: -```bash -python scripts/build_settlement_history_from_csv.py -python scripts/export_probability_training_dataset.py -python scripts/fit_probability_calibration.py -python scripts/evaluate_probability_calibration.py -python scripts/backfill_probability_shadow_history.py -python scripts/build_probability_shadow_report.py +```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 ``` -如果历史天气 CSV 还没补全,再先执行: +只有 `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. 怎么判断这次训练有没有进步 @@ -301,12 +309,13 @@ python scripts/backfill_historical_weather.py - 越低越好 - 反映概率分布质量 -只有同时满足下面条件,才可以说训练效果真的进步: +当前自动门禁至少要求: - `CRPS` 下降 -- `MAE` 不上升 -- `Bucket Hit Rate` 不下降 -- `Bucket Brier` 不上升 +- `MAE` 最多轻微退化 `0.05` +- `Bucket Hit Rate` 退化不超过 `0.05` + +人工复核还应看城市级结果,避免少数关键城市大幅退化。`Bucket Hit Rate` 受整数结算边界影响大,不能单独作为唯一判断。 ## 10. 当前最重要的现实判断 @@ -328,7 +337,8 @@ python scripts/backfill_historical_weather.py 1. 新增 `probability_training_snapshots.jsonl` 2. 每次分析时自动追加一条快照 3. 当天结束后自动回填 `actual_high` -4. 每 1-2 周重新训练一次 +4. 每 1-2 周在本地电脑重新训练一次 +5. VPS 只加载通过评估的参数文件,不做全量训练 ## 12. 总结 diff --git a/docs/TECH_DEBT.md b/docs/TECH_DEBT.md index 435e6f5f..380ceff4 100644 --- a/docs/TECH_DEBT.md +++ b/docs/TECH_DEBT.md @@ -29,7 +29,7 @@ flowchart TD end subgraph S["状态与概率"] - S1["EMOS primary 线上监控"] + S1["EMOS 本地训练与 shadow 发布门禁"] end A --> P @@ -49,13 +49,13 @@ flowchart TD - 钱包异动支持独立频道路由。 - 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。 - 轻量可观测性已上线(`/healthz`、`/api/system/status`、`/metrics`)。 -- EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关。 +- EMOS/CRPS 校准链路已接通;生产主概率保持 `legacy` 或 `emos_shadow`,`emos_primary` 只允许本地训练通过门禁后人工灰度。 ## 3. 高优先级技术债 | 项目 | 影响 | 建议动作 | | :-- | :-- | :-- | -| EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` | +| EMOS 发布门禁 | 低配 VPS 不适合训练,主概率不能绕过评估 | 本地拉生产 SQLite 训练,`ready_for_promotion=true` 后先 `emos_shadow` | | 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 | | 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 | @@ -76,6 +76,6 @@ flowchart TD ## 6. 下阶段里程碑 -1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚。 +1. 固化 EMOS 本地训练流程,禁止低配 VPS 自动训练和自动主用。 2. 补外部监控抓取与告警阈值。 3. 评估并推进支付合约 V2 升级。 diff --git a/docs/TECH_DEBT_ZH.md b/docs/TECH_DEBT_ZH.md index 435e6f5f..380ceff4 100644 --- a/docs/TECH_DEBT_ZH.md +++ b/docs/TECH_DEBT_ZH.md @@ -29,7 +29,7 @@ flowchart TD end subgraph S["状态与概率"] - S1["EMOS primary 线上监控"] + S1["EMOS 本地训练与 shadow 发布门禁"] end A --> P @@ -49,13 +49,13 @@ flowchart TD - 钱包异动支持独立频道路由。 - 运行态状态/缓存与核心离线训练、评估、回填链路已完成 SQLite 主路径收口。 - 轻量可观测性已上线(`/healthz`、`/api/system/status`、`/metrics`)。 -- EMOS/CRPS 校准链路已切为默认主路径(`emos_primary`),保留 `emos_shadow` / `legacy` 回滚开关。 +- EMOS/CRPS 校准链路已接通;生产主概率保持 `legacy` 或 `emos_shadow`,`emos_primary` 只允许本地训练通过门禁后人工灰度。 ## 3. 高优先级技术债 | 项目 | 影响 | 建议动作 | | :-- | :-- | :-- | -| EMOS 线上监控 | 已切 primary,仍需观察概率质量漂移 | 持续跑 CRPS / MAE / bucket hit 回归,异常时切回 `emos_shadow` | +| EMOS 发布门禁 | 低配 VPS 不适合训练,主概率不能绕过评估 | 本地拉生产 SQLite 训练,`ready_for_promotion=true` 后先 `emos_shadow` | | 外部监控与告警 | 只有轻量指标,无外部抓取 | 接 Prometheus/Grafana 或最小巡检 | | 退款与售后链路 | 商业闭环不完整 | 增加退款状态机与工单系统 | @@ -76,6 +76,6 @@ flowchart TD ## 6. 下阶段里程碑 -1. 监控 EMOS primary 的 CRPS / MAE / bucket hit,并保留 shadow 回滚。 +1. 固化 EMOS 本地训练流程,禁止低配 VPS 自动训练和自动主用。 2. 补外部监控抓取与告警阈值。 3. 评估并推进支付合约 V2 升级。 diff --git a/frontend/README.md b/frontend/README.md index 23ea837f..f67ba10a 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -39,7 +39,7 @@ PolyWeather Pro 的生产前端工程。 - 城市详情会自动识别“单模型 / 单日”的稀疏缓存并主动刷新,避免误把残缺 detail 当作完整结果 - 右侧详情面板在多日预报仍未补齐时会显示同步占位卡,不再把“只有今天一张卡”的中间态伪装成完整数据 - 日内分析弹窗在 full detail / market scan 同步时会锁住旧内容并显示刷新状态,避免用户短暂看到旧城市或旧日期的数据 -- 概率区优先展示 LGBM / EMOS 等校准模型概率,模型共识和市场价格只作为辅助说明 +- 概率区展示当前生产概率引擎输出;EMOS / LGBM 只在评估通过或 shadow 对照时进入解释层,模型共识和市场价格只作为辅助说明 - `/ops` 现已展示 prewarm worker 运行态、缓存桶状态与 summary cache hit/miss ## 本地开发 @@ -201,4 +201,4 @@ Ops: 详见根目录策略文档:`docs/OPEN_CORE_POLICY.md` -最后更新:`2026-04-18` +最后更新:`2026-04-19` diff --git a/frontend/content/docs/docs.ts b/frontend/content/docs/docs.ts index 0305d221..ee533063 100644 --- a/frontend/content/docs/docs.ts +++ b/frontend/content/docs/docs.ts @@ -55,7 +55,7 @@ export const DOCS_PAGES: DocsPage[] = [ id: "core-modules", title: "你会在页面上看到什么", blocks: [ - { type: "bullets", items: ["锚点状态:先确认当前机场主站实测、日内已见高点和结算时钟。", "当前节奏:把“此刻应到温度”和“机场实测”放在一张卡里,判断今天跑得快还是慢。", "专业气象结论条:先给今日主判断、置信度、基准/上修/下修路径和下一观测点。", "校准模型概率 / 模型区间与分歧:概率层优先看 LGBM / EMOS 等校准分布,模型区间用于解释分歧。", "气象证据链 / 失效条件 / 确认条件:解释为什么这么判断,以及什么情况会让判断降级。", "历史对账:查看已结算样本、DEB MAE、单模型表现和新增模型参考。"] }, + { type: "bullets", items: ["锚点状态:先确认当前机场主站实测、日内已见高点和结算时钟。", "当前节奏:把“此刻应到温度”和“机场实测”放在一张卡里,判断今天跑得快还是慢。", "专业气象结论条:先给今日主判断、置信度、基准/上修/下修路径和下一观测点。", "校准模型概率 / 模型区间与分歧:概率层看当前生产概率引擎输出;EMOS / LGBM 只有在评估通过或 shadow 对照时进入解释层,模型区间用于解释分歧。", "气象证据链 / 失效条件 / 确认条件:解释为什么这么判断,以及什么情况会让判断降级。", "历史对账:查看已结算样本、DEB MAE、单模型表现和新增模型参考。"] }, ], }, {