MediaWiki:Gadget-LabelScanIndexer.js: Unterschied zwischen den Versionen
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
/* Gadget: LabelScanIndexer (Auto-Save) | /* Gadget: LabelScanIndexer (Auto-Save) | ||
* Erzeugt Embeddings lokal (CLIP) und speichert in MediaWiki:Gadget-LabelScan-index.json | * Erzeugt Embeddings lokal (CLIP) und speichert in MediaWiki:Gadget-LabelScan-index.json | ||
* Läuft nur auf der Seite "Hilfe:LabelScan-Indexer" | |||
*/ | */ | ||
/* global mw */ | /* global mw */ | ||
(function () { | (function () { | ||
'use strict'; | |||
// ---------- Seitenerkennung (im IIFE, also return ist erlaubt) ---------- | |||
// | const NS = mw.config.get('wgNamespaceNumber'); // 12 = Hilfe/Help | ||
const TITLE = mw.config.get('wgTitle'); // Titel ohne Namespace | |||
const ON_PAGE = (NS === 12 && TITLE === 'LabelScan-Indexer'); | |||
if (!ON_PAGE) { | |||
// Nur debuggen, kein Top-Level return außerhalb einer Funktion | |||
// console.debug('[LabelScanIndexer] nicht aktiv auf', NS, TITLE); | // console.debug('[LabelScanIndexer] nicht aktiv auf', NS, TITLE); | ||
return; | return; | ||
| Zeile 90: | Zeile 92: | ||
// mod.env.backends.onnx.preferredBackend = 'webgpu'; | // mod.env.backends.onnx.preferredBackend = 'webgpu'; | ||
// WASM-Runtime- | // WASM-Runtime-Pfad | ||
mod.env.backends = mod.env.backends || {}; | mod.env.backends = mod.env.backends || {}; | ||
mod.env.backends.onnx = mod.env.backends.onnx || {}; | mod.env.backends.onnx = mod.env.backends.onnx || {}; | ||
| Zeile 155: | Zeile 157: | ||
if (!runBtn) { | if (!runBtn) { | ||
console.warn('[LabelScanIndexer] Button #idx-run nicht gefunden – ist das HTML auf der Seite eingebunden?'); | console.warn('[LabelScanIndexer] Button #idx-run nicht gefunden – ist das HTML auf der Seite eingebunden?'); | ||
return; | } else { | ||
runBtn.addEventListener('click', async () => { | |||
try { | |||
if (!hasInterfaceRight()) { | |||
alert('⚠️ Du brauchst Admin/Interface-Rechte (editinterface).'); | |||
return; | |||
} | |||
const titleEl = $('idx-title'); | |||
const thumbEl = $('idx-thumb'); | |||
const fileEl = $('idx-file'); | |||
const title = titleEl ? titleEl.value.trim() : ''; | |||
const thumb = thumbEl ? thumbEl.value.trim() : ''; | |||
const file = fileEl?.files?.[0]; | |||
if (!title) { alert('Titel fehlt.'); return; } | |||
if (!file) { alert('Bitte eine Bilddatei wählen.'); return; } | |||
runBtn.disabled = true; | |||
status('Embedding berechnen …'); | |||
const vec = await buildEmbeddingFromFile(file); | |||
const b64 = float32ToBase64(vec); | |||
const outBox = $('idx-out'); | |||
if (outBox) outBox.value = JSON.stringify({ title, thumb, embed: b64 }, null, 2); | |||
status('Index laden …'); | |||
const arr = await fetchIndexJSON(); | |||
arr.push({ title, thumb, embed: b64 }); | |||
status('Speichern …'); | |||
await saveIndexJSON(arr, `LabelScan: +1 embedding für "${title}"`); | |||
status('Gespeichert ✅'); | |||
} catch (e) { | |||
console.error(e); | |||
status('Fehler ❌ ' + (e?.message || e)); | |||
alert('Fehler: ' + (e?.message || e)); | |||
} finally { | |||
runBtn.disabled = false; | |||
} | } | ||
} | }); | ||
} | |||
console.log('[LabelScanIndexer] bereit'); | console.log('[LabelScanIndexer] bereit'); | ||
})(); | })(); | ||