流式回答需要一个提交点
第一段文字出现,不代表一次回答已经完成。把生成中的预览与可追问的历史分开,才能处理断线、截断、引用检查与重试。
向下阅读
流式回答最直观的收益,是让用户尽早看见文字。等待不再只有一个旋转图标,而是逐步变成可以阅读的内容。但如果只把返回的文字不断拼到聊天记录中,我们也会提前把一个尚未完成的结果当成事实保存下来。
一次回答可能在中途断线,可能因为长度限制而截断,也可能在最后发现来源编号无效。已经显示出来的内容,和已经通过检查、能够继续追问的内容,需要有不同的状态。
看见结果与提交结果
可以把生成中的回答理解成预览。用户已经能够读它,但系统仍在接收剩余内容,也还没有完成全部检查。最终回答则意味着这次请求已经正常结束,并满足当前产品对结果的基本约束。
这不是单纯的变量命名。若临时文字已经写入正式历史,下一轮模型就可能把半段回答当成上下文。它原本缺少结论、引用或限定条件,进入下一轮之后却失去了“未完成”的标记,错误因而被沿用。
Field Agent 的处理是先更新临时回答,收到正常完成结果后,再把问题、最终回答和来源卡片一起写入当前会话。这个提交点让历史记录具有更明确的含义:里面保存的是已完成的对话,而不是所有曾经出现过的字符。
文字不是按句子到达的
网络分块与语言结构没有一一对应关系。一个中文字符的编码可能分在两段数据里,一条事件也可能跨越多次读取。收到一块数据就立即解析为完整消息,很容易产生偶发错误,而这种错误在网络顺畅时未必出现。
因此,读取流程需要分别处理字节解码、事件边界和文字内容。字节通过持续解码器转换,尚未结束的事件留在缓冲区,确认消息完整之后才读取增量文本。每一层都只对自己真正掌握的边界作判断。
界面也有类似的小边界。来源标识可能先收到左括号,再收到数字,最后才收到右括号。如果正文希望隐藏标识,只移除完整编号就会让未完成的片段短暂闪现。生成中的显示规则,需要考虑字符还没有收齐的时刻。
完成信号承担什么责任
把连接关闭当成成功结束,会掩盖中断。连接可能因为网络错误关闭,也可能在服务商尚未发出正常结束信号时消失。客户端应该知道自己等的是完整结果,而不是“已经没有更多数据”。
在本站的实现里,额度、文字增量、完成和错误是不同事件。额度可以提前更新,文字用于预览,完成事件携带最终回答和来源。模型的正常终止、回答长度与引用编号都参与结果判断;客户端还会检查有没有收到最终结果。
来源编号检查也有边界。它能够确认编号属于本次检索,却不能自动证明每一句话都被资料支持。把这两种保证区分清楚,既有利于继续改进回答质量,也避免把技术检查描述成过强的可信承诺。
失败之后留住什么
临时回答失败时,用户的问题仍然有价值。保留问题,可以让重试成为一个明确动作;若输入被清空,用户就需要先重写问题,再决定是否继续。
移除未完成的回答并显示错误,是 Field Agent 当前采用的选择。其他产品也可以保留半段内容,但应明确标记未完成,并决定它能不能进入后续上下文。没有一种界面策略适用于所有任务,关键是状态与实际保证一致。
流式交互并没有减少对完成条件的需求,反而让完成条件更重要。因为用户会在结果仍然变化时开始阅读,系统必须清楚说明哪些内容正在形成,哪些内容已经能够作为下一步的依据。