Download app.js from anmol-unitmole/05-grammar-error-correction-t5-encoder-decoder: direct link, hf CLI and curl.
- Browser
- Download file 7.43 kB
-
https://huggingface.co/spaces/anmol-unitmole/05-grammar-error-correction-t5-encoder-decoder/resolve/main/app.js
- Command line
-
hf download hf://spaces/anmol-unitmole/05-grammar-error-correction-t5-encoder-decoder/app.js
-
curl -L -o app.js https://huggingface.co/spaces/anmol-unitmole/05-grammar-error-correction-t5-encoder-decoder/resolve/main/app.js
7.43 kB
| 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) => `<span class="tag">${category}</span>`).join(''); | |
| $('#edit-list').innerHTML = result.categories.categorizedEdits.length | |
| ? result.categories.categorizedEdits.map((edit) => `<li><span class="edit-op">${edit.operation}</span><code>${edit.before || '∅'}</code><span>→</span><code>${edit.after || '∅'}</code><span class="tag subtle">${edit.category}</span></li>`).join('') | |
| : '<li>No edits detected.</li>'; | |
| const warning = $('#overcorrection-warning'); | |
| warning.className = `warning-card ${result.over.flag ? 'active' : 'clear'}`; | |
| warning.innerHTML = `<strong>${result.over.message}</strong>${result.over.reasons.length ? `<ul>${result.over.reasons.map((reason) => `<li>${reason}</li>`).join('')}</ul>` : ''}`; | |
| $('#meaning-warnings').innerHTML = result.meaning.warnings.length ? result.meaning.warnings.map((warningText) => `<li>${warningText}</li>`).join('') : '<li>No heuristic meaning warning detected.</li>'; | |
| $('#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) => `<tr> | |
| <td>${row.rowId}</td><td>${row.original}</td><td>${row.corrected}</td><td>${row.tracked.wordLevelEditCount}</td> | |
| <td>${row.categories.categories.join(', ')}</td><td>${(row.confidence.score*100).toFixed(0)}%</td><td>${(row.meaning.score*100).toFixed(0)}%</td><td>${row.over.flag ? 'Review' : 'No'}</td><td>${row.latencyMs.toFixed(1)}</td> | |
| </tr>`).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 = '<option value="">Choose a safe sample…</option>' + samples.map((sample, index) => `<option value="${index}">${sample.slice(0, 76)}${sample.length > 76 ? '…' : ''}</option>`).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')); | |