Kennisbank › Ai Maatjes › Vectorembeddings uitgelegd voor ontwikkelaars
ai maatjes expert 26 August 2026

Vectorembeddings uitgelegd voor ontwikkelaars

Dit artikel legt uit hoe vector embeddings werken en hoe u ze praktisch inzet voor semantische zoekopdrachten, specifiek voor ontwikkelaars die met Python en

Dit artikel legt uit hoe vector embeddings werken en hoe u ze praktisch inzet voor semantische zoekopdrachten, specifiek voor ontwikkelaars die met Python en OpenAI's API werken.

Vereisten

- Python 3.10 of hoger - `openai` Python-package versie 1.35.0 of hoger - Een OpenAI API-sleutel met toegang tot het `text-embedding-3-small` model - `numpy` versie 1.26.0 of hoger voor vectorberekeningen

Installeer de dependencies:

pip install openai==1.35.0 numpy==1.26.0

Stappen

1. Maak een embedding aan

Een embedding is een lijst van floating-point nummers die de semantische betekenis van een tekst representeert. OpenAI's `text-embedding-3-small` model zet tekst om naar een vector van 1536 dimensies.

from openai import OpenAI</p><p>client = OpenAI(api_key="uw-api-sleutel")</p><p>response = client.embeddings.create(
    model="text-embedding-3-small",
    input="De kat zit op de mat"
)</p><p>embedding = response.data[0].embedding
print(len(embedding))  Output: 1536

2. Sla embeddings op in een vectordatabase

Voor productie gebruikt u een dedicated vectordatabase zoals Pinecone, Weaviate of pgvector. Voor lokale ontwikkeling volstaat een NumPy-array.

import numpy as np</p><p>Sla embeddings op als matrix
documents = [
    "De kat zit op de mat",
    "De hond rent door het park",
    "Een vogel vliegt over het water"
]</p><p>embeddings = []
for doc in documents:
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=doc
    )
    embeddings.append(response.data[0].embedding)</p><p>embedding_matrix = np.array(embeddings)
np.save('document_embeddings.npy', embedding_matrix)

3. Bereken cosine similarity

Cosine similarity meet de hoek tussen twee vectoren. Een waarde van 1 betekent identiek, 0 betekent geen overlap. Dit is de standaardmanier om semantische gelijkenis te bepalen.

def cosine_similarity(vec_a, vec_b):
    dot_product = np.dot(vec_a, vec_b)
    norm_a = np.linalg.norm(vec_a)
    norm_b = np.linalg.norm(vec_b)
    return dot_product / (norm_a * norm_b)</p><p>Test met twee gerelateerde zinnen
query = "Een poes ligt op de vloer"
query_response = client.embeddings.create(
    model="text-embedding-3-small",
    input=query
)
query_embedding = query_response.data[0].embedding</p><p>similarities = [
    cosine_similarity(query_embedding, doc_emb)
    for doc_emb in embeddings
]</p><p>print(similarities)
Output: [0.82, 0.31, 0.28] — de eerste zin is het meest gerelateerd

4. Bouw een semantische zoekfunctie

Semantische zoekopdrachten vinden resultaten op basis van betekenis, niet op exacte woordovereenkomst. Dit werkt omdat embeddings woorden met vergelijkbare betekenis dicht bij elkaar plaatsen in de vectorruimte.

def semantic_search(query, embeddings, documents, top_k=3):
    query_response = client.embeddings.create(
        model="text-embedding-3-small",
        input=query
    )
    query_embedding = query_response.data[0].embedding
    
    similarities = [
        cosine_similarity(query_embedding, doc_emb)
        for doc_emb in embeddings
    ]
    
    top_indices = np.argsort(similarities)[-top_k:][::-1]
    
    results = []
    for idx in top_indices:
        results.append({
            'document': documents[idx],
            'similarity': similarities[idx]
        })
    
    return results</p><p>results = semantic_search("Een dier ligt te slapen", embeddings, documents)
for r in results:
    print(f"{r['similarity']:.2f}: {r['document']}")
Output:
0.79: De kat zit op de mat
0.45: De hond rent door het park
0.33: Een vogel vliegt over het water

5. Reduceer dimensionaliteit met PCA

1536 dimensies zijn veel voor visualisatie of opslag in het geheugen. Principal Component Analysis (PCA) reduceert de dimensionaliteit terwijl de relatieve afstanden behouden blijven.

from sklearn.decomposition import PCA</p><p>pca = PCA(n_components=2)
reduced_embeddings = pca.fit_transform(embedding_matrix)</p><p>print(reduced_embeddings.shape)  Output: (3, 2)

6. Implementeer caching voor embeddings

Embeddings genereren kost API-calls en tijd. Cache ze lokaal om herhaalde berekeningen te voorkomen.

import json
import hashlib
from pathlib import Path</p><p>CACHE_FILE = Path("embedding_cache.json")</p><p>def get_cached_embedding(text):
    if CACHE_FILE.exists():
        cache = json.loads(CACHE_FILE.read_text())
    else:
        cache = {}
    
    text_hash = hashlib.sha256(text.encode()).hexdigest()
    
    if text_hash in cache:
        return cache[text_hash]
    
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    embedding = response.data[0].embedding
    
    cache[text_hash] = embedding
    CACHE_FILE.write_text(json.dumps(cache))
    
    return embedding</p><p>Gebruik de cache
emb = get_cached_embedding("De kat zit op de mat")  API call
emb_cached = get_cached_embedding("De kat zit op de mat")  Uit cache

7. Batchverwerking voor efficiëntie

Verwerk meerdere documenten in één API-call. Dit verlaagt de latentie en kosten aanzienlijk.

teksten = [
    "Eerste document over kunstmatige intelligentie",
    "Tweede document over machine learning",
    "Derde document over natuurlijke taalverwerking"
]</p><p>batch_response = client.embeddings.create(
    model="text-embedding-3-small",
    input=teksten
)</p><p>batch_embeddings = [item.embedding for item in batch_response.data]
print(len(batch_embeddings))  # Uitvoer: 3

8. Implementeer een volledige zoekpipeline

Combineer alle stappen in een herbruikbare pipeline die u rechtstreeks in een applicatie kunt integreren.

class EmbeddingSearch:
    def __init__(self, model="text-embedding-3-small"):
        self.client = OpenAI()
        self.model = model
        self.documents = []
        self.embeddings = np.array([])
    
    def add_documents(self, docs):
        self.documents.extend(docs)
        response = self.client.embeddings.create(
            model=self.model,
            input=docs
        )
        new_embeddings = np.array([item.embedding for item in response.data])
        
        if self.embeddings.size == 0:
            self.embeddings = new_embeddings
        else:
            self.embeddings = np.vstack([self.embeddings, new_embeddings])
    
    def search(self, query, top_k=5):
        response = self.client.embeddings.create(
            model=self.model,
            input=query
        )
        query_embedding = np.array(response.data[0].embedding)
        
        similariteiten = [
            cosine_similarity(query_embedding, doc_emb)
            for doc_emb in self.embeddings
        ]
        
        top_indices = np.argsort(similariteiten)[-top_k:][::-1]
        
        return [
            (self.documents[idx], similariteiten[idx])
            for idx in top_indices
        ]</p><p># Gebruik van de pipeline
zoekmachine = EmbeddingSearch()
zoekmachine.add_documents(documenten)
resultaten = zoekmachine.search("Hoe werkt een kat?", top_k=2)</p><p>for doc, score in resultaten:
    print(f"{score:.3f} - {doc}")

Verificatie

Controleer of uw embeddings correct werken door de dimensionaliteit en semantische relaties te testen:

python -c "
from openai import OpenAI
import numpy as np</p><p>client = OpenAI()
response = client.embeddings.create(
    model='text-embedding-3-small',
    input=['hond', 'kat', 'auto']
)
embeddings = np.array([item.embedding for item in response.data])</p><p># Check dimensionaliteit
assert embeddings.shape == (3, 1536), f'Fout: verwacht (3, 1536), kreeg {embeddings.shape}'</p><p># Check semantische relaties
def cos_sim(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))</p><p>hond_kat = cos_sim(embeddings[0], embeddings[1])
hond_auto = cos_sim(embeddings[0], embeddings[2])</p><p>print(f'Dimensionaliteit: {embeddings.shape[1]}')
print(f'Hond vs kat similariteit: {hond_kat:.3f}')
print(f'Hond vs auto similariteit: {hond_auto:.3f}')
assert hond_kat > hond_auto, 'Semantische relatie klopt niet'
print('Alle checks geslaagd')
"

Veelgestelde problemen

1. API-fout: "model_not_found"

Uw API-sleutel heeft geen toegang tot het `text-embedding-3-small` model. Gebruik een oudere modelversie of upgrade uw account.

Oplossing: Vervang `text-embedding-3-small` door `text-embedding-ada-002` en pas de dimensionaliteit aan van 1536 naar 3072.

2. Lage similariteitsscores voor gerelateerde teksten

Embeddings werken goed voor semantische gelijkenis, maar niet voor exacte woordovereenkomst. Twee zinnen met dezelfde woorden maar een andere volgorde kunnen lage scores geven.

Oplossing: Combineer embeddings met een lexicale zoekmethode zoals BM25 voor hybride zoekopdrachten. Gebruik `text-embedding-3-large` voor betere semantische precisie.

3. Geheugenproblemen bij veel documenten

Het opslaan van honderdduizenden embeddings van 1536 dimensies kost veel RAM. Een miljoen documenten verbruikt ongeveer 6 GB.

Oplossing: Gebruik een dedicated vectordatabase zoals Pinecone of Weaviate. Deze slaan embeddings op schijf op en gebruiken approximate nearest neighbor (ANN)-algoritmen voor snelle zoekopdrachten.

De overstap van ruwe tekst naar embeddings is een fundamentele verschuiving: uw code werkt niet langer met woorden, maar met posities in een continue vectorruimte — en die ruimte bepaalt uiteindelijk wat uw zoekmachine wel en niet vindt.

← Terug naar kennisbank
← Terug naar kennisbank