diff --git a/bot_listener.py b/bot_listener.py index d02f6b9e..ee644e7d 100644 --- a/bot_listener.py +++ b/bot_listener.py @@ -174,6 +174,43 @@ def analyze_weather_trend(weather_data, temp_symbol, city_name=None): msg2 = f"⚡ 预报偏低:确定性预报 {om_today}{temp_symbol} 低于集合90%下限,更可能接近 {ens_median}{temp_symbol}。" ai_features.append(msg2) + # === 数学概率计算(基于集合预报正态分布拟合)=== + import math as _math + # 用 P10/P90 反推标准差: P10 = median - 1.28*sigma, P90 = median + 1.28*sigma + sigma = (ens_p90 - ens_p10) / 2.56 + if sigma < 0.1: sigma = 0.1 # 防止除以零 + mu = ens_median # 以集合中位数为中心 + + # 如果 DEB 融合值或多模型均值存在,用它们微调中心 + if forecast_median is not None: + mu = (ens_median + forecast_median) / 2 # 取集合中位数和模型中位数的均值 + + # 简化的正态 CDF (不依赖 scipy) + def _norm_cdf(x, m, s): + return 0.5 * (1 + _math.erf((x - m) / (s * _math.sqrt(2)))) + + # 计算每个 WU 整数区间 [N-0.5, N+0.5) 的概率 + center = round(mu) + candidates = range(center - 2, center + 3) # 5 个候选整数 + probs = {} + for n in candidates: + p = _norm_cdf(n + 0.5, mu, sigma) - _norm_cdf(n - 0.5, mu, sigma) + if p > 0.01: # 只保留概率 > 1% 的 + probs[n] = p + + # 归一化 + total_p = sum(probs.values()) + if total_p > 0: + probs = {k: v / total_p for k, v in probs.items()} + + # 格式化输出(按概率从高到低排列) + sorted_probs = sorted(probs.items(), key=lambda x: x[1], reverse=True) + prob_parts = [f"{int(t)}{temp_symbol}({p*100:.0f}%)" for t, p in sorted_probs[:4]] + if prob_parts: + prob_str = " | ".join(prob_parts) + insights.append(f"🎲 结算概率:{prob_str}") + ai_features.append(f"🎲 数学概率分布:{prob_str}") + # === 实测已超预报 & 趋势输出 === if max_so_far is not None and forecast_high is not None: if max_so_far > forecast_high + 0.5: diff --git a/src/analysis/ai_analyzer.py b/src/analysis/ai_analyzer.py index 41c6d9d4..68bde736 100644 --- a/src/analysis/ai_analyzer.py +++ b/src/analysis/ai_analyzer.py @@ -38,11 +38,7 @@ def get_ai_analysis(weather_insights: str, city_name: str, temp_symbol: str) -> 2. **阻碍因子**:由于高湿度(>80%)、降水或全阴天气导致的升温失速。 3. **结算推演**:根据我提供给你的【博弈区间】以及【当前所处时段(是否过了最热期)】推断并告诉我最终结算温度落在哪个区间的希望更大。 4. **结算边界**:如果当前温度处于 X.5 这种进位/舍位边缘,需特别预警。 -5. **概率估算(极其重要,务必仔细推理)**: - - WU 结算规则:实测最高温四舍五入到整数。即 X.5 以上进位,X.5 以下舍去。例如:3.5°C→4°C,3.4°C→3°C。 - - 你必须先判断 DEB 融合值和各模型预报落在哪个 WU 取整区间内。例如 DEB=3.6°C 落在 [3.5, 4.5) 区间,对应 WU 结算 4°C。 - - 然后综合集合预报 P10-P90 区间覆盖了哪些 WU 取整区间,按覆盖比例分配概率。 - - 最终给出 2-4 个 WU 结算整数温度的概率(必须加起来 = 100%)。 +5. **概率参考**:我已经通过数学模型计算好了结算概率分布(见【气象特征与事实】中的"数学概率分布"),请在你的逻辑分析中参考它来判断最终结算方向。 【输出要求】 1. **禁止废话**,整体控制在 200 字以内。 @@ -51,7 +47,6 @@ def get_ai_analysis(weather_insights: str, city_name: str, temp_symbol: str) -> 🤖 Groq AI 决策 - 🎲 盘口: [必须明确指出最热时段(如:预计最热在 14:00-16:00)以及当前的博弈区间(如:锁定在 27°C 或 28°C 之间博弈)。若已明确降温,请直接给出死盘结论。] - 💡 逻辑: [用 2-3 句话深度分析:①当前机场实测的风速风向和云量对升温的促进/阻碍;②结合辐射、暖平流等动力因子判断温度还有多少上升空间;③最终是否能达到预报值。不要泛泛而谈,请使用具体数值。] -- 📊 概率: [列出最可能的 2-4 个 WU 结算整数温度及概率。注意:概率应反映实测最高温落入对应取整区间的可能性。格式:4°C(55%) | 3°C(35%) | 5°C(10%)] - 🎯 置信度: [1-10]/10 """