从零开始构建 LLM 流式输出:让你的 AI 聊天像打字机一样丝滑
一、痛点:用户等不起
使用过早期 AI 产品的同学一定有过这种体验:问一个问题,页面卡住,几十秒后"啪"地一下甩出一大段文字。这种一次性返回的模式有三个致命问题:

- 等待焦虑:用户盯着空白屏幕,不知道 AI 是在思考还是已经卡死,也不知道还要等多久;
- 首字时间(TTFB)过长:必须等整个推理过程全部完成后才能看到第一个字;
- 体验割裂:生成结果一瞬间全量渲染,缺乏"AI 正在为你工作"的过程感。
对于复杂的推理计算(比如处理长文本、代码生成、多步推理),LLM 的耗时可能长达数十秒甚至数分钟。作为前端工程师,我们有责任把这段等待时间变成一个渐进式、可感知的交互过程——这就是流式输出(Streaming)的价值。
二、本质:从"一桶水"到"水龙头"
流式输出的核心思想非常朴素:
复制代码 传统方式:服务端生成完整回答 → 一次性返回 → 客户端渲染
流式方式:服务端每生成一个 token → 立即发送 → 客户端逐个拼接渲染
打个比方:传统方式就像等一桶水接满后一次性提走,而流式输出就像拧开水龙头,水(token)源源不断地流向客户端。
在技术实现上,这要求服务端和客户端达成一个共同约定——请求体中设置 stream: true。服务端收到这个标记后,不再等所有 token 生成完毕才返回一个完整的 JSON,而是每生成一个 token 就立即以 SSE(Server-Sent Events)或分块传输的方式推送给客户端。
三、客户端如何消费流式数据?
服务端返回的不再是一个 JSON 对象,而是一个 ReadableStream(可读流)。客户端需要:
- 获取 Reader:通过
response.body.getReader()拿到流的读取器; - 逐块解码:用
TextDecoder将二进制数据解码为文本; - 解析 SSE 格式:流式数据通常是
data: {...}nn的格式,需要逐行解析; - 拼接渲染:每解析出一个 token,就追加到界面上。
整个过程可以用一个 while 循环来完成——只要流没有关闭(done !== true),就不停地读取、解码、拼接、渲染,直到收到 [DONE] 标记。
四、用 Vue 3 实战:搭建 DeepSeek 流式聊天
下面我们基于 Vite + Vue 3 搭建一个最小化的流式输出 Demo,对接 DeepSeek API。
4.1 项目结构
复制代码stream-demo/
├── index.html # 入口 HTML,提供 #app 挂载点
├── src/
│ ├── main.js # Vue 应用初始化
│ ├── App.vue # 核心组件(聊天界面 + 流式逻辑)
│ └── style.css # 全局样式
└── .env.local # 存放 VITE_DEEPSEEK_API_KEY
4.2 入口文件:index.html
复制代码<div id="app"></div>
<script type="module" src="/src/main.js"></script>
非常简单——一个 #app 挂载点,加上 ES Module 方式引入入口脚本。Vite 的开发服务器(默认 :5173)会将 / 映射到 index.html,之后完全由 Vue 接管 DOM。
4.3 应用初始化:main.js
复制代码import { createApp } from 'vue'
import App from './App.vue'createApp(App).mount('#app')
createApp 创建一个 Vue 应用实例,以 App.vue 作为根组件,挂载到 #app 节点上。这就是整个 Vue 应用的起点。
4.4 核心组件:App.vue
这是整个 Demo 的灵魂所在,我们拆成三部分来看。
Template:模板层
复制代码<template>
<div class="container">
<div>
<label>输入:</label>
<input type="text" class="input" v-model="question">
<button @click="update">提交</button>
</div>
<div class="output">
<input type="checkbox" v-model="stream" />
<label>Streaming</label>
<div>{{ content }}</div>
</div>
</div>
</template>
这里展示了 Vue 的两个核心能力:
v-model:双向数据绑定。表单输入是单向数据流的特例——用户输入需要回流到数据层,v-model让question变量和<input>的 value 始终保持同步。{{ }}插值表达式:将 script 中的数据响应式地渲染到页面上。content变化,页面自动更新,完全不需要手动操作 DOM。
Script:逻辑层
复制代码import { ref } from 'vue'const question = ref('讲一个关于中国龙的故事')
const stream = ref(false)
const content = ref('')const update = async () => {
if (!question.value) return
content.value = '思考中....' const response = await fetch('https://api.deepseek.com/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`
},
body: JSON.stringify({
model: 'deepseek-v4-flash',
messages: [{ role: 'user', content: question.value }],
stream: stream.value // 关键参数:是否开启流式
})
}) if (stream.value) {
// === 流式输出路径 ===
content.value = ''
const reader = response.body?.getReader()
const decoder = new TextDecoder()
let done = false while (!done) {
const { value, done: doneReading } = await reader.read()
done = doneReading
if (value) {
// 解码二进制 → 文本 → 解析 SSE → 拼接 token
const chunk = decoder.decode(value, { stream: true })
// 解析 data: {...} 行,提取 delta content
// 追加到 content.value
}
}
} else {
// === 非流式路径 ===
const data = await response.json()
content.value = data.choices[0].message.content
}
}
这里的核心设计是:
-
ref()响应式数据:question、stream、content都是响应式状态。Vue 3 的ref包装后,.value的修改会自动触发模板重新渲染。这就是数据驱动视图——你只需要关心数据,不用碰 DOM。 -
API Key 管理:通过
import.meta.env.VITE_DEEPSEEK_API_KEY读取环境变量。Vite 会自动加载.env.local中以VITE_为前缀的变量。把 Key 放在环境变量里,既安全又方便切换。 -
stream参数分叉:代码通过if (stream.value)优雅地分出了两条路径——勾选 Streaming 走流式读取,不勾选走传统response.json()一次性解析。这让 Demo 可以直观对比两种模式。 -
ReadableStream 消费:
response.body.getReader()返回一个ReadableStreamDefaultReader,reader.read()每次返回{ value: Uint8Array, done: boolean }。循环读取直到done === true。
Style:样式层
样式层保持了极简风格,但在实际 AI 产品中,这里大有可为——打字机光标动画、逐字淡入效果、Markdown 实时渲染……这些都是在流式输出的基础上叠加的体验增强。
五、Vue 组件化思想:乐高积木
整个 Demo 体现了一个重要的现代前端理念——组件化。
一个 .vue 文件就是一个组件,它将 Template(结构) + Script(逻辑) + Style(样式) 封装在一起,形成一个独立、可复用、可维护的业务单元。
想象一下 Facebook 的网页由超过一万个组件构成——就像用乐高积木搭城堡,每个积木块独立且可替换,但组合起来就能构建出复杂的应用界面。
六、总结:流式输出 ≠ 技术炫技,是体验刚需
流式输出看起来只是"一个字一个字蹦出来",但它其实解决了 AI 产品中一个本质的用户体验问题——在不可消除的延迟面前,让用户感知到进展,而不是在空白中焦虑。
实现上,它的技术链路是:
复制代码服务端 stream:true → ReadableStream → getReader() → TextDecoder → SSE 解析 → 逐 token 拼接渲染
前端工程师掌握流式输出,几乎是做 LLM 应用的必修课,也是面试中的高频考点。搞懂了它,你就抓住了 AI 产品用户体验的第一把钥匙。
本文 Demo 源码基于 Vite + Vue 3 + DeepSeek API,完整实现了从 API 调用、流式读取、到界面响应式渲染的全链路。希望这篇文章能帮助你理解流式输出的原理和实现方式,也欢迎在评论区交流你的 AI 产品开发经验!
-
07.21
异人之下手游安卓手机版隐藏宝箱位置分享 异人之下手游安卓手机版隐藏宝箱位置在哪
-
07.21
遗忘之海怪异的臭味教程 遗忘之海怪异的臭味如何完成
-
07.21
酋长你别跑魔女有哪些技能-酋长你别跑魔女技能是什么
-
07.21
遗忘之海噩梦深浅普通难度怎么打 遗忘之海噩梦深潜普通难度通关攻略分享
-
07.21
遗忘之海统御巨像打法分享 遗忘之海统御巨像怎么打
-
07.21
梦幻西游如何退出帮派2026版
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏