ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI系统可用性设计实战:从超时重试到模型网关的四个关键策略

AI系统可用性设计实战:从超时重试到模型网关的四个关键策略 那次事故我记得很清楚凌晨两点模型供应商一次上游抖动我们整套智能客服系统跟着雪崩而监控面板上的服务健康度还是绿的。原因是监控只看了HTTP状态码根本没看“回答到底能不能用”。从那时起我意识到AI系统的可用性设计和传统后端的高可用完全是两回事。传统架构讲究超时、重试、熔断三板斧但这些动作搬到AI场景里处处都需要重新审视。这篇文章就是围绕AI系统可用性设计整理我在应用架构实践中真正用过的“奇招”不聊纸上谈兵的理论只讲踩过坑之后的解法。适合正在做AI应用架构、模型服务治理、或者被LLM不稳定输出折磨的工程师参考。1. 为什么传统高可用三板斧在AI系统里会失灵1.1 确定性假设LLM的重试不等于同一个结果传统后端的高可用设计有一个隐藏前提系统是确定性的。同一个请求发给同一个服务只要代码没变结果大概率一致。所以超时后重试是安全的幂等键加个缓存就能防止重复下单。但LLM本质上是一个采样系统温度大于0时同样的Prompt可能产出完全不同的结果。把传统重试策略直接套用后果很尴尬第一次调用返回超时重试之后虽然成功了但生成的内容可能已经不是用户想要的那一版甚至可能因为重试造成重复扣费。我在实际项目中吃过这个亏。当时给一个文档生成服务做网关上游模型偶尔出现5xx网关按老规矩自动重试结果用户拿到两篇不同风格的文档还在数据库里产生了重复记录。后来我改成“超时后先查结果缓存查到就返回查不到再重试重试后必须做输出比对”才把这个坑填上。这不是说AI系统不能用重试而是重试策略要改只对瞬时错误连接失败、429限流、503过载重试不对业务参数错误重试重试前确认操作不是写操作重试后尽量做一次输出校验。核心原则是把“同一个语义”当作幂等键而不是把“同一串请求”当作幂等键。1.2 “可用”的定义变了从请求成功到回答可信传统可用性指标是成功率、错误率、时延、吞吐这些当然还要看。但对AI系统来说HTTP 200只是最低门槛真正的可用性要看“回答是否解决了用户问题”。很多团队线上SLA写得漂亮模型调用成功率99.9%可用户一问就炸不是答非所问就是一本正经地胡说八道。这里有个反直觉的事实服务成功率和业务成功率之间可能差着好几个量级。比如一个法律咨询机器人模型每次都正常返回文本但其中30%的答案引用了不存在的法条。你说这个系统可用吗从基础设施角度可用从业务角度完全不可用。所以AI系统的可用性设计必须同时覆盖两层一层是传统的基础设施可用性另一层是模型输出质量可用性。后者的监控和治理往往才是决定用户体验的关键。我倾向于把“无效回答率”纳入核心SLO比如“每100次对话中因输出格式不合格、关键内容缺失、明显幻觉而需要重新生成的次数”。只有这个指标稳定了谈可用性才有意义。2. 超时、重试、熔断基础动作的AI化改造2.1 超时不能只看总耗时流式场景的TTFT很多人给模型服务配超时沿用以前接口的5000毫秒结果线上天天告警。这里有个误区LLM推理是增量生成一个300字的回答可能要生成几十秒但用户感知到的“响应快慢”主要取决于首字时间也就是TTFTTime To First Token。把总超时设成5秒大概率不是模型故障而是业务方根本不理解生成式接口的时延特征。流式场景下我建议设计两套超时首包超时TTFT和总超时。首包超时一般设3到5秒超过说明上游排队或者网络异常总超时根据业务容忍度设60到120秒超过就截断并走降级。监控上也要区分这两个指标不能只盯着P99延迟。曾经有个客户反馈“系统变慢了”一看数据平均延迟只涨了200毫秒但TTFT从800毫秒涨到3秒用户早就等不及了。这就是只监控总延迟漏掉首字时间的结果。非流式接口更不能一刀切。如果业务必须等完整结果超时时间要按模型输入长度动态计算粗略公式是预计耗时 输入Token数 / 输入速度 输出Token数 / 输出速度再乘上一个1.5到2的余量系数。不能拿一个固定值套所有请求。2.2 重试和熔断的降级层级AI系统的重试要带“降级层级”而不是原地再打一次同款模型。我设计的降级链一般是五层第一层主模型正常调用第二层主模型瞬时故障自动重试一次带指数退避和抖动第三层主模型持续故障切到备选模型或轻量模型第四层所有模型都不可用启用语义缓存返回同类问题最近的成功答案第五层兜底话术明确告知用户当前服务繁忙而不是让用户看白屏。这个链路的顺序很重要。很多团队一上来就把“固定兜底话术”放到第二层结果模型只是抖了一下用户就收到“对不起我暂时无法回答”体验非常割裂。正确的思路是先用低成本动作吸收瞬时故障再逐步降级到“效果变差但还能用”的服务最后才放弃。熔断器也要重新设计参数。传统熔断看错误率AI场景更建议看“连续失败次数错误类型”。比如上游连续返回10次429说明是配额问题熔断后直接切备选模型而不是傻等恢复如果返回内容校验失败超过阈值说明是模型质量漂移这时候熔断没用应该触发告警并切到更保守的Prompt版本。熔断不是目的保住“回答可用”才是目的。3. 奇招一模型网关不只是代理而是可用性的第一决策点3.1 语义路由和多级模型池把模型网关当成一个普通代理转发流量是可用性设计里最可惜的浪费。网关最该做的是成为“路由大脑”根据请求难度、业务优先级、实时可用性决定把请求发给哪个模型。我在实际项目中维护了一个三级模型池轻量模型、标准模型、高性能模型。轻量模型负责意图识别、摘要、分类等简单任务成本低、速度快标准模型处理大多数对话高性能模型只路由给复杂推理、关键业务场景。判断依据不能只靠人写规则还要结合“API返回的实时健康度”。某段时间轻量模型延迟恶化路由权重就要自动调低把流量切到标准模型。这不叫复杂这叫把可用性设计前移。实现上不一定要引入多复杂的框架一个Redis存健康分一个决策函数就够起步。语义路由还有一个容易被忽略的好处成本控制。把简单问题发给昂贵大模型不仅浪费还会掏空配额。配额一旦耗尽整个系统不可用。从可用性角度看语义路由是在避免“自我限流”。我见过一个项目所有请求都打最强模型月底额度耗尽业务直接停摆。后来加了语义路由成本降了40%可用性反而提高了。3.2 模型切换的隐藏成本Prompt差异与配额隔离多模型冗余最常踩的坑是天真地以为切换模型就是换个URL。实际上不同模型对指令的遵循能力、输出格式稳定性、甚至JSON返回习惯都不同。A模型能稳定输出的JSONB模型可能多包一层Markdown代码块导致下游解析崩溃。所以做主备切换时必须有一个“模型适配层”把业务Prompt拆成“通用指令模型差异配置”同一个任务在两套模型上都跑通了才能算真正具备冗余能力。另一件容易忽略的事是配额隔离。很多团队只接了同一家云厂商的两个模型结果上游一个账户限流两个模型一起挂。这就是伪冗余。真的冗余要跨供应商、跨可用区至少保证一个挂了另一个还有独立配额和独立网络路径。我建议给每个模型池单独统计健康分健康分不是简单的延迟加错误率而是“近5分钟内有效回答率延迟分位数配额剩余量”的综合值。路由决策时优先选健康分高、成本可接受的那个。这就像打车软件派单不是只选“最便宜”或“最近”而是综合司机评分、距离、当前路况做全局决策。4. 奇招二把“坏输出”纳入可用性管理4.1 强制结构化输出与失败自动重试模型输出“能用”的第一步是格式符合预期。现在主流模型都支持JSON模式或函数调用但实际落地时依然有相当比例的返回不符合Schema可能是多余的引号、缺字段、或者包含解释性文字。对付这种情况我从不指望模型一次做对而是在调用层加一道“输出校验闸门”解析失败就带着错误信息重新生成一次。伪代码大概是def call_model_with_schema(prompt, schema, max_retries2): for attempt in range(max_retries 1): raw llm.call(prompt, response_formatjson, schemaschema) if attempt 0: raw llm.call( prompt, response_formatjson, schemaschema, extra_instructionf上次输出无法通过校验错误{error_msg}请修正后重新输出。 ) try: result json_validate_and_coerce(raw, schema) return result except ValidationError as e: error_msg str(e) continue return fallback_result()这里的要点是重试时要把“错误信息回传给模型”让模型知道错在哪而不是原样再问一次。实测下来只要给出明确的字段级错误第二次生成的通过率能到90%以上。还过不了怎么办走fallback路径不要无限重试毕竟每次重试都在烧钱和加延迟。4.2 幻觉自检生成-验证-再生成比格式错误更棘手的是内容幻觉。传统监控完全看不到这个问题因为它在语义层面。我在高价值场景里常用的做法是“生成-验证-再生成”三步循环。第一步先生成一个答案第二步让模型用自己的话说出“答案里哪些事实有据可依、哪些是推断”第三步如果关键事实无法确认就再生成一个更保守的版本或者直接回答不知道。对需要引用知识库的场景还可以把答案切分成若干个断言claim逐条去检索原文比对算一个“归因分数”。低于阈值的答案直接拦截不回给用户。有人担心这样延迟太高。确实三步循环成本不低所以要把预算花在刀刃上低风险场景只做格式校验高风险场景才启用幻觉自检。所谓高风险比如医疗建议、法律结论、金融数值操作这类场景宁可慢一点也要保证不把幻觉传出去。还有一个非常实用的技巧在Prompt里给模型“安全出口”。明确告诉模型“如果你不确定答案直接回复‘我需要查证后再回答’不要猜测”。很多模型为了讨好用户会强行编造有了安全出口之后拒答率会上升但幻觉率会显著下降。你要做的是给这个安全出口配上业务兜底流程比如转人工或者异步查证。5. 奇招三RAG链路的降级和容错5.1 向量库故障时别让系统直接躺平RAG现在已经成了AI应用的主流形态但它把可用性问题放大了模型之外的向量库、Embedding接口、Rerank服务都成了关键依赖。很多RAG系统是这样设计的检索不到内容模型就直接编。检索链路一断错误答案就满天飞。我见过最夸张的情况是向量库超时系统把异常吞掉返回一个“空上下文”模型就凭记忆发挥结果用户被一本正经地误导。我对RAG链路的要求是“宁可回答不知道也不允许无中生有”。向量库不可用时正确的降级顺序是先从本地倒排索引BM25走关键词召回虽然语义匹配差一点但至少基于真实语料关键词也没有就让模型明确说“知识库暂不可用我无法回答”。同时把降级原因透出到日志和用户侧文案让用户知道不是模型傻了而是知识系统暂时不可用。这里的取舍逻辑很多人想不通降级到BM25效果差为什么不直接让最强模型自由发挥因为自由发挥的结果不可控而真实业务宁可接受“低配但可靠”也不能接受“高配但乱说”。可用性不是模型多强而是行为可预期。5.2 检索质量的主动兜底RAG还有一个隐性可用性问题检索服务本身正常但召回的内容是错的、旧的、或者和问题无关。这种“健康的坏结果”传统监控永远发现不了。我的做法是加两道主动检测第一道是“检索结果与问题的相关性分”。Embedding计算的相关性分数可以做阈值初筛低于阈值就不注入上下文直接走拒答或澄清流程。第二道是“索引新鲜度”监控。很多项目改了文档库却忘了重建向量索引用户还在问半个月前的旧内容。这个问题可观测性上线之前极难发现只能靠业务投诉。我建议对索引同步任务单独建SLO比如“文档更新到可检索的最长延迟不超过10分钟”超时就要告警。另外Rerank模型也要有超时和降级。Rerank虽然能显著提升检索精度但它是一个额外的实时依赖。一旦Rerank服务变慢整个RAG链路就跟着变慢。我会给Rerank单独设一个较短的超时比如300毫秒超时就跳过Rerank直接用召回TopK并在上下文标记里注明“未经过精排”让模型在回答时适当降低肯定语气。这种细节看似不起眼却是线上可用性打磨的关键。6. 奇招四给AI系统设计新的可观测性指标6.1 从黄金指标到AI四件套传统四类黄金指标延迟、流量、错误、饱和度在AI系统里不够用因为“错误”的定义严重失真。一个模型返回200但内容答非所问传统指标完全无感。我在AI项目里额外盯四个指标无效回答率、幻觉率、重试挽救率、单次会话成本。无效回答率输出无法通过Schema校验或关键字段缺失的比例幻觉率抽样评估中答案包含关键事实错误的比例线上一般靠人工标注抽样离线评估集跑回归重试挽救率通过自动重试避免最终失败的比例这个指标能反映重试策略是否真的有效单次会话成本每个用户会话平均消耗多少Token和费用接近预算Boundary时触发降级。这四件套不是替代传统指标而是叠加在传统指标之上。传统指标保证“服务活着”四件套保证“活着还能干活”。6.2 把评估集变成线上监控的一部分应对“语义错误难发现”最有效的手段不是加更多日志而是维护一个高质量回归评估集。我会从历史Badcase里提炼一批典型问题比如“包含不存在条款”“输出JSON缺字段”“对敏感话题回答过于绝对”每个问题配上期望行为标准。每次Prompt模板、模型版本、检索策略变更都在这个评估集上跑一遍不达标就不准上线。这套做法跑顺之后线上问题少很多。还有一个衍生价值评估集本身就是Prompt调优的加速器不用每次都等用户投诉光跑测试就能发现自己改坏了什么。有条件的团队可以把评估结果接入发布流水线让“AI质量回归测试”和普通CI一样成为硬门槛。日志侧也要给每个请求打上“生成指纹”模型名称、Prompt模板版本、Temperature、TopP、模型输出、校验结果、重试次数、检索来源。这些字段平时可以不索引等线上出现Badcase再拉出来做归因没有指纹基本没法排查。我自己排查线上问题的第一步永远是按traceId把这条链路拉全看它路由到哪个模型、检索到哪些片段、最终通过哪层校验。链路可视化的优先级比炫酷的Dashboard高得多。7. 配额、成本与可用性被忽视的隐形炸弹7.1 Token与速率限制是硬性约束很多团队把可用性等同于“故障恢复”却忽略了配额其实是更常见的杀手。外部模型API几乎都有每分钟请求数RPM和每分钟Token数TPM限制超过就返回429。流量稍微一冲节流阀先把自己人限流了。更麻烦的是不同模型池的配额互相隔离你辛辛苦苦做了多模型冗余却忘了给每个模型池预留独立配额。我建议在网关层做“配额预检”每次请求路由前先看目标模型池当前剩余配额够不够不够就直接路由到其他池而不是等上游返回429再去切换。这里要用到令牌桶算法但额度判断不是动态的还要考虑请求峰值。比如某业务高峰每秒产生1万Token输出而模型池每分钟TPM上限只有30万留60%安全边际后实际单池只能撑300秒峰值。算清楚这个数才能决定要不要切成多池分摊。7.2 预算耗尽时的动态降级策略比限流更隐蔽的是预算耗尽。尤其是创业团队账户余额打到一个阈值整个服务立刻停摆比服务器宕机还惨。这种故障是慢性的月初一切正常月底偷偷崩溃。我之前吃过一次亏月底模型账户余额不足上游直接返回403用户端全是“系统开小差”而我们的监控完全没把“账户余额”当成指标。现在我会把预算也纳入可用性设计日预算使用率超过70%自动把非核心流量切到轻量模型超过90%核心场景保留高性能模型非核心场景直接降级为缓存答案余额不足时提前告警并给付款流程留出至少48小时缓冲。这听起来像是成本管理但本质上就是可用性管理——预算耗尽导致的不可用和机房断电导致的不可用用户体验完全一样。这条经验后来也反哺了容量规划给模型网关做容量压测时不再只压“QPS能到多少”而是压“在Token成本预算范围内QPS能到多少”。两个数字之间的差值就是可用性的安全垫。8. 落地优先级与一次故障演练复盘8.1 按投入产出比排出实施顺序可用性设计条目很多不能一口吃成胖子。我的建议分三步走。第一步先把“基础韧性”补齐超时重试改造、多模型路由、输出Schema校验、兜底话术链。这几件事投入不大但能消除大部分“模型服务抖动导致业务雪崩”的问题。第二步再做“质量可见”上线无效回答率、成本、配额监控建立回归评估集给模型调用打指纹。没有这一步你连系统是不是真的可用都不知道后续优化都是盲人摸象。第三步才是“主动容错”做RAG降级、幻觉自检、预算动态降级、定期故障演练。这些功能复杂度高要等前两步稳定了再上否则一次引入了太多变量出问题都定位不了。8.2 一次模拟上游故障的演练最后分享一次我们内部做的故障演练。场景设定是主模型供应商全链路故障5分钟备选模型池配额只剩30%。我们把流量逐渐切到备选池同时观察重试挽救率、TTFT、无效回答率。演练中暴露了三个问题第一备选模型对复杂JSON Schema的遵循率明显低于主模型无效回答率从2%飙到18%触发了一批自动重试延迟骤增第二语义缓存命中率低于预期因为很多用户问题表述不同但语义相同缓存键却只用了文本Hash第三降级文案在用户端显示得不够明确用户一直重试反而加重了上游压力。这次演练后我们做了三处修改一是给备选模型另外准备一套更宽松的Prompt模板不盲目复用主模型的提示词二是把语义缓存键改成Embedding向量相似度匹配而不再是原始文本哈希三是降级时在客户端直接禁用重试按钮引导用户稍后再来。下一次再做同样的演练无效回答率降到了4%TTFT基本平稳。这个结果让我确信可用性不是靠运气而是靠提前把每条降级路径都跑过一遍。8.3 一点个人体会做AI应用架构这几年我最大的感受是传统可用性设计是“防御外部故障”而AI系统的可用性设计更像“管理不确定性”。模型会变、数据会漂移、供应商会抖动、输出会胡说你没办法消灭这些不确定性只能通过分层缓冲、主动校验、预算控制把不确定性对用户体验的影响压到最低。每个奇招拆开看都不算高深但组合在一起才是AI系统真正“扛得住事”的底气。希望你不用像我一样非等一次凌晨的事故才把这些道理挨个踩明白。
返回列表