← Lesson
Hybrid Search
Joeven
Run
Reset
Python loads on first run
import math import re from collections import Counter CHUNKS = { "a": "Refunds for INV-17 take 5-7 days. Never refund in cash.", "b": "Runner out of memory: raise worker limits and replay the DLQ.", "c": "Customer asked about a refund in cash for their invoice.", } def tokens(s): return re.findall(r"[a-z0-9-]+", s.lower()) def cosine_bow(q, d): vq, vd = Counter(tokens(q)), Counter(tokens(d)) keys = set(vq) | set(vd) a = [vq[k] for k in keys] b = [vd[k] for k in keys] na = math.sqrt(sum(x * x for x in a)) or 1.0 nb = math.sqrt(sum(x * x for x in b)) or 1.0 return sum(x * y for x, y in zip(a, b)) / (na * nb) def keyword_score(q, d): dt = Counter(tokens(d)) score = 0.0 for t in tokens(q): tf = dt[t] if not tf: continue score += 1.0 + math.log(1 + tf) if "-" in t or any(ch.isdigit() for ch in t): score += 2.0 return score def minmax(xs): lo, hi = min(xs), max(xs) if hi - lo < 1e-9: return [0.0 for _ in xs] return [(x - lo) / (hi - lo) for x in xs] def hybrid(q, alpha=0.5): names = list(CHUNKS) kw = [keyword_score(q, CHUNKS[n]) for n in names] vec = [cosine_bow(q, CHUNKS[n]) for n in names] fused = [alpha * k + (1 - alpha) * v for k, v in zip(minmax(kw), minmax(vec))] return sorted(zip(names, fused, kw, vec), key=lambda r: r[1], reverse=True) q = "status of INV-17 refund in cash" print("query:", q) for alpha in (0.0, 0.5, 1.0): print("alpha", alpha) for name, fused, kw, vec in hybrid(q, alpha): print(" ", name, "fused=" + str(round(fused, 3)), "kw=" + str(round(kw, 3)))
Run to execute this in your browser. Nothing is sent to a server.