要实现通过 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. H2数据库用户自定义函数方法及范例

    H2数据库,是Java实现的内存数据库.可使用它作为嵌入式内存数据库,但就其特性还用更多值得应用在实际项目中的意义.之前的一篇Blog中已经描述过其使用方法及丰富的连接数据库方式. 官方主页:http ...

  2. Qt通用方法及类库5

    函数名 //设置标签颜色 static void setLabStyle(QLabel *lab, quint8 type, const QString &bgColor = "&q ...

  3. Qt开源作品20-PNG图片警告去除工具

    一.前言 在新版的Qt5中,我们之前在Qt4中使用的png图片,到了这里经常会报一个警告,libpng warning: iCCP: known incorrect sRGB profile,尽管这种 ...

  4. C#HTTP网络请求时GetResponseAsync()方法抛出“远程服务器返回错误: (411) 所需的长度”异常

    在请求HttpWebRequest的报了如下的错误"远程服务器返回错误: (411) 所需的长度",结果网上 百度了一下说,再请求POST的时候,若没有参数的情况下,需要将进行如下 ...

  5. React中的 ref 及原理浅析

    前言 对于 ref 的理解,我们一部人还停留在用 ref 获取真实 dom 元素和获取组件层面上,但实际 ref 除了这两项功能之外,在使用上还有很多小技巧.本章我们就一起深入探讨研究一下 React ...

  6. JSON和XML的对比及应用领域

    JSON和XML的对比 对比表格 对比维度 JSON XML 可读性 通常更简洁,易于阅读和编写12 结构清晰,但可能因标签和属性而显得冗长1 解析难度 解析通常比XML简单,多数现代编程语言内置解析 ...

  7. 上位机能不能替代PLC呢?

    一.前言 大家好!我是付工. 之前有个学员问了这样的一个问题: 学会了上位机,是不是就可以不用PLC了呢? 今天跟大家分享一下上位机能不能代替PLC? 二.网络架构 首先我们看下这张网络架构图. 从图 ...

  8. 为什么在 Python 中 hash(-1) == hash(-2)?

    英文:https://omairmajid.com/posts/2021-07-16-why-is-hash-in-python 作者:Omair Majid 译者:豌豆花下猫&Claude- ...

  9. springboot-多模块构建-1

    1. 场景描述 先介绍下背景,项目为什么需要用多模块?springmvc难道还不够? (1)设计模式真言:"高内聚.低耦合",springmvc项目,一般会把项目分成多个包:con ...

  10. Redis中缓存预热、击穿、雪崩等问题解决方案-copy

    1.缓存雪崩 缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉. 解决方案 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生. ...