"""GGUF rerank wrapper (Option A): llama-server embeddings (mean pool, unnormalized) . score_weight""" import json, sys, csv, time, urllib.request, numpy as np URL = sys.argv[1] if len(sys.argv) > 1 else "http://127.0.0.1:8099" OUT = sys.argv[2] if len(sys.argv) > 2 else "scores.csv" w = np.load(__file__.rsplit("\\", 1)[0] + "\\score_weight.npy").astype(np.float32).reshape(-1) Z = "\u200c" def esc(t): return t.replace("[", "[" + Z).replace("<", "<" + Z) def fmt(q, d): return "query: " + esc(q) + "\n\npassage: " + esc(d) # chat_template.jinja, no BOS/EOS def emb(text): req = urllib.request.Request(URL + "/embedding", json.dumps({"content": text, "add_special": False}).encode(), {"Content-Type": "application/json"}) r = json.load(urllib.request.urlopen(req)) e = r[0]["embedding"] if isinstance(r, list) else r["embedding"] e = np.array(e, dtype=np.float32).reshape(-1, w.size); assert e.shape[0] == 1, e.shape; return e[0] def score(q, d): return float(np.dot(w, emb(fmt(q, d)))) if __name__ == "__main__": pairs = json.load(open(__file__.rsplit("\\", 1)[0] + "\\pairs.json", encoding="utf-8-sig")) rows = []; t = time.time() for i, p in enumerate(pairs): rows.append((i, p["rel"], round(score(p["q"], p["d"]), 4), p["q"], p["d"][:60])) with open(OUT, "w", newline="", encoding="utf-8") as f: c = csv.writer(f); c.writerow(["idx", "relevant", "score", "query", "doc"]); c.writerows(rows) for r in rows: print(r[0], r[1], r[2], r[3][:40]) print(f"{len(rows)} pairs in {time.time()-t:.1f}s")