vue 对接AI接口如何获取流式数据

1,395 阅读1分钟

最近的项目中需要对接suno转onepapi生成音乐,对接dify的接口等,流式响应让用户端实时展示返回数据,体验感好很多。返回数据是sse形式

1. Server-Sent Events (SSE)

Server-Sent Events (SSE) 是一种轻量的服务器向客户端推送消息的机制,基于 HTTP 协议实现单向通信,适用于需要实时更新的场景。

与 WebSocket 不同,SSE 只允许服务器向客户端发送数据,因此其实现简单、开销小,特别适合应用在以下场景:

  1. 实时数据流更新
  2. 实时通知或消息推送
  3. GPT-3/4 等 AI 模型的流式输出

2.@microsoft/fetch-event-source

微软的 @microsoft/fetch-event-source 是一个库,用于通过 Fetch API 实现 SSE 的流式数据传输。它封装了请求发送、消息接收和连接恢复的逻辑,非常适合流式数据的处理。

实现步骤

  1. 安装
npm install @microsoft/fetch-event-source
  1. 基本用法
import { fetchEventSource } from '@microsoft/fetch-event-source';

const attemptFetch = () => {
fetchEventSource('http://your-api-endpoint.com/stream', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
         Accept: "text/event-stream",
        Authorization: `Bearer ${apikey}`,
        "Transfer-Encoding": "chunked",
    },
    body: JSON.stringify({ query: '你的查询' }),
    signal: cancelTokenSourceRef.current.signal,
    onopen(response) {
        // 建立连接
        console.log(response, "open");
        if (response.ok) {
          console.log("成功建立连接");
         
        } else {
          throw new Error(JSON.stringify(response));
        }
      },
    onmessage(ev) {
        console.log('Received message:', ev.data);
        // 这里可以根据接收到的流式数据更新前端界面
    },
    onclose() {
         console.error("发生错误", err);
        throw err;
    },
    onerror(err) {
        console.log("关闭链接", res);
    },
     openWhenHidden: true, // 实时通知
});
}

增加对于请求报错错误,再去发送


const retryTime = ref(null); // 重复请求的timer
let retryDelay = 1000; // 初始重试延迟(毫秒)
const maxRetryDelay = 30000; // 最大重试延迟(毫秒)
const maxRetries = 3; // 最大重试次数

const attemptFetch = (retryCount) => {
 try{
   //上面的代码
    }catch(err){
     if (retryCount < maxRetries) {
          console.log(`尝试重连... (重试次数: ${retryCount + 1})`);
          clearTimeout(retryTime.value);
          retryTime.value = setTimeout(() => {
            attemptFetch(text, retryCount + 1);
          }, retryDelay);
          retryDelay = Math.min(retryDelay * 2, maxRetryDelay); // 指数退避
        } else {
          console.error("达到最大重试次数,停止重试");
        }
}
}

中断请求

// 用于中断会话,中断时调用cancelTokenSourceRef.current.abort();
const cancelTokenSourceRef = ref(new AbortController());
cancelTokenSourceRef.current = new AbortController();

// 终止对话
const stopGenerate = function () {
  cancelTokenSourceRef.current.abort();
};

效果图

aiwj.gif