要实现通过 API 将流式内容输出到前端,可以采用以下技术方案(以 Python 后端 + 前端 JavaScript 为例):

方案一:使用 Server-Sent Events (SSE)

这是浏览器原生支持的流式传输方案,推荐首选

# Flask 示例
from flask import Response, stream_with_context @app.route('/stream')
def stream_data():
def generate():
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
stream=True
) for chunk in response:
if chunk.choices:
content = chunk.choices[0].delta.content or ""
# SSE 格式要求 data: 前缀和双换行符
yield f"data: {json.dumps({'content': content})}\n\n" return Response(stream_with_context(generate()), mimetype='text/event-stream')
// 前端 JavaScript
const eventSource = new EventSource('/stream'); eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
document.getElementById('output').innerHTML += data.content;
}; eventSource.onerror = (err) => {
console.error('EventSource failed:', err);
eventSource.close();
};

方案二:使用流式 HTTP 响应(NDJSON)

更通用的流式传输方案,适合非浏览器客户端

# FastAPI 示例
from fastapi import APIRouter
from fastapi.responses import StreamingResponse
import json @app.get("/stream")
async def stream_data():
async def generate():
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
stream=True
) async for chunk in response:
if chunk.choices:
content = chunk.choices[0].delta.content or ""
yield json.dumps({"content": content}) + "\n" # NDJSON 格式 return StreamingResponse(generate(), media_type='application/x-ndjson')
// 前端 JavaScript 使用 Fetch API
async function streamData() {
const response = await fetch('/stream');
const reader = response.body.getReader();
const decoder = new TextDecoder(); while(true) {
const { done, value } = await reader.read();
if(done) break; const chunk = decoder.decode(value);
const data = JSON.parse(chunk);
document.getElementById('output').innerHTML += data.content;
}
}

关键配置说明

  1. 响应头设置

    # Flask
    headers = {
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
    } # FastAPI 自动处理
  2. 数据格式选择

    • SSE (text/event-stream):浏览器原生支持,自动重连
    • NDJSON (application/x-ndjson):更通用的流式 JSON 格式
    • 纯文本流:简单但结构化能力弱
  3. 前端处理建议

    // 更健壮的读取方式(处理分块不完整情况)
    let buffer = ''; async function processChunk(chunk) {
    buffer += chunk;
    while(buffer.includes('\n')) {
    const lineEnd = buffer.indexOf('\n');
    const line = buffer.slice(0, lineEnd);
    buffer = buffer.slice(lineEnd + 1); try {
    const data = JSON.parse(line);
    // 处理数据...
    } catch(e) {
    console.error('解析错误:', e);
    }
    }
    }

完整工作流程示例(FastAPI + React)

后端

# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
) @app.get("/chat")
async def chat_stream(prompt: str):
async def generate():
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": prompt}],
stream=True
) async for chunk in response:
if content := chunk.choices[0].delta.content:
yield json.dumps({"content": content}) return StreamingResponse(generate(), media_type="application/x-ndjson")

前端 React 组件

// ChatComponent.jsx
import { useState } from 'react'; export default function ChatComponent() {
const [output, setOutput] = useState(''); const startStream = async () => {
const response = await fetch('http://api/chat?prompt=你好');
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = ''; while(true) {
const { done, value } = await reader.read();
if(done) break; buffer += decoder.decode(value);
while(buffer.includes('}')) {
const endIndex = buffer.indexOf('}') + 1;
const chunk = buffer.slice(0, endIndex);
buffer = buffer.slice(endIndex); try {
const data = JSON.parse(chunk);
setOutput(prev => prev + data.content);
} catch(e) {
console.error('解析错误:', e);
}
}
}
}; return (
<div>
<button onClick={startStream}>开始对话</button>
<div id="output">{output}</div>
</div>
);
}

注意事项

  1. 连接管理

    • 设置合理的超时时间(通常 30-60 秒)
    • 处理客户端提前断开连接的情况
    # FastAPI 示例
    try:
    async for chunk in response:
    # ...处理数据
    if await request.is_disconnected():
    break
    finally:
    await client.close() # 清理资源
  2. 性能优化

    • 使用异步框架(FastAPI 性能优于 Flask)
    • 启用响应压缩
    app = FastAPI()
    @app.middleware("http")
    async def add_compression(request, call_next):
    response = await call_next(request)
    response.headers["Content-Encoding"] = "gzip"
    return response
  3. 安全考虑

    • 限制最大并发连接数
    • 实施速率限制
    from fastapi import Request
    from fastapi.middleware import Middleware
    from slowapi import Limiter
    from slowapi.util import get_remote_address limiter = Limiter(key_func=get_remote_address)
    app.state.limiter = limiter @app.get("/chat")
    @limiter.limit("10/minute")
    async def chat_stream(request: Request):
    # ...
  4. 错误处理增强

    async def generate():
    try:
    response = client.chat.completions.create(...)
    async for chunk in response:
    # 处理数据...
    except Exception as e:
    yield json.dumps({"error": str(e)})
    finally:
    await client.close() # 确保释放资源

这些方案可根据具体需求组合使用,建议优先选择 SSE 方案(浏览器兼容性好),需要支持更复杂场景时可考虑 WebSocket,但后者实现成本较高。

通过 API 将Deepseek响应流式内容输出到前端的更多相关文章

  1. HttpURLConnection的流式输出的缺陷和解决方法

    转自:http://www.mzone.cc/article/198.html 最近在用applet写文件上传控件的时候发现使用URLConnection来对服务器进行流式输出时的一些问题.我们通常要 ...

  2. Java8 流式 API(`java.util.stream`)

    熟悉 ES6 的开发者,肯定对数组的一些方法不是很陌生:map.filter 等.在对一组对象进行统一操作时,利用这些方法写出来的代码比常规的迭代代码更加的简练.在 C♯ 中,有 LINQ 来实现.那 ...

  3. ASP.NET Core Web API 流式返回,逐字显示

    Websocket.SSE(Server-Sent Events)和长轮询(Long Polling)都是用于网页和服务端通信的技术. Websocket是一种全双工通信协议,能够实现客户端和服务端之 ...

  4. CSS3与页面布局学习笔记(四)——页面布局大全(负边距、双飞翼、多栏、弹性、流式、瀑布流、响应式布局)

    一.负边距与浮动布局 1.1.负边距 所谓的负边距就是margin取负值的情况,如margin:-100px,margin:-100%.当一个元素与另一个元素margin取负值时将拉近距离.常见的功能 ...

  5. Openresty的同步输出与流式响应

    Openresty的同步输出与流式响应 默认情况下, ngx.say和ngx.print都是异步输出的,先来看一个例子: location /test { content_by_lua_block { ...

  6. 静态布局、自适应布局、流式布局、响应式布局、弹性布局简析、BFC

    静态布局:给页面元素设置固定的宽度和高度,单位用px,当窗口缩小,会出现滚动条,拉动滚动条显示被遮挡内容.针对不同分辨率的手机端,分别写不同的样式文件.例如:浏览器窗口是1000px,那么最小的宽度是 ...

  7. Django的视图流式响应机制

    Django的视图流式响应机制 Django的响应类型:一次性响应和流式响应. 一次性响应,顾名思义,将响应内容一次性反馈给用户.HttpResponse类及子类和JsonResponse类属于一次性 ...

  8. Hadoop_11_HDFS的流式 API 操作

    对于MapReduce等框架来说,需要有一套更底层的API来获取某个指定文件中的一部分数据,而不是一整个文件 因此使用流的方式来操作 HDFS上的文件,可以实现读取指定偏移量范围的数据 1.客户端测试 ...

  9. 流式布局&固定宽度&响应式&rem

    我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局.限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法. 1.流式布局: ...

  10. jackson 流式API

    http://www.cnblogs.com/lee0oo0/articles/2652528.html Jackson提供了三种可选的JSON处理方法 1.流式API     com.fasterx ...

随机推荐

  1. P10936 导弹防御塔 题解

    题目链接 题目大意 城堡有 m 个敌人.n 个能发射导弹的防御塔.导弹的速度固定,都为 v.导弹需要 T1 秒发射,T2 分钟冷却,还需要防御塔到敌人距离的 dis/v 的时间.给定防御塔和敌人的坐标 ...

  2. Qt开发经验小技巧236-240

    关于在头文件中定义函数使用static关键字的血的教训. 有时候我们需要将一些常用函数写在一个文件中供很多地方调用,如果写的是 int doxxx{} 这种,在你多个地方引用的时候,肯定会编译报错提示 ...

  3. Qt开源作品26-通用按钮地图效果

    一.前言 在很多项目应用中,需要根据数据动态生成对象显示在地图上,比如地图标注,同时还需要可拖动对象到指定位置显示,能有多种状态指示,安防领域一般用来表示防区或者设备,可以直接显示防区号,有多种状态颜 ...

  4. yarn : 无法加载文件 C:\Users\duany\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本

    在win10 下安装yarn后,在编辑器中检查yarn的安装的时候会出现: 解决方法 1:搜索powershell,以管理员方式运行powershell2:使用命令更改计算机的执行策略 执行: set ...

  5. minimind复现记录

  6. JVM实战—11.OOM的原因和模拟以及案例

    大纲 1.线上系统突然由于OOM内存溢出挂掉 2.什么是内存溢出及哪些区域会发生内存溢出 3.Metaspace如何因类太多而发生内存溢出 4.无限制调用方法如何让线程的栈内存溢出 5.对象太多导致堆 ...

  7. G1原理—1.G1回收器的分区机制

    大纲 1.G1垃圾回收器的分区(Region大小+G1分区+Region过大过小和计算) 2.Region大小的计算原理(先转字节然后确定2的n次幂再通过1左移n位) 3.新生代分区及自动扩展(新生代 ...

  8. CSP2024 游记

    前文 Day -1 上午考试了,多少分忘了. 晚上老师布置模板题. Day 0 继续前一天的模板题,并没有 AK. Day 1 J 组 先看 T1,发现是一道简单的水题,切了. 再看 T2,也是水题, ...

  9. ClickHouse-2接口

    客户端 ClickHouse提供了两个网络接口(两个都可以选择包装在TLS中以增加安全性): HTTP, 包含文档,易于使用. Native TCP,简单,方便使用. 在大多数情况下,建议使用适当的工 ...

  10. nginx详细参数配置(史上最全)

    Nginx (engine x) 是一个轻量级高性能的HTTP和反向代理服务器,同时也是一个通用 代理服务器 (TCP/UDP/IMAP/POP3/SMTP),最初由俄罗斯人Igor Sysoev编写 ...