Vue 3 实现 AI 流式输出(下篇):解析二进制流与实时渲染

58 阅读2分钟

上篇我们搭建了基于 Vue 3 的交互界面,本篇将聚焦核心技术:如何接收并解析大模型的流式响应。这涉及浏览器底层的流处理能力、二进制数据解码,以及对不完整 JSON 片段的容错拼接。

发起流式请求

调用支持流式输出的大模型 API(如 DeepSeek)时,只需在请求体中设置 stream: true

const response = await fetch(endpoint, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    model: 'deepseek-chat',
    stream: true,
    messages: [{ role: 'user', content: question.value }]
  })
})

关键在于,此时 response.body 不再是一个完整的 JSON 对象,而是一个 ReadableStream——一个可被逐步读取的数据流。

读取二进制流

浏览器通过 getReader() 获取流的读取器,每次 read() 返回一个包含 value(Uint8Array 二进制数据)和 done(是否结束)的对象。

const reader = response.body.getReader();
const decoder = new TextDecoder();
let done = false;
while (!done) {
  const { value, done: doneReading } = await reader.read();
  done = doneReading;
  // ...
}

由于网络传输以二进制为单位,我们需要使用 TextDecoderUint8Array 解码为可读字符串。这是 HTML5 提供的标准 API,兼容性良好。

处理 SSE 格式的分块数据

主流 LLM 的流式接口通常遵循 Server-Sent Events (SSE) 协议:每条消息以 data: {...}\n\n 格式发送。但一次 read() 可能包含多个完整消息,也可能只包含半个 JSON 字符串。

因此,我们必须维护一个 buffer,用于暂存未解析完的片段:

let buffer = '';
const chunkValue = buffer + decoder.decode(value);
buffer = '';
const lines = chunkValue.split('\n')
  .filter(line => line.startsWith('data: '));

我们将当前块与缓冲区拼接,按行分割,并筛选出以 data: 开头的有效行。

安全解析 JSON 片段

对每一行 data: {...},我们尝试解析其后的 JSON 内容:

for (const line of lines) {
  const incoming = line.slice(6);
  if (incoming === '[DONE]') break;
  try {
    const data = JSON.parse(incoming);
    const delta = data.choices[0].delta.content;
    if (delta) content.value += delta;
  } catch (err) {
    buffer += `data: ${incoming}`;
  }
}

若解析失败(说明 JSON 不完整),则将该行重新放回 buffer,等待下一次读取补全。这种“试错+回退”机制,确保了即使在网络抖动或分块不均的情况下,也能正确拼接出完整内容。

非流式模式的兼容处理

为便于对比,我们保留非流式选项:

if (!stream.value) {
  const data = await response.json();
  content.value = data.choices[0].message.content;
}

这展示了同一接口在不同模式下的处理差异:流式注重增量更新,非流式追求一次性获取。两者共存,方便调试与体验对比。

总结

通过结合 Vue 3 的响应式系统与浏览器原生的流处理能力,我们成功实现了一个支持 AI 流式输出的前端应用。整个过程无需第三方库,仅依赖标准 Web API,体现了现代浏览器的强大能力。

更重要的是,这种实现方式具有普适性——无论是 OpenAI、DeepSeek 还是其他兼容 SSE 的 LLM 接口,只需调整字段路径,即可无缝接入。掌握这一模式,意味着你已具备构建下一代智能交互界面的核心技能。