diff --git a/bot_listener.py b/bot_listener.py
index a73e2bc8..1324200e 100644
--- a/bot_listener.py
+++ b/bot_listener.py
@@ -15,8 +15,9 @@ from src.data_collection.weather_sources import WeatherDataCollector # type: ig
from src.data_collection.city_risk_profiles import get_city_risk_profile, format_risk_warning # type: ignore
def analyze_weather_trend(weather_data, temp_symbol):
- """根据实测与预测分析气温态势,增加峰值时刻预测"""
+ '''根据实测与预测分析气温态势,增加峰值时刻预测'''
insights: List[str] = []
+ ai_features: List[str] = []
metar = weather_data.get("metar", {})
open_meteo = weather_data.get("open-meteo", {})
@@ -25,11 +26,14 @@ def analyze_weather_trend(weather_data, temp_symbol):
mgm = weather_data.get("mgm", {})
if not metar or not open_meteo:
- return ""
+ return "", ""
curr_temp = metar.get("current", {}).get("temp")
max_so_far = metar.get("current", {}).get("max_temp_so_far") # 今日实测最高
daily = open_meteo.get("daily", {})
+ hourly = open_meteo.get("hourly", {})
+ times = hourly.get("time", [])
+ temps = hourly.get("temperature_2m", [])
# === 核心:整合多源预报最高温 ===
forecast_highs = [daily.get("temperature_2m_max", [None])[0]]
@@ -37,293 +41,182 @@ def analyze_weather_trend(weather_data, temp_symbol):
forecast_highs.append(mb["today_high"])
if nws.get("today_high") is not None:
forecast_highs.append(nws["today_high"])
- # 加入多模型预报 (ECMWF, GFS, ICON, GEM, JMA)
for mv in weather_data.get("multi_model", {}).get("forecasts", {}).values():
if mv is not None:
forecast_highs.append(mv)
forecast_highs = [h for h in forecast_highs if h is not None]
- # 取预报中的最高值作为风险防御基准
forecast_high = max(forecast_highs) if forecast_highs else None
- # 取最低值用于判断是否“已触及预报高位”
min_forecast_high = min(forecast_highs) if forecast_highs else forecast_high
- # 取中位数作为用户可见的"预期值"(避免极端模型误导)
- forecast_median = None
- if forecast_highs:
- sorted_fh = sorted(forecast_highs)
- forecast_median = sorted_fh[len(sorted_fh) // 2]
+ forecast_median = sorted(forecast_highs)[len(forecast_highs) // 2] if forecast_highs else None
wind_speed = metar.get("current", {}).get("wind_speed_kt", 0)
# 获取当地时间小时
local_time_full = open_meteo.get("current", {}).get("local_time", "")
try:
- local_date_str = local_time_full.split(" ")[0] # YYYY-MM-DD
+ local_date_str = local_time_full.split(" ")[0]
local_hour = int(local_time_full.split(" ")[1].split(":")[0])
except:
+ from datetime import datetime
local_date_str = datetime.now().strftime("%Y-%m-%d")
local_hour = datetime.now().hour
- # === 模型共识评分 ===
- # 主要来源: 多模型预报 (ECMWF, GFS, ICON, GEM, JMA)
- multi_model = weather_data.get("multi_model", {})
- mm_forecasts = multi_model.get("forecasts", {})
-
- labeled_forecasts = []
- for model_name, model_val in mm_forecasts.items():
- if model_val is not None:
- labeled_forecasts.append((model_name, model_val))
-
- # 额外独立源 (如有)
- if mb.get("today_high") is not None:
- labeled_forecasts.append(("MB", mb["today_high"]))
- if nws.get("today_high") is not None:
- labeled_forecasts.append(("NWS", nws["today_high"]))
-
- # Open-Meteo 确定性预报(用于后续偏差检测,不重复加入共识)
- om_today = daily.get("temperature_2m_max", [None])[0]
-
- # 集合预报数据 (仅用于不确定性区间展示)
- ensemble = weather_data.get("ensemble", {})
- ens_median = ensemble.get("median")
+ # === METAR 趋势分析 (移到前部判断降温) ===
+ recent_temps = metar.get("recent_temps", [])
+ trend_desc = ""
+ if len(recent_temps) >= 2:
+ temps_only = [t for _, t in recent_temps]
+ latest_val = temps_only[0]
+ prev_val = temps_only[1]
+ diff = latest_val - prev_val
+ if len(temps_only) >= 3:
+ all_same = all(t == latest_val for t in temps_only[:3])
+ all_rising = all(temps_only[i] >= temps_only[i+1] for i in range(min(3, len(temps_only)) - 1))
+ all_falling = all(temps_only[i] <= temps_only[i+1] for i in range(min(3, len(temps_only)) - 1))
+ trend_display = " → ".join([f"{t}{temp_symbol}@{tm}" for tm, t in recent_temps[:3]])
+ if all_same: trend_desc = f"📉 温度已停滞({trend_display}),大概率到顶。"
+ elif all_rising and diff > 0: trend_desc = f"📈 仍在升温({trend_display})。"
+ elif all_falling and diff < 0: trend_desc = f"📉 已开始降温({trend_display})。"
+ else: trend_desc = f"📊 温度波动中({trend_display})。"
+ elif diff == 0: trend_desc = f"📉 温度持平(最近两条都是 {latest_val}{temp_symbol})。"
+ elif diff > 0: trend_desc = f"📈 仍在升温({prev_val} → {latest_val}{temp_symbol})。"
+ else: trend_desc = f"📉 已开始降温({prev_val} → {latest_val}{temp_symbol})。"
- consensus_level = "unknown"
- consensus_spread = None
+ is_cooling = "降温" in trend_desc
+
+ # === 模型共识评分 ===
+ mm_forecasts = weather_data.get("multi_model", {}).get("forecasts", {})
+ labeled_forecasts = [(model_name, model_val) for model_name, model_val in mm_forecasts.items() if model_val is not None]
+ if mb.get("today_high") is not None: labeled_forecasts.append(("MB", mb["today_high"]))
+ if nws.get("today_high") is not None: labeled_forecasts.append(("NWS", nws["today_high"]))
+
if len(labeled_forecasts) >= 2:
f_values = [v for _, v in labeled_forecasts]
- f_max = max(f_values)
- f_min = min(f_values)
- consensus_spread = f_max - f_min
- f_avg = sum(f_values) / len(f_values)
-
- # 动态阈值:华氏度场景用更大的容差
- is_f = (temp_symbol == "°F")
- tight_threshold = 1.5 if is_f else 0.8 # 高共识
- mid_threshold = 3.0 if is_f else 1.5 # 中共识
-
+ consensus_spread = max(f_values) - min(f_values)
+ tight_threshold = 1.5 if temp_symbol == "°F" else 0.8
+ mid_threshold = 3.0 if temp_symbol == "°F" else 1.5
parts = " | ".join([f"{name} {val}{temp_symbol}" for name, val in labeled_forecasts])
if consensus_spread <= tight_threshold:
- consensus_level = "high"
- insights.append(
- f"🎯 模型共识:高 ({len(labeled_forecasts)}/{len(labeled_forecasts)}) — "
- f"{parts},极差仅 {consensus_spread:.1f}°,预报高度一致。"
- )
+ msg = f"🎯 模型共识:高 ({len(labeled_forecasts)}源) — {parts},极差仅 {consensus_spread:.1f}°,高度一致。"
elif consensus_spread <= mid_threshold:
- consensus_level = "medium"
- insights.append(
- f"⚖️ 模型共识:中 ({len(labeled_forecasts)}源) — "
- f"{parts},极差 {consensus_spread:.1f}°,有轻微分歧。"
- )
+ msg = f"⚖️ 模型共识:中 ({len(labeled_forecasts)}源) — {parts},极差 {consensus_spread:.1f}°,有轻微分歧。"
else:
- consensus_level = "low"
- # 找出最高和最低的源
highest = max(labeled_forecasts, key=lambda x: x[1])
lowest = min(labeled_forecasts, key=lambda x: x[1])
- insights.append(
- f"⚠️ 模型共识:低 ({len(labeled_forecasts)}源) — "
- f"{parts},极差 {consensus_spread:.1f}°!"
- f"{highest[0]} 最高 ({highest[1]}{temp_symbol}) vs {lowest[0]} 最低 ({lowest[1]}{temp_symbol}),不确定性大。"
- )
+ msg = f"⚠️ 模型共识:低 ({len(labeled_forecasts)}源) — {parts},极差 {consensus_spread:.1f}°!{highest[0]} 最高 vs {lowest[0]} 最低。"
+
+ # 移交 AI 处理,不再给用户直接显示博弈区间
+ ai_features.append(msg)
elif len(labeled_forecasts) == 1:
- name, val = labeled_forecasts[0]
- insights.append(
- f"📡 仅1个预报源 ({name} {val}{temp_symbol}) — 无法交叉验证,共识评分不可用。"
- )
+ msg = f"📡 仅1个预报源 ({labeled_forecasts[0][0]} {labeled_forecasts[0][1]}{temp_symbol})"
+ # 移交 AI 处理,不再给用户直接显示博弈区间
+ ai_features.append(msg)
- # === 博弈区间提醒 (基于 WU 四舍五入结算) ===
+ # === 博弈区间提醒 ===
if len(labeled_forecasts) >= 2:
import math
wu_round = lambda v: math.floor(v + 0.5)
settlement_vals = sorted(set(wu_round(v) for _, v in labeled_forecasts))
- unit_short = temp_symbol
- # 如果实测已超所有预报,用实测值重新评估博弈区间
+
if max_so_far is not None and forecast_high is not None and max_so_far > forecast_high + 0.5:
actual_settled = wu_round(max_so_far)
- if actual_settled not in settlement_vals:
- all_vals = sorted(set(settlement_vals + [actual_settled]))
- else:
- all_vals = settlement_vals
- insights.append(
- f"🎲 博弈区间:模型预报已失效!实测最高 {max_so_far}{unit_short} → WU {actual_settled}{unit_short},"
- f"但温度仍可能继续变化。"
- )
+ msg = f"🎲 博弈区间:预报已失效!实测最高 {max_so_far}{temp_symbol} → WU {actual_settled}{temp_symbol},温度仍可能波动。"
elif len(settlement_vals) == 1:
- insights.append(f"🎲 博弈区间:{len(labeled_forecasts)}个模型全部指向 {settlement_vals[0]}{unit_short} 结算。")
+ msg = f"🎲 博弈区间:模型全部指向 {settlement_vals[0]}{temp_symbol} 结算。"
elif len(settlement_vals) == 2:
- insights.append(f"🎲 博弈区间:温度在 {settlement_vals[0]}{unit_short} 和 {settlement_vals[1]}{unit_short} 之间博弈。")
+ msg = f"🎲 博弈区间:在 {settlement_vals[0]}{temp_symbol} 和 {settlement_vals[1]}{temp_symbol} 之间博弈。"
elif len(settlement_vals) == 3:
- insights.append(f"🎲 博弈区间:温度在 {settlement_vals[0]}{unit_short}、{settlement_vals[1]}{unit_short}、{settlement_vals[2]}{unit_short} 之间博弈。")
+ msg = f"🎲 博弈区间:在 {settlement_vals[0]}{temp_symbol}、{settlement_vals[1]}{temp_symbol}、{settlement_vals[2]}{temp_symbol} 之间博弈。"
else:
- insights.append(f"🎲 博弈区间:模型分歧太大,结算还不确定。")
- # 集合预报区间 (独立于共识评分显示)
+ msg = f"🎲 博弈区间:模型分歧太大,结算还不确定。"
+ # 移交 AI 处理,不再给用户直接显示博弈区间
+ ai_features.append(msg)
+
+ # === 集合预报区间 (去除了啰嗦的预报验证) ===
+ ensemble = weather_data.get("ensemble", {})
ens_p10 = ensemble.get("p10")
ens_p90 = ensemble.get("p90")
+ ens_median = ensemble.get("median")
+ om_today = daily.get("temperature_2m_max", [None])[0]
if ens_p10 is not None and ens_p90 is not None and ens_median is not None:
- ens_range = ens_p90 - ens_p10
- insights.append(
- f"📊 集合预报:中位数 {ens_median}{temp_symbol},"
- f"90% 区间 [{ens_p10}{temp_symbol} - {ens_p90}{temp_symbol}],"
- f"波动幅度 {ens_range:.1f}°。"
- )
- # 确定性预报 vs 集合分布偏差检测
+ msg1 = f"📊 集合预报:中位数 {ens_median}{temp_symbol},90% 区间 [{ens_p10}{temp_symbol} - {ens_p90}{temp_symbol}]。"
+ if not is_cooling: insights.append(msg1)
+ ai_features.append(msg1)
+
if om_today is not None:
- actual_reached = max_so_far is not None and max_so_far >= om_today - 0.5
- if om_today > ens_p90:
- if actual_reached:
- # 实测已达到预报值 → 确定性预报是对的,集合偏保守
- insights.append(
- f"✅ 预报验证:确定性预报 {om_today}{temp_symbol} 已被实测验证 "
- f"(实测最高 {max_so_far}{temp_symbol}),集合预报偏保守。"
- )
- else:
- # 还没到最高温,存在偏高风险
- delta = om_today - ens_median
- insights.append(
- f"⚡ 预报偏高警告:确定性预报 {om_today}{temp_symbol} "
- f"超过了集合 90% 上限 ({ens_p90}{temp_symbol}),"
- f"比中位数高 {delta:.1f}°。实际高温更可能接近 {ens_median}{temp_symbol}。"
- )
- elif om_today < ens_p10:
- if max_so_far is not None and max_so_far >= ens_median:
- # 实测已超过中位数 → 确定性预报偏低,集合更准
- insights.append(
- f"✅ 预报验证:实测最高 {max_so_far}{temp_symbol} "
- f"已超过确定性预报 {om_today}{temp_symbol},集合中位数 {ens_median}{temp_symbol} 更准确。"
- )
- else:
- delta = ens_median - om_today
- insights.append(
- f"⚡ 预报偏低警告:确定性预报 {om_today}{temp_symbol} "
- f"低于集合 90% 下限 ({ens_p10}{temp_symbol}),"
- f"比中位数低 {delta:.1f}°。实际高温更可能接近 {ens_median}{temp_symbol}。"
- )
-
- # === 核心判断:实测是否已超预报 ===
- is_breakthrough = False
-
- # METAR 趋势分析(最近 3-4 条报文)
- recent_temps = metar.get("recent_temps", []) # [("15:00", 5), ("14:20", 5), ("14:00", 3)] 倒序
- trend_desc = ""
- if len(recent_temps) >= 2:
- temps_only = [t for _, t in recent_temps] # 倒序:最新在前
- latest_val = temps_only[0]
- prev_val = temps_only[1]
- diff = latest_val - prev_val
-
- if len(temps_only) >= 3:
- # 3 条以上:判断整体趋势
- all_same = all(t == latest_val for t in temps_only[:3])
- all_rising = all(temps_only[i] >= temps_only[i+1] for i in range(min(3, len(temps_only)) - 1))
- all_falling = all(temps_only[i] <= temps_only[i+1] for i in range(min(3, len(temps_only)) - 1))
-
- trend_display = " → ".join([f"{t}{temp_symbol}@{tm}" for tm, t in recent_temps[:3]])
-
- if all_same:
- trend_desc = f"📉 温度已停滞({trend_display}),大概率到顶。"
- elif all_rising and diff > 0:
- trend_desc = f"📈 仍在升温({trend_display})。"
- elif all_falling and diff < 0:
- trend_desc = f"📉 已开始降温({trend_display})。"
- else:
- trend_desc = f"📊 温度波动中({trend_display})。"
- elif diff == 0:
- trend_desc = f"📉 温度持平(最近两条都是 {latest_val}{temp_symbol})。"
- elif diff > 0:
- trend_desc = f"📈 仍在升温({prev_val} → {latest_val}{temp_symbol})。"
- else:
- trend_desc = f"📉 已开始降温({prev_val} → {latest_val}{temp_symbol})。"
+ if om_today > ens_p90 and (max_so_far is None or max_so_far < om_today - 0.5):
+ msg2 = f"⚡ 预报偏高警告:确定性预报 {om_today}{temp_symbol} 超集合90%上限!更可能接近 {ens_median}{temp_symbol}。"
+ if not is_cooling: insights.append(msg2)
+ ai_features.append(msg2)
+ elif om_today < ens_p10 and (max_so_far is None or max_so_far < ens_median):
+ msg2 = f"⚡ 预报偏低警告:确定性预报 {om_today}{temp_symbol} 低于集合90%下限!更可能接近 {ens_median}{temp_symbol}。"
+ if not is_cooling: insights.append(msg2)
+ ai_features.append(msg2)
+ # === 实测已超预报 & 趋势输出 ===
if max_so_far is not None and forecast_high is not None:
if max_so_far > forecast_high + 0.5:
- is_breakthrough = True
exceed_by = max_so_far - forecast_high
- # 合并为一条:事实 + 趋势(不给主观建议)
- bt_msg = (
- f"🚨 实测已超预报:{max_so_far}{temp_symbol} 超过预报上限 "
- f"{forecast_high}{temp_symbol}(+{exceed_by:.1f}°)。"
- )
- if trend_desc:
- bt_msg += f"\n{trend_desc}"
+ bt_msg = f"🚨 实测已超预报:{max_so_far}{temp_symbol} 超过上限 {forecast_high}{temp_symbol}(+{exceed_by:.1f}°)。"
+ if trend_desc: bt_msg += f"\n{trend_desc}"
insights.append(bt_msg)
+ ai_features.append(f"🚨 异常: 实测已冲破所有预报上限 ({max_so_far}{temp_symbol} vs {forecast_high}{temp_symbol})。")
+ ai_features.append(trend_desc)
+ else:
+ if trend_desc:
+ insights.append(trend_desc)
+ ai_features.append(trend_desc)
+ elif trend_desc:
+ insights.append(trend_desc)
+ ai_features.append(trend_desc)
- # === 结算取整分析 (Wunderground 四舍五入到整数) ===
+ # === 结算取整分析 ===
if max_so_far is not None:
settled = round(max_so_far)
fractional = max_so_far - int(max_so_far)
- # 离取整边界的距离
dist_to_boundary = abs(fractional - 0.5)
-
if dist_to_boundary <= 0.3:
- # 在边界附近 (X.2 ~ X.8),取整结果可能随时翻转
if fractional < 0.5:
- insights.append(
- f"⚖️ 结算边界:当前最高 {max_so_far}{temp_symbol} → "
- f"WU 结算 {settled}{temp_symbol},"
- f"但只差 {0.5 - fractional:.1f}° 就会进位到 {settled + 1}{temp_symbol}!"
- )
+ msg = f"⚖️ 结算边界:当前最高 {max_so_far}{temp_symbol} → WU 结算 {settled}{temp_symbol},但只差 {0.5 - fractional:.1f}° 就会进位到 {settled + 1}{temp_symbol}!"
else:
- insights.append(
- f"⚖️ 结算边界:当前最高 {max_so_far}{temp_symbol} → "
- f"WU 结算 {settled}{temp_symbol},"
- f"刚刚越过进位线,再降 {fractional - 0.5:.1f}° 就会回落到 {settled - 1}{temp_symbol}。"
- )
+ msg = f"⚖️ 结算边界:当前最高 {max_so_far}{temp_symbol} → WU 结算 {settled}{temp_symbol},刚刚越过进位线,再降 {fractional - 0.5:.1f}° 就会回落到 {settled - 1}{temp_symbol}。"
+ insights.append(msg)
+ ai_features.append(msg)
- # --- 峰值时刻预测逻辑 (仍以 Open-Meteo 逐小时数据为准) ---
- hourly = open_meteo.get("hourly", {})
- times = hourly.get("time", [])
- temps = hourly.get("temperature_2m", [])
-
+ # === 峰值时刻预测 (只在还没过峰值时显示) ===
peak_hours = []
- om_high = daily.get("temperature_2m_max", [None])[0]
- if times and temps and om_high is not None:
+ if times and temps and om_today is not None:
for t_str, temp in zip(times, temps):
- if t_str.startswith(local_date_str):
- if abs(temp - om_high) <= 0.2:
- hour = t_str.split("T")[1][:5]
- peak_hours.append(hour)
-
- # 确定用于逻辑判断的峰值小时
+ if t_str.startswith(local_date_str) and abs(temp - om_today) <= 0.2:
+ peak_hours.append(t_str.split("T")[1][:5])
+
if peak_hours:
first_peak_h = int(peak_hours[0].split(":")[0])
last_peak_h = int(peak_hours[-1].split(":")[0])
-
window = f"{peak_hours[0]} - {peak_hours[-1]}" if len(peak_hours) > 1 else peak_hours[0]
- insights.append(f"⏱️ 预计最热时段:今天 {window}。")
- if last_peak_h < 6:
- insights.append(f"⚠️ 提示:预测最热在凌晨,后续气温可能一路走低。")
- elif local_hour < first_peak_h and (max_so_far is None or max_so_far < forecast_high):
- target_temp = om_today if om_today is not None else forecast_high
- insights.append(f"🎯 关注重点:看看那个时段温度能不能真的到 {target_temp}{temp_symbol}。")
+ if local_hour <= last_peak_h:
+ if last_peak_h < 6:
+ ai_features.append(f"⚠️ 提示:预测最热在凌晨,后续气温可能一路走低。")
+ elif local_hour < first_peak_h and (max_so_far is None or max_so_far < forecast_high):
+ target_temp = om_today if om_today is not None else forecast_high
+ ai_features.append(f"🎯 关注重点:看看那个时段能否涨到 {target_temp}{temp_symbol}。")
+
+ # 写给AI
+ if local_hour > last_peak_h: ai_features.append(f"⏱️ 状态: 预报峰值时段已过 ({window})。")
+ elif first_peak_h <= local_hour <= last_peak_h: ai_features.append(f"⏱️ 状态: 正处于预报最热窗口 ({window})内。")
+ else: ai_features.append(f"⏱️ 状态: 距最热时段还有 {first_peak_h - local_hour}h ({window})。")
else:
- # 兜底默认值
first_peak_h, last_peak_h = 13, 15
- # --- 简化的 AI 特征提取 (不对用户双重显示,仅供 AI 使用) ---
- ai_features = list(insights)
- # 不再生成死板的分析文案,仅保留核心事实描述
-
- # 1. 气温节奏特征
- if local_hour > last_peak_h:
- ai_features.append(f"⏱️ 状态: 预报峰值时段已过 ({window})。")
- elif first_peak_h <= local_hour <= last_peak_h:
- ai_features.append(f"⏱️ 状态: 正处于预报最热窗口 ({window})内。")
- else:
- ai_features.append(f"⏱️ 状态: 距最热时段还有 {first_peak_h - local_hour}h ({window})。")
-
- # 2. 气温偏差特征
- if max_so_far is not None and forecast_high is not None:
- gap = max_so_far - forecast_high
- if gap > 0.5:
- ai_features.append(f"🚨 异常: 实测已冲破所有预报上限 ({max_so_far}{temp_symbol} vs {forecast_high}{temp_symbol})。")
- elif abs(gap) <= 1.0:
- ai_features.append(f"⚖️ 状态: 实测已极度接近预报峰值。")
-
- # 3. 气象动力特征描述 (无主观推测)
+ # === 其他 AI 专供的事实特征 ===
+ if wind_speed:
+ wind_dir = metar.get("current", {}).get("wind_dir", "未知")
+ ai_features.append(f"🌬️ 当下风况: 约 {wind_speed}kt (方向 {wind_dir}°)。")
humidity = metar.get("current", {}).get("humidity")
- if humidity and humidity > 80:
- ai_features.append(f"💦 湿度极高 ({humidity}%)。")
+ if humidity and humidity > 80: ai_features.append(f"💦 湿度极高 ({humidity}%)。")
clouds = metar.get("current", {}).get("clouds", [])
if clouds:
@@ -332,10 +225,8 @@ def analyze_weather_trend(weather_data, temp_symbol):
ai_features.append(f"☁️ 天空状况: {c_desc}。")
wx_desc = metar.get("current", {}).get("wx_desc")
- if wx_desc:
- ai_features.append(f"🌧️ 天气现象: {wx_desc}。")
+ if wx_desc: ai_features.append(f"🌧️ 天气现象: {wx_desc}。")
- # 4. 暖平流事实提取
max_temp_time_str = metar.get("current", {}).get("max_temp_time", "")
if max_so_far is not None and max_temp_time_str:
try:
@@ -350,13 +241,6 @@ def analyze_weather_trend(weather_data, temp_symbol):
ai_features.append(f"🌙 动力事实: 最高温出现在低辐射时段 ({max_temp_time_str}, 辐射{max_temp_rad:.0f}W/m²)。")
except: pass
- # 5. 结算判定
- if max_so_far is not None:
- settled = round(max_so_far)
- fractional = max_so_far - int(max_so_far)
- if abs(fractional - 0.5) <= 0.2:
- ai_features.append(f"⚖️ 结算事实: 当前最高 {max_so_far}{temp_symbol} 处于进位关键点 ({settled}{temp_symbol})。")
-
display_str = "\n".join(insights) if insights else ""
return display_str, "\n".join(ai_features)
diff --git a/src/analysis/ai_analyzer.py b/src/analysis/ai_analyzer.py
index 0bb4f852..93c8da11 100644
--- a/src/analysis/ai_analyzer.py
+++ b/src/analysis/ai_analyzer.py
@@ -30,15 +30,16 @@ def get_ai_analysis(weather_insights: str, city_name: str, temp_symbol: str) ->
【分析重点】
1. **动力来源**:对比太阳辐射(W/m²)与最高温出现时间。如果低辐射时段气温冲高,说明是强暖平流,预报往往低估这种惯性。
2. **阻碍因子**:由于高湿度(>80%)、降水或全阴天气导致的升温失速。
-3. **模型 spread**:多模型极差如果很大,说明结算极具博弈价值。
+3. **结算推演**:根据我提供给你的【博弈区间】以及【当前所处时段(是否过了最热期)】推断并告诉我最终结算温度落在哪个区间的希望更大。
4. **结算边界**:如果当前温度处于 X.5 这种进位/舍位边缘,需特别预警。
【输出要求】
-1. **禁止废话**,整体控制在 80 字以内。
+1. **禁止废话**,整体控制在 100 字以内。
2. 严格按照以下 HTML 格式输出:
🤖 Groq AI 决策
-- 💡 逻辑: [简述动力来源/阻碍因子。例如:暖平流强势推高,且辐射极低时段创新高,极大概率超预报。]
+- 🎲 盘口: [一句话指出结算在哪里博弈,以及目前是否到了最热时段。例如:距最热时段还有3小时,目前预计在27或28之间博弈,有突破可能。]
+- 💡 逻辑: [不要重复模版例子!请使用一句话提炼机场实测(如风速风向、云量、气温变化趋势)及热力动力因子。例如:实测吹强劲西南风(15kt)伴随云量减少,辐射加热强劲,破预报阻力非常小。]
- 🎯 信心: [1-10]/10
"""