import { LlamaCppWasm } from "https://esm.sh/llama-cpp-wasm@0.0.4"; const C = window.GGUF_CONFIG; const $ = id => document.getElementById(id); let engine = null; let active = false; function status(s) { $("status").textContent = s; } function info(s) { $("info").textContent = s; } function progress(v) { $("bar").style.width = Math.max(0, Math.min(100, v)) + "%"; } async function createEngine() { if (engine) return engine; engine = await LlamaCppWasm.create({ moduleUrl: new URL("https://esm.sh/llama-cpp-wasm@0.0.3/wasm/llama-cpp-wasm.js").href, wasmUrl: new URL("https://esm.sh/llama-cpp-wasm@0.0.3/wasm/llama-cpp-wasm.wasm").href }); return engine; } async function loadModel(source) { $("load").disabled = true; status("loading runtime"); info("Starting WebAssembly runtime…"); progress(0); const e = await createEngine(); status("downloading model"); info("Downloading GGUF into browser memory…"); await e.load(source, { contextSize: C.contextSize, batchSize: C.batchSize, threads: C.threads }, p => { if (p && p.totalBytes) { progress((p.loadedBytes / p.totalBytes) * 100); } }); progress(100); status("ready"); info("Model loaded locally in this browser."); $("send").disabled = false; $("load").disabled = false; } $("load").onclick = async () => { try { const f = $("file").files[0]; await loadModel(f ? {file: f} : {url: C.modelUrl}); } catch (e) { console.error(e); status("error"); info(String(e?.message || e)); $("load").disabled = false; } }; $("file").onchange = () => { if ($("file").files[0]) info("Selected local GGUF: " + $("file").files[0].name); }; $("send").onclick = async () => { if (!engine || active) return; active = true; $("send").disabled = true; $("stop").disabled = false; $("output").textContent = ""; const temperature = Number($("temp").value) || C.defaultTemperature; const maxTokens = Number($("max").value) || C.defaultMaxTokens; const prompt = $("prompt").value; try { for await (const text of engine.completion(prompt, { maxTokens, temperature, topK: C.defaultTopK, topP: C.defaultTopP })) { $("output").textContent += text; } } catch (e) { if (!String(e?.message || e).toLowerCase().includes("cancel")) { $("output").textContent += "\n\n[ERROR] " + String(e?.message || e); } } finally { active = false; $("send").disabled = false; $("stop").disabled = true; } }; $("stop").onclick = () => { try { engine?.cancel(); } catch {} }; window.MyGGUFAPI = { async chat(prompt, options = {}) { if (!engine) throw new Error("Model is not loaded."); let text = ""; for await (const chunk of engine.completion(String(prompt), { maxTokens: options.maxTokens ?? C.defaultMaxTokens, temperature: options.temperature ?? C.defaultTemperature, topK: options.topK ?? C.defaultTopK, topP: options.topP ?? C.defaultTopP, seed: options.seed })) text += chunk; return { text, model: C.modelName }; }, model() { return C.modelName; }, loaded() { return !!engine; } };