import { normalizeText } from './text_preprocessing.js'; import { correctText } from './correction_inference.js'; import { tokenize, extractTrackedEdits, renderHighlighted } from './tracked_edits.js'; import { categorizeErrors } from './error_categories.js'; import { checkMeaningPreservation } from './meaning_preservation.js'; import { detectOvercorrection } from './overcorrection_warning.js'; import { correctBatch, downloadCsv } from './batch_correction.js'; import { renderEvaluationDashboard } from './evaluation_dashboard.js'; const state = { metadata: null, batchRows: [], samples: null }; const $ = (selector) => document.querySelector(selector); const $$ = (selector) => [...document.querySelectorAll(selector)]; function confidenceProxy(meaning, tracked, mode) { const editRatio = tracked.changedTokenCount / Math.max(1, tracked.sourceTokenCount); const modeComponent = mode === 'live-browser-model' ? 0.72 : 0.52; const score = Math.max(0, Math.min(1, modeComponent * 0.45 + meaning.score * 0.45 + (1 - Math.min(1, editRatio)) * 0.1)); return { score, label: score >= 0.8 ? 'high' : score >= 0.6 ? 'medium' : 'low', note: 'Confidence proxy only; not a calibrated correctness probability.', }; } function enrich(generation) { const tracked = extractTrackedEdits(generation.original, generation.corrected); const categories = categorizeErrors(tracked); const meaning = checkMeaningPreservation(generation.original, generation.corrected); const over = detectOvercorrection(tracked, meaning, false, categories.categories); const confidence = confidenceProxy(meaning, tracked, generation.mode); return { ...generation, tracked, categories, meaning, over, confidence }; } function setStatus(message, type = 'neutral') { const element = $('#run-status'); element.className = `run-status ${type}`; element.textContent = message; } function renderResult(result) { $('#results-panel').hidden = false; $('#original-output').textContent = result.original; $('#corrected-output').textContent = result.corrected; $('#original-highlight').innerHTML = renderHighlighted(tokenize(result.original), result.tracked.edits, 'source'); $('#corrected-highlight').innerHTML = renderHighlighted(tokenize(result.corrected), result.tracked.edits, 'target'); $('#mode-badge').textContent = result.mode.replaceAll('-', ' '); $('#confidence-value').textContent = `${(result.confidence.score * 100).toFixed(0)}% (${result.confidence.label})`; $('#meaning-value').textContent = `${(result.meaning.score * 100).toFixed(0)}%`; $('#latency-value').textContent = `${result.latencyMs.toFixed(1)} ms`; $('#edit-count-value').textContent = String(result.tracked.wordLevelEditCount); $('#category-list').innerHTML = result.categories.categories.map((category) => `${category}`).join(''); $('#edit-list').innerHTML = result.categories.categorizedEdits.length ? result.categories.categorizedEdits.map((edit) => `
  • ${edit.operation}${edit.before || '∅'}→${edit.after || '∅'}${edit.category}
  • `).join('') : '
  • No edits detected.
  • '; const warning = $('#overcorrection-warning'); warning.className = `warning-card ${result.over.flag ? 'active' : 'clear'}`; warning.innerHTML = `${result.over.message}${result.over.reasons.length ? `` : ''}`; $('#meaning-warnings').innerHTML = result.meaning.warnings.length ? result.meaning.warnings.map((warningText) => `
  • ${warningText}
  • `).join('') : '
  • No heuristic meaning warning detected.
  • '; $('#fallback-disclosure').hidden = result.mode === 'live-browser-model'; } async function runSingle() { const text = normalizeText($('#text-input').value); if (!text) { setStatus('Enter a sentence or paragraph first.', 'error'); return; } $('#run-button').disabled = true; setStatus('Running correction…', 'loading'); try { const result = enrich(await correctText(text, state.metadata, (progress) => setStatus(progress?.status ?? 'Loading browser model…', 'loading'))); renderResult(result); setStatus(result.mode === 'live-browser-model' ? 'Live browser model completed.' : 'Fallback demonstration completed. Review the disclosure.', result.mode === 'live-browser-model' ? 'success' : 'warning'); } catch (error) { setStatus(error.message, 'error'); } finally { $('#run-button').disabled = false; } } function renderBatchTable(rows) { const body = $('#batch-results-body'); body.innerHTML = rows.map((row) => ` ${row.rowId}${row.original}${row.corrected}${row.tracked.wordLevelEditCount} ${row.categories.categories.join(', ')}${(row.confidence.score*100).toFixed(0)}%${(row.meaning.score*100).toFixed(0)}%${row.over.flag ? 'Review' : 'No'}${row.latencyMs.toFixed(1)} `).join(''); $('#batch-result-panel').hidden = false; } async function runBatch() { $('#batch-run-button').disabled = true; try { state.batchRows = await correctBatch($('#batch-input').value, state.metadata, enrich); renderBatchTable(state.batchRows); } catch (error) { setStatus(error.message, 'error'); } finally { $('#batch-run-button').disabled = false; } } function setupTabs() { $$('.tab-button').forEach((button) => button.addEventListener('click', () => { $$('.tab-button').forEach((item) => item.classList.toggle('active', item === button)); $$('.tab-panel').forEach((panel) => { panel.hidden = panel.id !== button.dataset.tab; }); })); } function setupSamples() { const select = $('#sample-select'); const samples = [...state.samples.sentences, ...state.samples.paragraphs]; select.innerHTML = '' + samples.map((sample, index) => ``).join(''); select.addEventListener('change', () => { if (select.value !== '') $('#text-input').value = samples[Number(select.value)]; }); } async function initialize() { const [metadataResponse, samplesResponse] = await Promise.all([fetch(new URL('./metadata.json', import.meta.url)), fetch(new URL('./sample_texts/samples.json', import.meta.url))]); state.metadata = await metadataResponse.json(); state.samples = await samplesResponse.json(); $('#deployment-mode').textContent = state.metadata.enable_live_model ? 'Live browser ONNX model configured' : 'Static fallback mode active'; $('#model-name').textContent = state.metadata.selected_base_model; $('#legacy-model-name').textContent = state.metadata.legacy_notebook_model; setupTabs(); setupSamples(); renderEvaluationDashboard($('#evaluation-dashboard'), state.metadata); $('#run-button').addEventListener('click', runSingle); $('#batch-run-button').addEventListener('click', runBatch); $('#download-button').addEventListener('click', () => downloadCsv(state.batchRows)); $('#clear-button').addEventListener('click', () => { $('#text-input').value=''; $('#results-panel').hidden=true; setStatus('Ready.', 'neutral'); }); setStatus('Ready.', 'neutral'); } initialize().catch((error) => setStatus(`Application initialization failed: ${error.message}`, 'error'));