import json import numpy as np def cosine_rank(query_vec: list[float], links: list) -> list[tuple]: """Sortiere Links nach Kosinus-Ähnlichkeit zum Query-Vektor. Liefert eine Liste aus (Link, Score), absteigend sortiert. Links ohne Embedding werden ignoriert. """ if not query_vec: return [] q = np.asarray(query_vec, dtype=float) q_norm = np.linalg.norm(q) if q_norm == 0: return [] ranked: list[tuple] = [] for link in links: if not link.embedding: continue try: v = np.asarray(json.loads(link.embedding), dtype=float) except (ValueError, TypeError): continue if v.shape != q.shape: continue denom = q_norm * np.linalg.norm(v) if denom == 0: continue ranked.append((link, float(np.dot(q, v) / denom))) ranked.sort(key=lambda item: item[1], reverse=True) return ranked