Spaces:
Running
Running
| /* PXG-Tiny playground worker — runs the real NumPy pipeline in-browser | |
| via Pyodide. The model weights (~1.8 MB) load from this same site. */ | |
| let pyodideReady = null; | |
| async function boot() { | |
| importScripts("https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js"); | |
| const py = await loadPyodide(); | |
| self.postMessage({ type: "status", msg: "loading numpy…" }); | |
| await py.loadPackage("numpy"); | |
| self.postMessage({ type: "status", msg: "fetching model files…" }); | |
| // write runtime modules + weights into the Pyodide FS | |
| const files = [ | |
| ["pxg_tiny/__init__.py", "/lib/pxg_tiny/__init__.py"], | |
| ["pxg_tiny/config.py", "/lib/pxg_tiny/config.py"], | |
| ["pxg_tiny/tokenizer.py", "/lib/pxg_tiny/tokenizer.py"], | |
| ["pxg_tiny/quality.py", "/lib/pxg_tiny/quality.py"], | |
| ["pxg_tiny/runtime_pipeline.py", "/lib/pxg_tiny/runtime_pipeline.py"], | |
| ["webgen.py", "/lib/webgen.py"], | |
| ["weights/runtime.json", "/lib/bundle/runtime.json"], | |
| ["weights/tokenizer.json", "/lib/bundle/tokenizer.json"], | |
| ]; | |
| py.FS.mkdirTree("/lib/pxg_tiny"); | |
| py.FS.mkdirTree("/lib/bundle"); | |
| for (const [src, dst] of files) { | |
| const buf = await (await fetch(src)).arrayBuffer(); | |
| py.FS.writeFile(dst, new Uint8Array(buf)); | |
| } | |
| for (const npz of ["gen_int8.npz", "vq_int8.npz"]) { | |
| const buf = await (await fetch("weights/" + npz)).arrayBuffer(); | |
| py.FS.writeFile("/lib/bundle/" + npz, new Uint8Array(buf)); | |
| self.postMessage({ type: "status", msg: "fetched " + npz }); | |
| } | |
| self.postMessage({ type: "status", msg: "warming up the model…" }); | |
| await py.runPythonAsync(` | |
| import sys | |
| sys.path.insert(0, "/lib") | |
| from webgen import WebPipeline | |
| PIPE = WebPipeline("/lib/bundle") | |
| _g, _m = PIPE.generate("a golden sword", seed=0) | |
| "ready" | |
| `); | |
| self.postMessage({ type: "ready" }); | |
| return py; | |
| } | |
| const PYTHON_GEN = ` | |
| import json | |
| import numpy as np | |
| from webgen import WebPipeline | |
| def _run(prompt, seed, verify): | |
| grid, meta = PIPE.generate(prompt, seed=int(seed), enforce_quality=bool(verify)) | |
| if grid is None: | |
| return json.dumps({"gate": meta["gate"], "message": meta.get("message",""), "rgba": None, | |
| "seed": 0, "attempt": 0}) | |
| rgba = PIPE.grid_rgba(grid) | |
| return json.dumps({"gate": meta.get("gate",""), "message": meta.get("message",""), | |
| "rgba": rgba.reshape(-1).tolist(), | |
| "seed": int(meta.get("seed", seed)), | |
| "attempt": int(meta.get("attempt", 0))}) | |
| `; | |
| onmessage = async (e) => { | |
| const { type, prompt, seed, verify } = e.data; | |
| if (type === "init") { | |
| try { | |
| if (!pyodideReady) pyodideReady = boot(); | |
| await pyodideReady; | |
| const py = await pyodideReady; | |
| if (!py.globals.has("_run")) py.runPython(PYTHON_GEN); | |
| } catch (err) { | |
| self.postMessage({ type: "error", msg: String(err) }); | |
| } | |
| } else if (type === "generate") { | |
| try { | |
| if (!pyodideReady) pyodideReady = boot(); | |
| const py = await pyodideReady; | |
| if (!py.globals.has("_run")) py.runPython(PYTHON_GEN); | |
| py.globals.set("_prompt", prompt); | |
| py.globals.set("_seed", seed); | |
| py.globals.set("_verify", verify); | |
| const out = py.runPython( | |
| "_run(_prompt, _seed, _verify)"); | |
| self.postMessage({ type: "result", data: JSON.parse(out) }); | |
| } catch (err) { | |
| self.postMessage({ type: "error", msg: String(err) }); | |
| } | |
| } | |
| }; | |