首页 > 其他分享 >Uniapp仿ChatGPT Stream流式输出(非Websocket)

Uniapp仿ChatGPT Stream流式输出(非Websocket)

时间:2023-06-22 22:11:06浏览次数:58  
标签:Uniapp console log Stream text emitter Websocket data event

前言

最近写一个chagpt小程序,流式输出可以使用websocket也可以使用stream来实现,这里就不折腾websocket的了,我发现uniapp实现流式输出的方式挺多的,主要是有些小程序还不兼容,花了点时间研究了一下。

EventSource

EventSource也称为SSE(Server-Sent Events),是服务器推送的一个网络事件接口,一个EventSource会对http服务开启一个持久化链接,它发送的事件格式是‘text/stream’,开启EventSource事件后,它会一直保持开启状态,直到被要求关闭

SpringBoot实现SSE

@GetMapping("/sse")
public SseEmitter handleSse() {
    SseEmitter emitter = new SseEmitter();
    String data = "testStream";
    try {
        emitter.send(SseEmitter.event()
                     .id("[DATA]")
                     .data("hello")
                     .reconnectTime(3000));
        emitter.send(SseEmitter.event()
                     .id("[DATA]")
                     .data("你好,世界。")
                     .reconnectTime(3000));
        emitter.send(SseEmitter.event()
                     .id("[DONE]")
                     .data("done")
                     .reconnectTime(3000));
        emitter.send("啊啊啊");
    } catch (IOException e) {
        emitter.completeWithError(e);
    }

    emitter.complete();
    return emitter;
}

XHR方式

uniapp自带的uni.request()不支持stream方式,所以可以使用XHR来实现,但是小程序又不支持XHR

const requestChat = (msg)=>{
    // 在页面中创建 XMLHttpRequest 对象
    var xhr = new XMLHttpRequest()
    // 设置 XMLHttpRequest 对象
    xhr.open('GET', 'http://localhost:8090/chat?msg=' + msg)
    xhr.responseType = 'text'
    xhr.timeout = 0
    const msgNum = messageList.value.length;
    xhr.onreadystatechange = function () {
        if (xhr.readyState === XMLHttpRequest.LOADING) {
            // 处理 HTTP 数据块
            console.log(xhr.responseText)
        }
    }
    xhr.send()
}

EventSource方式

uniapp中也可以直接使用EventSource来实现流式输出,可惜小程序也不支持(难顶)

const chatStream = () => {
    const es = new EventSource("http://localhost:8090/sse")
    es.onmessage = function(event) {
        console.log(event)
        if (event.lastEventId=="[DONE]") {
            console.log(event.data);
            return es.close()
        }
        console.log(event.data);
    };
}

Transfer-Encoding Chunk

uniapp中使用uni.request(),配置enableChunked: true即可

const requestTask = uni.request({
    url: 'http://localhost:8090/sse',
    timeout: 15000,
    responseType: 'text',
    method: 'GET',
    enableChunked: true,  //配置这里
    data: {},
    success: response => {
        console.log(response)
    },
    fail: error => {}
})
requestTask.onHeadersReceived(function(res) {
    console.log(res.header);
});
// 这里监听消息
requestTask.onChunkReceived(function(res) {
    let decoder = new TextDecoder('utf-8');
    let text = decoder.decode(new Uint8Array(res.data));
    console.log(text)
})

由于接收到的数据是arraybuffer,所以我们要转换为字符串类型,但是编码会出现一点问题,上面这段代码使用TextDecoder来转换编码,但是小程序又不支持TextDecoder。。。

再换一种转换方式

requestTask.onChunkReceived(function(res) {
    const uint8Array = new Uint8Array(res.data);
    let text = String.fromCharCode.apply(null, uint8Array);
    text = decodeURIComponent(escape(text));
    console.log(text);
})

这样就可以在小程序中把Arraybuffer转换为字符串了

还有许多方式,比如调用第三方库来代替TextDecoder,我就不去尝试了

注意:

1.enableChunked: true流式响应开关,会自动在header中加入transfer-encoding chunked

2.arraybuffer转字符串问题,有TextDecoder就很好处理,没有也可以参照我上面的示例。

参考文章:

小程序如何实现类似ChatGPT的流式传输

微信小程序除了WebSocket其他思路实现流传输文字(打字机)效果

微信小程序ChatGpt流式响应

在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。

标签:Uniapp,console,log,Stream,text,emitter,Websocket,data,event
From: https://www.cnblogs.com/pigke/p/17498449.html

相关文章

  • Stream流
    1.  概述  11Java8的Stream使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。2.  案例数据准备  12pom.mxl<dependencies><dependency><groupId>org.projectlombok</groupI......
  • Vue / uniapp cart.js购物车
     constcart={namespaced:true,state:{//{"store_id":"","goods_id":"","goods_name":"","goods_price":"","goods_count":"","......
  • stringstream 与auto c++
    stringstream的用法,动态创建不同文件名for(inti=0;i<n;i++) { stringfilename; stringstreamss; ss<<"file"<<i<<".txt"; ss>>filename; ss.clear(); }auto的用法,通常用于for循环常规思路,我们想要输出一个数组的全部元素时,往往采用以下......
  • MongodChangeStream不生效
    interfaceChatMessageListener<T>extendsMessageListener<ChangeStreamDocument<Document>,T>{}1.检查mongodb是否启用了replicasets,参考配置https://stackoverflow.com/questions/59571945/the-changestream-stage-is-only-supported-on-replica-sets-error-......
  • InputStream和Reader区别
    InputStream,OutputStream  前者为字节输入流,后者为字节输出流。Reader   Writer  前者为字符输入流,后者为字符输出流。四个均为抽象类。fileInputStream 是InputStream 的实现类  fileReader 是Reader 的实现类字节流读取单位为一个字节,字符流读取单位为一个字符......
  • 使用poi时报错:java.io.EOFException: Unexpected end of ZLIB input stream
    原文:点击查看代码FileexcelFile=newFile(filePath);try{if(excelFile.exists()){wb=newSXSSFWorkbook(newXSSFWorkbook(excelFile),1000,true);}else{wb=newSXSSFWorkbook(1000);}}catch(IOExceptione){logger.error(tra......
  • Springboot实现WebSocket
    一、什么是webSocketWebSocket是HTML5下一种新的协议(Websocket协议本质上是一个基于tcp的协议),它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,WebSocket是一个持久化的协议。二、修改配置文件在application.properties,修改内容为:server.port=......
  • springboot+websocket简单使用
    一、引入依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.o......
  • uniapp 无线调试
    uniapp无线调试1、下载adb工具https://developer.android.google.cn/studio/releases/platform-tools?hl=zh-cn2、解压放到Hbuilder的adbs文件夹里HBuilder/plugins/launcher/tools/adbs3、进入解压后的文件夹cmd打开命令行4、使用配对码配对 adbpair adbpair 19......
  • 直播网站源码,uniapp几行代码解决滚动穿透
    直播网站源码,uniapp几行代码解决滚动穿透<template> <viewclass="">  <page-meta:page-style="spanStyle"></page-meta> </view></template><script> exportdefault{  data(){   return{    spanStyl......