abuzreq's picture
Contribute a run, model requests from the dataset's Discussions, likes through the Netlify likes server
ce28b3b verified
Raw History Blame
3.45 kB
// Where the knowledge base lives and how to read it. ?data=<base url> points the page at another copy of the
// dataset (e.g. a local working copy); every link the page makes keeps it.
export const PARAMS = new URLSearchParams(location.search);
export const DATA = (PARAMS.get("data") || "https://huggingface.co/datasets/abuzreq/model-bending-knowledge-base/resolve/main").replace(/\/$/, "");
export const DATASET = "abuzreq/model-bending-knowledge-base";
export const DATASET_URL = `https://huggingface.co/datasets/${DATASET}`;
export const NAVIGATOR = "https://abuzreq-model-bending-navigator.static.hf.space";
export const SKILL_URL = "https://github.com/abuzreq/comfyui-model-bending-agent";
export const NODES_URL = "https://github.com/abuzreq/ComfyUI-Model-Bending";
export const PAPER_URL = "https://arxiv.org/abs/2607.22428";
export const file = (p) => `${DATA}/${p}`;
export const baselineImg = (id) => file(`baselines/${id}.webp`);
export const recordImg = (dir) => file(`${dir}/output.webp`);
// Links inside the navigator: ?record=, ?cell=, ?base=, ?page=, always keeping ?data=.
export function linkTo(q = {}, hash = "") {
const p = new URLSearchParams();
if (PARAMS.get("data")) p.set("data", PARAMS.get("data"));
for (const [k, v] of Object.entries(q)) if (v !== undefined && v !== null && v !== "") p.set(k, v);
const s = p.toString();
return `${location.pathname}${s ? "?" + s : ""}${hash}`;
}
const cache = new Map();
function fetchText(p) {
if (!cache.has(p)) {
cache.set(p, fetch(file(p)).then((r) => {
if (!r.ok) throw Object.assign(new Error(`${p}: HTTP ${r.status}`), { status: r.status });
return r.text();
}));
cache.get(p).catch(() => cache.delete(p));
}
return cache.get(p);
}
export const getJSON = (p) => fetchText(p).then((t) => JSON.parse(t));
export const getLines = (p) => fetchText(p).then((t) => t.split("\n").filter(Boolean).map((l) => JSON.parse(l)));
let core;
// Cells, findings, the effect vocabulary and the index's counts: what every page needs.
export function loadCore() {
core ||= Promise.all([getLines("index/cells.jsonl"), getLines("index/findings.jsonl"), getJSON("vocab/effects.json"),
getJSON("index/meta.json").catch(() => null)])
.then(([cells, findings, vocab, meta]) => ({ cells, findings, vocab: vocab.tags || {}, meta }));
return core;
}
// The unbent bases (index/navigator/, built by kb_navigator_index.py). Null when this copy has none yet.
// Like counts, published by the likes server as community/likes.jsonl (counts only). Empty when none yet.
let likes;
export const loadLikes = () => (likes ||= getLines("community/likes.jsonl")
.then((rows) => new Map(rows.map((r) => [r.record, r.likes]))).catch(() => new Map()));
export const loadBases = () => getJSON("index/navigator/bases.json").then((d) => d.bases).catch(() => null);
export async function loadBase(base) {
const d = await getJSON(base.file);
return d.rows.map((row) => Object.fromEntries(d.cols.map((c, i) => [c, row[i]])));
}
// Old record and baseline ids (before an id migration) map to the current ones, possibly through several steps.
let aliases;
export async function resolveId(id, kind = "records") {
aliases ||= getJSON("index/id_aliases.json").catch(() => ({}));
const table = (await aliases)[kind] || {};
for (let i = 0; i < 10 && table[id]; i++) id = table[id];
return id;
}