【JavaScript】fetch 处理流式数据,实现类 chatgpt 对话

本文只包含最基础的请求后端大佬给得对话接口,大部分模型的传参是差不多的,核心还是如何处理 fetch 获取的流数据

ts 复制代码
import { defineStore } from 'pinia';
import { ElMessage } from 'element-plus';

type Role = 'system' | 'user' | 'assistant';
export interface Message {
  role: Role;
  content: string;
}
interface ChatStore {
  model: 'Gnosis' | 'chatglm2-6b' | 'cc-13b-chat';
  chatApi: string;
  messages: Message[];
  done: boolean | null;
}
const DEFAULT_PROMPT = `你应该根据用户回答生成答案。答案必须尽可能简明扼要。字数控制在512个字符以内`;

export const useChatStore = defineStore({
  id: 'chatStore',
  state: (): ChatStore => {
    return {
      model: 'cc-13b-chat',
      chatApi: 'chat_api/chat/knowledge_base_chat',
      messages: [
        {
          role: 'system',
          content: DEFAULT_PROMPT,
        },
      ],
      done: null,
    };
  },
  actions: {
    async fetchChat(query: string) {
      this.messages.push({
        role: 'user',
        content: query,
      });
      let response: any = null;
      try {
        response = await fetch(this.chatApi, {
          headers: {
            'Content-Type': 'application/json',
          },
          method: 'POST',
          body: JSON.stringify({
            query: query,
            history: this.messages,
            model_name: this.model,
            stream: true,
            knowledge_base_name: 'lb_test',
            top_k: 1,
            score_threshold: 1,
            temperature: 0.7,
            max_tokens: 4096,
            prompt_name: 'default',
          }),
        });
      } catch (error) {
        console.log(error);
        ElMessage.error('请求失败');
        return;
      }
      const data = response.body;
      this.messages.push({
        role: 'assistant',
        content: '',
      });
      // 处理流式数据
      if (data) {
        const reader = data.getReader();
        const decoder = new TextDecoder('utf-8');
        this.done = false;
        while (!this.done) {
          const { value, done: readerDone } = await reader.read();
          // value值
          // {"answer": "帮助解决"}
          if (value) {
            const char = decoder.decode(value);
            console.log(char);
            // if (char === '\n') {
            //   this.messages[this.messages.length - 1].content += '\n';
            //   continue;
            // }
            if (char) {
              const res = JSON.parse(char);
              this.messages[this.messages.length - 1].content += res.answer ?? '';
            }
          }
          if (!this.done) {
            this.done = readerDone;
          }
        }
      }
      // 对话结束
      this.done = null;
    },
  },
  // persist: {
  //   key: 'store',
  //   storage: window.localStorage,
  // },
});
相关推荐
SystickInt15 小时前
C语言 strcpy和memcpy 异同/区别
c语言·开发语言
CS Beginner15 小时前
【C语言】windows下编译mingw版本的glew库
c语言·开发语言·windows
FJW02081415 小时前
Python_work4
开发语言·python
多看书少吃饭16 小时前
从Vue到Nuxt.js
前端·javascript·vue.js
大学生资源网16 小时前
java毕业设计之儿童福利院管理系统的设计与实现(源码+)
java·开发语言·spring boot·mysql·毕业设计·源码·课程设计
JasmineWr16 小时前
JVM栈空间的使用和优化
java·开发语言
前端一小卒16 小时前
从 v5 到 v6:这次 Ant Design 升级真的香
前端·javascript
Poetinthedusk16 小时前
C#实现图片统一位深
开发语言·c#
吴佳浩 Alben17 小时前
Python入门指南(四)
开发语言·后端·python
一然明月17 小时前
QT之基础控件
开发语言·qt