要实现通过 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. Mybatis-plus 简单使用

    Mybatis-plus 特点介绍: 1.无侵入:只做增强不做改变,引入它不会对现有工程产生影响 2.强大的CRUD操作:内置通用Mapper.Service,仅仅通过少量配置即可实现单表大部分CRU ...

  2. CH32V203F6P6-TSSOP20测试之02---点灯成功

    一.问题思考 直接用官方提供的例程,为何下载程序后没有什么响应,难道自己设计的电路有什么不妥? 于是,对于电路进行具体分析,结果发现: 第一.官方的BOOT0采用杜邦线连接,在芯片手册好像找不到关于B ...

  3. 转载:大模型所需 GPU 内存笔记

    转载文章:大模型所需 GPU 内存笔记 引言 在运行大型模型时,不仅需要考虑计算能力,还需要关注所用内存和 GPU 的适配情况.这不仅影响 GPU 推理大型模型的能力,还决定了在训练集群中总可用的 G ...

  4. NTRU

    介绍 NTRU(Number Theory Research Unit),NTRU是一个带有专利保护的开源公开密钥加密系统,使用基于格的加密算法来加密数据.它包括两部分算法:NTRUEncrypt用来 ...

  5. VulNyx-Secrets

    扫端口 扫描80端口发现有个secrets目录 还有个注释 继续扫发现http://192.168.200.11/secrets/login_form.php 有这个登录框 估计就是要爆破 usern ...

  6. 基于生成式AI的访问控制, 迁移传统安全策略到基于LLM的风险分类器

    基于规则的风险分类 风险分类是网络安全系统的核心能力之一,它将访问请求和命令映射到其风险级别/类别:高(High).中(Medium).低(Low).目前,即便是在大规模环境中,风险分类器仍主要采用基 ...

  7. 玩转云端 | AccessOne实用窍门之三步搞定门户网站防护与加速

    随着互联网的飞速发展,网站建设已成为企事业单位推广.提供服务的重要途径之一.在数字技术快速迭代的当下,如何在保障网站安全的前提下提供高效服务,是企事业单位需要着重考虑的内容. 网站安全防护是网站建设后 ...

  8. C# 深度学习框架 TorchSharp 原生训练模型和图像识别-自定义网络模型和识别手写数字

    目录 使用 Torch 训练模型 定义神经网络 加载数据集 创建网络模型 定义损失函数 训练 识别手写图像 教程名称:使用 C# 入门深度学习 作者:痴者工良 教程地址:https://torch.w ...

  9. 春节福利来啦!Mac用户快来抽大奖

    亲爱的Mac俱乐部(MaClub)用户及所有果粉朋友们: 值此新春佳节之际,Mac俱乐部特别推出春节抽奖活动,以回馈广大用户长期以来的支持与厚爱.我们精心准备了丰富的奖品,希望能为您的新年增添一份惊喜 ...

  10. 十四. Redis 新功能

    十四. Redis 新功能 @ 目录 十四. Redis 新功能 1. ACL 2. IO多线程 3. 工具支持 Cluster 4. 其它新功能-介绍 5. 最后: 1. ACL ACL 参考官网: ...