"""Slim, shippable variant of the offline existence atlas: a bloom filter over the 16.7M normalized titles. Why: the exact sqlite atlas is 446MB — too big to ship inside a GGUF/Ollama-tier package. A bloom filter trades ~33MB for a tunable false-POSITIVE rate and ZERO false-negatives. The no-false-negative property is exactly right for grounding: every REAL title still matches (reals stay 100% grounded, same as sqlite); only a small FPR can spuriously "ground" a fabrication (a false-rescue). We size for a low per-query FPR so the structural zero-false-rescue guarantee degrades only negligibly. Build: python bloom_atlas.py build wiki_titles.db wiki_titles.bloom [bits_per_item] Probe: python bloom_atlas.py probe wiki_titles.bloom ../eval/hl_battery.json The BloomGrounder mirrors Grounder.grounded() candidate logic exactly, querying the bloom instead of sqlite. """ import sys, os, sqlite3, hashlib, struct, math, json, re import numpy as np sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from offline_atlas import norm, STOP, _sig MAGIC = b"LBLOOM1\n" def _two_hashes(b): d = hashlib.blake2b(b, digest_size=16).digest() return struct.unpack("> 3] |= (1 << (p & 7)) def __contains__(self, key): for p in self._pos(key): if not (self.bits[p >> 3] >> (p & 7)) & 1: return False return True def save(self, path): with open(path, "wb") as f: f.write(MAGIC); f.write(struct.pack("= 2 and len(wsig) / len(esig) >= 0.6: wn = " ".join(w) if self._exists(wn): return {"matched": True, "hit": wn} return {"matched": False, "hit": ""} def probe(bloom_path, battery_path): g = BloomGrounder(bloom_path) items = json.load(open(battery_path))["items"] y = np.array([it["label"] for it in items]) key = "name" if "name" in items[0] else "entity" matched = np.array([g.grounded(it[key])["matched"] for it in items]) fake, real = y == 1, y == 0 print(f"bloom grounder on {os.path.basename(battery_path)} ({len(items)} items):") print(f" REAL matched {matched[real].mean():.4f} (want 1.0 — bloom has no false-negatives)") print(f" FAKE matched {matched[fake].mean():.4f} (want ~0 — these are bloom false-positives = false-rescues)") fr = [items[i][key] for i in range(len(items)) if fake[i] and matched[i]] print(f" false-rescues (fakes matched): {len(fr)} {fr[:10]}") if __name__ == "__main__": cmd = sys.argv[1] if cmd == "build": build(sys.argv[2], sys.argv[3], int(sys.argv[4]) if len(sys.argv) > 4 else 16) elif cmd == "probe": probe(sys.argv[2], sys.argv[3])