Islamic3 / camelbert.js
Ghada-99-Ragab's picture
Upload 31 files
c08b36a verified
Raw History Blame Contribute Delete
2.66 kB
/* Detection back-ends for Subtask 1A.
- "standard": rules + corpus scanner (runs in the Python worker).
- "camelbert": fine-tuned CAMeLBERT-MSA token classifier (BIO tags: B/I-Ayah, B/I-Hadith, O).
* With ICV_CONFIG.HF_MODEL_ID set, the Hugging Face Inference API is called.
* Without it, a clearly labelled SIMULATION runs: no model weights are loaded; the spans come from the
standard detector and are re-expressed as BIO tags with deterministic pseudo-confidences. */
(function () {
const cfg = window.ICV_CONFIG;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function bioTags(text, spans) {
const tokens = []; const re = /\S+/g; let m;
while ((m = re.exec(text))) {
const s = spans.find((x) => m.index < x.end && m.index + m[0].length > x.start);
let tag = "O";
if (s) tag = (m.index <= s.start || !tokens.length || !String(tokens[tokens.length - 1].tag).endsWith(s.label) ? "B-" : "I-") + s.label;
tokens.push({ token: m[0], tag });
}
return tokens;
}
async function viaHuggingFace(text) {
const headers = { "Content-Type": "application/json" };
if (cfg.HF_TOKEN) headers.Authorization = "Bearer " + cfg.HF_TOKEN;
const r = await fetch("https://api-inference.huggingface.co/models/" + cfg.HF_MODEL_ID, {
method: "POST", headers, body: JSON.stringify({ inputs: text, parameters: { aggregation_strategy: "simple" }, options: { wait_for_model: true } })
});
if (!r.ok) throw new Error("HF " + r.status);
const groups = await r.json();
const spans = groups.map((g) => ({ label: /hadith/i.test(g.entity_group) ? "Hadith" : "Ayah", start: g.start, end: g.end, score: g.score }))
.filter((s) => s.end > s.start);
return { spans, simulated: false };
}
/* detectSpans: returns { spans, tags, simulated, note }. `standard` is a function returning the standard detector's spans. */
async function detectSpans(text, standard) {
if (cfg.HF_MODEL_ID) {
try { const out = await viaHuggingFace(text); out.tags = bioTags(text, out.spans); return out; }
catch (e) { /* fall through to the simulation so a demo never breaks */ }
}
await sleep(500 + Math.min(700, text.length / 8)); // model "inference" latency, for a realistic demo
const spans = await standard();
const conf = (s) => 0.9 + ((parseInt(window.icvCache.hash(text + s.start), 36) % 90) / 1000);
const scored = spans.map((s) => ({ ...s, score: Math.round(conf(s) * 1000) / 1000 }));
return { spans: scored, tags: bioTags(text, scored), simulated: true };
}
window.icvDetectors = { detectSpans, bioTags };
})();