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 """