/** * Query Service * * Сервис отправки запросов к RAG backend. */ import api from './api-client.js' import appState from '../state/appState.js' import { validateJSON } from '../utils/validation.utils.js' import { generateUUID } from '../utils/format.utils.js' import { loadFileAsJSON, loadFileAsText } from '../utils/file.utils.js' /** * Построить тело запроса из UI * @param {string} mode - Режим ('questions' или 'raw-json') * @param {string} questionsText - Текст вопросов (для режима questions) * @param {string} jsonText - JSON текст (для режима raw-json) * @returns {Array<{body: string, with_docs: boolean}>} Массив вопросов */ export function buildRequestBody(mode, questionsText, jsonText) { if (mode === 'questions') { const questions = questionsText .split('\n') .map(line => line.trim()) .filter(line => line.length > 0) if (questions.length === 0) { throw new Error('Введите хотя бы один вопрос') } const settings = appState.settings || {} const defaultWithDocs = settings.defaultWithDocs !== undefined ? settings.defaultWithDocs : true return questions.map(q => ({ body: q, with_docs: defaultWithDocs })) } else if (mode === 'raw-json') { const validation = validateJSON(jsonText) if (!validation.valid) { throw new Error(validation.error) } return validation.data } else { throw new Error(`Неизвестный режим: ${mode}`) } } /** * Отправить запрос к RAG backend * @param {string} environment - Окружение (ift/psi/prod) * @param {string} apiMode - Режим API ('bench' или 'backend') * @param {Array} questions - Массив вопросов * @param {boolean} resetSession - Сбрасывать ли сессию (только для backend mode) * @returns {Promise} API response */ export async function sendQuery(environment, apiMode, questions, resetSession = true) { let apiResponse if (apiMode === 'bench') { apiResponse = await api.benchQuery(environment, questions) } else if (apiMode === 'backend') { apiResponse = await api.backendQuery(environment, questions, resetSession) } else { throw new Error(`Неизвестный режим API: ${apiMode}`) } // Validate response format if (!apiResponse.response || !apiResponse.response.answers || !Array.isArray(apiResponse.response.answers)) { throw new Error('Некорректный формат ответа: отсутствует поле "answers"') } return apiResponse } /** * Обработать результат запроса и обновить AppState * @param {string} environment - Окружение * @param {Array} requestBody - Тело запроса * @param {object} apiResponse - Ответ от API */ export function processQueryResponse(environment, requestBody, apiResponse) { const env = appState.getEnvironment(environment) // Update environment state env.currentRequest = requestBody env.currentResponse = apiResponse.response env.requestId = apiResponse.request_id env.requestTimestamp = apiResponse.timestamp env.currentAnswerIndex = 0 env.annotations = {} // Save to localStorage appState.saveEnvironmentToStorage(environment) return env } /** * Загрузить запрос из файла * @param {File} file - JSON файл с запросом * @returns {Promise} Массив вопросов */ export async function loadRequestFromFile(file) { try { const data = await loadFileAsJSON(file) // Validate it's an array if (!Array.isArray(data)) { throw new Error('Файл должен содержать JSON массив') } return data } catch (error) { console.error('Error loading request from file:', error) throw new Error(`Ошибка загрузки запроса: ${error.message}`) } } /** * Загрузить ответ из файла * @param {File} file - JSON файл с ответом * @param {string} environment - Текущее окружение * @returns {Promise} Загруженный ответ */ export async function loadResponseFromFile(file, environment) { try { const data = await loadFileAsJSON(file) // Validate response format if (!data.answers || !Array.isArray(data.answers)) { throw new Error('Файл должен содержать объект с полем "answers" (массив)') } const env = appState.getEnvironment(environment) // Set response env.currentResponse = data env.currentAnswerIndex = 0 env.requestTimestamp = new Date().toISOString() env.requestId = 'loaded-' + generateUUID() env.annotations = {} // Try to reconstruct request from questions in response env.currentRequest = data.answers.map(answer => ({ body: answer.question, with_docs: true })) // Save to localStorage appState.saveEnvironmentToStorage(environment) return data } catch (error) { console.error('Error loading response from file:', error) throw new Error(`Ошибка загрузки ответа: ${error.message}`) } } /** * Извлечь вопросы из textarea * @param {string} text - Текст из textarea * @returns {Array} Массив вопросов */ export function extractQuestions(text) { return text .split('\n') .map(line => line.trim()) .filter(line => line.length > 0) } // Export as default object export default { buildRequestBody, sendQuery, processQueryResponse, loadRequestFromFile, loadResponseFromFile, extractQuestions }