Spaces:
Running
Running
File size: 5,449 Bytes
a1dd5ba | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | """Sharp text search: student shortlist, teacher verdict, cracked cache.
THE PROBLEM THIS SOLVES
-----------------------
Student (FDNN-V) embeddings rank the whole corpus in ~1 ms but their text
ranking is measurably weak (top-10 agreement 0.5/10 vs the 4.3/10
teacher-self ceiling). The teacher ranks text pristinely but costs 27.7 ms
per frame — unaffordable corpus-wide, affordable on a SHORTLIST.
So the query plan is the database's oldest shape, applied to models:
cheap operator over everything -> expensive operator over survivors
student ranks all windows (~1ms) teacher re-scores top-N (~30ms each)
THE CRACKING PART
-----------------
Every teacher vector computed for a query is WRITTEN BACK to the
`teacher_windows` table. The next query that touches those windows pays
nothing. Like database cracking (Idreos et al., CIDR 2007), the index
materialises as a side effect of the workload: hot regions of the corpus
become pristine after their first visit, cold regions never cost a cent.
Cost scales with what users ask, not with what they store.
The teacher here is SigLIP-224 ("fast") — measured within the teacher-self
agreement band of the 384 model at a third of the price — and the query text
is embedded with the SAME checkpoint, so the rerank compares like with like.
"""
from __future__ import annotations
import time
import numpy as np
import pyarrow as pa
import pyarrow.compute as pc
TEACHER = "fast" # resolved by embeddings.resolve_model
_CACHE: dict = {} # (store, version) -> {key: vec}
def _cache_map(store):
t = store.table("teacher_windows")
st = t.state()
key = (str(store.dir), st.version)
if key not in _CACHE:
m = {}
if st.files:
tb = t.scan()
for s, a, v in zip(tb.column("stream").to_pylist(),
tb.column("ts").to_pylist(),
tb.column("vector").to_pylist()):
m[(s, int(a))] = np.asarray(v, np.float32)
_CACHE.clear()
_CACHE[key] = m
return _CACHE[key]
def _teacher_embed_windows(store, wins):
"""Decode ONE centre frame per window through the byte-range path and
embed with the teacher. `wins` = [(stream, t0, t1)]."""
from PIL import Image
from .embeddings import _embed_images
frames = store.table("frames").scan()
imgs, keys = [], []
for (s, a, b) in wins:
mid = (a + b) // 2
sel = frames.filter(pc.and_(
pc.equal(frames.column("stream"), s),
pc.and_(pc.greater_equal(frames.column("ts"),
mid - 2_000_000_000),
pc.less_equal(frames.column("ts"),
mid + 2_000_000_000))))
from .video import FrameSet
dec = FrameSet(store, "frames", sel).decode(stream=s, width=448,
limit=1)
if dec:
imgs.append(Image.fromarray(dec[0][1]))
keys.append((s, a, b))
if not imgs:
return {}
vecs = _embed_images(imgs, TEACHER)
return {k: v for k, v in zip(keys, vecs)}
def search_sharp(store, text, k=10, shortlist=48):
"""Student ranks everything; the teacher re-scores the shortlist; misses
are cached into the store. Returns (hits, stats)."""
from .embeddings import _vec_table, embed_text
t_start = time.perf_counter()
tbl, vecs = _vec_table(store, "embeddings")
a_t0 = tbl.column("ts").to_numpy()
a_t1 = tbl.column("t1").to_numpy()
a_s = tbl.column("stream").to_numpy(zero_copy_only=False)
q_student = embed_text(text) # 384-space (student's)
order = np.argsort(-(vecs @ q_student))[:shortlist]
wins = [(str(a_s[i]), int(a_t0[i]), int(a_t1[i])) for i in order]
cache = _cache_map(store)
missing = [w for w in wins if (w[0], w[1]) not in cache]
t_miss = time.perf_counter()
if missing:
fresh = _teacher_embed_windows(store, missing)
if fresh:
ft = pa.table({
"ts": pa.array([a for (_, a, _b) in fresh], pa.int64()),
"t1": pa.array([b for (_, _a, b) in fresh], pa.int64()),
"stream": pa.array([s for (s, _a, _b) in fresh]),
"vector": pa.array([v.tolist() for v in fresh.values()],
pa.list_(pa.float32(), 1152)),
})
store.table("teacher_windows").append(
ft, kind="embeddings",
meta={"model": TEACHER, "written_by": "query cracking"})
for (s, a, _b), v in fresh.items():
cache[(s, a)] = v
miss_ms = (time.perf_counter() - t_miss) * 1e3
q_teacher = embed_text(text, model_id=TEACHER) # same checkpoint as
hits = [] # the cached vectors
for (s, a, b) in wins:
tv = cache.get((s, a))
if tv is None:
continue
hits.append({"stream": s, "t0": a, "t1": b,
"score": float(tv @ q_teacher), "teacher": True})
hits.sort(key=lambda h: -h["score"])
stats = {"method": "sharp", "shortlist": len(wins),
"cache_misses": len(missing),
"teacher_ms": round(miss_ms, 1),
"cache_size": len(cache),
"ms": round((time.perf_counter() - t_start) * 1e3, 1)}
return hits[:k], stats
|