当前位置: 首页 > news >正文

前端使用fetch-event-source实现AI对话

安装

npm install --save @microsoft/fetch-event-source

使用

import {fetchEventSource} from '@microsoft/fetch-event-source';data() {return {question: '',isLoading: false,currentIndex: '',thinkFlag: false,ctrlAbout: null,conversationId: null,answering: false}
},
methods: {sendQuestion(question) {if (this.isLoading || this.answering) return;if (window.EventSource) {this.question = '';this.currentIndex = this.dataList.length;this.isLoading = true;this.dataList.push({index: this.currentIndex,type: 'q',code: 200,info: question});this.scrollTop();let _that = this;let ix = 0;const params = {question: question, conversationId: this.conversationId};this.ctrlAbout = new AbortController();fetchEventSource(process.env.VUE_APP_BASE_API + '/ai/aiQuestion', {method: 'POST',headers: {[tokenName]: 'Bearer ' + getToken(),accept: 'application/json;charset=UTF-8,text/plain,*/*','Content-Type': 'application/json;charset=UTF-8', // 文本返回格式},body: JSON.stringify(params),signal: _that.ctrlAbout.signal,openWhenHidden: true, // 在浏览器标签页隐藏时保持与服务器的EventSource连接onopen(resp) {console.log('SSE连接成功...', resp)_that.isLoading = false;_that.thinkFlag = false;},onmessage(esm) {let esmData = esm.data;if (esmData && esmData !== '' && esmData !== 'event: ping') {// console.log('esmData', esmData)let respData = JSON.parse(esmData.substring(esm.data.indexOf(":") + 1, esmData.length));if (respData.event && respData.event === 'message') {if (ix < 1) {_that.answering = true;}if (!_that.answering) return;let respAnswer = respData.answer;console.log('respAnswer', respAnswer)if (respAnswer === '<think>') {_that.thinkFlag = true;respAnswer = '';} else if (respAnswer === '</think>') {_that.thinkFlag = false;respAnswer = '';}let isExist = _that.dataList.some(d => d.type === 'a' && d.index === _that.currentIndex);if (isExist) {_that.dataList.forEach(item => {if (item.type === 'a' && item.index === _that.currentIndex) {if (item.info.state === 0) {if (_that.thinkFlag) {item.info.text.think += respAnswer;} else {item.info.text.answer += respAnswer;}} else {if (_that.thinkFlag) {item.info = {state: 0,text: {think: respAnswer,answer: ''}}} else {item.info = {state: 0,text: {think: '',answer: respAnswer}}}}}})} else {if (_that.thinkFlag) {_that.dataList.push({index: _that.currentIndex,type: 'a',code: 200,info: {state: 0,showInfo: true,text: {think: respAnswer,answer: ''}}});} else {_that.dataList.push({index: _that.currentIndex,type: 'a',code: 200,info: {state: 0,showInfo: true,text: {think: '',answer: respAnswer}}});}}} else {_that.dataList.forEach(item => {if (item.type === 'a' && item.index === _that.currentIndex && item.info.state === 0) {item.info.state = 1;}})_that.answering = false;_that.ctrlAbout = null;_that.getHistorySession();}}_that.scrollTop();},onclose() {this.ctrlAbout = null;console.log('SSE已关闭...')},onerror(e) {console.log('SSE出现错误...', e)this.stopAnswer();this.$message.error('系统错误,请联系管理员进行处理!');throw e;}});} else {this.$message.warning('您的浏览器不支持SSE!');}},eventSourceClose() {if (this.ctrlAbout) {this.ctrlAbout.abort();this.ctrlAbout = null;aiQuestionByClose(this.taskId).then(resp => {console.info('SSE已中断...')})}},stopAnswer() {this.answering = false;this.eventSourceClose();this.dataList.forEach(item => {if (item.type === 'a' && item.index === this.currentIndex && item.info.state === 0) {item.info.state = 2;}});this.scrollTop();this.getHistorySession();},scrollTop() {this.$nextTick(() => {if (this.$refs.kqaWindow.scrollHeight) {this.$refs.kqaWindow.scrollTo({top: this.$refs.kqaWindow.scrollHeight,behavior: 'smooth'});}});},eventSourceClose() {if (this.ctrlAbout) {this.ctrlAbout.abort();this.ctrlAbout = null;aiQuestionByClose(this.taskId).then(resp => {console.info('SSE已中断...')})}},
}

参考文档

        https://juejin.cn/post/7518783423273664547

        fetchEventSource使用+源码解析 - 漫思 - 博客园

        https://juejin.cn/post/7411047482652262415

http://www.dtcms.com/a/271674.html

相关文章:

  • AI Agent:我的第一个Agent项目
  • 爬虫-数据解析
  • [C语言初阶]操作符
  • ZeroMQ 代理架构实现(Python 服务端 + C++ 代理 + C++ 客户端)
  • RabbitMQ 4.1.1-Local random exchange体验
  • 解决Ollama下载太慢问题
  • Claude Code 环境搭建教程
  • Java SE--继承
  • Python 机器学习核心入门与实战进阶 Day 7 - 复盘 + 综合实战挑战
  • NW658NW659美光固态闪存NW660NW708
  • 陶哲轩:数学界的莫扎特与跨界探索者
  • 离线二维码生成器,无需网络快速制作
  • 神经网络基础及API使用详解
  • 【项目经理】经典面试题0002:项目经理和交付经理的区别?
  • 变频器实习DAY3
  • S7-1500——(一)西门子PLC编程从入门到精通3、基于TIA 博途结构化控制语言——SCL(一)
  • 全连接神经网络(MLP)原理与PyTorch实现详解
  • 【freertos-kernel】MemMang
  • Deepseek搭建智能体个人知识库
  • LeetCode经典题解:1、两数之和(Two Sum)
  • Python Day8
  • 第九篇:信息化知识 --系统集成项目管理工程师 第3版专题知识点笔记
  • MySQL--函数
  • [Python 基础课程]关键字
  • 1068.产品销售分析Ⅰ
  • S7-1500——(一)从入门到精通1、基于TIA 博途解析PLC程序结构(三)
  • 2025年ATL宁德新能源Verify测评演绎推理数字计算SHL测评题库高分攻略分享
  • 10.9 大模型训练数据优化实战:3步让准确率从68%飙升至79%
  • Redis-哨兵机制doctor环境搭建
  • 虚拟机安装与使用vim编辑器简单使用