引言
2026年3月15日,OpenAI API 全球性宕机 47 分钟。那些没有降级方案的 Agent 应用全部显示"服务不可用",而准备好容灾方案的产品几乎无感知地度过了这次故障。LLM 是 Agent 的核心,但它不是 100% 可靠的基础设施。本文将系统化构建 Agent 的多级降级体系。
一、故障分类与影响分析
1.1 LLM 服务故障类型
┌──────────────────────────────────────────────────┐
│ LLM 故障分类 │
├──────────────┬───────────┬───────────────────────┤
│ 故障类型 │ 持续时间 │ 影响范围 │
├──────────────┼───────────┼───────────────────────┤
│ API 完全宕机 │ 5-60min │ 所有请求失败 │
│ 限流(429) │ 1-10min │ 超额请求失败 │
│ 超时 │ 30-120s │ 单请求受影响 │
│ 模型退版 │ 永久 │ 特定版本不可用 │
│ 区域故障 │ 5-30min │ 特定区域不可用 │
│ 质量退化 │ 未知 │ 输出质量下降 │
└──────────────┴───────────┴───────────────────────┘
1.2 故障影响评估
@dataclass
class FaultImpact:
fault_type: str
user_visible: bool # 用户是否感知
data_loss: bool # 是否丢数据
recovery_time: str # 恢复时间
business_impact: str # 低/中/高/严重
LLM_FAULT_IMPACTS = [
FaultImpact("API宕机", True, False, "5-60min", "严重"),
FaultImpact("限流", True, False, "1-10min", "中"),
FaultImpact("超时", True, False, "30-120s", "低"),
FaultImpact("质量退化", False, False, "未知", "中"),
]
二、多级降级架构
┌──────────────────────────────────────────────────────┐
│ 请求入口 │
│ ┌──────┴──────┐ │
│ │ 请求路由 │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────────────────────▼──────────────────────┐ │
│ │ Level 0: 主模型 (GPT-5) │ │
│ │ 延迟 < 2s, 成功率 99.5% │ │
│ └────────────────┬───────────────────────────┘ │
│ 失败 ↓ │
│ ┌─────────────────▼──────────────────────────┐ │
│ │ Level 1: 备用模型 (Claude Opus) │ │
│ │ 延迟 < 3s, 成功率 99.5% │ │
│ └────────────────┬───────────────────────────┘ │
│ 失败 ↓ │
│ ┌─────────────────▼──────────────────────────┐ │
│ │ Level 2: 降级模型 (GPT-5-mini) │ │
│ │ 延迟 < 1s, 功能受限 │ │
│ └────────────────┬───────────────────────────┘ │
│ 失败 ↓ │
│ ┌─────────────────▼──────────────────────────┐ │
│ │ Level 3: 缓存/预计算结果 │ │
│ │ 精度下降,但可用 │ │
│ └────────────────┬───────────────────────────┘ │
│ 失败 ↓ │
│ ┌─────────────────▼──────────────────────────┐ │
│ │ Level 4: 规则引擎/模板回复 │ │
│ │ 基本功能,无AI能力 │ │
│ └────────────────┬───────────────────────────┘ │
│ 失败 ↓ │
│ ┌─────────────────▼──────────────────────────┐ │
│ │ Level 5: 优雅错误页面 │ │
│ │ 引导用户重试或联系人工 │ │
│ └────────────────────────────────────────────┘ │
三、各级降级实现
Level 0-1:模型切换
from enum import Enum
import asyncio
class ModelTier(Enum):
PRIMARY = "gpt-5"
FALLBACK = "claude-opus-4-2026"
DEGRADED = "gpt-5-mini"
EMERGENCY = "gpt-4o-mini"
class LLMFailoverChain:
"""LLM 多级故障转移链"""
def __init__(self):
self.chain = [
{"model": "gpt-5", "timeout": 30, "retries": 2},
{"model": "claude-opus-4-2026", "timeout": 45, "retries": 1},
{"model": "gpt-5-mini", "timeout": 15, "retries": 2},
{"model": "gpt-4o-mini", "timeout": 10, "retries": 3},
]
self.circuit_breakers = {m["model"]: CircuitBreaker() for m in self.chain}
self.health_checker = HealthChecker()
async def invoke(self, messages: list, **kwargs) -> str:
errors = []
for tier in self.chain:
model = tier["model"]
cb = self.circuit_breakers[model]
# 检查熔断器状态
if not cb.can_call():
errors.append(f"{model}: circuit breaker open")
continue
# 检查健康状态
if not await self.health_checker.is_healthy(model):
errors.append(f"{model}: unhealthy")
continue
try:
response = await self._call_with_retry(
model, messages,
timeout=tier["timeout"],
retries=tier["retries"],
**kwargs
)
cb.record_success()
# 如果降级了,通知调用方
if model != self.chain[0]["model"]:
logger.warning(f"Degraded to {model}")
return response
except (TimeoutError, RateLimitError) as e:
cb.record_failure()
errors.append(f"{model}: {e}")
continue
except Exception as e:
cb.record_failure()
errors.append(f"{model}: {e}")
continue
# 所有模型都失败,进入更深层的降级
raise AllModelsFailedError(errors)
Level 2:功能降级
class DegradedMode:
"""降级模式:功能减少但核心可用"""
DEGRADATION_RULES = {
"gpt-5-mini": {
"disable_tools": False, # 仍可用工具
"max_iterations": 3, # 减少迭代次数
"disable_multi_step": True, # 禁用多步推理
"simplified_prompt": True, # 简化 System Prompt
"max_context_messages": 5, # 减少上下文
},
"gpt-4o-mini": {
"disable_tools": True, # 禁用工具
"max_iterations": 1, # 单轮回复
"disable_multi_step": True,
"simplified_prompt": True,
"max_context_messages": 3,
}
}
def apply(self, request: dict, model: str) -> dict:
rules = self.DEGRADATION_RULES.get(model, {})
degraded_request = request.copy()
if rules.get("simplified_prompt"):
degraded_request["system"] = self._simplify_prompt(request.get("system", ""))
if rules.get("disable_tools"):
degraded_request.pop("tools", None)
if rules.get("max_context_messages"):
messages = degraded_request.get("messages", [])
degraded_request["messages"] = messages[-rules["max_context_messages"]:]
degraded_request["max_tokens"] = min(
degraded_request.get("max_tokens", 4096),
1024 # 降级时限制输出长度
)
return degraded_request
Level 3:缓存降级
class CacheFallback:
"""缓存降级:使用历史相似查询的结果"""
async def try_cached_response(self, query: str) -> CachedResponse | None:
# 1. 精确匹配
exact = await self.cache.get(query)
if exact:
return CachedResponse(
content=exact,
source="exact_cache",
warning="This response is from cache due to AI service degradation."
)
# 2. 语义匹配
similar = await self.semantic_cache.search(query, threshold=0.85)
if similar:
return CachedResponse(
content=similar.response,
source="semantic_cache",
warning="This response is based on a similar historical query."
)
# 3. 预计算回答(高频问题)
precomputed = await self.precomputed_db.get(query)
if precomputed:
return CachedResponse(
content=precomputed,
source="precomputed",
warning=None # 预计算结果质量有保证
)
return None
Level 4:规则引擎降级
class RuleEngineFallback:
"""规则引擎:LLM 不可用时的最终保底"""
def __init__(self):
self.rules = self._load_rules()
def _load_rules(self) -> list[Rule]:
"""加载预定义规则"""
return [
# 意图匹配规则
Rule(
pattern=r"(.*)价格(.*)",
action=lambda m: f"我们的产品价格请参考:{self._get_pricing_table()}",
intent="pricing_inquiry"
),
Rule(
pattern=r"(.*)退款(.*)",
action=lambda m: f"退款申请已记录。您的退款将在3-5个工作日内处理。"
f"工单号:{self._generate_ticket()}",
intent="refund_request"
),
Rule(
pattern=r"(hello|hi|你好|嗨)",
action=lambda m: "您好!我是智能助手。"
"AI服务暂时受限,但我可以处理基础请求。请说明您需要什么帮助。",
intent="greeting"
),
]
def handle(self, user_input: str) -> str:
for rule in self.rules:
match = re.match(rule.pattern, user_input, re.IGNORECASE)
if match:
return rule.action(match)
# 兜底回复
return (
"AI 服务暂时不可用,我无法处理您的复杂请求。\n"
"您可以:\n"
"1. 稍后重试\n"
"2. 联系人工客服:400-xxx-xxxx\n"
"3. 访问帮助中心:https://help.example.com"
)
四、降级决策器
class DegradationOrchestrator:
"""降级编排器:协调各级降级策略"""
def __init__(self):
self.llm_chain = LLMFailoverChain()
self.cache = CacheFallback()
self.rules = RuleEngineFallback()
self.degraded_mode = DegradedMode()
self.health_monitor = HealthMonitor()
async def handle_request(
self,
messages: list,
tools: list | None = None,
user_id: str = "",
priority: str = "normal"
) -> Response:
# 检查系统健康状态
health = await self.health_monitor.get_status()
# 根据健康状态选择策略
if health.llm_available:
try:
return await self.llm_chain.invoke(messages, tools=tools)
except AllModelsFailedError:
health.llm_available = False
if health.cache_available:
cached = await self.cache.try_cached_response(
messages[-1]["content"]
)
if cached:
return Response(
content=cached.content,
degraded=True,
source=cached.source,
warning=cached.warning
)
# 规则引擎兜底
rule_response = self.rules.handle(messages[-1]["content"])
return Response(
content=rule_response,
degraded=True,
source="rule_engine",
warning="AI 服务暂时不可用,正在使用规则引擎处理。"
)
async def health_check_loop(self):
"""持续健康检查,自动恢复"""
while True:
await asyncio.sleep(30) # 每30秒检查一次
if not self.health_monitor.llm_available:
# 尝试恢复
test_result = await self._test_llm_health()
if test_result:
self.health_monitor.llm_available = True
logger.info("LLM service recovered!")
await self._notify_recovery()
五、降级通知与用户体验
class DegradedUX:
"""降级时的用户体验设计"""
MESSAGES = {
"model_switch": {
"inline": "(响应速度可能略有不同)",
"banner": "⚠️ AI 服务正在切换到备用节点,响应可能略有延迟。"
},
"cache_fallback": {
"inline": "(以下为缓存回复)",
"banner": "⚠️ AI 服务暂时繁忙,正在使用历史缓存回复您。"
},
"rule_engine": {
"inline": "(基础模式)",
"banner": "⚠️ AI 服务暂时不可用,正在使用基础模式处理您的请求。"
},
"full_failure": {
"banner": "❌ AI 服务暂时不可用。您可以通过以下方式获取帮助:\n"
"📞 客服热线:400-xxx-xxxx\n"
"💬 在线客服:点击右下角\n"
"📧 邮件:support@example.com\n"
"我们正在紧急修复中,请稍后重试。"
}
}
def render(self, response: Response) -> dict:
if not response.degraded:
return {"content": response.content, "banner": None}
ux = self.MESSAGES.get(response.source, {})
return {
"content": response.content,
"banner": ux.get("banner"),
"inline_note": ux.get("inline"),
"retry_available": True,
}
六、降级演练
class DegradationDrill:
"""降级演练:定期验证降级策略有效性"""
async def run_drill(self):
"""模拟 LLM 故障,验证降级链"""
results = []
# 测试 1: 主模型超时
with mock_llm_timeout(ModelTier.PRIMARY):
result = await self.orchestrator.handle_request(
messages=[{"role": "user", "content": "What is 2+2?"}]
)
results.append(DrillResult(
test="primary_timeout",
passed=result.degraded == True,
response_source=result.source
))
# 测试 2: 所有模型宕机
with mock_all_llm_down():
result = await self.orchestrator.handle_request(
messages=[{"role": "user", "content": "你好"}]
)
results.append(DrillResult(
test="all_llm_down",
passed=result.source == "rule_engine",
response_source=result.source
))
# 测试 3: 缓存命中
with mock_all_llm_down():
# 先正常请求一次建立缓存
await self.orchestrator.handle_request(
messages=[{"role": "user", "content": "What is your return policy?"}]
)
# 再次请求相同问题
result = await self.orchestrator.handle_request(
messages=[{"role": "user", "content": "What is your return policy?"}]
)
results.append(DrillResult(
test="cache_hit",
passed=result.source in ("exact_cache", "semantic_cache"),
response_source=result.source
))
return DrillReport(results=results)
七、降级 Checklist
□ 多 LLM Provider 热备,自动切换 < 5s
□ 降级模型已配置,功能限制明确
□ 语义缓存层已部署,命中率 > 30%
□ 高频问题预计算,离线生成
□ 规则引擎已覆盖核心业务意图
□ 降级通知 UX 已设计,用户可感知
□ 健康检查每 30s 执行,自动恢复
□ 降级演练每月执行,结果归档
□ 人工客服兜底渠道畅通
□ 降级期间数据不丢失(请求排队)
结语
降级策略的本质是"接受不完美,但永不不可用"。在 LLM 依赖度越来越高的今天,没有降级方案的 Agent 系统就像没有安全网的走钢丝。投资降级不是悲观——它是工程成熟度的标志。最好的降级是用户从未注意到的降级。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
