流式协议与会话状态
把聊天理解为“事件驱动的运行记录”,而非不断拼接的一条字符串。网络负责运送字节,协议负责划分事件,运行状态决定内容归属,界面负责按用户能阅读的速度呈现。四层拥有不同的完成条件,任何一层结束都不能替其他层宣布成功。
核心模型
把聊天理解为“事件驱动的运行记录”,而非不断拼接的一条字符串。网络负责运送字节,协议负责划分事件,运行状态决定内容归属,界面负责按用户能阅读的速度呈现。四层拥有不同的完成条件,任何一层结束都不能替其他层宣布成功。
原理与机制
从字节恢复完整事件
一次 read 可能切断中文字符、SSE 行或 JSON,也可能同时带来多个事件。因此先流式解码 UTF-8,再处理 LF、CR、CRLF 和空行边界,合并同一事件的多行 data,最后按应用契约解析 JSON。注释心跳不算正文,结束标记也不属于 SSE 标准。读取前检查 HTTP 状态、类型和 body;EOF 前缺少结束空行的半条事件必须丢弃,即使其 data 恰好可解析。已确认正文可以保留,但运行应标为中断,直到取得可信终态。
让每次状态写入都有归属
会话、分支、消息和生成尝试分别需要身份;messageId 与 parentId 描述历史关系,runId 描述一次尝试。编辑祖先问题应建立新分支,多设备写入通过版本检查处理冲突。AbortController 只能尽力取消传输,已经排队的 delta、error、finally 仍可能执行,所以每次写 UI 前还要检查本分支的运行版本。取消时先失效版本再 abort,可避免同步监听器重入破坏新状态。切换显示分支不必取消所有后台任务,清理范围须明确。
把恢复与再次执行分开
断网后首先用 runId 查询原任务,并从最后确认序号重放或获取快照;重新创建生成是另一项操作。客户端忽略重放,发现序号缺口就恢复,不能跳过缺口继续拼接。快照必须携带身份、覆盖序号和状态,原子替换文本与游标,再应用其后的事件。创建任务及副作用工具还需服务端持久化幂等记录和并发唯一约束。超时代表结果未知;上游缺乏查询或幂等能力时,应核对结果,不能保证盲重试不会重复执行或计费。
控制渲染频率并保护阅读位置
增量先进入有容量上限的分块缓冲,按帧或短窗口合并为快照,只更新活跃消息。每个 token 都 join 全文并重解析 Markdown,会产生随长度放大的累计工作;高亮和表格可延后处理,净化规则不能放松。用户向上阅读或选中文字时暂停跟随,保留锚点并提示新内容。视觉更新与读屏播报分离,用礼貌状态区按句段或阶段提示,不反复朗读全篇。窗口化不能移除正在聚焦的节点;本地背压也不保证远端立即停算。
把草稿转为可提交结果
结构化流可以展示字段草稿,但提交必须等待完整终态、排除拒绝,并通过 schema、业务校验和必要确认。合法字符串仍可能表示不存在的日期,半个 JSON 不能靠补括号取得执行资格。用户改过的字段通过 dirty 标记与版本保留,后续模型值只能作为候选差异。上下文摘要同样是有损派生物;会话删除和重新生成不能撤销已发送邮件等现实动作,执行回执应独立保留并按目的限制访问和保存期限。
最小示例
javascript每个会话分支各建一个 gate,正文、错误和结束状态都走 commit。write 必须同步、短小;异步计算结束后再调用 commit,不能把 async 回调放进去。示例验证本地写入归属,不提供服务端取消、持久化幂等或事务隔离。
核验:Node v24.19.0:旧运行不回写、最新回写、同步abort重入及取消后禁写断言通过;未测试SSE解析或服务端恢复。
边界与取舍
边界
- SSE 的 Last-Event-ID 只是恢复线索;服务端必须实际保存可重放事件或快照。
- 缓冲上限需配合暂停、持久化或显式失败;静默丢字与无限增长都不可取。
- 普通浏览器埋点只能近似可见时间,EOF、JSON.parse 成功和用户批准是不同证据。
取舍
- 批处理降低主线程压力,但窗口过大会削弱流式反馈,应联合测量首字、输入响应和峰值内存。
- 事件重放恢复细,成本较高;只存最终快照更简单,但中途只能展示待完成状态。
口述示范
我先按协议恢复事件,再按分支与 run 校验状态归属;取消、恢复和重新生成各有契约。正文批量呈现,读屏与滚动尊重用户。只有可信终态和校验通过后,生成草稿才能进入提交。
章节练习
参考来源与核验边界
- WHATWG HTML Server-sent events · 核验 2026-10-04
- OpenAI Background mode · 核验 2026-10-04
- OpenAI Structured model outputs · 核验 2026-10-04
- OpenAI Conversation state · 核验 2026-10-04
核验日期 2026-10-04。后台恢复参数、SDK 支持与数据保留依服务版本而变;不要照搬为所有 SSE 服务的默认能力。官方说明 previous_response_id 仍会计入链中历史输入 token,状态托管不代表上下文免费。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。