运行时与集成

Android LiteRT-LM 流式输出处理

流式输出是一系列事件,不保证每个片段都是完整且可直接展示为最终答案。

审核状态: 内容已校验;中文稿供用户审核 · 2026-10-03 · Fact IDs: LITERTLM-01, COVE-LIFECYCLE-01, LITERTLM-KOTLIN-ANDROID-2026-01

直接回答

流式输出是一串事件,不意味着每个片段都完整或适合直接显示为最终答案。LiteRT-LM Kotlin API 文档展示了从对话收集生成输出的方式,但应用仍负责线程、请求标识、界面状态、取消、解析和资源生命周期。初始化与推理应远离主线程;把有限事件传给 ViewModel 或 Repository;并区分部分文本、完成、错误和取消。 流式界面应有明确状态机:空闲、初始化、生成、收尾、完成、取消和失败。开始新请求时分配唯一请求 ID,并有意清空或保留旧结果。每个事件都要与当前 ID 比对,避免旧流的延迟片段覆盖新请求。重组只负责绘制状态,不应重新创建对话或重复订阅原生输出从而重复推理。 部分输出可能是未完成的句子、格式错误的 JSON、不完整工具提案,或后来被用户取消的敏感文字。应决定是立即展示片段、标作草稿还是等安全边界后再显示。若输出是结构化内容,不要对任意中间片段运行解析器或工具处理器;应等协议边界结束,严格解析并验证。停止操作在运行时支持时应传到实际协程和引擎取消路径。仅移除屏幕订阅不能证明原生生成停止。 各层应有明确所有权:推理协调器按库契约拥有引擎和对话;ViewModel 管理任务状态与活动 Job;UI 只负责渲染,不拥有原生资源。离开页面时,要决定生成继续还是取消。进程死亡后,进程内流已经消失,不能把加载转圈恢复成仍在运行。若需要恢复任务,应持久化任务输入与阶段标记,再重新初始化运行时,而不是序列化原生对话。 错误处理要保留阶段:模型初始化、对话创建、流式输出、结果校验、取消或关闭。流以错误结束时,不得把部分答复显示成成功。模型没有输出时应明确表示无结果,不要编造回退答案。除非用户主动选择支持导出,否则不要把敏感提示和响应写入日志。 测试固定提示样例,覆盖短输出、多事件输出、空输出、结构错误、事件间取消、首个请求未完成又开始第二个、旋转、导航、进程重建和关闭。记录事件顺序与最终状态。测试只证明准确模型、运行时和 UI 策略,不构成生成速度或质量基准。实施时使用应用自有状态机和请求 ID;在后台协程收集不可变事件;让 Compose 只渲染状态;将停止操作传给引擎所有者;只在完成边界校验最终结果;最后用确定样例验证每条事件序列。流式输出是生成之上的 UI 和生命周期契约,不证明 Cove 某个公开版本支持它,也不表示所有运行时的取消行为相同。

首个输出流未结束时用户又提交第二个提示

Android 用户提交问题并看到部分文本,完成前更改请求并再次点击生成。此时旧流又发出文本,新请求已经开始。

决策

为请求分配唯一身份,决定旧任务是否取消,并丢弃旧事件,不能把两个流合并成一个答案。

预期结果

页面保持单一连贯状态,不会把中断或过期的部分响应标为新请求的最终结果。

需要收集的证据

只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:

  • 请求 ID 与事件顺序
  • 部分、完成、错误和取消状态
  • 停止与关闭后的资源记录

只有记录了模型身份、构建配置、实际后端、任务样例和失败情况,运行时比较才可复核。

实施流程

  1. 定义事件与请求身份. 将初始化、部分输出、完成、取消和失败表示成不同不可变事件,并绑定一个请求 ID。新请求到达时明确决定旧流的处理策略。
  2. 不要在 UI 重组中收集推理. 在应用协调器或 ViewModel 的任务作用域启动收集,发出状态更新,并确保 Compose 只绘制当前状态。重组不得重复创建引擎或再发起请求。
  3. 安全处理部分输出. 选择草稿展示策略;结构化数据要等待完整边界后再解析;运行时支持时传递取消;所有不属于当前请求 ID 的事件都应忽略。
  4. 覆盖生命周期和失败场景. 测试空流、解析错误、片段间停止、重叠请求、旋转、导航、进程死亡和关闭。确认 UI 最终状态与真实终止事件一致。

让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。

验收标准

  • 每个事件绑定单个请求 ID,旧片段无法更改当前结果。
  • 取消操作到达实际执行所有者,部分输出不会被报告为完成。
  • 初始化、生成、校验、取消和关闭错误可以分别识别。

决策对照表

维度选择或证据解读方式
等到完整后再展示只显示最终校验结果边界更简单,但不提供增量显示。
将部分输出标作草稿增量 UI 加明确草稿状态更快反馈,但需要处理旧事件和取消。
把每个片段当成最终结果没有边界或请求跟踪可能展示格式错误或过期文本并触发下游动作。

需要避免的失败模式

  • 把部分 JSON 当最终动作
  • 让 Composable 重组启动第二个流
  • 仅移除订阅就认为原生推理已停止

还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。

最小复现记录

层级记录内容
设备厂商、型号、芯片、内存档位、操作系统版本
软件应用版本和 Git 提交号
模型系列、变体、版本、格式、文件长度、摘要、量化方式
运行时名称、版本、请求后端及实际后端证据
工作负载样例版本、输入摘要、提示词摘要、输出策略
结果完成、失败、取消、回退及保护隐私的诊断信息

发布检查表

  • ☐ 主要搜索问题已回答,且没有未经支持的数字。
  • ☐ 所有模型文件和运行时版本均已固定。
  • ☐ 代表性任务和失败处理策略均有说明。
  • ☐ 生命周期、取消、清理和回退均已测试。
  • ☐ 用户内容与网络边界均有说明。
  • ☐ 结论只适用于被记录的配置。
  • ☐ 新增测试结果时链接到原始方法或证据。

来源与相关证据

中文部署与排错专题见。奇连 AI 端侧专题。

常见问题

离开页面会停止 LiteRT-LM 输出流吗?

不一定。移除 UI 订阅后,运行时任务仍可能继续。应将取消传到任务所有者,并按 API 契约验证原生工作确实结束,同时忽略过期请求片段。

可以从部分片段解析并执行函数调用吗?

不要执行中间片段。应等待文档定义的完整边界,解析完整结构,完成校验和宿主授权后再运行;不完整流要作为未完成状态处理。

流式输出会让模型回答质量更好吗?

流式只改变输出传递方式,并不代表答案正确。质量或速度结论需要独立任务样例、验收规则和可复核记录支持。