跳到主要内容

你的 try/catch 漏掉的 LLM 请求生命周期

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的 LLM 技术栈可能产生的最危险故障返回的是 HTTP 200。JSON 解析正常。你的 Schema 验证通过。没有抛出异常。而响应结果却是完全错误的 —— 事实错误、结构错误、话说到一半被截断,或者是凭空捏造。

围绕 LLM API 调用编写的一个简单 try/catch 只能处理那些明显的故障:速率限制、服务器错误、网络超时。这些是可见的故障。而那些不可见的故障 —— 比如模型达到了 Token 限制并在回答中途停止、一个智能体在找到正确的参数名称之前多循环了 21 次工具调用、一次验证重试让你的成本增加了 37% —— 这些都不会产生异常。它们会产生结果。

解决方法不是更好的错误处理,而是将 LLM 请求生命周期建模为一个显式的状态机。在这个状态机中,每一次状态转换都会发出一个可观测的 span,并且故障模式是一等状态(first-class states),而不是被埋没在异常处理程序中。

LLM 请求生命周期的真实样貌

大多数生产环境中的 LLM 请求并不是单一的 API 调用。它们是一个包含至少七个不同阶段的流水线,每个阶段都有自己的故障模式:

路由 (Routing) —— 在 Token 到达模型之前,路由层会根据任务复杂度、延迟要求、成本层级和供应商健康状况选择要使用的模型和供应商。路由决策是一个需要追踪的独立状态:触发了哪个规则、选择了哪个模型以及原因。

请求准备 (Request preparation) —— 上下文窗口预算、提示词模板选择、工具 Schema 注入、对话历史裁剪。这里的故障是无声的:超过上下文窗口会产生 400 错误(不可重试),或者更糟的是,如果 Token 计数估算有误,请求会被截断而没有任何提示。

主要生成 (Primary generation) —— 实际的 LLM 调用。这个阶段包含其自身的子状态:连接建立、队列等待时间(决定了首个 Token 时间/TTFT)以及解码阶段(每个输出 Token 的时间)。这些是需要不同优化的不同问题,但如果你只测量总请求时长,它们就是不可见的。

响应解析与 Schema 验证 (Response parsing and schema validation) —— 原始的 LLM 输出并非可信输出。对于结构化流水线,这意味着 JSON 解析、Schema 验证和语义验证。这个阶段本身就是一个微型状态机:已生成 → 已验证 → (有效 | 无效 → 修复提示词 → 已生成)

重试循环 (Retry loop) —— 针对速率限制、服务器错误或验证失败:带有抖动的指数退避、供应商故障转移或提示词变体重试。如果没有显式的状态追踪,每一次重试尝试都是不可见的 —— 你只能看到最终的成功或失败。

降级路由 (Fallback routing) —— 当主要生成失败时:次要供应商 → 更小的模型 → 缓存响应 → 基于规则的降级响应。降级链中的每一跳都是一个独立的状态,具有自己的延迟和成本概况。

升级 (Escalation) —— 在重试和降级耗尽后:人工队列、任务推迟或带有用户通知的安全降级响应。在大多数代码库中,升级只是一个 catch 子句,而不是一个命名的状态。

当你将这个流水线视为一个单一且不透明的函数调用时,你可以测量它的结果(成功或失败),但你无法测量内部发生了什么。

当前错误处理机制遗漏的状态

try/catch 处理的故障是简单的:429(速率限制)、500(服务器错误)、502/503/504(网关错误)、网络超时。这些会抛出异常,出现在错误日志中,并触发报警。

而那些导致实际生产问题的故障不会抛出异常:

finish_reason: "length" —— 模型在回答中途达到了 Token 限制并停止。HTTP 响应是 200。JSON 解析正常。如果不显式检查 finish_reason,你就会将截断的响应作为完整响应提供给用户。这并非理论推测:至少在一个知名的网关库中存在一个已知 Bug,当这种情况发生时,它会静默丢弃工具调用响应。

智能体中无声的重试膨胀 (Silent retry inflation in agents) —— 一个关于 AI 旅游智能体的记录案例研究显示,系统为了完成一个大约需要 28 次调用的任务,进行了 49 次 LLM 调用。每次调用都返回了 200。根本原因是参数名称不匹配 —— 智能体依次尝试了 camelCase、小写,然后是下划线变体,每一次都在语义层失败。智能体最终生成了正确的行程。没有报错。在每天 1,000 次运行的情况下,每个任务额外增加的 21 次调用所产生的复利成本,每年大约会导致 9,271 美元的可避免支出。

验证语义漂移 (Validation semantic drift) —— 响应通过了 JSON Schema 验证,但数值是错误的。一个 confidence_score 字段包含 0.99 —— 这不是计算出来的,而是幻觉产生的。字段存在,类型正确,但数值错误。这需要将语义验证作为一个独立的生命周期状态。JSON Schema 验证是必要的,但并不充分。

幻觉产生的成功 (Hallucinated success) —— 加拿大航空(Air Canada)的聊天机器人发明了一项并不存在的丧亲票价退款政策。API 返回了 200。响应在语法上是正确的,并且结构与真实政策一致。法庭后来判定加拿大航空对其聊天机器人的输出负责。OpenAI 的 Whisper 转录工具在医疗环境中使用时,被发现在约 1% 的样本中捏造短语 —— 其中近 40% 具有临床危害。这些不是基础设施故障,而是披着成功外衣的语义故障。

供应商性能退化但未彻底失效 (Provider degradation without failure) —— Anthropic 的 Claude API 错误率从 2025 年 6 月的 3.2% 攀升至 2025 年 9 月的 11.7%。测量总运行时间的系统将其视为可靠性事件。仅测量实际失败请求的系统看到的则更少。拥有多供应商路由的系统在同一时期的有效可用性为 99.7% —— 因为它们通过熔断器状态知道何时在每个请求失败之前停止向性能退化的端点发送流量。

将生命周期建模为状态机

一个明确的 LLM 请求状态机如下所示:

IDLE → ROUTING → PREPARING → CALLING_PRIMARY
↓ 成功 ↓ 429/5xx
VALIDATING BACKING_OFF → CALLING_PRIMARY (最大 N 次)
↓ 有效 ↓ 无效 ↓ 耗尽
COMPLETE REPAIR_RETRY → CALLING_PRIMARY CALLING_FALLBACK
↓ 成功
VALIDATING → COMPLETE
↓ 耗尽
CALLING_CACHE
↓ 命中 ↓ 未命中
DEGRADED_RESPONSE ESCALATING → HUMAN_QUEUE
加载中…
References:Let's stay in touch and Follow me for more thoughts and updates