欢迎光临
我们一直在努力

前端实现 AI 回复的流式数据(逐字展示效果)

前端实现 AI 回复的流式数据(逐字展示效果)

📌 点赞收藏关注不迷路!
你在使用 ChatGPT 时,一定见过这样一个“人性化”的体验:

机器人一边思考一边“打字”回应你,句子一点一点出现。

这其实就是“流式响应数据处理(Streaming Text Response)”的实现效果。

本文将带你深入理解并手把手实现一个流式 AI 回复前端组件👇


🚀 一、什么是“流式响应”?它怎么实现?

在标准 HTTP 请求中,前端只有等服务端全部返回之后,才能使用数据。

而“流式响应”则是服务端一边处理一边返回数据片段(chunk),前端边接收边显示。

它常用的技术有:

技术原理使用场景
SSE Server-Sent Events,基于 HTTP 日志/进度/通知推送
fetch stream Fetch 的 Response.body 是流 ChatGPT 类对话流输出
WebSocket 全双工持久连接 双向通信场景

🧪 二、实现流式回复的前端核心逻辑(Fetch 版)

async function streamAIAnswer(prompt: string, onData: (text: string) => void) {
const res = await fetch('/api/ai-stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt })
})

const reader = res.body?.getReader()
const decoder = new TextDecoder('utf-8')

if (!reader) return

let done = false
while (!done) {
const { value, done: doneReading } = await reader.read()
done = doneReading
const chunk = decoder.decode(value)
onData(chunk) // 每读取一块数据就触发回调
}
}

📌 onData(chunk) 每次都返回一段字符,前端可以累加拼接实现“逐字显示”。


💡 三、封装 Vue Hook:useAIStream()

// useAIStream.ts
import { ref } from 'vue'

export function useAIStream() {
const answer = ref('')
const loading = ref(false)

const ask = async (prompt: string) => {
answer.value = ''
loading.value = true

const res = await fetch('/api/ai-stream', {
method: 'POST',
body: JSON.stringify({ prompt }),
headers: { 'Content-Type': 'application/json' }
})

const reader = res.body?.getReader()
const decoder = new TextDecoder()

if (!reader) return

let done = false
while (!done) {
const { value, done: doneReading } = await reader.read()
done = doneReading
const text = decoder.decode(value)
answer.value += text
}

loading.value = false
}

return {
answer,
loading,
ask
}
}


🎨 四、Vue 实战组件展示(Chat AI)

<template>
<div>
<textarea v-model="prompt" placeholder="请输入问题" />
<button @click="ask(prompt)" :disabled="loading">发送</button>

<div class="answer-box">
<p v-if="loading">AI 正在思考…</p>
<p v-else>{{ answer }}</p>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useAIStream } from './composables/useAIStream'

const prompt = ref('')
const { answer, loading, ask } = useAIStream()
</script>

样式可以配个逐字动画或滚动条提升体验。


🌐 五、服务端示例(Node + OpenAI)

✅ Node 示例(Express)

import express from 'express'
import { OpenAI } from 'openai'

const app = express()
const openai = new OpenAI({ apiKey: 'YOUR_KEY' })

app.use(express.json())

app.post('/api/ai-stream', async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')

const completion = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: req.body.prompt }],
stream: true
})

for await (const chunk of completion) {
const text = chunk.choices?.[0]?.delta?.content || ''
res.write(text)
}

res.end()
})

📌 本质:后端使用 stream: true + for-await 输出,前端 fetch 逐字读取。


🧠 六、可选增强功能

1. 添加 loading 动画

<p v-if="loading"><span class="typing-cursor"></span> AI 正在回复中…</p>

2. 支持停止中断(AbortController)

const controller = new AbortController()
fetch('/api/ai-stream', { signal: controller.signal })
// 在需要中断时 controller.abort()

3. 自动滚动到最新内容

nextTick(() => {
answerBox.value?.scrollIntoView({ behavior: 'smooth' })
})


✅ 最后说一句

实现一个“打字机式的 AI 回复”,只需要一个 fetch + reader.read() 的小技巧。

相比 WebSocket,它更轻更快更稳,非常适合对接 OpenAI / Claude / 自定义推理服务的文本输出。

如果你觉得本文对你有帮助,记得点个 点赞 + 收藏 + 关注!

赞(0)
未经允许不得转载:171主机测评 » 前端实现 AI 回复的流式数据(逐字展示效果)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址