ChatGpt 使用fetch-event-source实现sse流式处理

news2024/11/19 21:19:35

@microsoft/fetch-event-source 是一个由微软提供的库,用于在客户端和服务器之间建立基于 EventSource 的连接。EventSource 是一种 HTTP 协议,允许服务器向客户端推送实时事件流。该库提供了对 EventSource 协议的封装,使得在前端 JavaScript 中使用 EventSource 变得更加方便。

在 @microsoft/fetch-event-source 中,主要使用 fetchEventSource 函数来创建一个新的 EventSource 连接。这个函数接受一个 URL 参数,以及一个配置对象,其中可以包含一些选项,如请求方法、请求头、请求体等。当服务器向客户端推送事件时,可以通过 onmessage 回调函数来处理这些事件。此外,还可以提供 onerror 和 onclose 回调函数来处理连接错误和关闭事件

一、安装
pnpm install @microsoft/fetch-event-source
二、使用

 前端vue3:

import { fetchEventSource } from '@microsoft/fetch-event-source'

class RetriableError extends Error {}
class FatalError extends Error {}

const EventStreamContentType = 'text/event-stream; charset=utf-8'

export const fetchEventGpt = (data: any, callData: (arg0: any) => void) => {
  const ctrl = new AbortController()
  fetchEventSource('/api/stream', {
    method: 'POST',
    mode: 'no-cors',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
    signal: ctrl.signal,
    openWhenHidden: true,
    async onopen(response: any) {
      // 成功连接时回调
      if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
        return // everything's good
      } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        // client-side errors are usually non-retriable:
        throw new FatalError()
      } else {
        throw new RetriableError()
      }
    },
    onmessage(msg: { data: any; event: string }) {
      // 服务器返回消息回调 返回{ data,event,id,retry } ,data即服务器返回数据
      // if the server emits an error message, throw an exception
      // so it gets handled by the onerror callback below:
      if (msg.event === 'FatalError') {
        throw new FatalError(msg.data)
      }

      if (msg.event == '') {
        // 进行连接正常的操作

        try {
          const data = JSON.parse(msg.data) || {}
          ctrl.abort()
          callData(data)
        } catch (err) {
          console.log(err)
          throw err
        }
      }

      if (msg.event === 'close') {
        ctrl.abort()
      }
    },
    onclose() {
      // 正常结束的回调
      ctrl?.abort()
      throw new RetriableError()
    },
    onerror(err: any) {
      // 连接出现异常回调
      // 必须抛出错误才会停止
      ctrl?.abort()
      if (err instanceof FatalError) {
        throw err // rethrow to stop the operation
      } else {
        // do nothing to automatically retry. You can also
        // return a specific retry interval here.
      }
    },
  })
}

 服务端python:

from gevent import monkey

monkey.patch_all()

import time


from flask import Response, stream_with_context
from flask import Flask
from gevent.pywsgi import WSGIServer
from flask import request

app = Flask(__name__)


def predict():
    chatbot = [""]
    mid = """
    一、引言\n1. 背景介绍\n2. 研究意义\n\n二、多旋翼无人机概述\n
                                      1. 多旋翼无人机的定义\n2. 多旋翼无人机的特点\n3. 多旋翼无人机的基本结构\n\n
                                      三、多旋翼无人机控制方法\n1. 手动控制\n2. 遥控控制\n3. 自主控制\n\n
                                      四、多旋翼无人机调度方法\n1. 手动调度\n2. 遥控调度\n3. 自主调度\n\n
                                      五、多旋翼无人机应用实例\n1. 农业领域\n2. 航拍领域\n3. 搜索救援\n
                                      4. 其他应用领域\n\n六、多旋翼无人机的安全问题\n1. 飞行安全隐患\n
                                      2. 数据隐私问题\n3. 人机交互问题\n\n七、结论\n1. 研究总结\n2. 研究局限\n3. 研究展望
    """
    s = ""
    for response in mid:
        s += response
        yield [s], []


@app.route("/api/stream", methods=["GET", "POST"])
def progress():
    @stream_with_context
    def generate():
        ratio = 1
        data_stream = predict()
        for data in data_stream:
            yield str("data:") + str(data) + "\n\n"
            print("ratio:", ratio)
            time.sleep(0.1)

    headers = {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        "X-Accel-Buffering": "no",
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET,POST",
        "Access-Control-Allow-Headers": "x-requested-with,content-type",
    }

    return Response(generate(), mimetype="text/event-stream", headers=headers)


if __name__ == "__main__":
    http_server = WSGIServer(("0.0.0.0", int(8081)), app)
    http_server.serve_forever()

        我们创建了一个指向 http://192.168.4.164:8081/gptchat/gpt 的 EventSource 连接,使用 POST 方法发送 JSON 格式的请求体数据。当接收到服务器推送的事件时,会打印事件数据。如果发生错误或连接关闭,也会打印相应的信息。

        需要注意的是,虽然 EventSource 本身不支持 POST 方法,但通过使用 fetchEventSource 函数和适当的配置,我们可以模拟 POST 请求的效果。在服务器端,需要正确处理这种 POST 请求,并返回正确格式的事件流数据。

        此外,由于 EventSource 是基于 HTTP 的协议,因此它只能在支持 HTTP 的环境中使用,如浏览器端或 Node.js 服务器端。同时,由于它是基于长连接的协议,因此在使用过程中需要注意连接的管理和错误处理。

三、遇到问题

   1、跨域问题

 设置mode: "no-cors" 解决跨域问题,但是返回的body信息为null

在vite.config.ts配置代理

  devServer: {
    port: 8089,
    proxy: {
      "/api": {
        target: "http://192.168.4.164:8081",
        changeOrigin: true,
      }
    },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1478567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CCF-A类 IEEE VIS‘24 3月31日截稿!探索可视化技术的无限可能!

会议之眼 快讯 IEEE VIS (IEEE Visualization Conference )即可视化大会将于 2024 年 10月13日 -18日在美国佛罗里达州皮特海滩的信风岛大海滩度假举行&#xff01;圣彼得海滩&#xff0c;以其迷人的日落和和煦的微风&#xff0c;作为激发创造力和促进可视化社区内合作的完美背…

数据结构与算法之美学习笔记:55 | 算法实战(四):剖析微服务接口鉴权限流背后的数据结构和算法

目录 前言鉴权背景介绍如何实现快速鉴权&#xff1f;限流背景介绍如何实现精准限流&#xff1f;总结引申 前言 本节课程思维导图&#xff1a; 微服务是最近几年才兴起的概念。简单点讲&#xff0c;就是把复杂的大应用&#xff0c;解耦拆分成几个小的应用。这样做的好处有很多。…

外汇天眼:Sumsub推出播客,讨论最新的欺诈威胁

Sumsub&#xff0c;一家全球验证平台&#xff0c;今天宣布推出自己的播客&#xff0c;名为《什么是欺诈&#xff1f;》。节目将邀请来自各行各业的专业嘉宾&#xff0c;包括人工智能、网络安全、金融科技、加密货币和互联网游戏等领域的专家。对话将集中讨论数字欺诈如何影响企…

服了,阿里云服务器价格和腾讯云1元之差,如何选择?

2024年阿里云服务器和腾讯云服务器价格战已经打响&#xff0c;阿里云服务器优惠61元一年起&#xff0c;腾讯云服务器62元一年&#xff0c;2核2G3M、2核4G、4核8G、8核16G、16核32G、16核64G等配置价格对比&#xff0c;阿腾云atengyun.com整理阿里云和腾讯云服务器详细配置价格表…

Apache Paimon Append Queue表解析

a) 定义 在此模式下&#xff0c;将append table视为由bucket分隔的queue。 同一bucket中的每条record都是严格排序的&#xff0c;流式读取将完全按照写入顺序将record传输到下游。 使用此模式&#xff0c;无需特殊配置&#xff0c;所有数据都将作为queue进入一个bucket&…

XSS中级漏洞(靶场)

目录 一、环境 二、正式开始闯关 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0B 0x0C 0x0D 0x0E ​ 0x0F 0x10 0x11 0x12 一、环境 在线环境&#xff08;gethub上面的&#xff09; alert(1) 二、正式开始闯关 0x01 源码&#xff1a; 思路&#xff1a;闭…

【vue3学习笔记】Suspense组件;vue3中的其它改变

尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 课程 P167节 《Suspense组件》笔记 想要学习suspense&#xff0c;先来了解静态组件与异步组件。 静态引入与异步引入&#xff1a; 在network中将网速调慢&#xff0c;观察在静态引入和异步引入模式下&#xff0c;两个组件的加载…

Programming Abstractions in C阅读笔记:p306-p307

《Programming Abstractions in C》学习第75天&#xff0c;p306-p307总结&#xff0c;总计2页。 一、技术总结 1.Quicksort algorithm(快速排序) 由法国计算机科学家C.A.R(Charles Antony Richard) Hoare&#xff08;东尼.霍尔&#xff09;在1959年开发(develop), 1961年发表…

力扣每日一题 使二叉树所有路径值相等的最小代价 满二叉树 贪心

Problem: 2673. 使二叉树所有路径值相等的最小代价 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 灵神题解 复杂度 ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( 1 ) O(1) O(1) Code class Solution {public int minIncrements(int …

瑞_23种设计模式_外观模式

文章目录 1 外观模式&#xff08;Facade Pattern&#xff09;1.1 介绍1.2 概述1.3 外观模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 jdk源码解析 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《23种设计模式》的外观模式篇。本文中的部分…

一篇关于,搬运机器人的介绍

搬运机器人是一种能够自动运输和搬运物品的机器人。它们通常配备有传感器和导航系统&#xff0c;可以在工厂、仓库、医院或其他场所自主移动&#xff0c;并且可以根据预先设定的路径或指令进行操作。 搬运机器人可以用于搬运重物、物料搬运、装卸货物、仓库管理等任务。它们可以…

Git自动忽略dll文件的问题

检查了半天发现是sourcetreee的全局忽略文件导致&#xff0c; 从里面删除dll即可。 我是干脆直接删了全局忽略&#xff0c;太恶心了&#xff0c;如下&#xff1a; #ignore thumbnails created by windows Thumbs.db #Ignore files build by Visual Studio *.exe .vsconfig .s…

如何在Windows部署TortoiseSVN客户端并实现公网连接内网VisualSVN服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

USACO 2024 Feb Bronze铜组题解

闲话:今天是4年一度的奇观——2月29日!(地球人都知道) 所以为了纪念这个特殊的日子&#xff0c;我决定倒着讲。这是什么奇怪的规矩&#xff1f;(雾 Maximizing Productivity: 二分即可。 #include <bits/stdc.h> using namespace std; const int maxn200005; int c[ma…

市场复盘总结 20240229

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率中 60% 最常用…

软考52-上午题-【数据库】-关系模式2

一、关系模式的回顾 见&#xff1a;软考38-上午题-【数据库】-关系模式 二、关系模式 2-1、关系模式的定义 示例&#xff1a; 念法&#xff1a;A——>B A决定B&#xff0c;或者&#xff0c;B依赖于A。 2-2、函数依赖 1、非平凡的函数依赖 如果X——>Y&#xff0c;&a…

06|Mysql内部组件结构

1. 连接器 客户端要向mysql发起通信都必须先跟Server端建立通信连接&#xff0c;而建立连接的工作就是由连接器完成的 mysql -h host[数据库地址] -u root[用户] -p root[密码] -P 3306连接步骤: 1、如果用户名或密码不对&#xff0c;你就会收到一个"Access denied for us…

插值、逼近、拟合、光顺

插值 插值&#xff08;Interpolation&#xff09;是数学和计算科学中的一个重要概念&#xff0c;它指的是通过已知的一系列数据点&#xff0c;构造一个函数或曲线&#xff0c;并据此估计未知数据点的值。这个过程通常发生在已知数据点之间&#xff0c;用于预测或估算在这些已知…

【Qt】鼠标拖拽修改控件尺寸---八个方位修改

前提 在开发一个类似qdesiger的项目中 使用QGraphicsProxyWidget将Qt基础控件作为item放在场景视图中显示和编辑 创建自定义类继承QGraphicsProxyWidget&#xff0c;管理控件 成员变量 有控件的xywh等&#xff0c;其中x、y坐标存储是基于最底层widgetitem的 坐标系 x轴以右为正…

LeetCode 刷题 [C++] 第148题.排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 题目分析 根据题意&#xff0c;可以使用归并排序来对链表进行排序。归并排序是基于分治的思想&#xff0c;比较容易实现的就是自顶向下的递归方式来实现。 先找出链表的中点&#x…