【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,
  // },
});
相关推荐
kruptos4 小时前
分布式系统怎么“选主“?Raft 共识一次讲清
开发语言·分布式·php·共识算法
吴声子夜歌5 小时前
ApacheCommons——commons-cli(命令行参数解析)
java·开发语言·apache
自动化监测Learner5 小时前
主流 Web 端地图引擎对比:选型指南与优劣分析
javascript
野区小女王6 小时前
Codex 接入 DeepSeek-V4-Flash保姆级教程
gpt·chatgpt
benchmark_cc6 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库6 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
Tairitsu_H6 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
泡海椒6 小时前
JQuick-Curl 性能分析:并发场景下的性能表现与调优,第三方接口调用不只要快写也要稳跑
java·开发语言·okhttp
小智老师PMP6 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
江畔柳前堤7 小时前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native