跳到正文

生产治理与降级 ​

一句话:生产治理不是给 Agent 多挂几个告警,而是把“一次任务最多花多少、失败时退到哪、钱花在谁身上”变成可计算、可执行、可回滚的约束;换来的是成本和故障可控,代价是每个场景都要用自己的任务分布校准,不能抄一套默认值。

为什么需要 ​

演示阶段只有一条链路:一个模型、一把密钥、几个用例。接进生产后,同一条链路会同时遇到三件事:一次“调研并写报告”不是一次调用,而是十几次到几十次;工具结果含糊、格式不合法、超时无反馈都会触发重试,而重试带着更长的上下文;模型无状态,每一轮重发历史,累计发送量接近平方增长。

这三件事叠在一起,账单和故障都不是线性增长。治理要回答的是:钱花在哪、什么时候必须停、某个组件挂了以后还能提供什么。它是贯穿接入、编排、运行态、模型网关的横切约束,不是“第八层”;平台分层见 01-项目总览与定位,运行态状态机见 04-运行态Pod池与任务编排。

核心机制 ​

一、Token 经济学的三大放大器 ​

路径爆炸:把任务拆成“读文件 → 分析 → 写稿 → 校对 → 格式整理 → 最终输出”六段,每段平均 2–5 次调用(规划、选工具、总结、返工),一次任务就是 12–30 次调用;按本书口径记为 10–30 次。假设每天 2,000 个任务、每任务 20 次调用,就是 4 万次/天;测试时 20 次/天没感觉,上线后是 2,000 倍。第一个放大器是调用次数,不是单价。

重试放大:设任务基础消耗 25K token、30% 的任务至少重试一次。若重试次数不设上限,期望倍数是 1/(1-0.3)≈1.43;最多重试两次是 1+0.3+0.3²=1.39。重试还要重发更长上下文,设每次为原来的 1.5 倍,成本倍数约为 1+0.3×1.5+0.09×2.25≈1.65。算例:2,000 任务/天 × 30% × 25K = 1,500 万 token/天,30 天 4.5 亿;按输入价 $15/百万 token 粗算,仅重试增量约 $6,750/月。若把 2,000×30×25K 全量都按 $15/百万计,才得到 $22,500/月——那是“全部流量都按该价计”的口径,不是重试增量,差异来自假设。

上下文膨胀:设每条用户消息和每条回答各约 1K token,第 i 轮输入约为 (2i-1)K,单轮线性增长;但 N 轮累计发送量是 Σ(2i-1)K = N²K,所以累计成本是 O(n²),不是单轮平方。10 轮累计约 100K token,最后一轮 19K;20 轮累计约 400K,最后一轮 39K。这里算的是发送量;前缀缓存命中会按缓存价打折,但发送与延迟仍在。三者是相乘关系,预算要按“单任务总成本”设,不能只盯单次价格。

二、五重预算(示例配置,不是默认值) ​

维度防什么客服分析超限动作
时间用户等待、长尾拖死连接30s180s先切短路径/降级,仍超时则终止
步数无进展空转、反复规划825强制压缩上下文并收尾
模型调用成本与 API 配额825剩余步骤改小模型或跳过非关键推理
工具调用外部资源、写操作风险1050只允许只读/幂等工具
Token输入输出总费用3,00015,000压缩历史、限制输出、降级

步数是循环轮次;模型调用通常与步数同阶(每次 THINK 一次,规划/重试另计),工具调用可多于步数(一步并行多个工具),所以不要用一个上限同时管两种资源。校准方法:每场景取 200–500 条真实任务,统计各维度的 P50/P95,预算取 max(P95×1.1, 业务 SLA),目标是把正常任务的误杀率压到 1% 以下;上线后按月复核,业务变化就重算。预警阈值 80/85/90/95 不是四个告警等级,而是四个动作触发器:时间到 80% 切短路径、关可选检索;步数到 85% 强制压缩并停止探索;模型调用到 90% 把剩余推理降级到小模型;工具调用到 95% 只放行只读操作;Token 到 80% 压缩上下文并限制输出。时间与 Token 已经花出去、不可回收,所以最早预警;工具调用单次便宜且可替换,允许更接近上限。到 100% 才硬终止,且先降级,降级仍不行才终止——降级是软失败,终止是硬失败。

三、L0–L6 降级阶梯 ​

级别保留能力典型触发(示意起点)
L0大模型 + RAG + 工具全部健康
L1检索 + 工具 + 模板回答LLM 延迟 > 5s 或成功率 < 95%
L2大模型 + 工具RAG 延迟 > 3s 或准确率 < 80%
L3小模型 + RAG工具成功率 < 90% 或 CPU > 85%
L4知识库查询模型全不可用或内存 > 90%
L5人工错误率 > 5%
L6稍后重试依赖维护或大面积网络故障

关键是 L1–L3 按“哪个组件先挂”跳级,不是按严重程度逐级下滑:LLM 挂进 L1,RAG 挂进 L2,工具挂或资源紧进 L3;L4–L6 才是资源、错误率、兜底链。恢复要逐级回升:每 30 秒探测,连续两次成功才升一级,恢复条件比触发条件更严,避免在阈值附近抖动。旧资料里的“5 级优雅降级”(主模型 → 备用模型 → 缓存/知识库 → 静态话术 → 排队/人工)是同一套链路的粗粒度说法,和 L0–L6 不是两套机制;本书统一用 L0–L6,不再并列“5 级”与“7 级”两套口径。

四、五层流量漏斗 ​

层作用命中率(场景假设)延迟(场景假设)
FAQ高频标准问题直接答入口流量的 90%~5ms
语义缓存相似问题复用答案入口流量的 4%~20ms
小模型简单分类/抽取入口流量的 0.6%~150ms
RAG检索后拼装回答入口流量的 0.4%~800ms
大模型复杂推理与生成入口流量的 5%~2s

口径要算清楚:100 万 CCU → 10% 活跃 → 10 万 QPS → 5,000 RPS 到大模型。CCU 是同时在线用户,不是 QPS;10 万活跃用户按每人每秒 1 次请求,才是 10 万 QPS。写成“100 万并发”会把单位从用户偷换成请求:100 万 QPS 相对 10 万 QPS 差 10 倍,相对 5,000 RPS 差 200 倍。上表命中率是“占入口流量”的份额,不是每层输入的命中率;若说“缓存命中率 85%”,分母通常是“到达该层的请求”,两者不能相加。另一组案例常见的说法是 FAQ 80%、缓存命中 85%、小模型过滤 60%,但三个分母分别是入口、到达缓存、到达小模型,不能直接推出“最后 5% 到大模型”;引用时要连分母一起写。延迟与成本同样要标场景。

五、容错六件套 ​

  • Supervisor Tree:父监控子,one-for-one 重启,失败上报;防止一个子任务拖垮整条链路,代价是多一层监督与状态同步。
  • 三态熔断:正常 → 熔断(快速失败)→ 半开探测一条;防止下游持续失败引发重试风暴,代价是窗口和阈值要调。
  • 幂等键:以租户+会话+任务+步骤+工具生成键,下游去重;防止重试重复扣款/建单,依赖下游支持。
  • Watchdog:最大轮次、单步超时、心跳,超时落检查点;防止卡死和无限循环,可能误杀慢任务。
  • 上下文压缩:到窗口 75% 摘要旧轮次,保留近期与钉住事实;防止撑爆窗口和成本上升,压缩本身要花一次调用。
  • 优雅降级:按 L0–L6 退到仍可用的能力;防止组件故障直接报错,代价是能力与质量下降。

层级化为什么比线性管道稳:线性 10 步、每步可靠率 0.85,端到端是 0.85^10≈0.197,约 20%。这个推导假设各步独立同分布;真实故障往往相关(同一网络、同一模型、同一依赖),所以不能把 20% 当成保证值。层级化的价值不是把概率乘回去,而是缩小故障域:一个子 Agent 挂了,父 Agent 可以重启、隔离或换路,兄弟节点不受影响;线性管道一个节点挂,整条断。

六、成本归因:Agent / 用户 / 任务 ​

  • Agent:哪个 Agent 设计最烧钱;看单成功任务成本、循环次数、降级率。
  • 用户/租户:谁在用、是否滥用、如何分摊;看人均成本 P95、配额使用率、拒绝率。
  • 任务:哪类任务不划算、预算怎么调;看单任务成本分布、成功率、人工接管率。

Trace 最小字段:trace_id、session_id、task_id、tenant_id、user_id、agent_id、step_no、span_type(THINK/TOOL/RAG/COMPRESS)、model、model_version、prompt_tokens、completion_tokens、cached_tokens、unit_price_version、tool_name、latency_ms、decision、outcome/error_class。没有 task_id 就只能看模型总账单,回答不了“哪个任务贵”;没有 unit_price_version,降价或换供应商后历史成本不可比。单位任务成本要用“总成本 ÷ 成功任务数”,否则一个便宜但大量失败的路由会显得很划算。

读图顺序是请求先过预算和漏斗,再进编排;Trace 不是终点,而是把实际成本、质量和降级路径回写给预算与漏斗,形成闭环。治理横切在每一段,不单独成层——所以它只有虚线,没有自己的位置。

图的第一层分叉就是全文的判据:局部故障按组件跳级(L1–L3),整体故障按严重程度下沉(L4–L6)。把这两类混在一个列表里排队,就会出现“LLM 挂了却先降小模型”这种既没治好病、又降低了质量的组合。回升侧只放一条边:每次只升一级,并且要求连续 2 次成功,目的是防止阈值附近来回抖动;回升不走跳级,因为降级可以激进、恢复必须保守。

实战场景 ​

场景一:月底账单超支三倍,五个长会话把预算烧穿 ​

现象:接入生产第 4 周对账,平台月度支出 6.9 万美元,是预算 2.1 万的 3.3 倍,增量的 64% 来自分析场景。财务限期两周给出任务粒度的解释,否则冻结额度。金额与倍数是经验值,需按自己的任务分布校准。

排查:按供给、流量、任务结构、预算配置四层分开定位。供给——unit_price_version 与上月一致,单价没变,不是换供应商引起的口径漂移;流量——入口 QPS 持平,10 万 QPS 压到 5,000 RPS 的比例没有恶化,不是用户涨了;任务结构——按 task_id 聚合,Top 5 个任务花掉 3.1 万美元,单个任务跑到 640 个循环轮次,而分析场景的步数预算是 25,按累计发送量 N²K = 640²×1K ≈ 4.1 亿 token,一个任务顶 32 个正常任务(按每任务 20 次调用);预算配置——计数器挂在单次请求和子任务上,主管编排下每个子 Agent 各领一份 25 步,检查点恢复后 step_no 归零、时间维度同步重置。五重里只有模型调用和工具调用真正生效,时间、步数、Token 三重的任务级总量从未落地。

sql
-- 分母用成功任务,否则便宜但大量失败的路由会显得很划算
SELECT task_id, tenant_id, agent_id, MAX(step_no) AS steps,
       SUM(prompt_tokens + completion_tokens - cached_tokens) AS billed,
       COUNT(*) FILTER (WHERE outcome = 'success') AS ok_tasks
FROM trace_span GROUP BY 1,2,3 ORDER BY billed DESC LIMIT 20;

对症做法:把预算从单次调用改成任务级总量,并与状态一起持久化;五重补齐,80/85/90/95 仍是动作触发器不是告警等级。为什么必须是五重而不是把 Token 上限调大:模型无状态、每轮重发历史,第 i 轮输入约 (2i-1)K,N 轮累计 N²K,累计成本随轮次近似二次增长,单靠每步上限拦不住长任务;时间与 Token 花出去不可回收,所以到 80% 就切短路径、压缩上下文,步数到 85% 强制收尾、模型调用到 90% 转小模型、工具到 95% 只放行只读,到 100% 先降级、降级仍不行才终止。

yaml
budget_scope:
  unit: task_id            # 不按子任务、不按单次请求
  persist_with: checkpoint # 恢复不清零
  subtask_share: 0.4       # 子任务最多消耗父任务预算四成(经验值,需校准)
  session_hard_cap_tokens: 120000  # 经验值,需校准
budgets:
  analysis: {time_s: 180, steps: 25, model_calls: 25, tool_calls: 50, tokens: 15000}

复盘要点:单一维度等于没有预算,计数器不与 task_id 一起落库,每恢复一次就重置一次;只看月总额是事后看账单,过账要看 Top-N task_id 集中度,没有 task_id 就只能回答“模型总账单花了多少”。

场景二:供应商限流 45 分钟,用户看到的是报错页 ​

现象:某周三 14:20–15:05,供应商对分析场景的调用批量返回 429;客服与分析共用一把供应商密钥,配额被分析侧吃满,客服入口整段报错,工单 217 条,人工接管率从 6% 拉到 100%,投诉升级到 CTO。触发时长与工单量为经验值,需校准。

排查:分四类定位。容量——运行态 Pod 池利用率不足 40%,不是 GPU 不够;模型——内网备用模型健康探测全绿,不是模型坏了;供给——网关侧 429 带 Retry-After,配额被上游掐住,是供给问题;流程——入口 QPS 无突增,不是活动带来。配置层只剩一条:降级触发源只挂在“LLM 延迟 > 5s 或成功率 < 95%”这类指标上,熔断器只做快速失败、抛错到底;限流风暴落在没有触发源的空档里,链路以硬失败收场——容错六件套里“优雅降级防止组件故障直接报错”这一条等于没接。

对症做法:给限流补显式触发源,并把逐档的用户可见后果写进 runbook,避免值班现场猜档位。

档位保留能力触发条件用户可见后果
L0大模型 + RAG + 工具全部健康完整回答
L1检索 + 工具 + 模板回答LLM 延迟 > 5s 或成功率 < 95%;限流后部分 200“当前为模板回答”,答案变短
L3小模型 + RAG工具成功率 < 90% 或 CPU > 85%只给结论,不给处置建议
L4知识库查询模型全不可用(含 429 耗尽配额)或内存 > 90%静态条目 + “未做推理”,无工单写操作
L5人工错误率 > 5%排队转人工,给预计等待时间
L6稍后重试依赖维护或大面积网络故障保留输入草稿,提示稍后自动重跑

这次实际链路:14:20 LLM 成功率跌破 95% 进 L1;14:26 配额耗尽、模型调用维度吃到 100%,按 degrade_then_terminate 先进 L4 再判要不要终止;14:41 错误率超过 5% 转 L5;14:58 配额恢复后每 30 秒探测、连续两次成功逐级回升到 L0,用户侧影响从 45 分钟压到 18 分钟。恢复条件比触发条件更严、回升一次只升一级;不这样做会:跳级和回升抖动同时发生,值班只能手改配置。

复盘要点:降级阈值补齐之后,供给侧还得按租户和场景分池配密钥,否则一个场景的限流会打穿另一个场景的入口。另外 L1、L4 返回的都是 200,但答案不完整,降级会掩盖质量问题——每档配一条质量门禁加一条用户提示,把“没报错”和“治理成功”分开。缺的 L2 不是笔误:这次 RAG 健康,按“哪个组件先挂跳哪级”本来就不经过它。

场景三:降级阈值设错,正常抖动天天触发 L1 ​

现象:上线第二周 L1 每天触发 40 多次,最长一次持续 22 分钟;同期 6% 的正常分析任务被误杀,口径要求是 1% 以下。触发次数是真实埋点计数,阈值来自另一套默认值,需按本场景分布校准。

排查:拉 7 天窗口看 LLM 延迟分布,P50 约 1.2s、P95 约 3.4s、最坏值 5.2s。三个问题叠在一起:触发窗口只有 10 秒、样本 20 条,一个慢尾请求就能翻档;阈值把最坏值当常态上界,P95 与 5s 之间没有缓冲;Token 预算按上月演示样本设的 15,000,没按新的任务分布重算,所以命中量集中在正常任务而不是异常任务。

对症做法:定阈用三档统计量——P50 定正常带,P50 到 P95 之间不翻档;P95 定触发线,取 max(P95×1.1, 业务 SLA);最坏值只定硬终止和 Watchdog,不做降级触发。触发和回升都带持续窗口与最小样本,恢复侧比触发侧更严;5s 这条线保留,但要求 120 秒窗口内 200 个样本同时越线才翻档:

yaml
triggers:
  llm: {latency_ms: 5000, success_rate: 0.95, level: L1, window_s: 120, min_samples: 200}
recover: {probe_interval_s: 30, recover_after_successes: 2}

阈值改动走版本、灰度、回滚,与模型灰度同一条链路;上线前把五类故障各演练一次:模型不可用、RAG 超时、工具 500、网络抖动、预算耗尽。

复盘要点:每周只看降级触发次数会把治理做反,次数下降可能是阈值设松;误杀率、单位成功任务成本、检查点恢复时长要和触发次数同一张表,每行有 owner,只发邮件等于没有治理。

最小上手 ​

yaml
# 示例,不是通用默认值
budgets:
  customer_service: {time_s: 30, steps: 8, model_calls: 8, tool_calls: 10, tokens: 3000}
  analysis: {time_s: 180, steps: 25, model_calls: 25, tool_calls: 50, tokens: 15000}
  warnings: {time: 0.80, steps: 0.85, model_calls: 0.90, tool_calls: 0.95, tokens: 0.80}
  on_exceed: degrade_then_terminate
degradation:
  probe_interval_s: 30
  recover_after_successes: 2
  triggers:
    llm: {latency_ms: 5000, success_rate: 0.95, level: L1}
    rag: {latency_ms: 3000, accuracy: 0.80, level: L2}
    tool: {success_rate: 0.90, cpu: 0.85, level: L3}
    memory: {usage: 0.90, level: L4}
    error_rate: {value: 0.05, level: L5}
    network: {outage: true, level: L6}
trace:
  required: [trace_id, session_id, task_id, tenant_id, user_id, agent_id, step_no, span_type, model, prompt_tokens, completion_tokens, cached_tokens, unit_price_version, tool_name, latency_ms, outcome]

生产动作 ​

  • 用真实分布校准:每场景采样 200–500 条任务,按 P95 设预算,误杀率超过 1% 就查预算或任务拆分;上线后每周看单位成功任务成本、降级率、误杀率、检查点恢复时长。
  • 阈值配动作和 owner:80/85/90/95 各对应一个自动动作与一个负责人,只有邮件告警等于没有治理。
  • 先定 Trace schema:task_id、模型版本、缓存命中、降级路径、计费单价版本必须落库。
  • 演练与灰度:模型不可用、RAG 超时、工具 500、网络抖动、预算耗尽各跑一次;预算与阈值改动走版本、灰度和回滚。

边界 ​

  • 小规模不必上全套,预算也治不了需求不清:并发低、任务单一时,固定步数上限加人工看账单更便宜;合法任务确实需要 50 步,8 步预算只会稳定误杀,先拆任务或改 SLA。
  • 降级会掩盖质量问题:L1/L2 仍返回 200,但答案可能不完整;要有质量门禁和用户提示,不能把“没报错”当成治理成功。0.85^10≈20% 依赖独立同分布,真实故障相关时不能这么算;层级化的收益主要是隔离故障域和可重调度。跨模型 token 计数可能差 30–50%(经验值),归因要用供应商返回的 usage 和当期单价。

讲清楚 ​

生产治理是把 Agent 的成本和故障从“事后看账单”变成“事前设约束、事中可降级、事后可归因”。先看三个放大器:一次任务十到三十次调用、三成重试放大 25K token 的算例、历史重发让累计发送量到 O(n²);再用时间/步数/模型/工具/Token 五重预算,在 80/85/90/95 触发不同动作,到顶才终止。组件挂了按 L0–L6 跳级降级,恢复逐级回升;入口用 FAQ、缓存、小模型、RAG、大模型五层漏斗把 10 万 QPS 压到 5,000 RPS。最后用 Supervisor Tree、熔断、幂等、Watchdog、压缩和降级兜住链路,用 Trace 把成本归到 Agent、用户和任务。它不适合任务定义不清或规模很小的团队,也不该被当成“多挂几个告警”。

适用:2026 年企业级 Agent 生产治理实践;预算与阈值为示例,需按真实任务分布校准 | 初稿 2026-10

把 AI 工程讲到既懂也会用