Search-Ranking-Stack: BM25, Embeddings und Reranking
Automatische Übersetzung Dieser Artikel wurde automatisch aus der englischen Originalversion übersetzt.
Search muss sowohl exakte als auch semantische Intentionen erfüllen. Eine Query nach „wireless headphones“ sollte diese Wörter matchen, aber die endgültige Reihenfolge kann auch von Produktqualität, Nutzerpräferenzen und Verfügbarkeit abhängen. Keine einzelne Ranking-Methode verarbeitet all diese Signale zuverlässig.
In diesem Beitrag bauen wir den Stack Schritt für Schritt auf: BM25-Retrieval, dichte Embeddings, Reciprocal Rank Fusion, Cross-Encoder-Reranking und schließlich LLM-Listwise-Ranking. Ein begleitendes Demo-Repository enthält ausführbaren Code für die einzelnen Stufen auf einem gesampelten Ausschnitt der Amazon-ESCI-Produkt-Suchdaten.
Eine kurze Anleitung zur Auswahl der Stufen findest du unter BM25 vs Embeddings vs Rerankers.
Stufen anhand des Failure Modes auswählen
Der Production-Stack ist ein Funnel, aber der passende Funnel hängt von Query und Business-Surface ab.
| Anwendungsfall | Empfohlener Ausgangs-Stack | Validieren |
|---|---|---|
| Produktsuche | BM25 + Dense Retrieval + RRF + Cross-Encoder | Attribute Recall, Substitutions, Latency, Business Constraints |
| Dokumentationssuche | Hybrid Retrieval + Cross-Encoder | Exakte Identifier, semantische Fragen, Versionsfilter |
| Support-Deflection | Hybrid Retrieval + Citation Checks | Retrieval Recall, Grounding, Abstention |
| Marketplace oder Listings | Lexical Filters + Dense Retrieval + Business-Reranker | Verfügbarkeit, Aktualität, Richtlinien, Seller-Diversität |
| Kleines internes Corpus | BM25-Baseline, danach ein Reranker | Ob ein Vocabulary Mismatch einen Dense Index rechtfertigt |
| Rechtliche oder medizinische Suche mit hohen Risiken | Recall-fokussiertes Retrieval plus Expertenprüfung | Coverage, Provenance, kalibrierte Abstention |
Starte mit BM25 als Baseline. Ergänze Dense Retrieval, wenn ein Vocabulary Mismatch den Recall beeinträchtigt. Füge einen Cross-Encoder hinzu, wenn die erste Seite die richtigen Candidates enthält, aber in der falschen Reihenfolge anzeigt. Setze ein LLM erst dann ein, wenn du die Latency tragen kannst und die Ranking-Entscheidungen evaluieren kannst.
Wie wir hierher gekommen sind
Der Stack lässt sich am einfachsten als drei Ebenen verstehen. Lexical Retrieval findet exakte Begriffe, Dense Retrieval schließt Vocabulary Gaps, und Reranker vergleichen die stärksten Candidates im Detail.
BM25 und Lexical Retrieval
Über Jahrzehnte war BM25 der Standard. Es handelt sich um ein probabilistisches Model, das Dokumente anhand der Häufigkeit von Query-Terms im Dokument bewertet, normalisiert nach Dokumentlänge und Inverse Document Frequency (IDF).
BM25 ist stark, wenn wörtliche Begriffe die Intention tragen: Error Codes, Product SKUs, Namen und API-Identifier. Seine wichtigste Einschränkung ist der Vocabulary Mismatch. Eine Query nach „cheap laptop“ kann ein Dokument über einen „budget notebook computer“ verfehlen, wenn der indexierte Text keine Verbindung zwischen den Ausdrücken herstellt.
Trotzdem ist BM25 eine solide Baseline. Die BEIR-Leaderboard berichtet für ihren BM25 multifield-Run über einen durchschnittlichen nDCG@10-Wert von 0.429 über 18 Datasets. Pyserinis Reproduktion verwendet einen Lucene-Multifield-Index mit contents=1.0 und title=1.0, durchsucht mit --bm25. Das ist nicht die einfache, per Whitespace tokenisierte rank_bm25-Implementierung dieses Demos. BM25 schlägt außerdem einige Neural Models bei Argumentative-Retrieval-Tasks wie Touche-2020.
Dense Retrieval und Embeddings
BERT-basierte Encoder machten Dense Retrieval praktikabel. Sie projizieren Queries und Dokumente in einen gemeinsamen Vektorraum und ranken anschließend Candidates mit einer Similarity Function wie Cosine Similarity oder Dot Product.
Die Bi-Encoder- (oder „Two-Tower“-) Architektur verarbeitet Query und Dokument unabhängig voneinander durch separate Encoder-Türme und erzeugt Embeddings mit fester Länge. Dokumentvektoren können vorab berechnet, offline indexiert und anschließend per Approximate Nearest Neighbor (ANN)-Algorithmen schnell abgerufen werden. Dadurch liegen „cheap laptop“ und „budget notebook“ im Vektorraum nahe beieinander.
Einige Bi-Encoder verwenden eine Siamese Architecture, wie bei Sentence-BERT, bei der beide Seiten Weights teilen. Andere verwenden separate Query- und Document-Towers. Pooling, Vektorgröße, Similarity Function und Training Objective sind Model-Entscheidungen und keine Eigenschaften jedes Dense Retrievers.
Diese Models werden mit Contrastive Learning trainiert, üblicherweise mit dem InfoNCE-Loss. Für einen Batch aus (query, positive_document)-Paaren maximiert das Objective sim(query, positive_doc) und minimiert sim(query, negative_docs). Negatives stammen von den Positives anderer Queries im selben Batch (In-Batch Negatives). Ein Temperature-Parameter steuert, wie deutlich das Model die beiden trennen muss.
Die Trainingsdaten sind oft wichtiger als die Embedding-Dimension. Retrieval Models lernen aus Query-Positive-Paaren und sorgfältig ausgewählten Hard Negatives: plausiblen, aber nicht relevanten Dokumenten. Der spätere Trainingsabschnitt zeigt, wie SimANS sowohl triviale Negatives als auch wahrscheinliche False Negatives vermeidet.
Der Preis ist der Representation Bottleneck. Bi-Encoder komprimieren sämtliche semantischen Nuancen in einen einzelnen Vektor mit fester Größe und übersehen daher häufig feingranulare Interaktionen zwischen bestimmten Query-Terms und bestimmten Dokumentinhalten.
Cross-Encoder und LLMs
Cross-Encoder (Nogueira & Cho, 2019) führen Query und Dokument gemeinsam als konkatenierte Sequence in einen Transformer ein ([CLS] Query [SEP] Document), sodass jeder Query-Token über vollständige Self-Attention jedem Dokument-Token Aufmerksamkeit schenken kann. Diese tiefe Interaction erfasst Nuancen, die eine unabhängige Encoding-Strategie verfehlt.
LLM-Reranking verwendet ein per Prompt gesteuertes Model, um mehrere Candidates gleichzeitig zu vergleichen. RankGPT zeigte starke Zero-Shot-Listwise-Ergebnisse mit GPT-4 auf den evaluierten Benchmarks. Output-Stabilität, Kosten und Domain-Fit müssen jedoch weiterhin separat getestet werden.
Diese Scores können für beliebige Queries nicht vorab berechnet werden, daher wird Reranking hinter dem Retrieval platziert. Diese Kostenasymmetrie motiviert den Multi-Stage-Funnel.
Der Multi-Stage-Funnel
Ein teurer Cross-Encoder oder ein LLM über Millionen von Dokumenten ist nicht praktikabel, daher verwenden moderne Search-Stacks einen Funnel. Jede Stufe verkleinert die Candidate Pool, während die Model-Komplexität zunimmt.
Ein günstiger Retriever bietet außerdem keine ausreichende finale Precision. Deshalb verwendet der Funnel jedes Model nur dort, wo seine Kosten vertretbar sind.
| Stufe | Input-Skala | Primäres Objective | Typische Methoden | Exit-Messung |
|---|---|---|---|---|
| Retrieval | Corpus oder Index | Candidate Recall | BM25, Bi-Encoder | Recall am Candidate Cutoff |
| Pre-Ranking | Große Candidate Set | Günstiges Filtering | Leichtgewichtige Models, Rules | Erhaltener Recall pro Millisekunde |
| Full Ranking | Shortlist | Top-Rank-Qualität | Cross-Encoder, LLMs | NDCG/MRR, Latency, Kosten |
| Blending | Finale Ranked Lists oder Slots | Constraints und Mix | Rules, Multi-Objective Ranking | Policy, Diversität, Business Guardrails |
Retrieval setzt die Obergrenze, und Reranking optimiert innerhalb dieser Grenze. Wenn ein relevantes Dokument das Retrieval nicht überlebt, kann kein nachgelagertes Model es wiederherstellen.
Das Demo: eine Pipeline mit fünf Stufen
Um das zu veranschaulichen, habe ich ein search-ranking-stack-Demo erstellt, das eine Pipeline mit fünf Stufen auf dem Amazon-ESCI-Produktsuch-Benchmark ausführt. Jede Stufe wird unabhängig gemessen, sodass du siehst, woher die tatsächlichen Verbesserungen kommen.
Die Pipeline:
- BM25 Sparse Retrieval — lexikalische Baseline (
rank_bm25) - Dense-Bi-Encoder-Retrieval — semantische Candidate Generation (
all-MiniLM-L6-v2) - Hybrid-RRF-Fusion — rank-basierte Fusion von Sparse- und Dense-Ergebnissen
- Cross-Encoder-Reranking — paarweise Relevance Scores (
ms-marco-MiniLM-L-12-v2) - LLM-Listwise-Reranking — Prompt-basierter Vergleich der finalen Shortlist (Ollama, API oder lokales Model)
Die Schritte 1–3 bilden die Retrieval-Stufe des Funnels (Recall maximieren); die Schritte 4–5 bilden die Full-Ranking-Stufe (Precision maximieren). Das Demo überspringt Pre-Ranking und Blending. Bei etwa 8.500 Dokumenten kannst du dir leisten, alle Hybrid-Ergebnisse direkt an das Reranking zu senden.
Schnellstart
git clone https://github.com/slavadubrov/search-ranking-stack.git
cd search-ranking-stack
uv sync
# Download and sample ESCI dataset (~2.5GB download, ~5MB sample)
uv run download-data
# Run the full pipeline (without LLM reranking)
uv run run-all
# Run with LLM reranking via Ollama
uv run run-all --llm-mode ollama
Dataset und Sampling: Amazon ESCI
Das Demo verwendet das Amazon Shopping Queries Dataset (ESCI) aus dem KDD Cup 2022 — einen realen Produktsuch-Benchmark mit vierstufigen Relevance Labels:
| Label | Gain | Bedeutung | Beispiel (Query: „wireless headphones“) |
|---|---|---|---|
| Exact (E) | 3 | Erfüllt alle Query-Anforderungen | Sony WH-1000XM5 Wireless Headphones |
| Substitute (S) | 2 | Funktionale Alternative | Wired headphones with Bluetooth adapter |
| Complement (C) | 1 | Verwandter, nützlicher Artikel | Headphone carrying case |
| Irrelevant (I) | 0 | Keine bedeutsame Beziehung | USB charging cable |
Graded Relevance ist wichtig, weil du dadurch NDCG (Normalized Discounted Cumulative Gain) verwenden kannst. Diese Metrik unterscheidet ein „perfektes“ Ranking von einem „gerade noch ausreichenden“. Binäre Metriken bewerten beide gleich.
Ich habe das small_version-Sample des Demos verwendet: etwa 500 Queries, 8.500 Produkte und 12.000 Judgments. Der Downloader liest den einzelnen train-Split von tasksource/esci, filtert die englische us-Locale und small_version == 1 und verwendet anschließend Seed 42, um bis zu 500 eindeutige Query-IDs ohne Zurücklegen zu sampeln. Das Corpus enthält die eindeutigen Produkte aus den ausgewählten Judgment-Zeilen. Dies ist weder ein Held-out-Split noch ein unabhängiges Corpus. Das Sample ist klein genug, um auf einem Laptop ausgeführt zu werden, aber zu klein und zu stark domänenspezifisch, um ein Production Ranking zu begründen. Verwende es, um die Stufen zu reproduzieren und Failure Modes zu untersuchen; verwende Held-out-Queries, die die Produktion repräsentieren, für Deployment-Entscheidungen.
Retrieval: Hybrid Search
Die Aufgabe der Retrieval-Schicht besteht darin, den Recall zu maximieren: möglichst viele relevante Dokumente in die Candidate Set zu bringen.
BM25: die lexikalische Baseline
BM25 bewertet Dokumente anhand der Term-Überschneidung mit der Query, einschließlich Term-Frequency-Saturation und Normalisierung der Dokumentlänge:
Dabei ist die Inverse Document Frequency des Terms , die Term Frequency im Dokument , die Dokumentlänge und die durchschnittliche Dokumentlänge im gesamten Corpus. Zwei Parameter sind entscheidend: (typischerweise 1,2–2,0) steuert die TF-Saturation — also, wie schnell wiederholte Terms keinen zusätzlichen Wert mehr liefern — und (typischerweise 0,75) steuert die Normalisierung der Dokumentlänge.
Die Implementierung ist kurz. Einfaches Whitespace-Tokenizing mit rank_bm25:
# src/search_ranking_stack/stages/s01_bm25.py
from rank_bm25 import BM25Okapi
def run_bm25(data: ESCIData, top_k: int = 100):
doc_ids = list(data.corpus.keys())
tokenized_corpus = [text.lower().split() for text in data.corpus.values()]
bm25 = BM25Okapi(tokenized_corpus)
results = {}
for query_id, query_text in data.queries.items():
scores = bm25.get_scores(query_text.lower().split())
top_indices = np.argsort(scores)[::-1][:top_k]
results[query_id] = {doc_ids[idx]: float(scores[idx]) for idx in top_indices}
return results
BM25 erreicht einen Recall@100 von 0,741 — 74 % der relevanten Produkte erscheinen irgendwo in den Top 100. Für eine rein lexikalische Methode ist das nicht schlecht, aber 26 % der relevanten Artikel bleiben für alle nachgelagerten Stufen unsichtbar.
Dense-Bi-Encoder-Retrieval
Der Bi-Encoder projiziert Queries und Dokumente unabhängig voneinander in einen gemeinsamen Embedding-Raum:
# src/search_ranking_stack/stages/s02_dense.py
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
# Encode corpus once, cache to disk
corpus_embeddings = model.encode(
doc_texts,
batch_size=128,
normalize_embeddings=True, # Cosine sim = dot product
convert_to_numpy=True,
)
# At query time: encode query, compute dot product
query_embeddings = model.encode(query_texts, normalize_embeddings=True)
similarity_matrix = np.dot(query_embeddings, corpus_embeddings.T)
Bei normalisierten Embeddings reduziert sich Cosine Similarity auf ein Dot Product. Das Demo berechnet die vollständige Query-by-Corpus-Matrix, weil 8.500 Dokumente problemlos in den Speicher passen; ein Production Corpus würde normalerweise einen Approximate-Nearest-Neighbor-Index verwenden. In diesem Sample erhöht all-MiniLM-L6-v2 den Recall@100 von 0,741 auf 0,825.
Wie Bi-Encoder gute Repräsentationen lernen
Das Training von Bi-Encodern erfolgt üblicherweise in zwei Phasen. Zuerst wird das Model auf Natural Language Inference (NLI) und Semantic Textual Similarity (STS) Datasets vortrainiert. Diese vermitteln ein allgemeines semantisches Verständnis. In dieser Phase lernt das Model, dass „a cat sits on a mat“ und „a feline rests on a rug“ ähnliche Embeddings haben sollten. Anschließend wird es auf Retrieval-spezifischen Daten wie MS MARCO Fine-Tuned. Dabei lernt es, dass eine Search Query und ihr relevantes Passage näher beieinander liegen sollten als die Query und irrelevante Passagen.
Die zweite Phase hängt vom Hard-Negative-Mining ab. Zufällige Negatives — etwa ein Dokument über Kochen, das mit einer Query über Kopfhörer gepaart wird — sind trivial zu unterscheiden, sodass das Model daraus wenig lernt. Stattdessen verwendest du das aktuelle Model selbst, um Dokumente zu finden, die es hoch rankt, die aber tatsächlich nicht relevant sind.
Der SimANS-Ansatz (Simple Ambiguous Negatives Sampling) formalisiert dies. Rank alle Dokumente mit dem aktuellen Bi-Encoder, schließe anschließend einfache Negatives aus, die für das Model zu weit unten ranken, sowie potenzielle False Negatives, die so hoch ranken, dass sie tatsächlich relevant, aber nicht gelabelt sein könnten. Was in der Mitte übrig bleibt, trägt das stärkste Trainingssignal.
# What a training triplet looks like after hard negative mining
training_triplet = {
"query": "wireless noise canceling headphones",
"positive": "Sony WH-1000XM5 Wireless Noise Cancelling Headphones",
"negative": "Sony headphone replacement ear pads", # Hard negative: same brand, related product, but wrong intent
}
# The bi-encoder must learn that "ear pads" is NOT what the user wants,
# even though it shares many tokens with the positive document.
Die Contrastive-Loss-Funktion (InfoNCE) verbindet diese Aspekte. Für jede Query mit positivem Dokument und einer Menge negativer Dokumente gilt:
Dabei ist die Cosine Similarity zwischen Query- und Dokument-Embeddings und der Temperature-Parameter (typischerweise 0,05–0,1). Niedrigere Werte machen den Loss empfindlicher gegenüber Hard Negatives. Im Grunde handelt es sich um eine Softmax Cross-Entropy: Die Similarity des positiven Paars wird relativ zu allen Negatives erhöht. Wenn klein ist, erzeugen bereits geringe Similarity-Unterschiede große Gradienten, wodurch das Model zu feingranulareren Unterscheidungen gezwungen wird.
Bi-Encoder-Embeddings im großen Maßstab bereitstellen
Der architektonische Vorteil eines Bi-Encoders ist die Offline/Online-Trennung. Dokument-Embeddings werden beim Indexieren berechnet und in einem Vector Index gespeichert. Zur Query-Zeit encodiert das System die Query und durchsucht die gespeicherten Vektoren. Die Latency hängt von Encoder, Hardware, Index, Filtern und Recall-Ziel ab. Profiliere daher beide Schritte getrennt.
Im Demo ist die Mathematik überschaubar: 8.500 Dokumente 384 Dimensionen 4 Byte pro Float ergeben ungefähr 13 MB Embeddings. Im Production-Maßstab werden die Zahlen deutlich größer: 1 Milliarde Dokumente mit 768-dimensionalen Embeddings benötigen ungefähr 3 TiB Speicher. Hier kommen Quantization (Komprimierung von 32-Bit-Floats auf 8-Bit-Integer), Product Quantization (Zerlegung von Vektoren in Subspaces) und SSD-basierte Indizes wie DiskANN zum Einsatz. Der Abschnitt zum Indexieren von Dense Vectors behandelt die Index-Algorithmen.
Warum Hybrid Retrieval testen?
Die beiden Methoden machen häufig unterschiedliche Fehler. BM25 eignet sich gut für Eigennamen, Product SKUs und Error Codes. Dense Retrieval kann einen Vocabulary Mismatch wie „cheap laptop“ gegenüber „budget notebook computer“ überwinden. Ob Fusion hilft, hängt davon ab, wie häufig diese komplementären Fälle im Ziel-Query-Set auftreten.
Ein übliches Folgeexperiment ist Hybrid Search: Beide Retrieval-Methoden ausführen und anschließend ihre Ranked Lists fusionieren.
Reciprocal Rank Fusion (RRF)
BM25 und Dense Retrieval erzeugen Scores mit unterschiedlicher Bedeutung und Skalierung. Eine lineare Kombination erfordert daher eine Calibration und Validierung, sobald sich Retriever oder Corpus ändern.
Reciprocal Rank Fusion (Cormack et al., 2009) verwirft die Raw Scores vollständig und verwendet nur die Rank-Position:
Hier ist eine Smoothing Constant; 60 ist ein üblicher Startwert. RRF belohnt Artikel, die in den Input-Listen weit oben ranken, ohne ihre Raw Scores miteinander zu vergleichen. Dadurch entfällt die Calibration der Score-Skalen, aber Retrieval-Cutoffs, Weights und müssen weiterhin evaluiert werden.
Die Implementierung:
# src/search_ranking_stack/stages/s03_hybrid_rrf.py
def reciprocal_rank_fusion(ranked_lists, k=60, top_k=100):
fused_results = {}
for query_id in all_query_ids:
rrf_scores = defaultdict(float)
for results in ranked_lists:
sorted_docs = sorted(results[query_id].items(),
key=lambda x: x[1], reverse=True)
for rank, (doc_id, _score) in enumerate(sorted_docs, start=1):
rrf_scores[doc_id] += 1.0 / (k + rank)
sorted_rrf = sorted(rrf_scores.items(),
key=lambda x: x[1], reverse=True)[:top_k]
fused_results[query_id] = dict(sorted_rrf)
return fused_results
Hybrid RRF erreicht einen Recall@100 von 0,842 und einen NDCG@10 von 0,628 — und übertrifft damit BM25 (0,585) und Dense (0,611) jeweils allein. Ein Dokument muss nur in einer Methode gut ranken, um die Fusion zu überleben.
Cross-Encoder-Reranking
!!! byte „Byte sagt“
Ich habe einen Cross-Encoder hinzugefügt, weil die Top-Ergebnisse falsch aussahen. Die Reihenfolge wurde besser. Der Recall@100 veränderte sich nicht, da ein Reranker nur das sortieren kann, was das Retrieval bereits geliefert hat.
Mit 100 Hybrid-Candidates pro Query kannst du dir ein teureres Model leisten. Der Cross-Encoder verarbeitet Query und Dokument gemeinsam durch einen einzelnen Transformer, mit vollständiger Cross-Attention zwischen allen Tokens.
Token-Level-Interaction
Der Unterschied liegt in der Attention Matrix. Bei einem Bi-Encoder ist die Attention blockdiagonal: Query-Tokens attendieren nur auf andere Query-Tokens, und Dokument-Tokens nur auf andere Dokument-Tokens. Die beiden Repräsentationen treffen sich auf Token-Ebene nie — sie überschneiden sich erst am Ende über ein Dot Product. Ein Cross-Encoder berechnet die vollständige Attention Matrix, in der jeder Query-Token auf jeden Dokument-Token und umgekehrt attendiert. Diese Cross-Attention ermöglicht tiefe Token-Level-Interaction.
Beim Bi-Encoder wird die Query „apple“ encodiert, bevor ein Dokument gesehen wurde. Ein Cross-Encoder sieht Query und Candidate gemeinsam und kann daher ihre Token-Level-Beziehung nutzen. Das kann unter anderem in folgenden Fällen helfen:
- Negation: „headphones that are not wireless.“ Ein gepooltes Embedding kann die Negation zu schwach gewichten, während Joint Encoding eine direkte Query-Document-Interaction ermöglicht. Dies ist eine zu überprüfende Hypothese und keine Garantie.
- Qualifikation: „laptop under $500.“ Joint Encoding kann die Constraint mit einem Preis im Produkttext verknüpfen, allerdings sind strukturierte Price Filters sicherer, wenn das Feld verfügbar ist.
Der Input des Cross-Encoders wird als [CLS] query tokens [SEP] document tokens [SEP] formatiert. [CLS] ist ein Classification Token, dessen finaler Hidden State durch einen Linear Head geführt wird, um einen einzelnen Relevance Score zu erzeugen. Segment Embeddings unterscheiden Query-Tokens von Dokument-Tokens, und [SEP] markiert die Grenze zwischen den Segmenten.
Wie Cross-Encoder trainiert werden
Cross-Encoder können mit (query, document, relevance_label)-Beispielen und Pointwise-, Pairwise- oder Listwise-Objectives lernen. Das folgende Pointwise-Beispiel verwendet ein einzelnes Relevance Label und ist nicht das einzige mögliche Trainingsdesign.
# Cross-encoder training data format
training_example = {
"query": "wireless headphones",
"document": "Sony WH-1000XM5 Wireless Headphones",
"label": 1.0, # Relevant
}
# Forward pass: [CLS] hidden state → Linear layer → sigmoid → score
# Loss: binary cross-entropy between predicted score and label
Ein üblicher Classifier bildet die finale [CLS]-Repräsentation auf einen Score ab. Binäre Labels können Binary Cross-Entropy verwenden; Graded Relevance kann mit Regression, ordinalen, paarweisen oder Listwise Losses trainiert werden. Wähle anhand von Ranking-Metriken auf Held-out-Daten, statt anzunehmen, dass ein Objective universell besser ist.
Hard-Negative-Mining ist für Cross-Encoder noch wichtiger als für Bi-Encoder. Cross-Encoder sind teuer zu trainieren — jedes Trainingsbeispiel benötigt einen vollständigen Forward Pass durch die konkatenierte Sequence — deshalb kannst du keine Compute-Kapazität für trivial einfache Negatives verschwenden. Das praktische Vorgehen: Verwende einen Bi-Encoder, um für jede Trainings-Query die Top-K-Candidates abzurufen, und wähle Hard Negatives aus bestimmten Rank-Bereichen aus (z. B. Ranks 10–100). So erhält der Cross-Encoder Beispiele, bei denen die Unterscheidung zwischen relevant und irrelevant tatsächlich tiefe Token-Level-Interaction erfordert.
# src/search_ranking_stack/stages/s04_cross_encoder.py
from sentence_transformers import CrossEncoder
model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-12-v2")
def run_cross_encoder(data, hybrid_results, top_k_rerank=50):
reranked_results = {}
for query_id, query_text in data.queries.items():
candidates = list(hybrid_results[query_id].items())[:top_k_rerank]
# Form (query, document) pairs for joint encoding
pairs = []
doc_ids = []
for doc_id, _ in candidates:
doc_text = data.corpus.get(doc_id, "")[:2048]
pairs.append([query_text, doc_text])
doc_ids.append(doc_id)
# Score all pairs with full cross-attention
scores = model.predict(pairs, batch_size=64)
# Rerank by cross-encoder score
scored_docs = sorted(zip(doc_ids, scores),
key=lambda x: x[1], reverse=True)
reranked = {
doc_id: float(score) for doc_id, score in scored_docs
}
# Keep original hybrid candidates at ranks 51--100 for Recall@100.
for doc_id, score in list(hybrid_results[query_id].items())[top_k_rerank:100]:
if doc_id not in reranked:
reranked[doc_id] = float(score) * 0.01
reranked_results[query_id] = reranked
return reranked_results
Im aufgezeichneten Demo-Run rerankt ms-marco-MiniLM-L-12-v2 50 Candidates pro Query und erhöht NDCG@10 von 0,628 auf 0,645. Miss die Latency auf der Deployment-Hardware; Model, Sequence Length, Batch Size und Runtime beeinflussen das Ergebnis.
Der Trade-off zwischen Geschwindigkeit und Qualität
Warum Cross-Encoder nicht für alles verwenden? Weil du die Scores nicht vorab berechnen kannst. Dokument-Embeddings eines Bi-Encoders sind Query-unabhängig, daher berechnest du sie einmal und speicherst sie. Der Output eines Cross-Encoders hängt dagegen gleichzeitig von Query und Dokument ab. Der Relevance Score für „wireless headphones“ zusammen mit einem Sony-Produkt entsteht aus der vollständigen Cross-Attention zwischen genau diesen Tokens. Du kannst ihn weder cachen noch für eine andere Query wiederverwenden.
Ein Bi-Encoder benötigt eine Query-Encoding-Operation plus Vector Search über vorab berechnete Dokument-Embeddings. Ein Cross-Encoder bewertet jedes Query-Document-Paar in der Shortlist, wobei die Kosten sowohl mit der Candidate-Anzahl als auch mit der Sequence Length steigen. Batching hilft, aber 100.000 Candidates zu bewerten ist weiterhin der falsche Operating Point; führe zuerst Retrieval aus und benchmarkt die größte Shortlist, die deine Qualitäts- und Latency-Ziele erfüllt.
Im Demo bleibt der Recall@100 während der gesamten Cross-Encoder-Stufe konstant bei 0,842. Reranking kann Ergebnisse neu ordnen, aber keine Dokumente hinzufügen. Retrieval setzt die Obergrenze.
LLM-Listwise-Reranking
!!! byte „Byte sagt“
Ich habe dem ersten LLM-Ranking vertraut, ohne das Parsing zu prüfen. Das Model hatte mehrere Dokument-IDs entfernt, und meine Padding-Logik füllte die Lücken stillschweigend auf. Ich bewertete meine eigene Fallback-Lösung.
Die finale Demo-Stufe verwendet ein LLM für Listwise-Reranking. Statt jedes Dokument unabhängig zu bewerten, sieht das Model die Top 10 und gibt eine Reihenfolge zurück. Inspiriert von RankGPT macht der Prompt den relativen Vergleich explizit, führt aber auch Context Limits, Position Bias, Parsing-Fehler und Run-to-Run-Varianz ein.
Der Listwise-Prompt
Das Prompt-Template fordert das LLM auf, die ESCI-Relevance-Hierarchy zu berücksichtigen:
# src/search_ranking_stack/stages/s05_llm_rerank.py
def _create_listwise_prompt(query, documents, max_words=200):
n = len(documents)
doc_texts = []
for i, (doc_id, doc_text) in enumerate(documents, start=1):
words = doc_text.split()[:max_words]
doc_texts.append(f"[{i}] {' '.join(words)}")
return (
f"I will provide you with {n} product listings, each indicated by "
f"a numerical identifier [1] to [{n}]. Rank the products based on "
f'their relevance to the search query: "{query}"\n\n'
"Consider:\n"
"- Exact matches should rank highest\n"
"- Substitutes should rank above complements\n"
"- Irrelevant products should rank lowest\n\n"
f"{chr(10).join(doc_texts)}\n\n"
"Output ONLY a comma-separated list of identifiers: [3], [1], [2], ...\n"
"Do not explain your reasoning."
)
Drei Ausführungsmodi
Das Demo unterstützt drei Backends für LLM-Reranking:
| Modus | Model | Ausführung |
|---|---|---|
ollama | llama3.2:3b (konfigurierbar) | Lokal über Ollama API |
api | claude-haiku-4-5-20251001 | Anthropic API |
local | Qwen/Qwen2.5-1.5B-Instruct | HuggingFace Transformers |
Parsing und Fallback
LLM-Outputs folgen nicht garantiert dem angeforderten Schema. Deshalb sind Parsing und ein Fallback-Pfad wichtig:
def _parse_ranking(output: str, n: int) -> list[int] | None:
"""Parse LLM output to extract ranking order."""
matches = re.findall(r"\[(\d+)\]", output)
if not matches:
return None
positions = [int(m) - 1 for m in matches]
# Pad with remaining positions if LLM returned partial output
if len(positions) < n:
seen = set(positions)
for i in range(n):
if i not in seen:
positions.append(i)
return positions[:n]
Wenn das Parsing vollständig fehlschlägt, fällt das Demo auf die Cross-Encoder-Reihenfolge zurück. Ein Production Parser sollte außerdem Identifier außerhalb des gültigen Bereichs und doppelte Identifier ablehnen, ausgelassene Candidates in ihrer vorherigen Reihenfolge anhängen, den Fehler loggen und die Fallback-Rate mit einem Launch Threshold vergleichen.
Ergebnisse dieses ESCI-Samples
Diese aufgezeichneten Ergebnisse vor dem LLM verwenden das small_version des Demos: die englische us-Locale nach dem small_version == 1-Filter, mit bis zu 500 Query-IDs, die mithilfe von Seed 42 ohne Zurücklegen gesampelt wurden, sowie einem Corpus, das aus den bewerteten Produkten dieser Queries aufgebaut wurde.
Sie stellen weder eine Held-out-Evaluation noch ein unabhängiges Corpus dar.
Die MRR-Werte verwenden die binäre Regel des Demo-Evaluators, relevance > 0: Ein Complement-, Substitute- oder Exact-Ergebnis gilt als relevant, ein Irrelevant-Ergebnis nicht. recip_rank evaluiert jede zurückgegebene Candidate List mit bis zu 100 Candidates; es handelt sich nicht um MRR@10.
| Stufe | NDCG@10 | MRR | Recall@100 | NDCG Delta |
|---|---|---|---|---|
| BM25 | 0,585 | 0,812 | 0,741 | — |
| Dense Bi-Encoder | 0,611 | 0,808 | 0,825 | +0,026 |
| Hybrid (RRF) | 0,628 | 0,834 | 0,842 | +0,017 |
| + Cross-Encoder | 0,645 | 0,860 | 0,842 | +0,017 |
Zentrale Beobachtungen
Hybrid Search schlägt beide Einzelmethoden. Der RRF-NDCG-Wert (0,628) liegt über BM25 (0,585) und Dense (0,611). Die beiden Methoden können bei unterschiedlichen Queries scheitern; ihre Kombination gewinnt daher Dokumente zurück, die jeweils einzeln verfehlt würden.
Der Recall wird beim Retrieval festgelegt. Recall@100 bleibt während der Cross-Encoder-Stufe bei 0,842. Reranker ordnen neu, sie fügen keine Dokumente hinzu. Wenn du höheren Recall möchtest, musst du die Retrieval-Schicht verbessern. Die oben aufgeführten MRR-Werte verwenden dieselbe demoweite Regel: Complement oder höher gilt als relevant.
Das LLM-Ergebnis wird nicht berichtet. Der Parser akzeptiert doppelte und außerhalb des gültigen Bereichs liegende Identifier; anschließend kann sein Padding-Pfad die Candidate List stillschweigend verändern. Der vorherige LLM-Vergleich ist daher illustrativ und kein auditierbares Ergebnis. Führe ihn mit strikter Identifier-Validierung, geloggtem Fallback-Verhalten, wiederholten Runs, Latency- und Kostenmessungen sowie einem Held-out-Domain-Set erneut aus, bevor du dem Reranker einen Gain zuschreibst.
Das begleitende Repository ist für Setup und Code nützlich, berichtet in seiner README jedoch weiterhin den ungültigen + LLM Reranker-NDCG@10-Wert von 0,717. Betrachte die Pre-LLM-Tabelle dieses Artikels und den obigen LLM-Hinweis als maßgebliche Dokumentation, bis das Repository über eine auditierbare LLM-Evaluation verfügt.
Dense Retrieval schlägt BM25 in diesem Sample. Untersuche Query-Slices, bevor du die Ursache bestimmst. Vocabulary Mismatch ist ein plausibler Faktor, aber auch Sample-Konstruktion, Tokenizer, Trainingsdomäne des Models und Corpus-Felder beeinflussen den Vergleich.
Evaluation: Was wirklich zählt
Das Demo verwendet drei Metriken, die das Ranking aus unterschiedlichen Perspektiven betrachten:
NDCG@10 (primäre Metrik)
Normalized Discounted Cumulative Gain misst die Qualität des Top-10-Rankings anhand von Graded Relevance. Die Metrik belohnt es, hochrelevante Dokumente weit oben zu platzieren, mit einem logarithmischen Discount:
Von den drei Metriken nutzt nur NDCG die vierstufige Graded Relevance von ESCI vollständig. Ein System, das einen Exact Match auf Position 1 platziert, erzielt einen höheren Score als eines, das dort ein Substitute platziert. Deshalb ist NDCG hier die primäre Metrik.
MRR (erstes Complement-oder-höher-Ergebnis)
Mean Reciprocal Rank verwendet die Position des ersten Ergebnisses, das als relevant gilt. In diesem Demo übergibt der Evaluator ESCIs Graded Qrels an pytrec_eval und verwendet recip_rank über jede zurückgegebene Liste mit bis zu 100 Candidates. relevance > 0 ist daher der binäre Threshold: Complement (1), Substitute (2) und Exact (3) gelten als relevant. Irrelevant (0) nicht. Ein relevantes Ergebnis auf Position 1 ergibt einen Reciprocal Rank von 1,0; auf Position 3 beträgt er 0,333. Dies ist MRR über die zurückgegebenen Candidate Lists, nicht MRR@10.
Recall@100 (Retrieval-Coverage)
Recall misst, welcher Anteil der bewerteten relevanten Dokumente in den Top 100 erscheint. Für die evaluierten Judgments ist Recall eine Candidate-Ceiling-Metrik: Ein Reranker kann kein Dokument hinzufügen, das Retrieval ausgelassen hat. Unvollständige Judgments können die scheinbare Obergrenze jedoch unsicher machen.
Dense Vectors jenseits des Demos indexieren
Dense Embeddings werden im großen Maßstab erst dann nützlich, wenn ein Approximate-Nearest-Neighbor- (ANN-)Index vorhanden ist. Das Demo verwendet Brute-Force-Cosine-Similarity, was bei etwa 8.500 Dokumenten in Ordnung ist; Production-Systeme benötigen spezialisierte Indizes.
HNSW (Hierarchical Navigable Small World)
HNSW baut einen Graphen mit mehreren Ebenen auf: Dünn besetzte obere Ebenen navigieren großflächig, dichtere untere Ebenen verfeinern die Nachbarschaft. M steuert die Graph Connectivity, während efSearch den Query-Aufwand gegen Recall abwägt. Sinnvolle Werte hängen von Dimension, Distanzverteilung, Filtern, Implementierung und Ziel-Recall ab.
Updates und Deletions sind operative Aspekte, da Graph-Indizes möglicherweise im Hintergrund repariert werden müssen. Das Verhalten variiert je nach Datenbank. Ein Qdrant-Issue berichtet beispielsweise von verschlechterter Filtered-Search-Qualität in einer Multi-Tenant-HNSW-Konfiguration. Der Bericht maß eine Mean Precision@100 von 0,597 ± 0,0541 mit einem library_id-Filter, während Exact Search in der tieferen Analyse 100 % Recall erreichte. Eine Änderung von payload_m erzwang einen Rebuild, der die Filtered-Search-Qualität wiederherstellte. Der Bericht behandelt Tenant-Filter, HNSW-Konfiguration und einen erzwungenen HNSW-Index-Rebuild, nicht einen Workload mit vielen Deletions. Reproduziere das für dein Ziel relevante Churn-Muster und berücksichtige Compaction- oder Rebuild-Verhalten in der Evaluation.
IVF (Inverted File)
IVF-Indizes partitionieren den Vektorraum in Cluster und durchsuchen anschließend die nprobe Cluster, die der Query am nächsten liegen. Besonders in Kombination mit Compression können sie einen guten Trade-off zwischen Memory, Build-Zeit und Recall bieten. Update-Semantik und Performance hängen jedoch von der Implementierung ab, nicht allein von der Index-Familie.
Für extreme Skalierung komprimiert IVF_RaBitQ (Gao & Long, SIGMOD 2024) Floating-Point-Vektoren in Single-Bit-Repräsentationen. In hochdimensionalen Räumen trägt das Vorzeichen einer Koordinate (+/−) genügend Winkelinformation für die Similarity-Berechnung.
| Dimension | HNSW-Graph | IVF-Cluster |
|---|---|---|
| Query-Steuerung | efSearch | nprobe |
| Build-Steuerung | Connectivity und Construction Beam | Cluster-Anzahl und Trainingssample |
| Memory-Profil | Graph-Kanten plus Vektoren | Centroids, Listen und gespeicherte Vektoren |
| Update-Verhalten | Datenbankspezifische Reparatur/Cleanup | Datenbankspezifische Listenpflege |
| Evaluieren mit | Recall-Latency-Memory-Churn-Kurve | Recall-Latency-Memory-Churn-Kurve |
In einer Uber-Case-Study zur Delivery Search reduzierte die Senkung eines Search-Parameters auf Shard-Ebene von 1.200 auf 200 die berichtete Latency um 34 % und die CPU-Auslastung um 17 %, bei kaum messbarem Recall-Verlust. Die übertragbare Lehre ist, die Recall-Cost-Kurve mit produktionsnahem Traffic zu tunen, nicht den Wert 200 zu kopieren.
Optionale Erweiterungen nach der Core-Pipeline
Sobald Retrieval und Reranking separat gemessen werden, lassen sich mehrere Erweiterungen leichter evaluieren, ohne die Core-Pipeline zu verschleiern.
Query Understanding
Query Expansion und Rewriting können Vocabulary Mismatch vor dem Retrieval adressieren. Query2doc erzeugte Pseudo-Dokumente und berichtete BM25-Gains in seinen MS-MARCO-Experimenten. Expansion kann jedoch auch die falsche Intention einführen. Vergleiche daher Recall und Precision auf Slices mit ambigen, navigationalen und exakten Identifier-Queries.
Praktische Patterns sind Abbreviation Expansion, Entity Enrichment, Sub-Query-Decomposition für Multi-Hop Reasoning und RAG-Fusion — das Erzeugen mehrerer Query-Varianten und die Kombination der Ergebnisse über RRF.
LLM-unterstütztes Relevance Labeling
LLMs können Relevance Labels vorab erstellen, wenn menschliche Judgments knapp sind. TALEC und Pinterests Arbeit zum Relevance Labeling stellen zwei evaluierte Designs vor. Ein LLM-Label ist weiterhin Model-Output: Kalibriere es gegen verblindete menschliche Judgments, untersuche Disagreement-Slices und behalte ein menschliches Gold-Set für Regression Tests.
Nützliche Controls sind:
- ein Rubric mit konkreten Relevance-Grenzen und Beispielen;
- verblindete menschliche Calibration und regelmäßige Rechecks;
- Randomisierung der Reihenfolge und wiederholte Judgments für instabile Fälle;
- Model Panels, wenn ihre zusätzlichen Kosten die Übereinstimmung verbessern; und
- explizite Checks auf Position Bias und Central-Tendency Bias.
Knowledge Distillation
Wenn ein LLM Teacher einen Mehrwert liefert, aber Serving Constraints nicht erfüllen kann, ist Distillation eine Option:
- Verwende ein leistungsfähiges LLM (den Teacher), um Tausende von Trainings-Queries zu reranken
- Trainiere einen kleinen, schnellen Cross-Encoder (den Student, etwa 100–200 Millionen Parameter), der die Ranking Distribution des LLM nachahmt
- Vergleiche den Student mit Teacher und Baseline anhand von Qualität, Calibration und Serving-Kosten
InRanker destilliert MonoT5-3B in Models mit 60 Millionen und 220 Millionen Parametern — eine Reduktion der Größe um den Faktor 50 bei konkurrenzfähiger Performance. Der Ansatz Rank-Without-GPT erzeugt offene Listwise-Reranker mit 7B, die durch QLoRA-Fine-Tuning 97 % der GPT-4-Wirksamkeit erreichen.
Veröffentlichte Compression-Ergebnisse sind Ausgangspunkte und keine erwartbaren Production Ratios. Distillation kann die Biases des Teachers übernehmen und bei seltenen Query-Slices Qualität verlieren. Behalte daher die ursprünglichen Relevance Judgments in der Evaluation.
Personalization und Position Bias
Generische Relevance bringt dich nur bis zu einem gewissen Punkt. Eine Search nach „apple“ sollte einem Tech-Enthusiasten iPhones liefern und jemandem, der Cooking Content angesehen hat, Rezepte mit Äpfeln.
Eine übliche Retrieval-Architektur für Personalization verwendet ein Two-Tower-Embedding-Model: Der Query-Tower encodiert Query und User Context, während der Item-Tower Items und Metadaten encodiert. Die Offline/Online-Trennung unterstützt Approximate-Nearest-Neighbor-Retrieval. Die Latency hängt weiterhin von Encoder, Index, Filtern und Serving-System ab.
Airbnbs Listing Embeddings, Pinterests OmniSearchSage und Ubers Two-Tower-Systeme zeigen unterschiedliche Production Designs. Ihre Skalierung und berichteten Uplifts gehören zu diesen Systemen; das übertragbare Pattern ist ein Offline-Item-Tower plus ein Online-Query-/User-Tower.
Click-Daten enthalten Position- und Exposure-Bias. PAL ist ein Debiasing-Ansatz: Nutze die Position während des Trainings und halte sie beim Serving konstant. Das ist keine universelle Lösung; für ein anderes Produkt können randomisierte Interventionen, Inverse-Propensity-Methoden und Counterfactual Evaluation geeigneter sein.
Domain Adaptation mit synthetischen Queries
Ein häufiger Fehler bei Search-Strategien ist die Annahme, dass ein Model, das auf allgemeinen Webdaten wie MS MARCO trainiert wurde, in einer spezialisierten Domäne gut funktioniert. Das ist das Out-of-Domain-(OOD)-Problem.
LLMs können den Bottleneck bei gelabelten Daten durch Generative Pseudo-Labeling (GPL, InPars) reduzieren, aber nicht eliminieren:
- Nimm dein domänenspezifisches Dokument-Corpus
- Bitte ein LLM per Prompt: „Generate a search query that this document would answer“
- Verwende die synthetischen (Query, Document)-Paare für Fine-Tuning von Retriever und Reranker
Synthetische Paare können helfen, wenn echte Queries knapp sind, spiegeln aber Generator und Prompt wider. Entferne Duplikate, filtere unplausible Queries und validiere auf echtem Held-out-Traffic.
Eine Experimentabfolge
Füge Komplexität nur dann hinzu, wenn die vorherige Stufe einen gemessenen Failure Mode offenlegt:
Schritt 1 (Baseline): Implementiere BM25 oder das aktuelle Lexical System und erstelle ein bewertetes Query-Set. Zeichne Recall, NDCG, Latency und Failure Slices auf.
Schritt 2 (Candidate Recall): Teste Dense Retrieval und Fusion nur dann, wenn die Baseline relevante Dokumente verfehlt. Tune den Candidate Cutoff anhand von Recall und Kosten.
Schritt 3 (Ranking Precision): Füge einen Cross-Encoder hinzu, wenn die richtigen Candidates vorhanden sind, aber in der falschen Reihenfolge erscheinen. Wähle die Shortlist-Größe anhand einer Quality-Latency-Kurve.
Schritt 4 (Domain-Fit): Führe Fine-Tuning oder Distillation erst durch, wenn generische Models stabile domänenspezifische Fehler zeigen. Halte echte Held-out-Judgments von synthetischen Trainingsdaten getrennt.
Schritt 5 (optionale teure Schicht): Teste Listwise- oder Reasoning-basiertes Reranking nur dann, wenn seine inkrementelle Qualität in wiederholten Runs bestehen bleibt und Latency, Kosten, Privacy sowie Fallback-Komplexität rechtfertigt.
Research-Richtungen separat evaluieren
Reasoning-Reranker und Search-Using Agents sind vielversprechend, beantworten aber andere Fragen als das fünfstufige Produktsuch-Demo.
Reasoning-basierte Reranker
Rank1 trainiert Reranker mit Reasoning Traces und berichtet starke Ergebnisse auf dem BRIGHT-Benchmark. Diese Evidenz ist für Reasoning-lastiges Retrieval relevant, aber keine direkte Vorhersage für die ESCI-Produktsuche.
Für rechtliche oder wissenschaftliche Search solltest du Reasoning-Reranker mit starken Cross-Encoder- und Listwise-Baselines anhand von Experten-Judgments, Citations, Latency und Failure Consistency vergleichen.
Agentic Search
Search-o1 untersucht ein Model, das während Multi-Hop Question Answering zusätzliche Searches ausführt. Das ist ein Orchestration-Problem — Query Generation, Stopping, Evidence Use und Answer Evaluation — und keine weitere Reranking-Stufe. Evaluiere es anhand der Correctness der End-Task und der Citation Support, nicht nur anhand von Retrieval-Metriken.
Zentrale Erkenntnisse
-
Betrachte den Stack als Abfolge von Experimenten. Etabliere eine lexikalische Baseline und ein bewertetes Query-Set, bevor du Dense Retrieval, Fusion oder Reranking hinzufügst.
-
Miss Candidate Recall getrennt von Ranking Precision. In diesem ESCI-Sample erreicht Recall@100 nach der Fusion 0,842 und bleibt über beide Reranking-Stufen hinweg konstant.
-
Verwende Hybrid Retrieval bei komplementären Fehlern. RRF verbesserte im Demo sowohl Recall@100 als auch NDCG@10, aber ein anderes Corpus rechtfertigt möglicherweise keine zwei Indizes.
-
Füge einen Cross-Encoder hinzu, wenn die Shortlist stimmt, aber die Reihenfolge falsch ist. Wähle die Candidate-Anzahl anhand einer gemessenen Quality-Latency-Kurve.
-
Behandle LLM-Reranking als optionales finales Experiment. Der aktuelle LLM-Vergleich des Demos ist illustrativ, weil sein Parser keine vollständige Permutation der Candidate-IDs validiert. Striktes Parsing, geloggte Fallbacks, wiederholte Runs und Kostenmessungen gehören in die Evaluation, bevor du einen Gain meldest.
-
Halte die Evidenztypen getrennt. Ein Paper-Ergebnis, eine Vendor-Case-Study, dieses Laptop-Demo und ein Production-A/B-Test beantworten unterschiedliche Fragen.
Der vollständige Pipeline-Code befindet sich im begleitenden Repository. Klone es, um die Pre-LLM-Stufen zu reproduzieren oder andere Models und Parameter zu testen; behandle die veraltete LLM-Zeile nicht als Ergebnis.
Referenzen
Papers
- Reciprocal Rank Fusion — Cormack et al., 2009
- RankGPT: LLMs as Zero-Shot Listwise Rerankers — Sun et al., EMNLP 2023 Outstanding Paper
- Rank1: Reasoning-Based Reranking — Weller et al., COLM 2025
- SCaLR: Self-Calibrated Listwise Reranking — Framework für Self-Calibrating Listwise Reranking
- GCCP: Global-Consistent Comparative Pointwise — Adressiert Calibration beim Pointwise LLM Ranking
- Rank-DistiLLM: Knowledge Distillation for Reranking — Schlatt et al., ECIR 2025
- Query2doc: LLM Query Expansion — Wang et al., EMNLP 2023
- GPL: Generative Pseudo Labeling — Domain Adaptation für Dense Retrieval
- InRanker: Distilled Reranker — Reduktion der Größe um den Faktor 50 bei konkurrenzfähiger Performance
- Search-o1: Agentic Retrieval — EMNLP 2025
- TALEC: LLM-as-a-Judge for Search — Evaluations-Framework
- BEIR Benchmark — Thakur et al., NeurIPS 2021
- BEIR Leaderboard —
BM25 multifield-Baseline und Aggregat über 18 Datasets - Sentence-BERT — Reimers & Gurevych, EMNLP 2019
- InfoNCE / CPC — van den Oord et al., 2018
- SimANS: Hard Negative Sampling — Zhou et al., EMNLP 2022
- Passage Reranking with BERT — Nogueira & Cho, 2019
- HNSW — Malkov & Yashunin, 2016
- DiskANN — Subramanya et al., NeurIPS 2019
- RaBitQ — Gao & Long, SIGMOD 2024
- Replacing Judges with Juries — Verga et al., 2024
- RAG-Fusion — Rackauckas, 2024
- InPars — Bonifacio et al., SIGIR 2022
- BRIGHT Benchmark — Su et al., ICLR 2025
- Rank-without-GPT — Zhang et al., ECIR 2025
- Pinterest LLM Search Relevance — Wang et al., 2024
- OmniSearchSage — Agarwal et al., WWW 2024
- PAL: Position-bias Aware Learning — Guo et al., RecSys 2019
Datasets und Benchmarks
- Amazon ESCI: Shopping Queries Dataset — KDD Cup 2022
- BEIR: Benchmarking IR — Heterogener Benchmark für Zero-Shot-Evaluation
- MTEB: Massive Text Embedding Benchmark — Leaderboard für Embedding Models
- ESCI Paper — Reddy et al., 2022
Im Demo verwendete Models
- all-MiniLM-L6-v2 — Bi-Encoder mit 22M Parametern
- ms-marco-MiniLM-L-12-v2 — Cross-Encoder mit 33M Parametern
- Sentence-Transformers — Framework für Neural Retrieval Models
Tools und Plattformen
- rank_bm25 — BM25-Implementierung in Python
- Pyserini BEIR Reproductions —
bm25-multifield-Index und Evaluationsbefehle - pytrec_eval — TREC-Evaluations-Toolkit
- Elasticsearch — Hybrid Search mit Retrievers API
- Vespa — Einheitliche Search- und Recommendation Engine
- Weaviate — Vector Database mit Hybrid Search
- Qdrant — Vector Database mit Multi-Stage Queries
Industry-Referenzen
- Airbnb Listing Embeddings — Grbovic & Cheng, KDD 2018
- Uber Delivery Search — Uber Engineering, 2025
- Uber Two-Tower Embeddings — Uber Engineering, 2023
- Elastic Rerank — Elastic, 2024
Demo-Projekt
- search-ranking-stack — Funktionsfähiges Demo mit dem vollständigen Code aus diesem Beitrag