通过 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 ...
随机推荐
- H2数据库用户自定义函数方法及范例
H2数据库,是Java实现的内存数据库.可使用它作为嵌入式内存数据库,但就其特性还用更多值得应用在实际项目中的意义.之前的一篇Blog中已经描述过其使用方法及丰富的连接数据库方式. 官方主页:http ...
- 网页转换成电脑exe软件简单办法
准备windows电脑,其他电脑步骤差不多 1.安装nodejs(nodejs自带npm),前往nodejs官网下载,选择Windows 安装包 (.msi) 64位,一直点击下一步安装即可 2.wi ...
- Qt5离线安装包无法下载问题解决办法
1.前言 Qt5离线安装包目前在国内已经被墙了,无法下载,只能下载在线安装包: 直接访问会显示Download from your IP address is not allowed: 本文就提出两种 ...
- 微服务实战系列(七)-网关springcloud gateway-copy
1. 场景描述 springcloud刚推出的时候用的是netflix全家桶,路由用的zuul,但是据说zull1.0在大数据量访问的时候存在较大性能问题,2.0就没集成到springcloud中了, ...
- 第六章 (Nginx+Lua)Web开发实战HTTP服务
此处我说的HTTP服务主要指如访问京东网站时我们看到的热门搜索.用户登录.实时价格.实时库存.服务支持.广告语等这种非Web页面,而是在Web页面中异步加载的相关数据.这些服务有个特点即访问量巨大.逻 ...
- MySQL---锁、变量、存储过程、游标、自定义函数
一概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制. MySQL各存储引擎使用了三种类型 ...
- DeepSeek V3 两周使用总结
2024 年 12 月 26 日,杭州深度求索人工智能基础技术研究有限公司发布 DeepSeek-V3 大模型.官方宣称:(1)基于自研的 MoE 模型和 671B 参数,在 14.8T token ...
- GD32F4xx FLASH存储
一.GD32F4xx的内存 GD32F4xx的内存结构由:主存储器.系统信息存储器.一次性编程区域和选项字节等 4 部分组成. 主存储器:用来存放代码和数据常数(如 const 类型的数据).分为 2 ...
- 腾讯云 TI 平台部署与调用DeepSeek-R1大模型的实战指南
今天我们将继续探讨如何部署一个私有化的 DeepSeek-R1 大模型,具体的部署过程我们将利用腾讯云的 TI 平台进行操作.当前,腾讯云 TI 平台为用户提供了免费体验的满血版 DeepSeek-R ...
- Serverless函数计算介绍
本文分享自天翼云开发者社区<Serverless函数计算介绍>,作者:余凯 随着互联网和移动互联网的快速发展,越来越多的应用程序需要具备高可用性.高扩展性和高性能等特点.而云计算作为一种新 ...