brief-rags-bench/static/js/ui/annotations.ui.js

245 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Annotations UI
*
* UI компонент для работы с аннотациями ответов.
*/
import appState from '../state/appState.js'
import { getInputValue, setInputValue } from '../utils/dom.utils.js'
/**
* Инициализировать аннотацию для ответа
* @param {number} index - Индекс ответа
*/
export function initForAnswer(index) {
const env = appState.getCurrentEnv()
if (!env.annotations[index]) {
env.annotations[index] = {
overall: { rating: '', comment: '' },
body_research: { issues: [], comment: '' },
body_analytical_hub: { issues: [], comment: '' },
docs_from_vectorstore: { research: {}, analytical_hub: {} },
docs_to_llm: { research: {}, analytical_hub: {} }
}
}
}
/**
* Загрузить аннотации для ответа
* @param {number} index - Индекс ответа
*/
export function loadForAnswer(index) {
initForAnswer(index)
const env = appState.getCurrentEnv()
const annotation = env.annotations[index]
// Load overall rating
const ratingSelect = document.getElementById('overall-rating')
const overallComment = document.getElementById('overall-comment')
if (ratingSelect) {
ratingSelect.value = annotation.overall.rating || ''
}
if (overallComment) {
setInputValue(overallComment, annotation.overall.comment || '')
}
// Load body annotations
loadSection('body_research', annotation.body_research)
loadSection('body_analytical_hub', annotation.body_analytical_hub)
// Load document annotations
loadDocuments('docs_from_vectorstore', 'research', annotation.docs_from_vectorstore?.research)
loadDocuments('docs_from_vectorstore', 'analytical_hub', annotation.docs_from_vectorstore?.analytical_hub)
loadDocuments('docs_to_llm', 'research', annotation.docs_to_llm?.research)
loadDocuments('docs_to_llm', 'analytical_hub', annotation.docs_to_llm?.analytical_hub)
// Setup event listeners for current answer
setupListeners()
}
/**
* Загрузить аннотацию секции (body)
* @param {string} section - Название секции
* @param {object} data - Данные аннотации
*/
export function loadSection(section, data) {
// Load checkboxes
document.querySelectorAll(`input[data-section="${section}"]`).forEach(checkbox => {
if (checkbox.type === 'checkbox') {
const issue = checkbox.dataset.issue
checkbox.checked = data.issues.includes(issue)
updateCheckboxStyle(checkbox)
}
})
// Load comment
const textarea = document.querySelector(`textarea[data-section="${section}"]:not([data-doc-index])`)
if (textarea) {
setInputValue(textarea, data.comment || '')
}
}
/**
* Загрузить аннотации документов
* @param {string} section - Секция (docs_from_vectorstore, docs_to_llm)
* @param {string} subsection - Подсекция (research, analytical_hub)
* @param {object} docs - Объект с аннотациями документов
*/
export function loadDocuments(section, subsection, docs) {
if (!docs) return
Object.keys(docs).forEach(docIndex => {
const data = docs[docIndex]
// Load checkboxes
document.querySelectorAll(
`input[data-section="${section}"][data-subsection="${subsection}"][data-doc-index="${docIndex}"]`
).forEach(checkbox => {
if (checkbox.type === 'checkbox') {
const issue = checkbox.dataset.issue
checkbox.checked = data.issues?.includes(issue) || false
updateCheckboxStyle(checkbox)
}
})
// Load comment
const textarea = document.querySelector(
`textarea[data-section="${section}"][data-subsection="${subsection}"][data-doc-index="${docIndex}"]`
)
if (textarea) {
setInputValue(textarea, data.comment || '')
}
})
}
/**
* Настроить обработчики событий для аннотаций
*/
export function setupListeners() {
const env = appState.getCurrentEnv()
const index = env.currentAnswerIndex
// Overall rating
const ratingSelect = document.getElementById('overall-rating')
const overallComment = document.getElementById('overall-comment')
if (ratingSelect) {
ratingSelect.onchange = (e) => {
env.annotations[index].overall.rating = e.target.value
saveDraft()
}
}
if (overallComment) {
overallComment.oninput = (e) => {
env.annotations[index].overall.comment = getInputValue(e.target)
saveDraft()
}
}
// Section checkboxes and textareas
document.querySelectorAll('input.checkbox, textarea').forEach(element => {
const section = element.dataset.section
const subsection = element.dataset.subsection
const docIndex = element.dataset.docIndex
if (!section) return
if (element.type === 'checkbox') {
element.onchange = (e) => {
const issue = e.target.dataset.issue
if (docIndex !== undefined) {
// Document annotation
if (!env.annotations[index][section]) {
env.annotations[index][section] = { research: {}, analytical_hub: {} }
}
if (!env.annotations[index][section][subsection]) {
env.annotations[index][section][subsection] = {}
}
if (!env.annotations[index][section][subsection][docIndex]) {
env.annotations[index][section][subsection][docIndex] = { issues: [], comment: '' }
}
const issues = env.annotations[index][section][subsection][docIndex].issues
if (e.target.checked) {
if (!issues.includes(issue)) issues.push(issue)
} else {
const idx = issues.indexOf(issue)
if (idx > -1) issues.splice(idx, 1)
}
} else {
// Body annotation
const issues = env.annotations[index][section].issues
if (e.target.checked) {
if (!issues.includes(issue)) issues.push(issue)
} else {
const idx = issues.indexOf(issue)
if (idx > -1) issues.splice(idx, 1)
}
}
updateCheckboxStyle(e.target)
saveDraft()
}
} else if (element.tagName === 'TEXTAREA') {
element.oninput = (e) => {
const value = getInputValue(e.target)
if (docIndex !== undefined) {
// Document annotation
if (!env.annotations[index][section][subsection][docIndex]) {
env.annotations[index][section][subsection][docIndex] = { issues: [], comment: '' }
}
env.annotations[index][section][subsection][docIndex].comment = value
} else if (section !== 'overall') {
// Body annotation
env.annotations[index][section].comment = value
}
saveDraft()
}
}
})
}
/**
* Обновить стиль чекбокса (добавить checked класс к label)
* @param {HTMLElement} checkbox - Чекбокс элемент
*/
export function updateCheckboxStyle(checkbox) {
const label = checkbox.closest('.issue-checkbox')
if (label) {
if (checkbox.checked) {
label.classList.add('checked')
} else {
label.classList.remove('checked')
}
}
}
/**
* Сохранить черновик аннотаций в localStorage
*/
export function saveDraft() {
const currentEnv = appState.getCurrentEnvironment()
appState.saveEnvironmentToStorage(currentEnv)
}
// Export as default object
export default {
initForAnswer,
loadForAnswer,
loadSection,
loadDocuments,
setupListeners,
updateCheckboxStyle,
saveDraft
}