| | |
| | | top_k: 3, |
| | | score_threshold: 2, |
| | | history: [ |
| | | |
| | | ], |
| | | stream: true, |
| | | model: "Qwen25-32B-Instruct", |
| | | temperature: 0.7, |
| | | max_tokens: 64, |
| | | temperature: 1.15, |
| | | max_tokens: 512, |
| | | prompt_name: "default", |
| | | return_direct: false |
| | | }, |
| | | msgIndex: null, |
| | | msgRole: null |
| | | msgRole: null, |
| | | chunkRef: null, // ai回答临时数据 |
| | | haveThinkStart: false, // ai回答响应数据是否有think标签 |
| | | haveThinkEnd: false, // ai回答响应数据是否有think标签 |
| | | controller: null, // ai回答请求控制器,可以根据业务中断请求 |
| | | }; |
| | | }, |
| | | methods: { |
| | |
| | | return roleNames[role]; |
| | | }, |
| | | |
| | | // 发送消息 |
| | | async sendMessage() { |
| | | if (this.inputMessage.trim() === '') return; |
| | | |
| | | // 添加用户消息 |
| | | this.messages.push({ |
| | | role: 'user', |
| | | content: this.inputMessage, |
| | | }); |
| | | this.messages.push({ |
| | | role: 'assistant', |
| | | content: '' |
| | | }) |
| | | this.sendMsgForm.query = this.inputMessage |
| | | // 清空输入框 |
| | | // 初始化状态 |
| | | this.chunkRef = ''; |
| | | this.haveThinkStart = false; |
| | | this.haveThinkEnd = false; |
| | | this.controller = new AbortController(); |
| | | |
| | | // 添加用户消息和占位助理消息 |
| | | this.messages.push( |
| | | { role: 'user', content: this.inputMessage }, |
| | | { role: 'assistant', content: '' } |
| | | ); |
| | | this.sendMsgForm.query = this.inputMessage; |
| | | this.inputMessage = ''; |
| | | const assistantIndex = this.messages.length - 1; |
| | | try { |
| | | const response = await fetch('/api/chat/kb_chat', { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | "Accept": 'text/event-stream', |
| | | 'Cache-Control': 'no-cache, no-transform' |
| | | }, |
| | | signal: this.controller.signal, |
| | | body: JSON.stringify(this.sendMsgForm) |
| | | }); |
| | | |
| | | const response = await fetch('/api/chat/kb_chat', { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify(this.sendMsgForm) |
| | | }); |
| | | const reader = response.body.getReader(); |
| | | const decoder = new TextDecoder(); |
| | | if (!response.ok) throw new Error(`HTTP ${response.status}`); |
| | | |
| | | // eslint-disable-next-line no-constant-condition |
| | | while (true) { |
| | | const { done, value } = await reader.read(); |
| | | if (done) break; |
| | | console.log("结束循环") |
| | | const chunk = decoder.decode(value, { stream: false }); |
| | | const dataList = chunk.split('\r\n\r\n') |
| | | console.log("获取到了流式响应数据", dataList) |
| | | if (dataList && dataList.length > 0) { |
| | | for (const data of dataList) { |
| | | if (data.startsWith("data: ")) { |
| | | const jsonStr = data.slice(6).trim(); |
| | | if (jsonStr) { |
| | | const json = JSON.parse(jsonStr); |
| | | if (json.docs && json.docs.length > 0) { |
| | | console.log("1", json) |
| | | json.docs.forEach(str => { |
| | | this.messages[this.messages.length - 1].content += str |
| | | // 强制Vue更新视图 |
| | | this.$forceUpdate(); |
| | | }) |
| | | } else if (json.choices && json.choices.length > 0) { |
| | | console.log("2", json) |
| | | json.choices.forEach(choice => { |
| | | this.messages[this.messages.length - 1].content += choice.delta.content |
| | | // 强制Vue更新视图 |
| | | this.$forceUpdate(); |
| | | }) |
| | | const reader = response.body.getReader(); |
| | | const decoder = new TextDecoder(); |
| | | let jsonBuffer = ''; |
| | | |
| | | // eslint-disable-next-line no-constant-condition |
| | | while (true) { |
| | | const { done, value } = await reader.read(); |
| | | if (done) { |
| | | this.sendMsgForm.history.push({ role: 'user', content: this.inputMessage }) |
| | | this.sendMsgForm.history.push({ role: 'assistant', content: this.messages[assistantIndex].content }) |
| | | break; |
| | | } |
| | | |
| | | const chunk = decoder.decode(value, { stream: true }); |
| | | const lines = chunk.split('\n'); |
| | | |
| | | for (const line of lines) { |
| | | if (!line.startsWith('data:')) continue; |
| | | |
| | | const rawData = line.slice(5).trim(); |
| | | if (rawData === '[DONE]') continue; |
| | | |
| | | try { |
| | | jsonBuffer += rawData; |
| | | const data = JSON.parse(jsonBuffer); |
| | | jsonBuffer = ''; |
| | | let content = ''; |
| | | if (data.docs) { |
| | | for (let i = 0; i < data.docs.length; i++) { |
| | | content += data.docs[i] |
| | | } |
| | | } else { |
| | | content = data?.choices?.[0]?.delta?.content || ''; |
| | | } |
| | | |
| | | if (!content) continue; |
| | | // 实时更新 |
| | | this.messages[assistantIndex].content += content; |
| | | this.messages[assistantIndex].content = this.messages[assistantIndex].content.replace(/<\/?think>/g, ''); |
| | | await this.$nextTick(); |
| | | } catch { |
| | | // JSON不完整,等待下次数据 |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } catch (error) { |
| | | if (error.name !== 'AbortError') { |
| | | console.error('Request failed:', error); |
| | | this.messages[assistantIndex].content = '请求异常'; |
| | | } |
| | | } |
| | | // sendKbMsg(this.sendMsgForm).then(res => { |
| | | // console.log(res, "拿到回复了!!") |
| | | // this.sendMsgForm.history.push({ |
| | | // role: 'assistant', |
| | | // content: JSON.parse(res.data).choices[0].message.content, |
| | | // }); |
| | | // }) |
| | | }, |
| | | } |
| | | |
| | | }, |
| | | }; |