/* * @Author: ysh * @Date: 2025-07-08 16:43:22 * @LastEditors: Please set LastEditors * @LastEditTime: 2025-07-16 15:49:45 */ import request from '@/utils/request' import { getToken } from '@/utils/auth' // 查询cmc聊天记录列表 export function getAnswer(question, collectionName) { return request({ url: '/llm/rag/answer', method: 'get', params: { question, collectionName } }) } // 查询上下文引用文件 export function getContextFile(question, collectionName) { return request({ url: '/llm/rag/context', method: 'get', params: { question, collectionName } }) } // 流式回答API - 使用fetch API处理流式响应 export function getAnswerStream(question, collectionName, onMessage, onError, onComplete) { const baseURL = process.env.VUE_APP_BASE_API const url = `${baseURL}/llm/rag/answer?question=${encodeURIComponent(question)}&collectionName=${encodeURIComponent(collectionName)}` const controller = new AbortController() fetch(url, { method: 'GET', headers: { 'Authorization': 'Bearer ' + getToken(), 'Accept': 'application/json, text/event-stream', 'Cache-Control': 'no-cache' }, signal: controller.signal }).then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } const reader = response.body.getReader() const decoder = new TextDecoder() let buffer = '' function readStream() { return reader.read().then(({ done, value }) => { if (done) { console.log('=== 流式读取完成 ===') // 处理缓冲区中剩余的数据 if (buffer.trim()) { console.log('=== 处理剩余缓冲区数据 ===', buffer) const lines = buffer.split(/\r?\n/) lines.forEach(line => { line = line.trim() if (!line || line.startsWith(':')) return console.log('处理剩余数据行:', line) // 尝试提取JSON数据 let jsonData = null if (line.startsWith('data: ')) { try { jsonData = JSON.parse(line.slice(6)) console.log('解析的剩余SSE数据:', jsonData) } catch (error) { console.error('解析剩余SSE数据失败:', error, line) } } else if (line.startsWith('data:')) { try { jsonData = JSON.parse(line.slice(5)) console.log('解析的剩余SSE数据(无空格):', jsonData) } catch (error) { console.error('解析剩余SSE数据失败(无空格):', error, line) } } else { try { jsonData = JSON.parse(line) console.log('解析的剩余JSON数据:', jsonData) } catch (error) { console.error('解析剩余JSON数据失败:', error, line) } } // 处理解析成功的数据 if (jsonData) { console.log('=== 解析成功的剩余数据 ===', jsonData) if (jsonData.resultContent) { console.log('=== 准备发送剩余resultContent ===', jsonData.resultContent) onMessage(jsonData.resultContent) } else if (jsonData.choices && jsonData.choices[0] && jsonData.choices[0].delta && jsonData.choices[0].delta.content) { console.log('=== 准备发送剩余OpenAI格式内容 ===', jsonData.choices[0].delta.content) onMessage(jsonData.choices[0].delta.content) } else if (typeof jsonData === 'string') { console.log('=== 准备发送剩余字符串 ===', jsonData) onMessage(jsonData) } else { console.log('=== 剩余数据格式不匹配,跳过content字段 ===', jsonData) } } }) } onComplete() return } const chunk = decoder.decode(value, { stream: true }) console.log('接收到原始数据块:', chunk) buffer += chunk // 处理可能包含\r\n的情况 const lines = buffer.split(/\r?\n/) // 保留最后一行,因为它可能不完整 buffer = lines.pop() || '' console.log('处理的行数:', lines.length) lines.forEach(line => { line = line.trim() if (!line || line.startsWith(':')) return console.log('处理数据行:', line) // 尝试提取JSON数据 let jsonData = null if (line.startsWith('data: ')) { try { jsonData = JSON.parse(line.slice(6)) console.log('解析的SSE数据:', jsonData) } catch (error) { console.error('解析SSE数据失败:', error, line) } } else if (line.startsWith('data:')) { try { jsonData = JSON.parse(line.slice(5)) console.log('解析的SSE数据(无空格):', jsonData) } catch (error) { console.error('解析SSE数据失败(无空格):', error, line) } } else { try { jsonData = JSON.parse(line) console.log('解析的JSON数据:', jsonData) } catch (error) { console.error('解析JSON数据失败:', error, line) } } // 处理解析成功的数据 if (jsonData) { console.log('=== 解析成功的数据 ===', jsonData) if (jsonData.resultContent) { console.log('=== 准备发送resultContent ===', jsonData.resultContent) onMessage(jsonData.resultContent) } else if (jsonData.choices && jsonData.choices[0] && jsonData.choices[0].delta && jsonData.choices[0].delta.content) { console.log('=== 准备发送OpenAI格式内容 ===', jsonData.choices[0].delta.content) onMessage(jsonData.choices[0].delta.content) } else if (typeof jsonData === 'string') { console.log('=== 准备发送字符串 ===', jsonData) onMessage(jsonData) } else { console.log('=== 数据格式不匹配,跳过content字段 ===', jsonData) } } }) return readStream() }) } return readStream() }) .catch(error => { if (error.name === 'AbortError') { console.log('请求被取消') return } console.error('流式请求错误:', error) onError(new Error('网络连接失败,请检查网络连接后重试')) }) // 返回controller以便外部可以取消请求 return controller }