feat(api): warn on unrecognized stage codes (B4 gray-release monitoring)

LLM/output stage codes outside STATUS_CODE_MAP were passed through
silently with an empty nextStage - undetectable drift between the
prompt output code set and the endpoint mapping table.

- endpoints: _stage_label / _warn_unknown_stage_code helpers; both
  streaming and non-streaming paths emit a warning with sessionId,
  clientMode, raw and normalized codes when the label lookup misses
  (transparency behavior unchanged: code passes through, label empty)
- known codes and covered internal normalizations (e.g. 2020->0002)
  stay silent; the warning fires on the normalized value

Verified: 229 unit tests (4 new monitoring tests)
This commit is contained in:
Eric Wang
2026-10-22 23:19:11 +08:00
parent b8008da959
commit 11131885a6
2 changed files with 145 additions and 2 deletions
+38 -2
View File
@@ -49,6 +49,28 @@ STATUS_CODE_MAP = {
'2016': '确认双车中的车牌'
}
def _stage_label(normalized_stage_code: str) -> str:
"""阶段码的中文标签;未知码返回空串(B4 监测点)。"""
return STATUS_CODE_MAP.get(normalized_stage_code, '')
def _warn_unknown_stage_code(
*, session_id: str, client_mode: str,
raw_stage_code: str, normalized_stage_code: str,
) -> None:
"""B4:LLM/后端输出映射表外的阶段码时告警(灰度监测)。
未知码当前行为:原样透传 nextStageCode、nextStage 为空串。
告警带全定位信息,用于确认提示词输出码集是否收敛。
"""
logger.warning(
"Unrecognized stage code "
f"sessionId={session_id} clientMode={client_mode} "
f"rawStageCode={raw_stage_code} "
f"normalizedStageCode={normalized_stage_code}"
)
def normalize_stage_code(stage_code: str) -> str:
"""Normalize FastGPT stage codes to external API stage codes."""
if stage_code in ['3001', '3002', '1002']:
@@ -315,7 +337,14 @@ async def chat(
client_mode,
normalized_stage_code,
)
nextStage = STATUS_CODE_MAP.get(normalized_stage_code, '')
nextStage = _stage_label(normalized_stage_code)
if not nextStage:
_warn_unknown_stage_code(
session_id=json_data['sessionId'],
client_mode=client_mode,
raw_stage_code=state_code,
normalized_stage_code=normalized_stage_code,
)
logger.info(
"FastGPT stream stage_code parsed "
f"sessionId={json_data['sessionId']} "
@@ -470,7 +499,14 @@ async def chat(
raise ValueError("大模型回复中缺少state")
normalized_stage_code = normalize_stage_code(raw_stage_code)
nextStageCode = external_stage_code(client_mode, normalized_stage_code)
nextStage = STATUS_CODE_MAP.get(normalized_stage_code, '')
nextStage = _stage_label(normalized_stage_code)
if not nextStage:
_warn_unknown_stage_code(
session_id=json_data['sessionId'],
client_mode=client_mode,
raw_stage_code=raw_stage_code,
normalized_stage_code=normalized_stage_code,
)
form_update = result.form_update
logger.info(
"Chat non-stream completed "