- Je bouwt een vectorindex met stabiele IDs en een expliciete embeddingruimte.
- Je vergelijkt benaderend zoeken met de exacte top-k en telt de onderzochte kandidaten.
Probeer ook echte tekstvectoren in het embedding-lab.
Een vraagvector kan met iedere passagevector worden vergeleken. Bij drie passages is dat gemakkelijk; bij veel passages wil je minder vergelijkingen doen. Een vectorindex bewaart daarom vectoren en IDs en organiseert het zoeken.
We beginnen met een flat index die alles vergelijkt. Daarna verdelen we de ruimte in buckets en meten we welke exacte buren verdwijnen. Dit is een kleine eigen NumPy-index; de bronverwijzing naar Faiss biedt verdere context en is geen snelheidsmeting van onze code.
1. Bewaar kopieën en het embeddingcontract
Een index bevat exact ids, vectors en space. De vectoren zijn genormaliseerd; de IDs koppelen ze aan passages. space benoemt in deze oefening het model, de revisie, pooling en normalisatie die bij elkaar horen.
x = np.array([[4.,3.],[3.,4.],[1.,0.]])
ids = ['a','b','c']
space = 'demo-v1'
index = build_flat_index(ids,x,space)
x[0] = [0,5]
ids[0] = 'gewijzigd'
print(index['ids']) # ['a', 'b', 'c']
print(index['vectors'][0]) # [0.8 0.6]
Maak build_flat_index met een nieuwe ID-lijst en vectorarray. Het voorbeeld wijzigt daarna de invoer; de index blijft de eerdere waarden bewaren. Zonder kopieën kan een latere bewerking ongemerkt je zoekresultaten veranderen.
De normalisatie- en zoekhelpers uit de vorige les zijn gegeven. De applicatie moet zelf een juiste space-string vastleggen; die string inspecteert geen modelgewichten. Verander je bronversies, chunking of encoder, bereken dan de betreffende vectoren opnieuw en bewaar hun metadata.
012. Bereken eerst de exacte top-k
Voor query [1,1] is de eenheidsrichting ongeveer [.7071,.7071]. Documenten a=[.8,.6] en b=[.6,.8] krijgen beide ongeveer .9899; c=[1,0] krijgt .7071. De exacte top-twee bestaat dus uit a en b.
hits = search_flat(index,[1,1],space,2)
print([h['id'] for h in hits])
# ['a', 'b']
try:
search_flat(index,[1,1],'anders',2)
except ValueError:
print('Andere embeddingruimte')
Maak search_flat met controle van het indexcontract, de querydimensie en space. Een gelijke dimensie is onvoldoende bij een andere embeddingruimte. Dezelfde querytekst kan met een ander model immers een andere vectorbetekenis krijgen.
De flat referentie berekent scores tegen alle N vectoren met D dimensies: het scorewerk groeit met N×D. Onze wrapper valideert en normaliseert opnieuw. Een geteste productie-index kan zulke interne invarianten bij het bouwen bewaken.
Exact zoeken betekent hier exact binnen de opgeslagen vectorruimte. Het bewijst geen inhoudelijke relevantie van de passages. Bewaar die twee evaluatievragen afzonderlijk.
023. Kies buckets en tel wat je overslaat
Neem twee gegeven centroiden: oost=[1,0] en noord=[0,1]. Iedere documentvector gaat naar het centrum met het grootste inproduct. Dat plaatst a en c in oost, en b in noord.
Voor eenheidsvectoren u en v geldt:
Daarom correspondeert maximaal inproduct hier met minimale kwadratische afstand. Dit sluit aan op k-means, maar deze functie traint geen centroiden: ze zijn invoer. Bij een centrumtie kiest de laagste centroidindex.
coarse = build_coarse_index(
index,[[1,0],[0,1]])
print(coarse['buckets'])
# [[0, 2], [1]]
for n in [1,2]:
r = search_coarse(
coarse,[1,1],space,2,n)
found = [h['id'] for h in r['hits']]
print(r['probed'],r['candidates'],
found)
# [0] 2 ['a', 'c']
# [0, 1] 3 ['a', 'b']
Maak build_coarse_index en search_coarse. Bij één probe wint oost de centroidtie en worden alleen a en c onderzocht. Bij twee probes worden alle drie kandidaten onderzocht en komt b weer in beeld.
Recall@2 tegenover de exacte top-twee is het aandeel exacte IDs dat je terugvindt. Eén probe levert één van twee op, dus .5. Twee probes herstellen beide exacte buren.
exact = {h['id'] for h in hits}
one = search_coarse(
coarse,[1,1],space,2,1)
approx = {h['id'] for h in one['hits']}
print(len(exact & approx)/len(exact))
# 0.5
Buckets kunnen leeg zijn en minder dan k kandidaten opleveren. Geef daarom probed, het kandidaatenaantal en maximaal k hits terug. De index is een intern in-memory-object, geen veilig opslagformaat voor willekeurige bestanden.
Vergelijk twee exacte buren met zoeken in alleen de gekozen buckets. De punten zijn geen echte tekstembeddings.
De vier vierkanten zijn gegeven centroiden én corpuspunten. Twee extra punten liggen bij de grens van oost en noord. Meer buckets kost meer vergelijkingen; exacte buren zijn nog geen bewijs van inhoudelijke relevantie.
Wat neem je mee?
- Kopieën en een expliciete embeddingruimte bewaken de indexbetekenis.
- Exact zoeken geeft een referentie voor benaderingsverlies.
- Meer probes kosten werk en kunnen gemiste buren terugbrengen.
Hierna combineer je deze vectorburen met een lexicale zoekroute.