[!NOTE] Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
De zoekrankingsstack in 2026: BM25, Embeddings, cross-encoders en LLM Reranking
Een zoekopdracht moet zowel de exacte als de semantische intentie weerspiegelen. Een zoekopdracht voor “wireless headphones” moet inderdaad producten bevatten die deze woorden bevatten, maar de uiteindelijke rangschikking kan ook afhangen van de productkwaliteit, gebruikersvoorkeuren en beschikbaarheid. Geen enkele enkelvoudige rangschikkingsmethode kan al deze factoren even goed verwerken.
In deze post wordt de technologiestack stap voor stap opgebouwd: BM25 retrieval, dense embeddings, Reciprocal Rank Fusion, cross-encoder reranking, en ten slotte LLM voor lijstgerichte rangschikking. A werkende demo benchmarks elke fase in de productzoekfunctie van Amazon ESCI dataset.
TL;DR: Bouw de zoekfunctie op als gemeten stappen. Begin met BM25, voeg dense retrieval toe zodra dit de recall voor uw query’s verbetert, fuseer alleen wanneer de twee retrievers complementaire fouten vertonen, en rangschik opnieuw alleen de kandidaatsets die binnen het latency budget vallen. In deze ESCI-demo ter grootte van een laptop steeg de volledige pipeline verbeterde NDCG@10 van 0,585 naar 0,717. Dit resultaat is een voorbeeld uit de praktijk, en geen bewijs dat elke productiestack alle vijf de stappen of een online LLM nodig heeft.
Kies de fasen op basis van het fallemode
De productiestack fungeert als een trechter, maar welke trechter wordt gebruikt, hangt af van de query en de bedrijfsinterface.
| Gebruiksgeval | Kandidaat-startstack | Valideren |
|---|---|---|
| Productzoekopdracht | BM25 + dichte retrieval + RRF + kruisencoder | Attribuutherinnering, substituties, latency, bedrijfsbeperkingen |
| Documentatiezoeken | Hybride retrieval + kruisencoder | Exacte identificatoren, semantische vragen, filters voor versies |
| Ondersteuning voor deflectie | Hybride retrieval + citatiecontroles | Retrieval recall, grounding, afwezigheid van correcte classificatie |
| Marktplaats of productlijsten | Lexicaal filteren + intensieve retrieval + bedrijfskritische reranker | Beschikbaarheid, versheid, beleid en diversiteit van verkopers |
| Klein intern corpus | De BM25-baseline, gevolgd door een reranker | Of een onovereenkomst in het woordenschat een dichte index rechtvaardigt |
| Een risicovolle juridische of medische zoekopdracht | Recall-gerichte retrieval in combinatie met expertbeoordeling | Dekking, herkomst en gecalibreerde afzijdigheid |
Begin met BM25 als basismodel. Voeg een dense retrieval toe wanneer een onovereenkomstig woordenschat de recall negatief beïnvloedt. Gebruik een cross-encoder wanneer de eerste pagina de juiste kandidaten bevat, maar in de verkeerde volgorde. Pas een LLM toe pas nadat je de kosten van een latency kunt dragen en de rangschikkingsbeslissingen kunt evalueren.
Hoe we hier zijn gekomen
De stack is eenvoudiger te begrijpen wanneer deze wordt gezien als drie lagen. Lexicaal retrieval vindt exacte termen, gedetailleerd retrieval vult woordenschatgaten op, en rerankers vergelijkt de sterkste kandidaten grondig met elkaar.
BM25 en lexicaal retrieval
Al decennia lang, BM25 Dit was de standaardinstelling. Het gaat om een probabilistisch model model dat documenten beoordeelt op basis van de frequentie van zoektermen daarin, gecorrigeerd voor de lengte van het document en de inverse documentfrequentie (IDF).
BM25 presteert goed wanneer letterlijke termen de intentie weerspiegelen: foutcodes, product-SKU’s, namen en API-identificatoren. De belangrijkste beperking is echter een woordenlijstmismatch. Een zoekopdracht naar “goedkope laptop” kan een document over een “budgetnotebookcomputer” negeren, mits de gearchiveerde tekst geen verband legt tussen deze uitdrukkingen.
Desondanks vormt BM25 een solide basis. Het behaalt een gemiddelde nDCG@10 van 0,429 over de gehele dataset. BEIR benchmark’s 18 datasets en Blijft nog steeds beter dan sommige neurale models-modellen. bij argumentatieve retrieval-taken zoals Touche-2020.
Dichte retrieval en embeddings
BERT-achtige encoders maken dichte retrieval implementaties mogelijk. Zij zetten zoekopdrachten en documenten om in een gedeelde vectorruimte, waarna kandidaten worden gerangschikt met behulp van een similariteitsfunctie zoals cosinussimilariteit of dotproduct.
De bi-encoder-architectuur (of “two-tower”-architectuur) verwerkt de query en het document afzonderlijk via aparte encoder-torens, waardoor embeddings van vaste lengte worden gegenereerd. Documentvectoren kunnen van tevoren worden berekend en offline worden geïndexeerd, zodat ze vervolgens snel kunnen worden opgehaald met behulp van Approximate Nearest Neighbor (ANN)-algoritmen. Hierdoor liggen termen als “goedkope laptop” en “budgetnotebook” nu dicht bij elkaar in de vectordimensie.
Sommige bi-encoders maken gebruik van een Siamese architectuur, net zoals in Sentence-BERT, Waar beide kanten weights delen, maken anderen gebruik van afzonderlijke query- en documenttorens. Het samenbrengen van gegevens, de vectorgrootte, de similariteitsfunctie en het trainingsdoel zijn model keuzemogelijkheden en geen eigenschappen die voor elke dense retriever gelden.
Deze models worden getraind met contrastieve learning, meestal met de InfoNCE Verlies. Voor een batch met paren (query, positief document) wordt het doelstellingfunctie maximaliseerd. sim(query, positive_doc) terwijl dit wordt geminimaliseerd sim(query, negative_docs). Negatieve voorbeelden komen voort uit de positieve voorbeelden van andere query’s in dezelfde batch (in-batch negaties). Een temperatuurparameter bepaalt in hoeverre de verdeling scherp is: lagere waarden zorgen ervoor dat de model de onderscheiding tussen positieve en negatieve voorbeelden moeilijker maakt.
Trainingsgegevens spelen vaak een belangrijkere rol dan de embedding-dimensie. Retrieval models leren van query-positieve paren en zorgvuldig geselecteerde harde negatieven: plausibele, maar niet relevante documenten. Het volgende gedeelte over training laat zien hoe SimANS Het vermijdt zowel triviale negatieve resultaten als waarschijnlijk valse negatieve resultaten.
De kosten zijn gelijk aan de representatie van bottleneck. Bi-encoders comprimeren alle semantische nuances tot een enkele vector met vaste grootte, waardoor ze vaak fijne interacties tussen specifieke zoektermen en specifiek documentinhoud over het hoofd zien.
Cross-encoders en LLMs
Cross-encoders (Nogueira & Cho, 2019) Voer de query en het document samen in als een gecombineerde sequentie naar de Transformer.[CLS] Query [SEP] Document), zodat elke query token elk document token kan verwerken via een volledige self-attention. Deze diepe interactie maakt nuances zichtbaar die bij een aparte codering worden gemist.
LLM reranking maakt gebruik van een opgevraagde model om meerdere kandidaten tegelijkertijd te vergelijken. RankGPT Er werden sterke zero-shot, lijstgewijze resultaten geboekt met GPT-4 op de geteste benchmarks, maar de stabiliteit van de uitvoer, de kosten en de passendheid voor het desbetreffende domein vereisen nog aparte tests.
Aangezien deze scores niet van tevoren kunnen worden berekend voor willekeurige queries, wordt reranking geplaatst na retrieval. Deze kostenasymmetrie vormt de reden voor het gebruik van een meestagesfunnel.
De meestagede funnel
Het uitvoeren van een dure cross-encoder of LLM op miljoenen documenten is niet haalbaar, waardoor moderne zoekarchitecturen gebruikmaken van een leidingsysteem. Elke fase filtert het aantal mogelijke resultaten verder af, terwijl de model complexiteit toeneemt.
Een complex model is te traag om het hele corpus te kunnen beoordelen, terwijl een goedkope retriever niet voldoende nauwkeurigheid biedt. De funnel maakt gebruik van elke model alleen wanneer de bijbehorende kosten redelijk zijn.
| Fase | Invoerschaal | Primair doelstelling | Typische methoden | Meting van het vertrekpunt |
|---|---|---|---|---|
| Retrieval | Corpus of index | Kandidaatherinneringsratio | BM25, bi-encoders | Herinnering bij het kandidaatcutoff-punt |
| Voor-rangschikking | Groot aantal kandidaten | Goedkope filtering | Lichtgewicht models, regels | Herinnerd aantal acties per milliseconde |
| Volledige ranglijst | Shortlist | Hogekwalitatieve top-ranking | Cross-encoders, LLMs | NDCG/MRR, latency, kosten |
| Blending | Uiteindelijke gerangschikte lijsten of posities | Beperkingen en combinaties | Regels, rangschikking voor meerdere doelstellingen | Beleid, diversiteit en bedrijfsvoering guardrails |
Retrieval stelt het plafond vast en reranking optimaliseert binnen die grenzen. Als een relevante document niet overleeft retrieval, kan geen latere model deze herstellen.
De demo: een vijfstappige pipeline
Om dit concreet te maken, heb ik een search-ranking-stack demo die een vijfstadige pipeline uitvoert op de Amazon ESCI Productzoekopdracht benchmark. Elke fase wordt apart gemeten, zodat u kunt zien waar de verbeteringen daadwerkelijk vandaan komen.
De pipeline:
- BM25 sparse retrieval — lexicale referentiebasis (
rank_bm25) - Dichte bi-encoder retrieval — generatie van semantische kandidaten
all-MiniLM-L6-v2) - Hybride RRF-fusie — rang gebaseerde fusie van spaarzame en dichte resultaten
- Kruisencoder reranking — paar voor paar relevanciescores (
ms-marco-MiniLM-L-12-v2) - LLM lijstsgewijs reranking — een op verzoek uitgevoerde vergelijking van de uiteindelijke korte lijst (Ollama, API, of lokale model)
Stappen 1–3 vormen de retrieval-fase van de funnel (maximalisatie van de recall); stappen 4–5 zijn de fase van de volledige rangschikking (maximalisatie van de precisie). De demo slaat de voor-rangschikking en het mengen over. Bij ongeveer 8.500 documenten kun je het zich veroorloven om alle hybride resultaten rechtstreeks naar reranking te sturen.
Snel starten
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 en sampling: Amazon ESCI
De demo maakt gebruik van de Amazon Shopping Queries Dataset (ESCI) uit KDD Cup 2022 — een echte productzoekfunctie benchmark met vier niveaus van gerangschikte relevantielabels:
| Label | Verkrijgen | Betekenis | Voorbeeld (query: “wireless headphones”) |
|---|---|---|---|
| Exact (E) | 3 | Voldoet aan alle vereisten voor de query. | Sony WH-1000XM5 draadloze koptelefoon |
| Vervanger (S) | 2 | Functionele alternatiefoplossing | Kabelheadset met Bluetooth-adaptor |
| Complement (C) | 1 | Gerelateerd nuttig item | Headfonskoffer |
| Irrelevant (I) | 0 | Geen betekenisvolle relatie | USB-laderkabel |
Gegradeerde relevantie is belangrijk omdat het het mogelijk maakt om NDCG (Normalized Discounted Cumulative Gain) te gebruiken; deze methode onderscheidt een “perfecte” rangschikking van een “slechts voldoende” rangschikking. Binaire metrieken beschouwen beide als even relevant en kunnen geen onderscheid maken tussen verschillende niveaus van relevantie op dezelfde positie.
Ik heb de demo gebruikt. small_version Voorbeeld: ongeveer 500 zoekopdrachten, 8.500 producten en 12.000 beoordelingen. Het is klein genoeg om op een laptop te draaien, maar te beperkt en te domeinspecifiek om een productieve rangschikking te kunnen opzetten. Gebruik het om de verschillende stappen na te bootsen en foutpatronen te onderzoeken; gebruik apart gehouden, representatieve zoekopdrachten om deployment-beslissingen te nemen.
Retrieval: hybride zoekopdracht
De taak van de laag retrieval is om de recall te maximaliseren – men moet zo breed mogelijk vissen zodat niets relevants onopgemerkt blijft.
BM25: de lexicaal referentieniveau
BM25 bepaalt de scores van documenten op basis van de termoverlappingsgraad met de query, waarbij rekening wordt gehouden met saturatie van de termfrequentie en normalisatie van de documentlengte:
Waar \text{IDF}(t) is de inverse documentfrequentie van term ; is de termfrequentie in document .|d|\text{avgdl}k_1b$ (meestal 0,75) regelt de normalisatie van de documentlengte.
De implementatie is kort. Eenvoudige witruimte tokenization met 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 levert een Recall@100 op van 0,741 — 74% van de relevante producten verschijnt ergens in de top 100. Dat is niet slecht voor een puur lexicaal model, maar 26% van de relevante items blijft onzichtbaar voor alle volgende verwerkingsstappen.
Dichte bi-encoder retrieval
De bi-encoder vertaalt vragen en documenten afzonderlijk naar een gedeelde embedding-ruimte:
# 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)
Met gecentraliseerde embeddings reduceert de cosinusgelijkenis tot een puntproduct. De demo berekent de volledige matrix van query’s tegenover het corpus, omdat 8.500 documenten gemakkelijk in het geheugen passen; in een productieomgeving zou men normaal gesproken een index op basis van de meest nabije buur gebruiken. In dit voorbeeld all-MiniLM-L6-v2 De Recall@100-waarde stijgt van 0.741 naar 0.825.
Hoe bi-encoders goede representaties leren
De training van een bi-encoder verloopt meestal in twee fasen. Eerst wordt de model vooraf getraind op Natural Language Inference (NLI) en Semantic Textual Similarity (STS) datasets, waardoor algemene semantische begripvaardigheid wordt ontwikkeld — de model leert dat zinnen als “een kat zit op een mat” en “een kat rust op een tapijt” een vergelijkbare embeddings moeten hebben. Vervolgens wordt de model getuned op retrieval-specifiek data zoals MS MARCO, zodat het leert dat een zoekopdracht en de bijbehorende relevante tekst dichter bij elkaar moeten staan dan de opdracht en irrelevante teksten.
Het cruciale element in de tweede fase is hard negative mining. Willekeurige negatieven (bijvoorbeeld een document over koken dat wordt gecombineerd met een zoekopdracht naar koptelefoons) zijn zeer gemakkelijk van elkaar te onderscheiden — de model leert er niets van. In plaats daarvan maakt men gebruik van de huidige model zelf om documenten te vinden die door deze model hoog worden gerangschikt, maar die in werkelijkheid niet relevant zijn.
De SimANS De aanpak van (Simple Ambiguous Negatives Sampling) formaliseert dit proces: eerst worden alle documenten gerangschikt met behulp van de huidige bi-encoder, waarna de gemakkelijke negatieven (die te laag zijn gerangschikt – model handelt deze al af) en potentiële valse negatieven (die te hoog zijn gerangschikt – ze kunnen eigenlijk relevant zijn maar nog niet gelaabeld zijn) worden uitgesloten. De “moeilijke middenweg” zorgt voor het maximale leerseignaal.
# 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.
De contrastieve verliesfunctie (InfoNCE) brengt dit met elkaar in verband. Voor elke query met een positief document en een verzameling negatieve documenten :
Waarbij de cosinusgelijkenis is tussen de query en het document embeddings, en de temperatuurparameter is (meestal 0,05–0,1) die bepaalt hoe scherp de verdeling is — lagere waarden maken dat de verliesfunctie gevoeliger wordt voor sterke negatieve resultaten. Het is in feite een softmax-kruisentropie: Verhoog de similariteit van het positieve paar ten opzichte van alle negatieve waarden. Wanneer klein is, leiden zelfs kleine verschillen in similariteit tot grote gradienten, waardoor de model gedwongen wordt om fijnere onderscheidingen te maken.
Serving bi-encoder embeddings op grote schaal
Het architectonische voordeel van een bi-encoder is de offline/online split. De documenten embeddings worden bij het indexeren berekend en opgeslagen in een vectorindex. Tijdens het zoeken wordt de query gecodeerd en worden deze opgeslagen vectoren doorzocht. Latency hangt af van de encoder, de hardware, de index, de filters en het doel voor herinnering, dus is het belangrijk om deze twee stappen apart te profileren.
In de demo is de rekenkundige last beperkt: 8.500 documenten × 384 dimensies × 4 bytes per float = ongeveer 13 MB aan embeddings. Op productieniveau worden deze cijfers echter aanzienlijk: 1 miljard documenten met 768-dimensionale embeddings vereisen ongeveer 3 TiB aan opslagruimte. Hier komt quantization (het compresseren van 32-bits float-getallen naar 8-bits gehele getallen) om de hoek kijken. product quantization (decompositie van vectoren in subspaceën), en indexen gebaseerd op SSD’s zoals DiskANN Kom binnen. De Sectie over dense-vectorindexering bevat de algoritmen voor het indexeren.
Waarom testen op hybride retrieval-systemen?
Deze twee methoden falen vaak op verschillende manieren. BM25 is zeer geschikt voor eigennamen, product-SKUs en foutcodes. Dichte retrieval kan onovereenstemmingen in het woordenschatgebruik herstellen, zoals bij uitdrukkingen als “cheap laptop” versus “budget notebook computer”. Of fusing helpt, hangt af van de frequentie waarmee deze complementaire gevallen voorkomen in de doelqueryset.
Een veelvoorkomend volgend experiment is hybride zoekopdracht: voer beide retrieval methoden uit en fuseer daarna hun gerangschikte lijsten.
Reciproque rangfusie (RRF)
BM25 en dichte retrieval genereren scores met verschillende betekenissen en schalen. Een lineaire combinatie vereist daarom calibration en validatie wanneer de retrievers of het corpus veranderen.
Reciproque rangfusie (Cormack et al., 2009) gebruikt de ruwe scores geheel niet en houdt alleen rekening met de rangpositie:
Hierin is een smoothing-constante; 60 is een veelgebruikte startwaarde. RRF beloont elementen die zich bovenaan de lijsten van invoer bevinden, zonder hun brute scores met elkaar te vergelijken. Het vermijdt schaalproblemen met betrekking tot de calibration, maar de retrieval-cutoffs, weights en vereisen nog steeds evaluatie.
De implementatie:
# 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
De Hybrid RRF behaalt een Recall@100 van 0,842 en een NDCG@10 van 0,628 — waarmee deze zowel BM25 (0,585) als Dense (0,611) overtreft wanneer ze alleen worden gebruikt. Documenten hoeven slechts goed te scoren in één methode om te overleven bij de fusie.
Kruisencoder reranking
Met 100 hybride kandidaten per zoekopdracht kunt u zich een duurder model veroorloven. De cross-encoder verwerkt de zoekopdracht en het document samen via één enkele Transformer, waarbij er volledige cross-attention bestaat tussen alle tokens.
Token-niveau interactie
Het echte verschil zit in de attention-matrix. Bij een bi-encoder is de attention-structuur blok-diagonaal: query’s tokens richten zich uitsluitend op andere query’s tokens, en documenten tokens richten zich uitsluitend op andere documenten tokens. De twee representaties komen nooit op het niveau van de token met elkaar in contact — ze snijden alleen aan het eind met elkaar door middel van een dotproduct. Een cross-encoder berekent de volledige attention-matrix, waarbij elke query token contact heeft met elk document token en omgekeerd. Het is juist dit cross-attention dat diepe interacties op het niveau van de token mogelijk maakt.
Bij een bi-encoder wordt de query “apple” al gecodeerd voordat er ook maar één document wordt bekeken. Een cross-encoder ziet zowel de query als het kandidaatdocument tegelijkertijd, waardoor hij gebruik kan maken van hun relatie op token-niveau. Dit kan van pas komen in situaties zoals:
- Ontkenning: “Koptelefoons die niet draadloos zijn.” Een gecombineerde embedding kan de nadruk op de ontkenning verminderen, terwijl gecombineerde codering ervoor zorgt dat de model een directe interactie met het zoekdocument heeft. Dit is een hypothese die moet worden getoetst met een gerichte steekproef, en geen garantie.
- Beperking: “Laptop onder $500.” Gecombineerde codering maakt het mogelijk om deze beperking te koppelen aan een prijs in de productbeschrijving, hoewel gestructureerde prijsfilters veiliger zijn wanneer dit veld beschikbaar is.
De invoer voor de cross-encoder is geformateerd als [CLS] query tokens [SEP] document tokens [SEP]. [CLS] het is een classificatie token waarvan de uiteindelijke verborgen toestand via een lineaire head wordt doorgegeven om één enkele relevantiescore te genereren. Segmenteer embeddings om de query tokens te onderscheiden van het document tokens, en [SEP] dient als grens tussen de segmenten.
Hoe cross-encoders getraind worden
Cross-encoders kunnen leren van (query, document, relevance_label) Voorbeelden met puntsgewijze, paarsgewijze of lijstsgewijze doelstellingen. Het hieronder staande puntsgewijze voorbeeld maakt gebruik van één relevanțielabel; dit is niet de enige manier om training te ontwerpen.
# 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
Een veelgebruikte classificator maakt een kaart van de eindresultaten [CLS] De omzetting van een representatie naar een score. Voor binaire labels kan binary cross-entropy worden gebruikt; bij geclassificeerde relevantie zijn regressielossen, ordinale lossen, paarwee‑lossen of lijstgewijze lossen mogelijk. Kies op basis van gevalideerde rangschikkingsmetrieken in plaats van te veronderstellen dat één doelstelling universeel beter is.
Hard negative mining is des te belangrijker voor cross-encoders. in vergelijking met bi-encoders. Cross-encoders zijn kostbaar om te trainen — elke trainingsvoorbeeld vereist een volledige forward pass door de gecombineerde sequentie — dus je kunt het je niet veroorloven rekenkracht te verspillen aan negatieven die zeer gemakkelijk te bepalen zijn. Het praktische recept is om een bi-encoder te gebruiken om de top-K kandidaten voor elke trainingsvraag op te halen, en vervolgens zware negatieven te selecteren uit specifieke rangbereiken (bijvoorbeeld rangen 10–100). Hierdoor krijgt de cross-encoder voorbeelden waarin het onderscheiden van relevante van irrelevante informatie daadwerkelijk diepe token interactie vereist.
# 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):
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_results[query_id] = {
doc_id: float(score) for doc_id, score in scored_docs
}
Tijdens de opgenomen demo-run, ms-marco-MiniLM-L-12-v2 Het rangschikt 50 kandidaten per zoekopdracht en verhoogt de NDCG@10 van 0,628 naar 0,645. Meet de latency op de deployment hardware; model, de sequentielengte, de batchgrootte en runtime hebben allemaal invloed op het resultaat.
De afweging tussen snelheid en kwaliteit
Waarom worden er niet voor alles cross-encoders gebruikt? Omdat voorkalkulatie onmogelijk is. Bi-encoder-documenten embeddings zijn onafhankelijk van de query, zodat je ze één keer kunt berekenen en opslaan. De uitvoer van een cross-encoder hangt af van zowel de query als het document samen. De relevantiescore voor “draadloze koptelefoons” in combinatie met een Sony-product komt voort uit de volledige cross-attention tussen die specifieke tokens. Je kunt deze niet opslaan in een cache of hergebruiken voor een andere query.
Een bi-encoder heeft één query-encoding nodig, samen met een vector search van vooraf berekende documenten embeddings. Een cross-encoder evalueert elk query-document-paar uit de shortlist, waarbij de kosten toenemen naarmate zowel het aantal kandidaten als de sequentielengte toeneemt. Het groeperen van verzoeken helpt, maar het evalueren van 100.000 kandidaten blijft een ongewenste werkwijze; haal eerst de gegevens op en benchmark selecteer vervolgens de grootste shortlist die voldoet aan de kwaliteits- en latency-eisen.
De regel die de demo bevestigt, is dat Recall@100 op een constant niveau van 0,842 blijft gedurende beide reranking fasen. Reranking kan de resultaten hersorteren, maar voegt nooit nieuwe documenten toe. Retrieval bepaalt het maximale niveau.
LLM lijstvoorlijst reranking
In de finale demonstratiefase wordt een LLM gebruikt voor lijstsgewijze reranking verwerking. In plaats van elk document afzonderlijk te beoordelen, bekijkt de model de 10 beste resultaten en geeft een rangorde terug. Geïnspireerd op RankGPT, De prompt maakt relatieve vergelijkingen expliciet, maar zorgt tevens voor contextuele beperkingen, positiebias, parsingfouten en variatie tussen opeenvolgende uitvoeringen.
De lijstgewijze prompt
Het prompt-template vraagt de LLM om rekening te houden met de relevantiehiërarchie van ESCI:
# 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."
)
Drie uitvoermodi
De demo ondersteunt drie backends voor LLM reranking:
| Modus | Model | Hoe het werkt |
|---|---|---|
ollama | llama3.2:3b (configureerbaar) | Lokaal via Ollama API |
api | claude-haiku-4-5-20251001 | Anthropic API |
local | Qwen/Qwen2.5-1.5B-Instruct | HuggingFace Transformers |
Parseren en fallback-mechanismen
De uitvoer van LLM garandeert niet dat deze voldoet aan het opgevraagde schema; daarom zijn parsing en een fallback-route van essentieel belang:
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]
Als de parsing volledig faalt, grijpt de demo terug op de volgorde van de cross-encoder. Een productie-parser moet ook identificatoren die buiten het bereik vallen of duplicaten weigeren, de weggelaten opties in hun oorspronkelijke volgorde toevoegen, de fout registreren en het falenpercentage vergelijken met een vastgesteld drempelwaarde.
Resultaten van dit ESCI-voorbeeld
Hieronder staan de resultaten van het uitvoeren van de volledige pipeline op ongeveer 500 ESCI-queries:
| Fase | NDCG@10 | MRR@10 | Recall@100 | NDCG-delta |
|---|---|---|---|---|
| BM25 | 0.585 | 0.812 | 0.741 | — |
| Dichte bi-encoder | 0.611 | 0.808 | 0.825 | +0.026 |
| Hybride (RRF) | 0.628 | 0.834 | 0.842 | +0.017 |
| + Cross-encoder | 0.645 | 0.860 | 0.842 | +0.017 |
| + LLM Reranker | 0.717 | 0.901 | 0.842 | +0.072 |
Belangrijkste observaties
Een hybride zoekmethode presteert beter dan elk van de afzonderlijke methoden op zichzelf. De RRF NDCG-waarde (0,628) is het hoogst, voorbij zowel BM25 (0,585) als Dense (0,611). Sparse en dense retrieval hebben complementaire manieren om fouten te maken, en door ze te combineren kunnen documenten worden teruggevonden die anders door één van beide methoden over het hoofd gezien zouden worden.
De recall-waarde is ingesteld op retrieval. De recall@100-waarde blijft constant op 0,842 gedurende beide reranking-fasen. Tijdens de Rerankers-hertekening worden er geen nieuwe documenten toegevoegd. Als u een hogere recall wilt, moet u de retrieval-laag aanpassen.
De opgevraagde LLM levert de grootste gemeten sprong op in deze uitvoering. De NDCG@10 stijgt met 0,072 na de LLM-fase. Omdat de prompt de ESCI-relevantheidshierarchie omvat, wordt hiermee deze combinatie van model-prompt-dataset getest. Voordat de verbetering kan worden toegeschreven aan een algemeen superieur reranker, zijn herhaalde uitvoeringen, betrouwbaarheidsintervallen, latency, kosten en een apart gehouden domeinset vereist.
Dichte retrieval presteert beter dan BM25 op dit voorbeeld. Controleer eerst de query-slices voordat je de oorzaak vaststelt. Een onovereenkomst in het woordenbestand is een mogelijke oorzaak, maar de opbouw van het voorbeeld, tokenizer, het model-trainingsdominium en de velden in het corpus hebben eveneens invloed op de vergelijking.
Evaluatie: meten van wat belangrijk is
De demo maakt gebruik van drie complementaire metrieken. Elke metriek bekijkt de rangschikking vanuit een andere hoek:
NDCG@10 (belangrijkste metriek)
Gecentraliseerde gereduceerde cumulatieve winst meet de kwaliteit van de top-10 rangschikking op basis van gegradueerde relevantie. Het beloont het plaatsen van zeer relevante documenten dicht bij de bovenkant met een logaritmische correctie:
NDCG is de enige metriek die volledig gebruikmaakt van ESCI’s viergradensysteem voor het bepalen van relevantie — een systeem waarbij een exacte overeenkomst op positie 1 een hogere score krijgt dan wanneer er een vervangende overeenkomst op die plek staat. Daarom wordt het gebruikt als de belangrijkste metriek voor de algehele zoekkwaliteit.
MRR@10 (eerst resultaat dat van toepassing is)
Gemiddelde wederkerige rang hanteert de positie van het eerste als relevant beschouwde resultaat. Als dit zich op positie 1 bevindt, is de wederkerige rang 1,0; op positie 3 is deze 0,333. Bij gegradueerde classificaties zoals ESCI dient de relevantheidsschijf te worden vermeld die wordt gebruikt om deze graden om te zetten in een binaire beslissing.
Recall@100 (retrieval dekking)
Recall geeft aan wat het aandeel is van de als relevant beoordeelde documenten dat zich bevindt in de top 100. Het is een ‘candidate-ceiling’-metriek voor de geëvalueerde oordelen: een reranker kan geen document toevoegen dat door retrieval is weggelaten, terwijl onvolledige oordelen de zichtbare bovengrens onzeker kunnen maken.
Indexeren van dichte vectoren buiten het demo-scenario
Dichte embeddings worden pas echt nuttig op grote schaal wanneer je beschikt over een index voor Approximate Nearest Neighbor (ANN). De demo maakt gebruik van brute-force cosinusgelijkenis (wat voldoende is bij ongeveer 8.500 documenten), maar productiesystemen hebben gespecialiseerde indexen nodig.
HNSW (hiërarchische, navigeerbare kleine wereld)
HNSW Er wordt een meervoudig laaggrafiek opgebouwd: de spaarzame bovenste lagen bieden een brede oriëntatie, terwijl de dichtere onderste lagen de nabije omgeving verfijnen. M beheert de connectiviteit van het graf, terwijl efSearch Het vervangt het optimaliseren van de query-efficiëntie door het maximaliseren van de recall. De bruikbare waarden hangen af van de dimensie, de afstandsdistributie, de filters, de implementatie en het gewenste niveau van recall.
Updates en verwijderingen vormen een operationeel aspect, aangezien grafindexen gedenkstenen kunnen behouden of achtergrondreparaties nodig hebben. Het gedrag verschilt per database. A Qdrant-probleem, Bijvoorbeeld: er worden rapporten geleverd waarin de kwaliteit verslechtert na een specifieke workload met zware verwijderingen. Repliceer het gewenste patroon van klantenverlies en neem bij de evaluatie ook het gedrag met betrekking tot compressie of heropbouw in overweging.
IVF (omgekeerde bestand)
IVF-indexen verdelen de vectorruimte in clusters en scannen vervolgens deze. nprobe De clusters die het dichtst bij de query liggen. Zij bieden een nuttige afweging tussen geheugengebruik, compilatietijd en herinneringsratio, vooral wanneer ze worden gecombineerd met compressie. De semantiek en prestaties van updates hangen af van de implementatie en niet uitsluitend van het type index.
Voor uiterst grote schaal. IVF_RaBitQ (Gao & Long, SIGMOD 2024) comprimeert vloeiendekommavectoren tot éénbitrepresentaties. In een hoge-dimensionale ruimte bevat het teken (+/-) van een coördinaat voldoende hoekinformatie voor het uitvoeren van vergelijkingen op gelijkenis.
| Dimensie | HNSW grafiek | IVF-clusters |
|---|---|---|
| Vraagbeheer | efSearch | nprobe |
| Buildbeheer | Connectiviteit en constructiebalk | Aantal clusters en trainingsvoorbeelden |
| Geheugenprofiel | Grafiekranden plus vectoren | Centra, lijsten en opgeslagen vectoren |
| Updategedrag | Database-specifieke reparatie/zuivering | Database-specifieke onderhoud van lijsten |
| Evalueer met | Recall-latency-curve van geheugenverbruik | Recall-latency-curve van geheugenverbruik |
In één Case study: Uber Delivery Search, Het verlagen van een zoekparameter op shard-niveau van 1.200 naar 200 leidde tot een daling van het gerapporteerde latency met 34% en van CPU met 17%, zonder significante afname in de recall. De belangrijkste les is om de recall-kostencurve af te stemmen op verkeersomstandigheden die lijken op die in productieomgevingen, in plaats van simpelweg de waarde 200 over te nemen.
Optionele uitbreidingen na de kern pipeline
Zodra retrieval en reranking afzonderlijke metingen hebben, worden verschillende uitbreidingen gemakkelijker te evalueren, zonder dat de kern pipeline wordt verduisterd.
Vraagbegrip
Vraaguitbreiding en -herformulering kunnen een onovereenkomst in het woordenschatgebruik oplossen vóór retrieval. Query2Doc Er werden geproduceerde pseudo-documenten gegenereerd en werden de voordelen van BM25 gemeld op basis van de MS MARCO-experimenten. Expansie kan bovendien tot verkeerde intenties leiden; daarom moet men de recall en precisie vergelijken voor ambiguë, navigatieve en vragen met exacte identificatoren.
Praktische patronen: uitbreiding van afkortingen, verrijking van entiteiten, en decompositie van subquery’s voor multi-hop reasoning. RAG-Fusie — meerdere queryvarianten genereren en de resultaten combineren met behulp van RRF.
LLM-geassisteerde relevantie-labeling
LLMs kan relevanțielabels opstellen wanneer er weinig menselijke beoordelingen beschikbaar zijn. TALEC en De werking van Pinterest’s labelen van relevantie Geef twee geëvalueerde ontwerpen. Een LLM-label is nog steeds model-output: kalibreer het aan de hand van geblokkeerde menselijke beoordelingen, onderzoek de verschillen tussen resultaten en bewaar een menselijk referentiebestand voor regressietests.
Usefulle controles omvatten:
- een rubriek met specifieke grenzen voor relevantie en voorbeelden;
- geblindeerde menselijke calibration beoordelingen en periodieke hercontroles;
- randomisatie van de volgorde en herhaalde beoordelingen voor onstabiele gevallen;
- model panels waarbij de extra kosten leiden tot een betere overeenstemming; en
- expliciete controles op positie- en centrale-tendensbias.
Kennisdistillatie
Wanneer een LLM-leraar waarde toevoegt maar de serving-beperkingen niet kan nakomen, is distillatie een mogelijkheid:
- Gebruik een krachtige LLM (de leraar) om duizenden trainingsvragen opnieuw te rangschikken.
- Traineer een kleine, snelle cross-encoder (de leerling, met ongeveer 100M–200M parameters) om de rangschikkingsverdeling van de LLM na te bootsen.
- Vergelijk de leerling met zowel de leraar als de baseline op basis van kwaliteit, calibration en serving-kosten.
InRanker Het MonoT5-3B-model wordt geconsolideerd tot versies met respectievelijk 60 miljoen en 220 miljoen parameters models — wat een verkleining van 50 keer oplevert bij gelijkaardige prestaties. De Rank-Without-GPT Deze benadering genereert een lijst van 7B open-source modellen die op lijstniveau rerankers werken en 97% van de effectiviteit van GPT-4 bereiken door middel van QLoRA fine-tuning.
De gepubliceerde compressieresultaten vormen uitgangspunten, en niet de verwachte productieratio’s. Distillatie kan de voorkeuren van de ‘teacher’ overnemen en kwaliteit verliezen bij zeldzame query-sets; houd daarom de oorspronkelijke relevantiebeoordelingen behouden in de evaluatieronde.
Personalisatie en positiebias
Algemene relevantie brengt je maar tot op zekere hoogte. Een zoekopdracht naar “apple” moet voor een technologiefan iPhones opleveren, terwijl iemand die kookinhoud bekijkt recepten met appel moet vinden.
Een veelgebruikte retrieval-architectuur voor personalisatie maakt gebruik van een tweeperonsige embedding model: de query-toren encodeert de query en de gebruikerscontext, terwijl de item-toren de items en metadata encodeert. De splitsing tussen offline- en online-modus ondersteunt approximate-nearest-neighbor retrieval; de latency hangt nog steeds af van de encoder, de index, de filters en het serving-systeem.
De Airbnb-aanbieding embeddings, Pinterests OmniSearchSage, en Ubers twee-torensystemen Toon verschillende productiedesigns. Hun schaal en gemelde verbeteringen behoren tot die systemen; het overdraagbare patroon bestaat uit een offline item-toren gecombineerd met een online query-/gebruikerstoren.
Klikgegevens bevatten een positie- en blootstellingsbias. PAL Een benadering om bias te verminderen is het gebruik van positie tijdens het trainen, om deze vervolgens constant te houden tijdens serving. Dit is geen universele oplossing; gerandomiseerde interventies, inverse-propentie-methoden en counterfactale evaluatie kunnen voor een ander product meer geschikt zijn.
Domeinadaptatie met synthetische query’s
Een veelvoorkomende fout in zoekstrategieën is het aannemen dat een model die is getraind op algemene webdata (zoals MS MARCO) goed zal presteren in een gespecialiseerd domein. Dit vormt het out-of-domain (OOD) probleem.
LLMs kan de gemarkeerde gegevens bottleneck verminderen, maar niet volledig elimineren, door middel van Generatief Pseudomarkeren.GPL, InPars):
- Neem uw domeinspecifieke documentencorpus.
- Prompt een LLM om “Een zoekopdracht te genereren die dit document kan beantwoorden”.
- Gebruik de synthetische (opdracht, document)-paren om uw retriever en reranker verder af te stemmen.
Synthetische paren kunnen van pas komen wanneer er weinig echte query’s beschikbaar zijn, maar ze weerspiegelen de generator en prompt. Duplicaten moeten worden weggehaald, onwaarschijnlijke query’s gefilterd, en de resultaten gevalideerd aan de hand van echte, apart gehouden verkeersdata.
Een experimentenserie
Voeg complexiteit alleen toe wanneer de vorige fase een gemeten fout blootlegt:
Stap 1 (baseline): implementeer BM25 of het huidige lexicaal systeem en bouw een gecorrigeerde queryset op. Noteer de recall-waarde, NDCG, latency, en de foutsegmenten.
Stap 2 (kandidaatherinnering): test zowel de gedenseerde retrieval-methode als de fusing-methode alleen wanneer de baseline relevante documenten mist. Stel de kandidaatsdrempel af op basis van herinneringsratio en kosten.
Stap 3 (precisie van rangschikking): voeg een cross-encoder toe wanneer de juiste kandidaten aanwezig zijn maar in de verkeerde volgorde verschijnen. Kies de grootte van de shortlist op basis van een kwaliteits-latency-curve.
Stap 4 (domain fit): voer pas fine-tuning of distillatie uit nadat de algemene models stabiele, domeinspecifieke fouten hebben aangetoond. Houd de echte, niet-gedetecteerde oordelen gescheiden van de synthetische trainingsgegevens.
Stap 5 (optionele, dure laag): voer alleen lijstsgewijs of op basis van reasoning-gebaseerde reranking tests uit wanneer de incrementele kwaliteit na herhaalde uitvoeringen behouden blijft en voldoende rechtvaardiging biedt voor de latency, de kosten, de privacyaspecten en de complexiteit van alternatieve oplossingen.
Onderzoekrichtingen die apart geëvalueerd moeten worden
Reasoning en rerankers, evenals zoekopdrachten met agents, vertonen veelbelovend potentieel, maar ze beantwoorden andere vragen dan die van de vijfstadia-demo voor productzoekfuncties.
Reasoning-gebaseerde rerankers
Rank1 Traint rerankers met reasoning traces en levert sterke resultaten op de BRIGHT benchmark. Die bewijsstukken zijn relevant voor reasoning-intensieve retrieval, en niet voor een directe voorspelling bij het zoeken naar ESCI-producten.
Voor juridische of wetenschappelijke zoekopdrachten dient reasoning rerankers te worden vergeleken met sterke cross-encoder-baselines en lijstgerichte baselines op basis van expertbeoordelingen, citaten, latency, en consistentie bij fouten.
Agentic zoeken
Search-o1 Het onderzoekt een model die extra zoekopdrachten uitvoert tijdens vragenbeantwoording over meerdere stappen. Dit is een orchestration probleem — querygeneratie, stoppen van het proces, gebruik van bewijsmateriaal en evaluatie van antwoorden — en niet een andere reranking fase. Beoordeel dit aan de hand van correctheid bij het voltooien van de taak en ondersteuning door citaten, en niet alleen op basis van retrieval-metrieken.
Belangrijkste conclusies
-
Behandel de stack als een reeks experimenten. Stel eerst een lexicale basislijn en een geselecteerd vragenbestand vast, voordat er dichte retrieval-, fusie- of reranking-technieken worden toegevoegd.
-
Meet de recall van kandidaten apart van de ranking-precisie. In dit ESCI-voorbeeld bereikt Recall@100 na fusing een waarde van 0,842 en blijft deze constant gedurende beide reranking fasen.
-
Gebruik een hybride retrieval wanneer de fouten elkaar aanvullen. RRF verbeterde zowel Recall@100 als NDCG@10 in de demo, maar een ander corpus biedt mogelijk geen reden om twee indices te gebruiken.
-
Voeg een cross-encoder toe wanneer de shortlist correct is maar de volgorde niet. Kies het aantal kandidaten op basis van een gemeten kwaliteitscurve-latency.
-
Beschouw LLM reranking als een optioneel eindexperiment. De hier behaalde stijging van 0,072 NDCG@10 valt onder deze prompt, model, steekproef en de relevantierubriek. Herhaalde uitvoeringen, strikte parsing, fallback-mechanismen en kosten maken deel uit van de evaluatie.
-
Houd de verschillende soorten bewijsmateriaal gescheiden. Een onderzoeksresultaat, een casestudy van een leverancier, deze laptopdemo en een productietest A/B beantwoorden verschillende vragen.
De volledige pipeline-code bevindt zich op github.com/slavadubrov/search-ranking-stack. Kopieer het, start het op, vervang de models en parameters door andere waarden, en bekijk zelf de cijfers.
Referenties
Artikelen
- Reciproque rangfusie — Cormack et al., 2009
- RankGPT: LLMs als Zero-Shot Listwise Rerankers — Sun et al., EMNLP 2023 Uitstekend Artikel
- Rank1: Reasoning-gebaseerde Reranking — Weller et al., COLM 2025
- SCaLR: Zelfkalibreerde lijstgewijze Reranking — Zelfkalibrerende lijstgewijze reranking framework
- GCCP: Globaal-consistente vergelijkende puntsgewijs analyse — Het aanpakken van calibration in een puntsgewijze LLM rangschikking
- Rank-DistiLLM: Kennisdistillatie voor Reranking — Schlatt et al., ECIR 2025
- Query2doc: LLM Expansie van de query — Wang et al., EMNLP 2023
- GPL: Generatief pseudo-labelen — Domeinadaptatie voor dichte retrieval
- InRanker: Geconcentreerde Reranker — Verkleining van 50 keer met concurrerende prestaties Search-o1: Agentic Retrieval — EMNLP 2025
- TALEC: LLM als een Judge voor zoekopdrachten — Evaluatie framework
- BEIR Benchmark — Thakur et al., NeurIPS 2021 Sentence-BERT — Reimers & Gurevych, EMNLP 2019
- InfoNCE / CPC — van den Oord et al., 2018
- SimANS: Harde negatieve sampling — Zhou et al., EMNLP 2022
- Passage Reranking met BERT — Nogueira & Cho, 2019
- HNSW — Malkov & Yashunin, 2016
- DiskANN — Subramanya e.a., NeurIPS 2019 RaBitQ — Gao & Long, SIGMOD 2024
- Het vervangen van Judges door Juries — Verga e.a., 2024
- RAG-Fusie — Rackauckas, 2024
- InPars — Bonifacio e.a., SIGIR 2022
- BRIGHT Benchmark — Su et al., ICLR 2025 Ranking zonder GPT — Zhang et al., ECIR 2025
- Pinterest LLM Zoekrelevantie — Wang et al., 2024
- OmniSearchSage — Agarwal et al., WWW 2024 Pal: Leren dat rekening houdt met positiebias — Guo et al., RecSys 2019
Datasets en benchmarks
- Amazon ESCI: Aankoopvragen Dataset — KDD Cup 2022
- BEIR: IR-benchmarking — Heterogene benchmark voor zero-shot evaluatie
- MTEB: Grote hoeveelheden tekst Embedding Benchmark — Embedding model ranglijst
- ESCI-artikel — Reddy et al., 2022
Models die wordt gebruikt in de demo
- all-MiniLM-L6-v2 ms-marco-MiniLM-L-12-v2 — Cross-encoder met 33 miljoen parameters
- Sentence-Transformers — Neuronale retrieval model framework
Hulpmiddelen en platforms
- rank_bm25 — Implementatie van BM25 in Python pytrec_eval — TREC-evaluatietoolkit
- Elasticsearch — Hybride zoekoplossing met retrievers API
- Vespa — Geïntegreerde zoek- en aanbevelingsengine Weaviate — Vector database met hybride zoekopdracht
- Qdrant — Vector database met meervoudige queryfases
Industriële referenties
- Airbnb-vermelding Embeddings — Grbovic & Cheng, KDD 2018 Uber Delivery Zoeken — Uber Engineering, 2025
- Uber Two-Tower Embeddings — Uber Engineering, 2023
- Elastic herranken — Elastic, 2024
Demo-project
- search-ranking-stack — Werkende demo met al het code uit deze post