想象你体内住着一支不知疲倦的免疫军队:巡逻的白细胞在血管里游弋,任何陌生细菌都逃不过它们的眼睛;一旦发现入侵者,分诊台立刻判定它是感冒病毒还是食物中毒,抗体工厂加班赶制专属武器;即便高烧不退,身体也会自动降温、让你卧床休息,把伤害降到最低。更妙的是,病好之后体内会留下“记忆细胞”,下次同样的病毒再来,直接被拒之门外。 LLM 应用就像这样一个“数字身体”。用户请求是它每天要消化的营养,而超时、上下文爆掉、模型抽风、恶意输入,就是源源不断的“病菌”。所谓“错误恢复与自愈”,就是给这个数字身体装上一套完整的免疫系统:能看见故障(检测)、能认清故障(分类)、能对抗病毒(自愈)、会紧急兜底(降级)、会安抚情绪(体验)、会记录病历(回放)、会研发疫苗(改进)。这套能力正是 Harness Engineering(大模型应用的“安全带与缰绳”工程)中,让 LLM 生产系统“大病化小、小病化了”的关键。

岗位关联

掌握错误恢复与自愈机制,你就能让 LLM 应用从“一碰就碎”升级为“百毒不侵”。这是大模型落地生产中降低人工干预、保障服务稳定性的核心技能,也是 AI 工程师从“能调模型”走向“能扛生产”的分水岭。

目录
  1. 可视化演示
  2. 1. 故障检测机制:免疫巡逻队
  3. 2. 错误分类识别:病原分诊台
  4. 3. 自愈策略设计:抗体工厂
  5. 4. 恢复动作实现:急救组上场
  6. 5. 降级兜底保障:节能模式
  7. 6. 用户体验守护:温柔安抚
  8. 7. 自愈回放复盘:病历档案
  9. 8. 事后分析改进:疫苗研发
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

动态演示错误恢复与自愈的核心机制,通过概览/流程/对比/趋势四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

错误恢复与自愈:故障检测 故障检测与分类识别方法 自愈策略与恢复动作设计 核心机制可视化 错误恢复与自愈整体架构与关键组件

1. 故障检测机制:免疫巡逻队

在数字身体的世界里,小卫是一颗白细胞。它和伙伴们顺着“血管”——也就是一条条请求链路——日夜巡逻,用触角感受体液里的异常气息。身体还有体温计和心率仪,也就是各项监控指标,任何一项读数越界,小卫都能第一时间察觉。

LLM 应用的“血液”是用户请求与模型响应的洪流。要做到“看见故障”,必须先埋好仪表:响应时延、错误率、成功率、Token 消耗量,这些指标就像体温与心率。再配合日志与调用链追踪,就能定位“发烧”发生在哪一段血管。

工程上常把多个指标加权合成一个“健康度评分”,让巡逻队一眼看懂全局。把成功率作为正向信号,把时延偏离与错误率作为负向惩罚,健康度 H(t) 定义为:

H(t)=w1S(t)−w2D(t)−w3R(t)H(t) = \displaystyle w_1 S(t) - w_2 D(t) - w_3 R(t)

1. 健康度函数 H(t):综合反映系统在 t 时刻整体健康水平的输出值,数值越高代表身体越强壮,是巡逻队的总报警灯。

H(t)H(t)

2. 权重系数 w1、w2、w3:由工程经验或回归调参得到,决定成功率、时延、错误率各自的影响力度,三者通常归一化到和为 1。

w1, w2, w3∈[0,1]w_1,\ w_2,\ w_3 \in [0,1]

3. 成功率 S(t):滑动窗口内请求成功数占总请求数的比例,越高越健康,它是唯一的正向信号。

S(t)=NokNtotalS(t) = \frac{N_{\text{ok}}}{N_{\text{total}}}

4. 时延惩罚 D(t) 与错误率 R(t):时延偏离基线越远、错误率越高,健康度被扣得越多,二者是负向信号。

D(t)=latency(t)baseline,R(t)=NerrNtotalD(t) = \frac{\text{latency}(t)}{\text{baseline}},\qquad R(t) = \frac{N_{\text{err}}}{N_{\text{total}}}

有了度量,还得有规则:为每个指标配置告警阈值,避免“狼来了”式的误报刷屏。这正是 Harness Engineering 中“可观测性”落地到自愈系统的第一步。

巡逻队终于能在病菌刚探头的瞬间大喊“发现敌情”。所有后续的自愈动作都依赖这一步——看不见的故障,永远治不好。

2. 错误分类识别:病原分诊台

警报拉响后,分诊台的白细胞大姐登场了。她能一眼分辨:打喷嚏是着凉,拉肚子是吃坏东西,烧伤要送急诊。不同病原体走不同通道,绝不能统统按感冒处理,否则会耽误病情。

LLM 应用的“病原体”也要分类:模型超时、上下文溢出、输出格式非法、内容安全违规……每种错误的重试价值差异巨大。超时可能只是网络抖动,重试有用;上下文溢出重试一百遍也没用,只会再白白烧一遍 Token 钱。

工程上常用“错误分级函数”把连续的错误影响值映射成离散等级。设 e 为错误的可量化影响值(如耗时偏离度或语义校验得分),θ1<θ2<θ3 为三级阈值:

grade(e)={3e≥θ32θ2≤e<θ31θ1≤e<θ20e<θ1\text{grade}(e) = \begin{cases} 3 & e \geq \theta_3 \\ 2 & \theta_2 \leq e < \theta_3 \\ 1 & \theta_1 \leq e < \theta_2 \\ 0 & e < \theta_1 \end{cases}

1. 分级函数 grade(e):把连续的错误影响值映射成离散等级 0/1/2/3,每个等级对应一类处置通道,0 级可忽略、3 级必须熔断。

grade(e)\text{grade}(e)

2. 错误影响值 e:综合错误类型、耗时偏离、校验得分得到的量化值,需要先做归一化才能比较。

e∈[0,+∞)e \in [0, +\infty)

3. 阈值 θ1、θ2、θ3:根据历史故障分布确定的分级分界点,满足递增关系,决定“小病”与“大病”的分水岭。

θ1<θ2<θ3\theta_1 < \theta_2 < \theta_3

4. 分段映射:e 落在不同区间得到不同等级,等级越高处置越重,等级越低越可以轻描淡写。

grade(e)∈{0,1,2,3}\text{grade}(e) \in \{0,1,2,3\}

分类还要看“长相”:超时类看耗时是否超限,上下文类看 Token 数与窗口上限,输出异常类看格式校验与内容安全检测。分诊结果决定了后续走“重试通道”还是“降级通道”。

认错病,比治得慢更可怕。分诊台的一句话,决定了整场免疫战斗的走向。

3. 自愈策略设计:抗体工厂

认准病原后,抗体工厂连夜赶制“对症武器”。疫苗要分批接种,不能一次打完全部剂量,身体扛不住;抗体也不能盲打,剂量要按感染程度递增,上来就猛药反而会出问题。

自愈策略的核心是“重试 + 退避 + 降级路径”。第一次失败后立刻重试,往往撞在同一个故障上;所以要指数退避:第一次等 0.3 秒,第二次等 0.6 秒,第三次 1.2 秒,给下游系统留出喘息之机。

第 n 次重试前的等待时间满足如下公式:

twait=tbase×2n−1+jittert_{\text{wait}} = \displaystyle t_{\text{base}} \times 2^{n-1} + \text{jitter}

1. 等待时长 t_wait:第 n 次重试前必须休息的时间,让故障方有时间自我恢复。

twaitt_{\text{wait}}

2. 基础等待 t_base:首次重试的基准等待时间,典型取值在 0.3 秒到 1 秒之间,由服务容忍度决定。

tbaset_{\text{base}}

3. 指数因子 2^(n-1):n 从 1 开始计数,每多一次重试等待翻倍,形成“越等越久”的退避节奏。

2n−12^{n-1}

4. 随机抖动 jitter:加上一个随机量打散同步,防止大量请求同时重试造成“重试风暴”,像打疫苗时错开人群。

jitter∼U(0, c)\text{jitter} \sim U(0,\ c)

围绕重试还要设计“抗体梯度”:强模型 → 轻量模型 → 固定模板,逐级降级;以及补偿修正:截断过长的历史、压缩对话摘要、把模糊指令改写清楚,让模型“吃得下”再作答。

好的自愈策略不是蛮力重试,而是像接种疫苗一样有节奏、有梯度、有剂量。抗体工厂的出库单上,写满了“何时打、打多少、打完去哪”。

4. 恢复动作实现:急救组上场

高烧 39.5 度,只靠多喝水已经不够。急救组上场:先物理降温,再上退烧药,压不住就静脉输液。恢复动作是策略的执行层,讲究“手要快、路要通、刹得住”。

在代码里,恢复动作包含四类:触发重试(去抖执行)、切换备用模型(绕过失效引擎)、重构提示词(压缩上下文、改写指令)、以及链路熔断——当错误率飙到阈值,直接打开“免疫屏障”拦截后续请求,避免雪崩。

当存在多个备用模型时,需要给它们打分排序。设 a_m 为模型 m 的历史准确率、c_m 为归一化推理成本、d_m 为归一化响应时延:

Vm=αam−βcm−γdmV_m = \displaystyle \alpha a_m - \beta c_m - \gamma d_m

1. 模型综合得分 V_m:选择备用模型时对每个候选打的综合分,分数高者优先接管服务。

VmV_m

2. 权衡系数 α、β、γ:准确率、成本、时延的权重,由业务优先级决定,比如金融场景会把 α 调大。

α, β, γ>0\alpha,\ \beta,\ \gamma > 0

3. 准确率 a_m:候选模型在相似任务上的历史准确率,越高越好,是正向信号。

am∈[0,1]a_m \in [0,1]

4. 归一化成本 c_m 与时延 d_m:把推理价格和响应速度压到 0~1 区间,越高扣分越多,是负向信号。

cm, dm∈[0,1]c_m,\ d_m \in [0,1]

熔断器则是“刹车的刹车”:正常态(closed)放行,故障率超标进入打开态(open)直接拒绝,冷却时间结束进入半开态(half-open)放行少量试探请求验证恢复。

急救组的动作环环相扣:重试解决“假故障”,切换模型解决“模型失效”,熔断保护解决“下游雪崩”。身体不会在一场感冒里同时启动所有急救方案,动作要有优先级。

5. 降级兜底保障:节能模式

就算病毒暂时压不下去,身体也会启动“节能模式”:卧床、喝水、退烧。别小看这些兜底手段,它们保证你不会因为一场感冒就丢掉性命。

LLM 应用同理:强模型不可用时,降级到轻量模型;实时计算失败时,返回缓存答案;实在不行,给一段稳妥的模板回复并引导人工客服。降级不是摆烂,而是用“有限能力”守住“核心承诺”。

用“加权可用度”来衡量兜底效果——完整回答记 1 分,降级回答记 λ 分(0<λ<1),失败记 0 分:

Aw=Nfull+λNdegradeNtotalA_w = \displaystyle \frac{N_{\text{full}} + \lambda N_{\text{degrade}}}{N_{\text{total}}}

1. 加权可用度 A_w:衡量降级兜底后用户实际体验到的“服务质量”指标,越接近 1 越好。

AwA_w

2. 完整回答数 N_full:走完全链路、质量达标的结果数量,它们拿到满分 1 分。

NfullN_{\text{full}}

3. 降级回答数 N_degrade 与折扣系数 λ:降级回答只算部分功劳,λ 表示简化回答相对于完整回答的打折程度。

Ndegrade,λ∈(0,1)N_{\text{degrade}},\quad \lambda \in (0,1)

4. 总请求数 N_total:窗口内全部请求数量,作为分母,保证比例语义正确。

NtotalN_{\text{total}}

兜底方案还要分层:固定模板给“最低安保”,功能降级模式砍掉非核心能力(如禁用联网搜索),缓存兜底用高频问答命中存量答案,人工接管通道则是最后的“转院手术”。

降级兜底是免疫系统的“休克保护”:先保住生命体征(可用性),再谈彻底痊愈(完美回复)。体温计上的加权可用度,告诉我们这次兜底做得到不到位。

6. 用户体验守护:温柔安抚

病人最怕的不是疼,而是没人告诉他“现在什么情况”。好医生会在排队时说“前面还有三位”,在打针时说“会有一点点疼”。确定性,是最好的止痛药。

自愈过程中用户会感受到延迟或异常,体验守护的目标是“坏事发生但用户不难受”:请求排队时给进度反馈,恢复期间提示“正在努力”,结果异常时用温和话术引导重试或转人工,而不是甩出一段冰冷的报错。

用户的耐心随时间流逝呈指数衰减。设 U_max 为峰值满意度、k 为耐心衰减系数、t_wait 为等待时长:

U(t)=Umax⁡×e−k twaitU(t) = \displaystyle U_{\max} \times e^{-k\, t_{\text{wait}}}

1. 满意度 U(t):用户在等待过程中的主观体验评分,随时间流逝而下降。

U(t)U(t)

2. 峰值满意度 U_max:零等待时用户的原始满意度上限,是服务体验的天花板。

Umax⁡U_{\max}

3. 衰减系数 k:用户耐心流失的速度,k 越大用户越没耐心,一般用实验数据拟合。

k>0k > 0

4. 等待时长 t_wait:从请求发出到收到响应的秒数,是自愈过程能争取到的“黄金窗口”。

twaitt_{\text{wait}}

围绕这个公式,工程上会做四件事:请求排队缓冲(不让请求瞬间压垮系统)、进度感知反馈(“正在生成,预计 3 秒”)、结果温和呈现(异常时道歉并给出可行的替代路径)、负面体验对冲(送优惠券或积分补偿)。

小卫后来明白了:免疫系统不只是打打杀杀,还会弯腰给病人掖被角。体验守护让用户在故障风暴里依然觉得“被温柔以待”。

7. 自愈回放复盘:病历档案

病好了,病历不能丢。医院会把每次发烧的时间、症状、用药、疗效都记进病历卡。下次遇到相似病人,医生翻病历就能快速对症,不用重新摸索。

LLM 应用也需要“病历卡”:把故障现场完整录制下来(请求原文、上下文快照、错误类型、触发动作、恢复结果),放进回放管道,用真实流量反复验证自愈策略是否真的有效。

自愈成功率是回放复盘的核心指标:

Sheal=NrecoverNtriggerS_{\text{heal}} = \displaystyle \frac{N_{\text{recover}}}{N_{\text{trigger}}}

1. 自愈成功率 S_heal:触发自愈动作后最终成功恢复的比例,是免疫系统“战斗力”的直接体现。

ShealS_{\text{heal}}

2. 成功恢复数 N_recover:通过重试、降级、切换模型等动作最终拿到可用结果的数量。

NrecoverN_{\text{recover}}

3. 触发自愈数 N_trigger:检测到故障并进入自愈流程的总次数,是分母。

NtriggerN_{\text{trigger}}

4. 比率解读:S 越接近 1 说明免疫越强;低于 0.9 意味着策略需要迭代,不能只看“恢复了”就放心。

0≤Sheal≤10 \le S_{\text{heal}} \le 1

回放管道搭建好后,每次策略变更都要跑一遍历史故障集做回归验证,防止“修好 A 打坏 B”。还要把每个案例标注上“治好了还是没治好”,沉淀成可量化的策略效果评估报告。

白细胞的记忆不写在基因里,写在一本本病历里。回放复盘让免疫系统的每一次战斗都不白费。

8. 事后分析改进:疫苗研发

最厉害的是疫苗工厂:研究完病毒的长相后,提前造出“通缉令”,让免疫军队在病毒还没进门时就认得它。预防,永远大于治疗。

复盘之后要输出改进:根因定位(为什么超时?上游慢还是提示词太长?)、成功案例沉淀(哪些自愈动作有效)、策略库迭代(调整阈值与退避参数)、预防性加固(加缓存、加限流、加前置校验)。

免疫记忆强度会随时间衰减,但每次成功复盘都会给它“叠 Buff”:

M(t)=M0 e−λt+DreinforceM(t) = \displaystyle M_0 \, e^{-\lambda t} + D_{\text{reinforce}}

1. 免疫记忆强度 M(t):策略库积累的防护能力随时间变化的值,记忆越强同类故障越难复发。

M(t)M(t)

2. 初始记忆 M_0:某类故障刚复盘完毕时的防护强度,是“疫苗刚接种”时的保护力。

M0M_0

3. 记忆衰减 e^(-λt):λ 是遗忘系数,时间越长记忆越弱,提醒我们要定期复测与温习。

e−λte^{-\lambda t}

4. 复盘强化 D_reinforce:每次新的成功案例复盘都会给记忆增加强度,相当于“加强针”。

DreinforceD_{\text{reinforce}}

疫苗不是打一次就一劳永逸,疾病预防是一场持续博弈。有了“复盘—改进—预防”循环,LLM 应用会越病越强,从此“久病成医”。

AI 应用场景

电商大促智能客服

阶段:运行时监控与故障治理

解决的问题:大促流量洪峰带来超时、限流等问题,纯靠人工盯守成本高、响应慢。自愈系统用健康度评分自动识别“发烧”,超时自动重试+退避,限流时降级到高频问答缓存,让绝大部分故障在几秒内自动恢复,无需人工介入。

具体案例:某电商 618 大促,客服机器人请求量翻了 20 倍,调用方 5xx 错误率一度飙到 12%。自愈系统触发熔断保护、轻模型降级、模板兜底三级联动,整体可用性从 95% 拉回 99.2%,当天人工介入仅 3 次。

金融投顾助手

阶段:安全护栏与用户体验保障

解决的问题:金融场景容错率极低,自愈动作还必须保证合规与用户体验。上下文溢出时自动压缩历史并重写对话摘要;模型输出非法时转为固定合规话术;全链路失败则无缝转接人工投顾,让用户在故障中依然感到“被稳稳接住”。

具体案例:某券商 App 的智能投顾,用户连续追问导致上下文窗口溢出报错。系统检测到“上下文类错误”后不重试、直接走降级通道,调用摘要模型压缩历史后重新生成,回答成功率从 71% 升至 96%。

企业知识库 RAG 助手

阶段:持续评估与回放改进

解决的问题:RAG 链路环节多(检索—重排—生成),任一处失败都会让用户得不到答案。把每次失败录制进回放管道,策略迭代后回归验证历史故障集,避免“修好检索、坏了生成”的连锁问题,持续提升自愈成功率。

具体案例:某企业内部 FAQ 机器人上线首月收集了 400 多个失败案例,回放分析发现 60% 源于检索超时。团队优化了索引缓存与并发策略后,自愈成功率从 82% 提升到 97%,用户满意度提升 21%。

Python 演示

python86 行
import randomimport time  class SelfHealingLLM:    """带免疫系统的 LLM 客户端: 检测-重试-降级-回放"""     def __init__(self, models, fallback="系统繁忙, 请稍后再试"):        self.models = models  # [(名字, 调用函数), ...], 第一个为主力模型        self.fallback = fallback        self.retry_limit = 3        self.base_wait = 0.3        self.replay_log = []      # 故障病历        self.health_count = {"ok": 0, "recover": 0, "fail": 0}     def call(self, prompt, history):        for attempt in range(1, self.retry_limit + 1):            try:                reply = self.invoke(attempt, prompt, history)                self.health_count["ok"] += 1                return reply            except TimeoutError as err:                wait = self.base_wait * (2 ** (attempt - 1)) + random.uniform(0, 0.1)                self.record(prompt, "timeout", attempt, err, wait)                time.sleep(wait)            except ValueError as err:                # 上下文溢出属于不可重试错误, 直接进入降级                self.record(prompt, "context_overflow", attempt, err, 0)                break        try:            reply = self.invoke(0, prompt, history)            self.health_count["recover"] += 1            return reply        except Exception as err:            self.health_count["fail"] += 1            self.record(prompt, "fallback_fail", 0, err, 0)            return self.fallback     def invoke(self, level, prompt, history):        if level == 0:            return self.models[1][1](prompt)        if len(history) > 8:            raise ValueError("上下文超出窗口")        if random.random() < 0.35:            raise TimeoutError("上游模型响应超时")        return self.models[0][1](prompt)     def record(self, prompt, error_type, attempt, err, wait):        self.replay_log.append({            "prompt": prompt[:16],            "error_type": error_type,            "attempt": attempt,            "detail": str(err),            "wait": round(wait, 2),        })     def replay_report(self):        total = sum(self.health_count.values())        heal_rate = self.health_count["recover"] / total if total else 0.0        return {            "total": total,            "ok": self.health_count["ok"],            "recover": self.health_count["recover"],            "fail": self.health_count["fail"],            "heal_rate": round(heal_rate, 3),            "replay_cases": len(self.replay_log),        }  def strong_model(prompt):    return "[强模型] 完整回答:" + prompt[:8]  def light_model(prompt):    return "[轻量模型] 简述:" + prompt[:8]  if __name__ == "__main__":    random.seed(42)    client = SelfHealingLLM([("strong", strong_model), ("light", light_model)])    for i in range(20):        history = [f"历史消息{j}" for j in range(i % 12)]        result = client.call(f"用户提问{i}", history)        if i % 4 == 0:            print("第{}次 -> {}".format(i, result[:22]))    print("自愈回放报告:", client.replay_report())
目的:实现一个带免疫系统的 LLM 客户端,演示“健康检测—分类重试—指数退避—降级兜底—回放报告”的完整自愈闭环。
  1. wait = self.base_wait * (2 ** (attempt - 1)) + random.uniform(0, 0.1)指数退避加上随机抖动,避免重试风暴
  2. except TimeoutError as err:超时属于可重试错误,先记病历再等待重试
  3. except ValueError as err:上下文溢出不可重试,直接 break 进入降级通道
  4. reply = self.invoke(0, prompt, history)降级调用轻量模型,用有限能力守住核心承诺
  5. self.replay_log.append({...})把每一条故障录成“病历”,供事后回放复盘
  6. heal_rate = self.health_count["recover"] / total计算自愈成功率,衡量免疫系统战斗力
  7. random.seed(42)固定随机种子,让演示结果可复现,方便回归验证

常见误区

误区系统出错就拼命重试,想着“多试几次总能成功”,于是把重试上限调到 10 次甚至无限重试。

正解重试不是免费的。每次重试都在消耗下游资源和用户时间,无限重试会把一次性抖动放大成“重试风暴”,反而拖垮整个系统。正确做法是限制重试次数(通常 2~3 次)+ 指数退避 + 熔断保护,把重试当作“疫苗”而非“猛药”,剂量要小、间隔要稳。

为何常见:直觉上“再试一次”成本很低,但忽略了故障期间所有请求会同频重试,形成对下游的二次冲击。

误区反正都出错了,直接丢给用户一句“系统繁忙,请稍后再试”就算完成了兜底。

正解降级的目标是“用有限能力守住核心承诺”。高明的兜底会先尝试缓存命中,再降级到轻量模型给简化回答,最后才用模板回复并引导人工。加权可用度告诉我们,不同兜底路径的“功劳”完全不同,把兜底当偷懒会让用户大量流失。

为何常见:把“降级”理解成“放弃”,忽略了用户真正在乎的是“还能不能用、有没有人管”。

误区系统自己恢复了,说明问题解决了,日志看一眼就完事,不需要深入分析。

正解自愈只是“治好了症状”,不等于“清除了病因”。必须做回放复盘和根因分析,判断是超时、上下文还是模型缺陷;再把成功案例沉淀进策略库、做预防性加固。否则同一类故障会像慢性病一样反复发作,免疫系统永远停在“被动挨打”阶段。

为何常见:看到绿色恢复信号就放松警惕,忽视了免疫记忆需要“复盘强化”才能长期有效。

误区把上百个指标全部接进来,每个都设告警,总觉得“看得越多越放心”。

正解指标过多会产生告警噪声,值班人员被无关告警刷屏后,真正致命的故障反而被淹没——这就是“告警疲劳”。正确做法是收敛关键指标(成功率、时延、错误率、Token 消耗),用健康度评分做加权合成,并精心调优阈值,让告警“少而准”。

为何常见:做监控时容易陷入“数据收集癖”,忘了监控的最终目的是让人在关键时刻抓住真正重要的信号。

面试题

Q1. 健康度评分 H(t)=w1·S(t)−w2·D(t)−w3·R(t) 中,哪个指标是正向信号?

单选题 · easy

  • A.成功率 S(t)← 正确答案
  • B.时延 D(t)
  • C.错误率 R(t)
  • D.请求量 P(t)

答案:A。健康度公式里成功率越高越健康,是正向信号;时延偏离和错误率越高越不健康,是负向信号。请求量本身不反映健康程度,选 A。

Q2. 指数退避策略中,第 n 次重试前的等待时间与什么有关?

单选题 · mid

  • A.固定的三秒间隔
  • B.n 的指数函数← 正确答案
  • C.用户输入的长度
  • D.模型参数量大小

答案:B。指数退避的等待时间等于基础等待乘以 2 的 n−1 次方,随重试次数指数增长,再加随机抖动。它只与重试次数有关,与用户输入和模型规模无关。

Q3. 下列哪些错误适合“不重试、直接降级”处理?

多选题 · mid

  • A.上下文超窗溢出← 正确答案
  • B.上游瞬时超时
  • C.输出格式非法← 正确答案
  • D.网络偶发抖动

答案:AC。上下文溢出重试一百遍还是会溢出,输出格式非法重试也不会变合法,二者应直接降级或校验修正。上游超时和网络抖动是瞬时问题,重试通常有效,属于可重试错误。

Q4. 自愈回放复盘的首要目的是什么?

单选题 · mid

  • A.删除历史故障日志
  • B.复现并验证自愈策略← 正确答案
  • C.重启所有生产服务
  • D.压缩模型推理参数

答案:B。回放复盘是把历史故障场景录制下来,在管道里重放以验证自愈策略是否有效,并做回归验证防止“修 A 坏 B”。它不是清理日志、重启服务或压缩模型的手段。

Q5. 熔断器处于半开状态时,系统通常怎么做?

单选题 · hard

  • A.永久拒绝所有请求
  • B.放行少量试探请求← 正确答案
  • C.无限放行全部请求
  • D.立即重启应用进程

答案:B。半开状态是熔断器从打开到关闭的过渡,放行少量试探请求验证下游是否恢复:成功则关闭熔断器恢复全量流量,失败则重新打开。永久拒绝或无限放行都违背了熔断器的设计意图。

Q6. 下列哪些属于降级兜底的合理手段?

多选题 · mid

  • A.缓存答案优先响应← 正确答案
  • B.简化回答保留核心← 正确答案
  • C.静默吞掉所有错误
  • D.转接人工客服通道← 正确答案

答案:ABD。缓存、简化回答、人工接管都是“用有限能力守住核心承诺”的兜底手段。静默吞掉错误会让用户面对无声失败,破坏信任,是错误做法。

Q7. 用户体验守护中“进度感知反馈”的作用是什么?

单选题 · easy

  • A.让用户知道系统正在工作← 正确答案
  • B.隐藏所有等待时间细节
  • C.强制用户刷新页面重试
  • D.提前结束会话节省成本

答案:A。进度感知反馈的核心是给用户确定性,比如“正在生成,预计还需 2 秒”。它既不隐藏信息,也不强迫用户操作或提前结束会话,而是用透明度缓解等待焦虑。

Q8. 某请求重试三次均超时,最合适的后续动作是什么?

单选题 · mid

  • A.无限重试直到成功
  • B.触发降级或兜底方案← 正确答案
  • C.丢弃请求不作处理
  • D.向用户展示原始堆栈

答案:B。重试次数耗尽后应走降级路径:轻量模型、缓存或模板兜底,尽全力给用户一个可用的结果。无限重试会放大负载,丢弃请求和展示堆栈则严重伤害体验。

Q9. 关于事后分析改进,下列哪些做法正确?

多选题 · hard

  • A.对高频故障做根因分析← 正确答案
  • B.把成功案例沉淀进策略库← 正确答案
  • C.只统计指标不更新规则
  • D.针对根因做预防加固← 正确答案

答案:ABD。事后分析的核心是根因定位、案例沉淀和预防加固——相当于研究病毒后造疫苗。只统计指标而不更新规则,等于记了病历却不治疗,无法形成免疫记忆。

Q10. “降级路径选择”中,从强到弱的梯度通常指什么?

单选题 · hard

  • A.强模型到轻模型再到模板← 正确答案
  • B.模板到强模型再到人工
  • C.人工到模板再到轻模型
  • D.轻模型到模板再到人工

答案:A。降级梯度遵循“能力从强到弱、成本从高到低”的顺序:先试强模型,不行换轻量模型,再不行用固定模板兜底,最后转人工。其余选项顺序颠倒,不符合“尽最大努力保留能力”的原则。