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

Embedding-model kiezen voor RAG

Hoe je het juiste embedding-model kiest voor je RAG-systeem op basis van taal, kwaliteit, kosten en latentie, met aandacht voor Nederlands.

Wat doet een embedding-model?

Een embedding-model converteert tekst naar een vector: een array van getallen (typisch 768 tot 3072 dimensies) die de semantische betekenis van de tekst representeert. Twee teksten met een vergelijkbare betekenis krijgen vergelijkbare vectoren en liggen daardoor dicht bij elkaar in de vectorruimte.

De kwaliteit van je RAG-systeem staat of valt met de kwaliteit van de embeddings. Een goed embedding-model:

  • Begrijpt de semantische betekenis, niet alleen trefwoordovereenkomst.
  • Werkt goed in jouw domein (technisch, juridisch, medisch).
  • Ondersteunt jouw taal, in dit geval Nederlands of meertalig.
  • Heeft een acceptabele dimensionaliteit, want dat beinvloedt opslagkosten en zoeksnelheid.

Overzicht van populaire modellen

De tabel hieronder geeft de stand van zaken in juni 2026. Prijzen zijn per miljoen input-tokens en kunnen wijzigen, dus controleer altijd de actuele prijslijst van de provider.

Model Provider Dimensies Max tokens Talen Kosten
gemini-embedding-001 Google 3072 (MRL) 2048 Meertalig (100+) $0,15/1M
text-embedding-3-large OpenAI 3072 8191 Meertalig $0,13/1M
text-embedding-3-small OpenAI 1536 8191 Meertalig $0,02/1M
embed-v4 Cohere 1536 128k Meertalig + beeld $0,12/1M
text-multilingual-embedding-002 Google 768 2048 Meertalig (18) $0,01/1M
E5-NL (base/large) Universiteit (open) 768 tot 1024 512 Nederlands Gratis (zelf hosten)
nomic-embed-text-v2-moe Nomic 768 512 Meertalig (100+) Gratis (zelf hosten)
info

Wat is MRL?

gemini-embedding-001 en de text-embedding-3-modellen gebruiken Matryoshka Representation Learning. Daarmee kun je de vector inkorten tot bijvoorbeeld 1536 of 768 dimensies zonder grote kwaliteitsverlies, zodat je opslag en zoeklatentie bespaart.

Meertalige modellen voor Nederlands

Voor Nederlandstalige RAG heb je grofweg drie sporen: een sterke commerciele meertalige API, een algemeen open-source model dat je zelf host, of een model dat specifiek voor Nederlands is getraind.

  • Hoogste kwaliteit via API: gemini-embedding-001 staat in juni 2026 bovenaan de meertalige MTEB-leaderboard en doet het goed op Nederlands. text-embedding-3-large van OpenAI zit daar net onder en is een prima alternatief.
  • Nederlands-specifiek: sinds 2025 bestaan er dedicated Nederlandse modellen, de E5-NL-familie, geevalueerd op de MTEB-NL-benchmark. Voor puur Nederlandse corpora kunnen die compacte modellen grotere meertalige modellen verslaan, tegen lagere kosten omdat je ze zelf host.
  • Meertalig en open: nomic-embed-text-v2-moe dekt meer dan honderd talen en draait lokaal via Ollama.
lightbulb

Verifieer op je eigen data

Benchmarks zoals MTEB en MTEB-NL geven richting, maar niet het laatste woord. Bouw een kleine testset met echte vragen en de bijbehorende relevante documenten uit jouw domein, en meet de retrieval-kwaliteit per model. Dat voorspelt je productieresultaat beter dan een gemiddelde leaderboard-score.

Een minimaal voorbeeld met de OpenAI-API, inclusief batching om rate limits te respecteren:

async function embedWithOpenAI(texts: string[]): Promise<number[][]> {
  const response = await openai.embeddings.create({
    model: "text-embedding-3-large",
    input: texts,
    encoding_format: "float",
  });
  return response.data.map(item => item.embedding);
}

async function embedBatch(texts: string[], batchSize = 100): Promise<number[][]> {
  const results: number[][] = [];
  for (let i = 0; i < texts.length; i += batchSize) {
    const batch = texts.slice(i, i + batchSize);
    const embeddings = await embedWithOpenAI(batch);
    results.push(...embeddings);
    if (i + batchSize < texts.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
  return results;
}

Lokale modellen met Ollama

Voor privacygevoelige data of kostenbesparing bij grote volumes kun je een open-source model lokaal draaien. De data verlaat je server dan niet.

async function embedWithOllama(texts: string[]): Promise<number[][]> {
  const results = await Promise.all(
    texts.map(async (text) => {
      const response = await fetch("http://localhost:11434/api/embeddings", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ model: "nomic-embed-text-v2-moe", prompt: text }),
      });
      const data = await response.json();
      return data.embedding as number[];
    })
  );
  return results;
}
warning

Houd indexeren en zoeken op hetzelfde model

Embeddings van verschillende modellen zijn niet uitwisselbaar. Als je tijdens het experimenteren van model wisselt, moet je je hele index opnieuw opbouwen. Leg daarom vroeg vast met welk model en welke dimensie je naar productie gaat.

Dimensie-reductie

De gemini-embedding-001- en text-embedding-3-modellen ondersteunen dimensie-reductie zonder grote kwaliteitsverlies, dankzij Matryoshka Representation Learning:

const response = await openai.embeddings.create({
  model: "text-embedding-3-large",
  input: texts,
  dimensions: 512,
});

Kleinere dimensies verlagen opslagkosten en zoeklatentie aanzienlijk. Test de kwaliteitsimpact op jouw data voor je de dimensies verkleint, want vanaf een bepaald punt gaat het wel ten koste van de recall.

Embedding-modellen evalueren

Een eenvoudige offline evaluatie met een testset van vragen en bekende relevante documenten:

interface EmbeddingEvalResult {
  model: string;
  avg_retrieval_score: number;
  latency_ms: number;
  cost_per_million_tokens: number;
}

async function evaluateEmbeddingModel(
  model: EmbedFunction,
  testQueries: { query: string; relevant_doc_ids: string[] }[],
  documents: Document[]
): Promise<EmbeddingEvalResult> {
  const docEmbeddings = await model(documents.map(d => d.content));
  let totalScore = 0;

  for (const test of testQueries) {
    const queryEmbedding = await model([test.query]);
    const scores = docEmbeddings.map((emb, i) => ({
      id: documents[i].id,
      score: cosineSimilarity(queryEmbedding[0], emb),
    }));
    scores.sort((a, b) => b.score - a.score);
    const top5 = scores.slice(0, 5).map(s => s.id);
    const relevantFound = test.relevant_doc_ids.filter(id => top5.includes(id)).length;
    totalScore += relevantFound / test.relevant_doc_ids.length;
  }

  return {
    model: model.name,
    avg_retrieval_score: totalScore / testQueries.length,
    latency_ms: 0,
    cost_per_million_tokens: 0,
  };
}

Afwegingen per prioriteit

Welk model het beste past hangt af van wat je belangrijkste eis is. Gebruik onderstaande opsomming als snelle gids.

  • Kwaliteit voorop: gemini-embedding-001 (Google) of text-embedding-3-large (OpenAI). Sterke Nederlandse taalondersteuning en hoge nauwkeurigheid via een eenvoudige API.
  • Kosten voorop: text-embedding-3-small of text-multilingual-embedding-002 van Google. Een veelvoud goedkoper dan de large-varianten, met een redelijke kwaliteit.
  • Privacy voorop: de Dutch-specifieke E5-NL-modellen of nomic-embed-text-v2-moe via Ollama. Je host zelf en de data verlaat je server niet.
  • Beeld en tekst samen: Cohere embed-v4 of het multimodale gemini-embedding-2-preview als je naast tekst ook afbeeldingen wilt embedden.
Moet ik hetzelfde model gebruiken voor indexeren en zoeken?

Ja, altijd. Embeddings van verschillende modellen zijn niet compatibel, want de vectorruimten zijn anders georienteerd. Als je van model wisselt, moet je de hele index herbouwen.

Hoe ga ik om met lange documenten die het tokenmaximum overschrijden?

Knip je documenten in chunks zodat elk chunk onder het tokenmaximum blijft. Kap nooit zomaar een document af en embed dat, want dan verlies je de informatie aan het einde.

Kan ik meerdere embedding-modellen combineren?

Ja, met late fusion: bereken scores met model A en model B en combineer die, bijvoorbeeld als gemiddelde of gewogen som. Dat kost meer rekenkracht maar geeft vaak een betere recall.

Hoe update ik embeddings na een model-upgrade?

Je bouwt de volledige index opnieuw op. Plan dit als een migratietaak: indexeer parallel naar een nieuwe collectie en zet de applicatie pas over als de nieuwe index compleet is.

Welk model kies ik specifiek voor Nederlands?

Voor de hoogste kwaliteit via een API kies je gemini-embedding-001 of text-embedding-3-large. Wil je lokaal draaien, dan zijn de E5-NL-modellen interessant omdat ze speciaal voor Nederlands zijn getraind en op de MTEB-NL-benchmark goed scoren.

Zijn duurdere modellen altijd beter?

Nee. Een hogere MTEB-score betekent niet automatisch betere resultaten op jouw data. Meet altijd met een eigen testset, want een goedkoper of kleiner model is soms net zo goed voor jouw domein en taal.