brief-rags-bench/static/js/services/query.service.js

187 lines
5.7 KiB
JavaScript
Raw Normal View History

2025-12-25 09:39:58 +01:00
/**
* 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<object>} 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<Array>} Массив вопросов
*/
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<object>} Загруженный ответ
*/
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<string>} Массив вопросов
*/
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
}