Revise fallback highs after observed breaks
Fast evidence mode should not say DEB and models support the center when the latest METAR has already exceeded that center or the model upper edge. The fallback now treats the live observation as a lower bound for the daily high and explains the upward revision pressure. Constraint: Fallback output must remain useful before the full AI bulletin read returns Rejected: Keep the original DEB center until AI completes | it can be lower than an already-observed temperature Confidence: high Scope-risk: narrow Tested: pytest tests/test_web_observability.py::test_city_ai_fallback_revises_up_when_latest_metar_breaks_above_models tests/test_web_observability.py::test_city_ai_fallback_reasoning_identifies_fast_evidence_mode tests/test_web_observability.py::test_city_ai_stream_request_only_asks_provider_for_observation_read -q Tested: npm run build
This commit is contained in:
@@ -685,6 +685,27 @@ def _build_city_ai_fallback(
|
||||
predicted = current_temp
|
||||
range_low = min(values) if values else predicted
|
||||
range_high = max(values) if values else predicted
|
||||
model_range_high = range_high
|
||||
current_above_predicted = (
|
||||
current_temp is not None
|
||||
and predicted is not None
|
||||
and current_temp > predicted + 0.2
|
||||
)
|
||||
current_above_model_range = (
|
||||
current_temp is not None
|
||||
and model_range_high is not None
|
||||
and current_temp > model_range_high + 0.2
|
||||
)
|
||||
observed_high_break = bool(current_above_predicted or current_above_model_range)
|
||||
original_predicted = predicted
|
||||
if observed_high_break:
|
||||
predicted = max(
|
||||
value
|
||||
for value in (predicted, current_temp)
|
||||
if value is not None
|
||||
)
|
||||
if range_high is not None and current_temp is not None:
|
||||
range_high = max(range_high, current_temp)
|
||||
city = str(ai_input.get("city_display_name") or ai_input.get("city") or "this city")
|
||||
station = str((airport_current.get("station_code") if is_airport_metar else None) or observation_anchor.get("station_code") or current_obs.get("station_code") or "")
|
||||
raw_metar = str(airport_current.get("raw_metar") or "").strip() if is_airport_metar else ""
|
||||
@@ -718,12 +739,18 @@ def _build_city_ai_fallback(
|
||||
metar_zh = f"当前没有可用的{source_name_zh}正文,暂以 DEB、多模型路径与最新实测为主。"
|
||||
metar_en = f"No raw {source_name_en} text is available, so DEB, latest observations and the model cluster carry the read."
|
||||
predicted_text = _format_ai_temperature(predicted, unit) or "--"
|
||||
current_text = _format_ai_temperature(current_temp, unit) or "--"
|
||||
original_predicted_text = _format_ai_temperature(original_predicted, unit) or "--"
|
||||
model_range_high_text = _format_ai_temperature(model_range_high, unit) or "--"
|
||||
if partial_ai.get("final_judgment_zh") or partial_ai.get("final_judgment_en"):
|
||||
final_zh = str(partial_ai.get("final_judgment_zh") or partial_ai.get("final_judgment_en") or "").strip()
|
||||
final_en = str(partial_ai.get("final_judgment_en") or partial_ai.get("final_judgment_zh") or "").strip()
|
||||
elif partial_ai:
|
||||
final_zh = f"{city} 预计最高温暂以 {predicted_text} 附近为中枢;AI 已先完成{bulletin_zh}解读,最高温结论结合 DEB、多模型与最新实测校准。"
|
||||
final_en = f"{city} daily high is centered near {predicted_text}; AI has already read the {bulletin_en}, with the high calibrated against DEB, the model cluster and latest observations."
|
||||
elif observed_high_break:
|
||||
final_zh = f"{city} 最新实测已达 {current_text},高于原先 {original_predicted_text} 中枢;最高温中枢需先上修到至少 {predicted_text} 附近。"
|
||||
final_en = f"{city} latest observation has reached {current_text}, above the prior {original_predicted_text} center; the daily-high center should be revised up to at least near {predicted_text}."
|
||||
elif timed_out:
|
||||
final_zh = f"{city} 预计最高温暂以 {predicted_text} 附近为中枢;当前已先用 DEB、多模型和{source_name_zh}快速证据模式判断。"
|
||||
final_en = f"{city} daily high is centered near {predicted_text}; the current read uses the fast DEB/model/{source_name_en} evidence mode."
|
||||
@@ -733,15 +760,27 @@ def _build_city_ai_fallback(
|
||||
reasoning_zh = str(partial_ai.get("reasoning_zh") or "").strip() or (
|
||||
f"AI {bulletin_zh}解读已用于校准日内节奏;DEB 与多模型集合继续约束最高温中枢,后续{source_name_zh}用于确认是否需要上调或下修。"
|
||||
if partial_ai
|
||||
else f"当前为快速证据模式;最新{source_name_zh}已高于原先 {original_predicted_text} 中枢{(',并超过模型上沿 ' + model_range_high_text) if current_above_model_range else ''},本轮最高温判断应优先承认实测突破并等待完整 AI {bulletin_zh}解读合并。"
|
||||
if observed_high_break
|
||||
else f"当前为快速证据模式;DEB、多模型集合和最新{source_name_zh}共同支撑本轮最高温中枢,完整 AI {bulletin_zh}解读返回后再合并。"
|
||||
)
|
||||
reasoning_en = str(partial_ai.get("reasoning_en") or "").strip() or (
|
||||
f"The AI {bulletin_en} read is already used to calibrate the intraday pace; DEB and the model cluster still constrain the high-temperature center, while later {source_name_en} updates confirm whether to revise it."
|
||||
if partial_ai
|
||||
else f"This is the fast evidence mode; latest {source_name_en} is above the prior {original_predicted_text} center{(' and above the model upper edge ' + model_range_high_text) if current_above_model_range else ''}, so the high-temperature read should first acknowledge the observed break and merge the full AI {bulletin_en} read when available."
|
||||
if observed_high_break
|
||||
else f"This is the fast evidence mode; DEB, the model cluster and latest {source_name_en} jointly support the current daily-high center, and the full AI {bulletin_en} read will be merged when available."
|
||||
)
|
||||
risks_zh = [f"后续{source_name_zh}若明显偏离模型路径,需及时修正最高温中枢。"]
|
||||
risks_en = [f"If later {source_name_en} updates diverge from the model path, revise the daily-high center promptly."]
|
||||
risks_zh = (
|
||||
[f"最新{source_name_zh}已突破原模型路径,若后续报文继续持平或升温,需要继续上修最高温中枢。"]
|
||||
if observed_high_break
|
||||
else [f"后续{source_name_zh}若明显偏离模型路径,需及时修正最高温中枢。"]
|
||||
)
|
||||
risks_en = (
|
||||
[f"Latest {source_name_en} has already broken above the prior model path; if later reports hold steady or warm further, keep revising the daily-high center upward."]
|
||||
if observed_high_break
|
||||
else [f"If later {source_name_en} updates diverge from the model path, revise the daily-high center promptly."]
|
||||
)
|
||||
return {
|
||||
"predicted_max": partial_ai.get("predicted_max", predicted),
|
||||
"range_low": partial_ai.get("range_low", range_low),
|
||||
|
||||
Reference in New Issue
Block a user