Wat embeddings en semantisch zoeken zijn
Een embedding is een lijst getallen, meestal een paar honderd tot een paar duizend, die de betekenis van een stuk tekst weergeeft. Een embeddingmodel is zo getraind dat teksten met een vergelijkbare betekenis dicht bij elkaar uitkomen. Semantisch zoeken maakt een embedding van de zoekvraag en vindt de documenten of producten waarvan de embeddings er het dichtst bij liggen.
Zo vindt een zoekfunctie de bedoeling, ook als de woorden verschillen. Een klant die zoekt op "warme jas om naar je werk te fietsen" vindt een product dat is beschreven als "winddichte gevoerde forensenjas". Een medewerker die vraagt "hoe declareer ik reiskosten" vindt het declaratiebeleid.
Deze gids is voor productmanagers en engineers die productzoeken, zoeken op de website of zoeken in interne kennis willen verbeteren. We behandelen hoe je een model kiest, waar je vectoren opslaat, hoe je semantische ranking combineert met ranking op trefwoord en hoe je relevantie meet, zodat je ziet of een wijziging heeft geholpen.
Een embeddingmodel kiezen
Er zijn veel goede embeddingmodellen, commercieel en met open gewichten. Openbare ranglijsten zijn een redelijk startpunt, maar ze rangschikken modellen op benchmarkdata. Wat telt, is hoe een model presteert op jouw zoekvragen en jouw content. Weeg deze factoren af:
- Zoekkwaliteit op je eigen data, gemeten met je eigen evaluatieset zoals hieronder beschreven.
- Talen. Een Nederlandse en Engelse catalogus vraagt om een meertalig model dat beide aankan, ook bij gemengde zoekvragen.
- Dimensies en opslag. Grotere vectoren kunnen meer vastleggen, maar kosten meer opslag en zoekwerk. Sommige modellen ondersteunen verkorte embeddings met een beperkt kwaliteitsverlies.
- Lengte van de input. Het maximale aantal tokens per input bepaalt hoe lang een chunk of productbeschrijving mag zijn.
- Hosting en regels voor data. Een model via een API is eenvoudig in gebruik; een model met open gewichten dat je zelf host, houdt data binnen je eigen omgeving.
- Kosten en latency, zowel voor het indexeren van de hele catalogus als voor elke zoekvraag.
Kies twee of drie kandidaten, maak embeddings van een representatieve steekproef en vergelijk ze op dezelfde evaluatieset. Sla bij elke vector de naam en versie van het model op. Wissel je van model, dan moet je alles opnieuw embedden, omdat vectoren van verschillende modellen niet vergelijkbaar zijn.
pgvector of een aparte vectordatabase
Staat je data al in Postgres, dan voegt pgvector een kolomtype voor vectoren toe, plus afstandsoperatoren en indexen voor approximate nearest neighbour search (HNSW en IVFFlat). De basis past in een paar regels:
Aparte vectordatabases voegen functies toe voor zeer grote of zeer veeleisende workloads. De afwegingen:
| Afweging | pgvector | Aparte vectordatabase |
|---|---|---|
| Beheer | Eén database die je al draait, back-upt en beveiligt | Nog een systeem om te draaien, te monitoren en voor te betalen |
| Filteren en joins | Volledige SQL: rechten, voorraad, prijs en categorie in dezelfde query | Metadatafilters, met wisselende ondersteuning voor complexe voorwaarden |
| Consistentie | Vectoren worden bijgewerkt in dezelfde transactie als de bronrij | Vraagt om een sync-pipeline vanuit je leidende bron |
| Schaal | Kan veel productieworkloads goed aan, met afgestelde indexen | Gebouwd voor zeer grote indexen en veel query's |
| Extra's | Alles wat Postgres en zijn extensies bieden | Vaak ingebouwd hybride zoeken, multi-tenancy en beheerde schaalbaarheid |
Onze standaard is pgvector, tot metingen een reden geven om over te stappen. Bij de meeste productcatalogi en kennisbanken voorkom je een hele categorie synchronisatiefouten door vectoren naast de data te bewaren die ze beschrijven.
Hybride ranking
Puur semantisch zoeken heeft blinde vlekken. Het kan een vergelijkbaar product hoger zetten dan het exacte product dat een gebruiker intypte, en het gaat slecht om met SKU's, modelnummers, merknamen en maten. Zoeken op trefwoord, met BM25 of de full-text search van Postgres, is juist daar sterk.
Hybride ranking voert beide uit en voegt de resultaten samen. Veelgebruikte aanpakken:
- Reciprocal rank fusion (RRF) combineert de posities uit elke lijst, zonder dat de scores vergelijkbaar hoeven te zijn. Het is eenvoudig en een goede standaard.
- Gewogen scores mengen normaliseert beide scores en mengt ze. Dat geeft meer controle, maar vraagt om afstemming.
- Reranking geeft de samengevoegde topresultaten aan een cross-encoder of LLM, die elk resultaat scoort tegen de zoekvraag.
- Bedrijfssignalen zoals voorraad, marge, populariteit en personalisatie komen als laatste laag. Die houd je apart, zodat je de relevantie los kunt meten.
Onze gids voor een RAG-chatbot in productie bevat een hybride query voor pgvector met RRF.
Relevantie meten met recall@k en nDCG
Zonder metingen wordt het afstellen van zoeken een discussie over losse zoekvragen. Bouw een beoordeelde set: een paar honderd echte zoekvragen uit je zoeklogs, elk met de items die relevant zijn. Geef die items bij voorkeur een cijfer, bijvoorbeeld 0 voor niet relevant, 1 voor deels relevant, 2 voor een goede match en 3 voor precies goed.
Twee metrics dekken de meeste behoeften:
- recall@k is het aandeel relevante items dat in de bovenste k resultaten staat. Het laat zien of de juiste resultaten überhaupt gevonden worden. Dat telt het meest voor RAG en voor de kandidatenfase vóór reranking.
- nDCG@k (normalised discounted cumulative gain) beloont het bovenaan zetten van de meest relevante items, op basis van beoordelingen met cijfers. Het sluit aan bij hoe mensen een pagina met resultaten scannen.
Volg deze metrics per groep zoekvragen, zoals veelgezochte vragen, long-tail-vragen en vragen met SKU's, omdat een gemiddelde een achteruitgang in één groep kan verbergen. Worden de offline metrics beter, bevestig dat dan met online metrics zoals de doorklikratio, het aandeel zoekopdrachten dat tot een winkelwagen leidt en het aandeel zoekopdrachten zonder resultaten. Voor de retrieval-kant van RAG lees je hoe je RAG evalueert.
Waar je begint
- 01Exporteer een paar honderd echte zoekvragen uit je zoeklogs, ook vragen die nu slechte of geen resultaten geven.
- 02Beoordeel per zoekvraag de relevante resultaten, waar het kan met cijfers.
- 03Meet je huidige zoekfunctie met recall@k en nDCG@k als baseline.
- 04Voeg embeddings in
pgvectortoe voor twee kandidaat-modellen en vergelijk ze. - 05Combineer met zoeken op trefwoord via RRF, voeg zo nodig een reranker toe en meet elke stap.
- 06Zet het live achter een feature flag en vergelijk daarna de online metrics met de baseline.
Deze aanpak volgden we voor semantisch productzoeken in retail. Wil je hulp bij het opzetten van de evaluatie of de zoekfunctie zelf, dan legt onze aanpak uit hoe we zulke projecten uitvoeren.