MiMo AI 能力扩展:TAF解读、概率分布解读、异常检测、市场概览
AI 解读字段扩展:
- 新增 taf_read_zh/en:解读机场预报中影响今日峰值窗口的变化
- 新增 probability_read_zh/en:描述概率分布形态(最高桶、偏左/偏右)
- stream max_tokens 900→1200 容纳新输出字段
- 缓存 key 简化为 METAR原文+观测时间,大幅提升命中率
- 兜底函数补全 TAF 和概率字段的确定性生成
异常检测:
- 纯数学计算,零 AI 延迟:实测温度 vs 全部模型预测上下限
- 三级告警:breakout_above / breakout_below / deviation
市场概览:
- 新增 POST /api/scan/terminal/overview(MiMo 批量解读,缓存10分钟)
- 前端 MarketOverviewBanner 可折叠横幅(顶栏与标签栏之间)
- 移动端适配 640px/768px 断点,暗色/亮色双主题
Scope-risk: MEDIUM — 170 测试通过,TypeScript 零错误,ruff 零告警
Tested: python -m pytest -q (170 passed), npx tsc --noEmit (0 errors), ruff check .
This commit is contained in:
@@ -333,6 +333,34 @@ def _build_city_ai_fallback(
|
||||
"range_low": range_low,
|
||||
"range_high": range_high,
|
||||
}
|
||||
taf_data = ai_input.get("taf") if isinstance(ai_input.get("taf"), dict) else {}
|
||||
if partial_ai.get("taf_read_zh") or partial_ai.get("taf_read_en"):
|
||||
taf_zh = str(partial_ai.get("taf_read_zh") or partial_ai.get("taf_read_en") or "").strip()
|
||||
taf_en = str(partial_ai.get("taf_read_en") or partial_ai.get("taf_read_zh") or "").strip()
|
||||
elif taf_data.get("raw_taf"):
|
||||
taf_zh = f"TAF 可用,需人工判读:{str(taf_data.get('raw_taf', ''))[:120]}"
|
||||
taf_en = f"TAF available, manual read: {str(taf_data.get('raw_taf', ''))[:120]}"
|
||||
else:
|
||||
taf_zh = "无可用 TAF"
|
||||
taf_en = "No TAF available"
|
||||
|
||||
prob_data = ai_input.get("probability") if isinstance(ai_input.get("probability"), dict) else {}
|
||||
if partial_ai.get("probability_read_zh") or partial_ai.get("probability_read_en"):
|
||||
prob_zh = str(partial_ai.get("probability_read_zh") or partial_ai.get("probability_read_en") or "").strip()
|
||||
prob_en = str(partial_ai.get("probability_read_en") or partial_ai.get("probability_read_zh") or "").strip()
|
||||
elif prob_data.get("top_buckets"):
|
||||
top = prob_data["top_buckets"][0] if isinstance(prob_data["top_buckets"], list) else {}
|
||||
if isinstance(top, dict) and top.get("label"):
|
||||
skew_text = f",分布{'偏右' if prob_data.get('skew') == 'right' else '偏左' if prob_data.get('skew') == 'left' else '对称'}" if prob_data.get("skew") else ""
|
||||
prob_zh = f"最高概率桶 {top.get('label', '')}({top.get('prob', '?')}%){skew_text}"
|
||||
prob_en = f"Peak bucket {top.get('label', '')} ({top.get('prob', '?')}%){skew_text.replace('偏右', ', right-skewed').replace('偏左', ', left-skewed').replace('对称', ', symmetric')}"
|
||||
else:
|
||||
prob_zh = "概率分布数据可用但格式异常"
|
||||
prob_en = "Probability data available but malformed"
|
||||
else:
|
||||
prob_zh = "概率分布暂未生成"
|
||||
prob_en = "Probability distribution not yet generated"
|
||||
|
||||
return {
|
||||
"predicted_max": partial_ai.get("predicted_max", predicted),
|
||||
"range_low": partial_ai.get("range_low", range_low),
|
||||
@@ -343,6 +371,10 @@ def _build_city_ai_fallback(
|
||||
"final_judgment_en": final_en,
|
||||
"metar_read_zh": metar_zh,
|
||||
"metar_read_en": metar_en,
|
||||
"taf_read_zh": taf_zh,
|
||||
"taf_read_en": taf_en,
|
||||
"probability_read_zh": prob_zh,
|
||||
"probability_read_en": prob_en,
|
||||
"reasoning_zh": reasoning_zh,
|
||||
"reasoning_en": reasoning_en,
|
||||
"risks_zh": risks_zh,
|
||||
|
||||
Reference in New Issue
Block a user