整体对话稳定性专题总览

AI Chat 的稳定性问题,通常不是“模型会不会回答”这么简单。

真实用户使用时,会遇到网络抖动、流式输出中断、接口超时、重复点击发送、用户中途停止、浏览器刷新、服务端重试、消息顺序错乱、工具调用失败、模型供应商不可用等问题。每一种失败都可能让对话状态变得不可信:前端显示了一半答案,后端却写入完整答案;用户点了重试,系统生成了两条回复;模型已经调用工具,页面却还停在 loading。

整体对话稳定性的目标,不是让系统永远不失败,而是让失败可见、可恢复、可降级、可复盘。

场景

先看一个具体场景。

在一个面向企业用户的 AI 客服助手里,用户输入:

帮我查一下上周企业版发票为什么还没开,并给客户写一段解释。

系统需要完成几件事:

  • 前端立即显示用户消息,并展示模型正在流式生成。
  • 后端调用模型理解问题,必要时查询订单、发票和客户信息。
  • 模型边生成边返回,让用户不用等完整答案。
  • 如果工具或模型超时,系统要说明失败原因,并给出重试或转人工入口。
  • 如果用户点击停止,系统要保留已生成内容,但不能把未完成答案当成成功结果。
  • 如果用户刷新页面,历史消息和生成状态要能恢复到一致状态。

这个场景里,稳定性问题来自多层链路。

如果没有稳定性设计,用户看到的可能是:

  • 助手一直转圈,不知道是模型慢还是系统坏了。
  • 答案输出到一半停住,没有失败提示。
  • 点击重试后出现两条内容相近但互相矛盾的回答。
  • 用户点了停止,后台仍然继续扣费生成。
  • 页面刷新后,前端显示失败,历史记录里却出现成功回答。
  • fallback 模型给出降级答案,但没有标记能力边界。

这些问题不是 prompt 能解决的。它们属于产品状态、接口协议、后端任务、持久化和观测体系共同承担的工程问题。

问题类型

整体对话稳定性可以拆成五类常见问题。

问题类型常见表现主要影响
流式中断SSE 断开、WebSocket 断连、浏览器切后台、代理超时用户只看到半截答案,不知道是否可用
超时模型慢、工具慢、网关超时、函数执行超限用户等待过久,后端任务状态不确定
重试用户重复点击、前端自动重试、后端重放请求生成重复消息、重复工具调用、成本上升
状态错乱前后端消息状态不一致、顺序错、临时 ID 未替换UI 显示成功但后端失败,或反过来
fallback主模型失败、工具不可用、上下文过长、限流需要降级回答、转人工或延后处理

这些问题和 AI 任务类型也有关。

  • 生成任务最容易受流式中断影响,因为输出是逐步出现的。
  • 工具调用任务最容易受超时和幂等影响,因为工具可能有副作用。
  • 多轮对话最容易状态错乱,因为每条消息都依赖前文顺序。
  • 高风险业务最需要 fallback,因为不能让失败变成静默错误。
  • 需要引用、结构化输出或写库的场景,重试必须更谨慎。

模型适合处理的部分是:在可用上下文内生成回答、解释降级原因、根据已知信息给出下一步建议。

程序应该处理的部分是:请求 ID、消息状态机、超时、取消、重试、幂等、持久化、fallback 路由、日志和告警。

必须保留人工确认的部分是:高风险工具调用、不可逆操作、对外承诺、涉及权益的降级处理,以及多次失败后的人工接管。

收益和成本判断

对话稳定性的收益,不只是“少报错”。

  • 用户知道系统正在做什么,等待焦虑下降。
  • 失败后可以继续,而不是整轮对话报废。
  • 后端可以避免重复生成、重复扣费和重复执行工具。
  • 产品可以定位问题是模型、工具、网络、前端还是存储。
  • 运营和客服能接住失败会话,而不是让用户自己猜。
  • 团队能通过日志回放复盘线上事故。

但稳定性也有成本:

  • 前端需要更细的消息状态和交互设计。
  • 后端需要任务状态、取消、重试、幂等和持久化。
  • fallback 会增加模型路由、质量控制和产品文案成本。
  • 观测系统需要记录 trace、错误类型、耗时和供应商状态。
  • 过度重试会增加成本和延迟,甚至放大故障。

低风险场景不需要一开始就做完整可靠性平台。例如内部写作助手,输出只给员工编辑,失败后重新生成即可。这时简单的 loading、失败提示和手动重试就够了。

一旦对话进入客户服务、订单处理、工作流自动化、知识库问答、代码修改或数据分析,稳定性就不能只靠“刷新页面再试”。系统必须明确:这条消息现在是什么状态,失败在哪里,能不能重试,重试会不会重复执行副作用,降级后用户看到的内容是否可信。

方案阶梯

对话稳定性可以从轻到重逐级建设。

第一层是基础 UI 状态。至少让用户知道正在生成、失败了、可以重试或停止。

第二层是消息状态机。不要只有 loading: true。一条 assistant 消息可能处于 queued、streaming、completed、failed、stopped、retrying、fallback 等状态。

第三层是请求和消息 ID。每次发送、重试、停止都要能关联到同一条用户消息和同一轮 assistant 响应,避免重复插入和顺序错乱。

第四层是超时和取消。前端停止不等于后端停止,后端超时也不等于模型供应商已经取消。需要明确取消信号和最终状态。

第五层是有限重试。只有可重试错误才重试,例如网络抖动、429、5xx、临时超时。业务校验失败、权限失败、用户输入不足,不应该盲目重试。

第六层是幂等和持久化。对话消息、工具调用和扣费记录都要能防重复。工具有副作用时,必须用 idempotency key 或事务边界保护。

第七层是 fallback 路由。主模型失败时可以换轻量模型、关闭工具、返回部分结果、进入人工队列或提示用户稍后再试。

第八层是观测和回放。记录每轮对话的状态流转、模型、耗时、错误、重试次数、fallback 路径和用户操作,才能持续改进。

什么时候简单策略足够

以下情况通常可以先用简单策略:

  • 输出只是草稿,用户会编辑。
  • 没有工具调用、写库或外部副作用。
  • 对话轮次短,刷新后丢失也能接受。
  • 用户量小,失败可以人工反馈。
  • 重试只会重新生成文本,不会改变业务状态。
  • 失败代价是体验下降,而不是权益损失。

这时可以做到:前端显示 streaming、failed、retry;后端设置合理超时;失败时保留用户输入;重试生成一条新回答或覆盖原失败回答;记录基础错误日志。

什么时候需要工程方案

以下情况应该升级到完整工程方案:

  • 回复会进入客户沟通、工单、审批或业务记录。
  • 对话中会调用工具、查询私有数据或执行动作。
  • 用户会多次重试、停止、刷新或跨设备继续会话。
  • 需要区分“用户取消”“模型失败”“工具失败”“系统超时”。
  • 主模型不可用时必须提供降级服务。
  • 需要统计成功率、失败率、超时率、重试率和 fallback 质量。
  • 失败可能导致重复扣费、重复发消息、重复创建工单或错误承诺。

这时要把 AI Chat 当成一个有状态的分布式流程,而不是一个单次 HTTP 请求。

方案选型表

场景条件推荐方案不推荐方案判断理由额外成本
低风险草稿生成loading / failed / retry完整任务队列和复杂 fallback失败后重新生成即可少量前端状态
流式输出经常中断消息状态机 + partial 内容保存把半截答案当成功用户需要知道内容是否完整状态字段、恢复逻辑
用户可能重复点击发送requestId + messageId 去重只靠按钮禁用网络慢时按钮状态不可靠ID 设计、后端去重
工具调用可能有副作用幂等 key + 工具调用记录失败后直接整轮重试重试可能重复执行动作工具封装、事务和审计
模型或工具偶发超时错误分类 + 有限重试 + 退避无限自动重试要控制成本和用户等待retry 策略、超时预算
主模型不可用但业务要继续fallback 模型 / 转人工 / 稍后处理静默失败或假装成功降级比错误成功更可靠路由、提示、质量验证
高并发生产系统队列 + 状态持久化 + trace单请求内完成所有事需要恢复、排查和限流基础设施和观测

反模式

第一种反模式:把流式输出当成普通字符串追加。

流式输出不是“多次 setState”这么简单。每个 chunk 都应该属于某一条 assistant 消息、某一次响应、某个状态。否则重试或并发时,chunk 可能追加到错误消息上。

第二种反模式:只有 loadingerror 两种状态。

AI Chat 至少要区分 streaming、failed、stopped、retrying、completed。否则用户取消、模型失败和网络断开都会变成同一种“失败”,后续无法恢复。

第三种反模式:失败后直接重新发送整段历史。

如果上一轮已经调用工具或写入状态,整段重试可能重复执行副作用。重试应该基于明确的响应 ID、失败阶段和幂等策略。

第四种反模式:前端停止按钮只停止 UI。

如果后端仍继续生成,用户以为已经取消,系统却继续消耗 token,甚至把结果写入历史。停止需要有取消信号和最终状态。

第五种反模式:fallback 不告诉用户。

降级模型、关闭工具或返回部分结果时,如果仍用正常成功口吻,用户会误以为答案具备同等可信度。fallback 应该明确能力边界。

第六种反模式:没有 trace,只看错误率。

对话失败常常跨越前端、网关、模型、工具和数据库。只有错误率无法定位问题,必须记录状态流转和关键耗时。

工程清单

  • 场景边界:对话是草稿生成、知识问答、客户服务,还是工具执行。
  • 状态模型:用户消息和 assistant 消息有哪些状态,状态如何流转。
  • 流式协议:chunk、完成、错误、取消、fallback 是否有明确事件类型。
  • 超时策略:前端、网关、后端、模型和工具各自的超时预算是否一致。
  • 重试策略:哪些错误可重试,最大次数、退避和总时长是多少。
  • 幂等设计:发送、重试、工具调用、写库和扣费是否有 idempotency key。
  • 持久化:partial、failed、stopped、completed 是否都能被恢复和审计。
  • fallback:主模型、工具、上下文、供应商失败时分别如何降级。
  • 用户体验:失败原因、重试入口、停止入口和人工接管是否清晰。
  • 可观测性:是否记录 traceId、messageId、requestId、模型、耗时、错误类型。
  • 成本控制:重试和 fallback 是否有成本上限和限流策略。
  • 回放复盘:线上失败能否按一次对话完整重建状态流转。

小结

整体对话稳定性不是某一个 SDK 参数,而是一套围绕“消息状态”的产品和工程设计。

低风险草稿类功能,可以先用基础状态、手动重试和简单失败提示。只要涉及流式输出、工具调用、业务记录、多轮恢复或 fallback,就需要把消息、请求、工具和模型调用都纳入可追踪的状态流转。

这个专题的后两篇会继续展开:

  • 前端如何设计 AI Chat 的 retry、stop、failed、streaming 状态。
  • 后端如何做 timeout、retry、fallback、幂等和降级。