DEB 降级为模型集群中的普通一员,AI 不再照搬 DEB 做预测

此前 DEB 以独立字段 deb.prediction 传给 AI,提示词又要求"必须综合 DEB",
导致 AI 直接输出 DEB 值而非独立判断。改动:
- 移除 AI 输入中的独立 deb 字段,DEB 只作为 model_cluster.sources 中的
  一条记录 (model: "DEB (fusion)"),与其他模型平等
- 提示词改为:以模型集群集中区间为基线,用报文观测信号独立判断上修/下修/维持
- 流式/非流式提示词均强调"不要直接照搬 DEB 的值,差异是正常的"
- 回退路径改用模型集群中位数作为默认预测,DEB 仅作为备选参考
This commit is contained in:
2569718930@qq.com
2026-05-06 16:03:22 +08:00
parent f9d0ea31bc
commit eb42d644a3
4 changed files with 83 additions and 47 deletions
+39 -12
View File
@@ -39,26 +39,37 @@ def _city_ai_model_cluster_note(ai_input: Dict[str, Any], *, locale: str) -> str
if isinstance(item, dict) and _safe_float(item.get("value")) is not None
]
count = len(values)
deb_value = _safe_float((ai_input.get("deb") or {}).get("prediction") if isinstance(ai_input.get("deb"), dict) else None)
deb_value = next(
(_safe_float(item.get("value")) for item in sources if isinstance(item, dict) and "DEB" in str(item.get("model") or "")),
None,
)
non_deb_values = [
_safe_float(item.get("value"))
for item in sources
if isinstance(item, dict) and _safe_float(item.get("value")) is not None and "DEB" not in str(item.get("model") or "")
]
cluster_median = (
sorted(non_deb_values)[len(non_deb_values) // 2]
if non_deb_values
else (values[0] if values else None)
)
if locale == "en-US":
if count <= 0:
return f"No usable model cluster was returned; rely on DEB and {observation_label} only."
return f"No usable model cluster was returned; rely on {observation_label} only."
if count <= 2:
return f"Only {count} model source(s) are available, so model support is thin and should be treated as context."
range_text = f"{min(values):.1f}{unit} to {max(values):.1f}{unit}"
if deb_value is None:
return f"{count} model sources cluster between {range_text}; DEB support cannot be cross-checked."
supporting = sum(1 for value in values if abs(value - deb_value) <= 2.0)
return f"{supporting}/{count} model sources sit within 2{unit} of DEB; model range is {range_text}."
return f"{count} model sources cluster between {range_text}."
return f"{count} model sources cluster between {range_text}; DEB sits at {deb_value:.1f}{unit}."
if count <= 0:
return f"没有可用的多模型集合,只能把 DEB 与{observation_label}作为主要依据。"
return f"没有可用的多模型集合,只能把{observation_label}作为主要依据。"
if count <= 2:
return f"当前只有 {count} 个模型来源,模型支撑偏薄,只能作为辅助上下文。"
range_text = f"{min(values):.1f}{unit} ~ {max(values):.1f}{unit}"
if deb_value is None:
return f"{count} 个模型集中在 {range_text},但无法与 DEB 做一致性校验"
supporting = sum(1 for value in values if abs(value - deb_value) <= 2.0)
return f"{supporting}/{count} 个模型落在 DEB ±2{unit} 内;模型区间为 {range_text}"
return f"{count} 个模型集中在 {range_text}"
return f"{count} 个模型集中在 {range_text}DEB 位于 {deb_value:.1f}{unit}"
def _build_city_ai_fallback(
@@ -71,12 +82,26 @@ def _build_city_ai_fallback(
) -> Dict[str, Any]:
unit = str(ai_input.get("temp_symbol") or "")
cluster = ai_input.get("model_cluster") if isinstance(ai_input.get("model_cluster"), dict) else {}
all_sources = cluster.get("sources") if isinstance(cluster.get("sources"), list) else []
values = [
_safe_float(item.get("value"))
for item in (cluster.get("sources") if isinstance(cluster.get("sources"), list) else [])
for item in all_sources
if isinstance(item, dict) and _safe_float(item.get("value")) is not None
]
deb_value = _safe_float((ai_input.get("deb") or {}).get("prediction") if isinstance(ai_input.get("deb"), dict) else None)
deb_value = next(
(_safe_float(item.get("value")) for item in all_sources if isinstance(item, dict) and "DEB" in str(item.get("model") or "")),
None,
)
non_deb_values = [
_safe_float(item.get("value"))
for item in all_sources
if isinstance(item, dict) and _safe_float(item.get("value")) is not None and "DEB" not in str(item.get("model") or "")
]
cluster_median = (
sorted(non_deb_values)[len(non_deb_values) // 2]
if non_deb_values
else (sorted(values)[len(values) // 2] if values else None)
)
observation_anchor = ai_input.get("observation_anchor") if isinstance(ai_input.get("observation_anchor"), dict) else {}
is_airport_metar = observation_anchor.get("is_airport_metar") is not False
airport_current = ai_input.get("airport_current") if isinstance(ai_input.get("airport_current"), dict) else {}
@@ -100,7 +125,9 @@ def _build_city_ai_fallback(
default=None,
)
observed_high_for_revision = None if observation_stale else observed_high_so_far
predicted = deb_value
predicted = cluster_median
if predicted is None and deb_value is not None:
predicted = deb_value
if predicted is None and values:
predicted = sum(values) / len(values)
if predicted is None: