通过 API 将Deepseek响应流式内容输出到前端
要实现通过 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;
}
}
关键配置说明
响应头设置:
# Flask
headers = {
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
} # FastAPI 自动处理
数据格式选择:
- SSE (
text/event-stream):浏览器原生支持,自动重连 - NDJSON (
application/x-ndjson):更通用的流式 JSON 格式 - 纯文本流:简单但结构化能力弱
- SSE (
前端处理建议:
// 更健壮的读取方式(处理分块不完整情况)
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>
);
}
注意事项
连接管理:
- 设置合理的超时时间(通常 30-60 秒)
- 处理客户端提前断开连接的情况
# FastAPI 示例
try:
async for chunk in response:
# ...处理数据
if await request.is_disconnected():
break
finally:
await client.close() # 清理资源
性能优化:
- 使用异步框架(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
安全考虑:
- 限制最大并发连接数
- 实施速率限制
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):
# ...
错误处理增强:
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响应流式内容输出到前端的更多相关文章
- HttpURLConnection的流式输出的缺陷和解决方法
转自:http://www.mzone.cc/article/198.html 最近在用applet写文件上传控件的时候发现使用URLConnection来对服务器进行流式输出时的一些问题.我们通常要 ...
- Java8 流式 API(`java.util.stream`)
熟悉 ES6 的开发者,肯定对数组的一些方法不是很陌生:map.filter 等.在对一组对象进行统一操作时,利用这些方法写出来的代码比常规的迭代代码更加的简练.在 C♯ 中,有 LINQ 来实现.那 ...
- ASP.NET Core Web API 流式返回,逐字显示
Websocket.SSE(Server-Sent Events)和长轮询(Long Polling)都是用于网页和服务端通信的技术. Websocket是一种全双工通信协议,能够实现客户端和服务端之 ...
- CSS3与页面布局学习笔记(四)——页面布局大全(负边距、双飞翼、多栏、弹性、流式、瀑布流、响应式布局)
一.负边距与浮动布局 1.1.负边距 所谓的负边距就是margin取负值的情况,如margin:-100px,margin:-100%.当一个元素与另一个元素margin取负值时将拉近距离.常见的功能 ...
- Openresty的同步输出与流式响应
Openresty的同步输出与流式响应 默认情况下, ngx.say和ngx.print都是异步输出的,先来看一个例子: location /test { content_by_lua_block { ...
- 静态布局、自适应布局、流式布局、响应式布局、弹性布局简析、BFC
静态布局:给页面元素设置固定的宽度和高度,单位用px,当窗口缩小,会出现滚动条,拉动滚动条显示被遮挡内容.针对不同分辨率的手机端,分别写不同的样式文件.例如:浏览器窗口是1000px,那么最小的宽度是 ...
- Django的视图流式响应机制
Django的视图流式响应机制 Django的响应类型:一次性响应和流式响应. 一次性响应,顾名思义,将响应内容一次性反馈给用户.HttpResponse类及子类和JsonResponse类属于一次性 ...
- Hadoop_11_HDFS的流式 API 操作
对于MapReduce等框架来说,需要有一套更底层的API来获取某个指定文件中的一部分数据,而不是一整个文件 因此使用流的方式来操作 HDFS上的文件,可以实现读取指定偏移量范围的数据 1.客户端测试 ...
- 流式布局&固定宽度&响应式&rem
我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局.限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法. 1.流式布局: ...
- jackson 流式API
http://www.cnblogs.com/lee0oo0/articles/2652528.html Jackson提供了三种可选的JSON处理方法 1.流式API com.fasterx ...
随机推荐
- Mybatis-plus 简单使用
Mybatis-plus 特点介绍: 1.无侵入:只做增强不做改变,引入它不会对现有工程产生影响 2.强大的CRUD操作:内置通用Mapper.Service,仅仅通过少量配置即可实现单表大部分CRU ...
- CH32V203F6P6-TSSOP20测试之02---点灯成功
一.问题思考 直接用官方提供的例程,为何下载程序后没有什么响应,难道自己设计的电路有什么不妥? 于是,对于电路进行具体分析,结果发现: 第一.官方的BOOT0采用杜邦线连接,在芯片手册好像找不到关于B ...
- 转载:大模型所需 GPU 内存笔记
转载文章:大模型所需 GPU 内存笔记 引言 在运行大型模型时,不仅需要考虑计算能力,还需要关注所用内存和 GPU 的适配情况.这不仅影响 GPU 推理大型模型的能力,还决定了在训练集群中总可用的 G ...
- NTRU
介绍 NTRU(Number Theory Research Unit),NTRU是一个带有专利保护的开源公开密钥加密系统,使用基于格的加密算法来加密数据.它包括两部分算法:NTRUEncrypt用来 ...
- VulNyx-Secrets
扫端口 扫描80端口发现有个secrets目录 还有个注释 继续扫发现http://192.168.200.11/secrets/login_form.php 有这个登录框 估计就是要爆破 usern ...
- 基于生成式AI的访问控制, 迁移传统安全策略到基于LLM的风险分类器
基于规则的风险分类 风险分类是网络安全系统的核心能力之一,它将访问请求和命令映射到其风险级别/类别:高(High).中(Medium).低(Low).目前,即便是在大规模环境中,风险分类器仍主要采用基 ...
- 玩转云端 | AccessOne实用窍门之三步搞定门户网站防护与加速
随着互联网的飞速发展,网站建设已成为企事业单位推广.提供服务的重要途径之一.在数字技术快速迭代的当下,如何在保障网站安全的前提下提供高效服务,是企事业单位需要着重考虑的内容. 网站安全防护是网站建设后 ...
- C# 深度学习框架 TorchSharp 原生训练模型和图像识别-自定义网络模型和识别手写数字
目录 使用 Torch 训练模型 定义神经网络 加载数据集 创建网络模型 定义损失函数 训练 识别手写图像 教程名称:使用 C# 入门深度学习 作者:痴者工良 教程地址:https://torch.w ...
- 春节福利来啦!Mac用户快来抽大奖
亲爱的Mac俱乐部(MaClub)用户及所有果粉朋友们: 值此新春佳节之际,Mac俱乐部特别推出春节抽奖活动,以回馈广大用户长期以来的支持与厚爱.我们精心准备了丰富的奖品,希望能为您的新年增添一份惊喜 ...
- 十四. Redis 新功能
十四. Redis 新功能 @ 目录 十四. Redis 新功能 1. ACL 2. IO多线程 3. 工具支持 Cluster 4. 其它新功能-介绍 5. 最后: 1. ACL ACL 参考官网: ...