Naar inhoud
lightbulb Welkom op de nieuwe kennisbank | We hebben de docs volledig vernieuwd met meer dan 160 features. Bekijk wat nieuw isarrow_forward

Embeddings genereren met de Gemini API

Genereer vectorrepresentaties van tekst met het model gemini-embedding-001 voor semantisch zoeken, clustering en aanbevelingen, via de nieuwe google-genai SDK.

Wat zijn embeddings

Embeddings zijn numerieke vectorrepresentaties van tekst waarbij semantisch vergelijkbare teksten dicht bij elkaar liggen in de vectorruimte. "Hond" en "hond loopt in het park" liggen dichter bij elkaar dan "hond" en "broodrooster", ook al hebben ze geen woorden gemeen.

Toepassingen: semantisch zoeken (vind documenten op betekenis, niet op trefwoorden), clustering (groepeer gerelateerde documenten), aanbevelingen (suggereer vergelijkbare items), anomaliedetectie en classificatie.

warning

Modelnaam en SDK zijn gewijzigd

Het oude model text-embedding-004 is op 14 januari 2026 uitgeschakeld en werkt niet meer. Gebruik nu gemini-embedding-001. Ook de oude google-generativeai-bibliotheek is vervangen door de nieuwe google-genai SDK met een Client-object. De voorbeelden hieronder zijn op die nieuwe SDK gebaseerd.

Installeren en authenticeren

Installeer de nieuwe SDK en zet je API-sleutel in een omgevingsvariabele.

pip install google-genai
export GEMINI_API_KEY="jouw_sleutel"

De client leest de sleutel automatisch uit GEMINI_API_KEY, je hoeft hem niet expliciet door te geven.

Een embedding genereren

from google import genai
from google.genai import types

client = genai.Client()

result = client.models.embed_content(
    model="gemini-embedding-001",
    contents="Machine learning helpt computers te leren zonder expliciet geprogrammeerd te worden.",
    config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"),
)

embedding = result.embeddings[0].values
print(f"Vectordimensies: {len(embedding)}")
print(f"Eerste 5 waarden: {embedding[:5]}")

Standaard geeft gemini-embedding-001 een vector van 3072 dimensies terug. De maximale invoer is 2048 tokens per tekst en het model ondersteunt meer dan 100 talen.

Task types voor betere kwaliteit

Het model is geoptimaliseerd voor verschillende taken via task_type in de EmbedContentConfig:

Task type Gebruik
RETRIEVAL_DOCUMENT Documenten die doorzocht worden
RETRIEVAL_QUERY Zoekquery van de gebruiker
SEMANTIC_SIMILARITY Vergelijken van tekstparen
CLASSIFICATION Classificatietaken
CLUSTERING Groeperingstaken
QUESTION_ANSWERING Vraag-antwoord paren
FACT_VERIFICATION Feitcontrole
CODE_RETRIEVAL_QUERY Zoeken in codebases

Gebruik RETRIEVAL_DOCUMENT voor documenten en RETRIEVAL_QUERY voor zoekopdrachten:

def embed_document(text: str) -> list:
    result = client.models.embed_content(
        model="gemini-embedding-001",
        contents=text,
        config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"),
    )
    return result.embeddings[0].values

def embed_query(query: str) -> list:
    result = client.models.embed_content(
        model="gemini-embedding-001",
        contents=query,
        config=types.EmbedContentConfig(task_type="RETRIEVAL_QUERY"),
    )
    return result.embeddings[0].values
lightbulb

Kies altijd het passende task type

Een document embedden als RETRIEVAL_QUERY geeft suboptimale zoekresultaten, ook al lijkt het technisch te werken. Belangrijk: de query en de documenten moeten met dezelfde modelnaam en dezelfde output_dimensionality worden geëmbed, anders zijn de vectoren niet vergelijkbaar.

Kleinere vectoren met output_dimensionality

gemini-embedding-001 gebruikt Matryoshka Representation Learning, waardoor je de vector kunt verkleinen vanaf de standaard 3072 dimensies. Kleinere vectoren zijn sneller te vergelijken en goedkoper op te slaan, maar verliezen wat nauwkeurigheid. Bij elke andere waarde dan 3072 moet je de vector zelf normaliseren voordat je gelijkenis berekent.

import numpy as np

result = client.models.embed_content(
    model="gemini-embedding-001",
    contents="Voorbeeldtekst om te embedden.",
    config=types.EmbedContentConfig(
        task_type="RETRIEVAL_DOCUMENT",
        output_dimensionality=768,
    ),
)

waarden = np.array(result.embeddings[0].values)
genormaliseerd = waarden / np.linalg.norm(waarden)
print(f"Dimensies: {len(genormaliseerd)}")

Meerdere teksten in één call

teksten = [
    "Python is een programmeertaal",
    "JavaScript draait in de browser",
    "Rust biedt geheugen-veiligheid",
    "Go is ontworpen voor concurrency",
]

result = client.models.embed_content(
    model="gemini-embedding-001",
    contents=teksten,
    config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"),
)

embeddings = [e.values for e in result.embeddings]
print(f"{len(embeddings)} embeddings gegenereerd")

Cosinus-gelijkenis berekenen

Bij de standaard 3072 dimensies zijn de vectoren al genormaliseerd, dus is het inproduct gelijk aan de cosinus-gelijkenis. De functie hieronder normaliseert voor de zekerheid, zodat hij ook klopt bij een aangepaste output_dimensionality.

import numpy as np

def cosine_similarity(vec1: list, vec2: list) -> float:
    v1 = np.array(vec1)
    v2 = np.array(vec2)
    return float(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))

tekst1 = "Python is een populaire programmeertaal"
tekst2 = "Python wordt veel gebruikt voor data science"
tekst3 = "Amsterdam is de hoofdstad van Nederland"

emb1 = embed_document(tekst1)
emb2 = embed_document(tekst2)
emb3 = embed_document(tekst3)

print(f"Gelijkenis 1-2: {cosine_similarity(emb1, emb2):.4f}")
print(f"Gelijkenis 1-3: {cosine_similarity(emb1, emb3):.4f}")

Semantisch zoeksysteem bouwen

import numpy as np
from dataclasses import dataclass
from typing import List

@dataclass
class Document:
    id: str
    tekst: str
    embedding: List[float] = None

def index_documents(documenten: List[Document]) -> List[Document]:
    teksten = [doc.tekst for doc in documenten]
    result = client.models.embed_content(
        model="gemini-embedding-001",
        contents=teksten,
        config=types.EmbedContentConfig(task_type="RETRIEVAL_DOCUMENT"),
    )
    for doc, emb in zip(documenten, result.embeddings):
        doc.embedding = emb.values
    return documenten

def search(query: str, documenten: List[Document], top_k: int = 3) -> List[tuple]:
    query_result = client.models.embed_content(
        model="gemini-embedding-001",
        contents=query,
        config=types.EmbedContentConfig(task_type="RETRIEVAL_QUERY"),
    )
    query_emb = np.array(query_result.embeddings[0].values)

    scores = []
    for doc in documenten:
        doc_emb = np.array(doc.embedding)
        score = float(np.dot(query_emb, doc_emb) / (np.linalg.norm(query_emb) * np.linalg.norm(doc_emb)))
        scores.append((score, doc))

    scores.sort(key=lambda x: x[0], reverse=True)
    return scores[:top_k]

docs = [
    Document("1", "Python is een krachtige programmeertaal voor data science."),
    Document("2", "Django is een web framework voor Python."),
    Document("3", "React is een JavaScript library voor UI."),
    Document("4", "Machine learning modellen worden getraind op data."),
]

docs = index_documents(docs)
resultaten = search("Welke talen zijn goed voor webontwikkeling?", docs)

for score, doc in resultaten:
    print(f"Score: {score:.4f} | {doc.tekst[:60]}...")

Embeddings opslaan in een vectordatabase

Voor productie sla je embeddings op in een vectordatabase zodat je niet bij elke zoekopdracht opnieuw hoeft te embedden. Onderstaand voorbeeld gebruikt Chroma. Zorg dat de dimensie van je collectie overeenkomt met de output_dimensionality die je gebruikt.

import chromadb

chroma_client = chromadb.Client()
collection = chroma_client.create_collection("kennisbank")

collection.add(
    documents=[doc.tekst for doc in docs],
    embeddings=[doc.embedding for doc in docs],
    ids=[doc.id for doc in docs],
)

query_result = client.models.embed_content(
    model="gemini-embedding-001",
    contents="Welke talen zijn goed voor webontwikkeling?",
    config=types.EmbedContentConfig(task_type="RETRIEVAL_QUERY"),
)
query_emb = query_result.embeddings[0].values

results = collection.query(
    query_embeddings=[query_emb],
    n_results=3,
)
lightbulb

Bespaar met de Batch API

Voor grote corpora die je niet realtime hoeft te embedden, gebruik je de Batch API. Dat is ongeveer de helft goedkoper dan losse realtime-aanvragen en is ideaal om in één keer een hele kennisbank te indexeren.

Hoeveel tekst kan ik per embedding verwerken?

gemini-embedding-001 accepteert tot 2048 tokens per invoer. Langere teksten moet je splitsen in chunks. Gebruik overlappende chunks, bijvoorbeeld 500 woorden met 50 woorden overlap, voor betere zoekkwaliteit.

Kan ik de dimensie van de vector aanpassen?

Ja, via de output_dimensionality-parameter. De standaard is 3072 dimensies; veelgebruikte kleinere waarden zijn 1536 en 768. Kleinere vectoren zijn sneller en goedkoper, maar minder nauwkeurig. Normaliseer de vector zelf zodra je een andere waarde dan 3072 kiest.

Waarom werkt mijn oude code met text-embedding-004 niet meer?

Dat model is op 14 januari 2026 uitgeschakeld en geeft nu een foutmelding. Stap over op gemini-embedding-001 en op de nieuwe google-genai SDK met een Client-object. Let op dat de standaarddimensie veranderde van 768 naar 3072, dus bestaande indexen moet je opnieuw opbouwen of expliciet op 768 zetten.

Hoe lees ik de embedding uit het antwoord?

In de nieuwe SDK staat het resultaat in result.embeddings, een lijst van objecten met een attribuut values. De eerste vector haal je op met result.embeddings[0].values. Dit verschilt van de oude SDK, die result["embedding"] gebruikte.

Wat kost embedden met de Gemini API?

gemini-embedding-001 kost ongeveer 0,15 dollar per miljoen tokens bij realtime-aanvragen en ongeveer 0,075 dollar per miljoen tokens via de Batch API. Controleer de actuele tarieven op de officiële prijspagina van Google, want prijzen kunnen wijzigen.

Moet ik query en documenten met hetzelfde task type embedden?

Nee, gebruik juist verschillende task types: RETRIEVAL_DOCUMENT voor de opgeslagen documenten en RETRIEVAL_QUERY voor de zoekopdracht. Wel moeten beide hetzelfde model en dezelfde output_dimensionality gebruiken, anders zijn de vectoren onvergelijkbaar.