Je hebt een RAG-pipeline gebouwd, een AI-agent in productie gezet, en alles draait lekker. Tot het moment dat het ineens níet meer werkt. Een modelupdate, een gewijzigde prompt, een net iets andere chunking-strategie — en je chatbot hallucineert er vrolijk op los. Het ergste? Je merkt het pas als een gefrustreerde gebruiker een klacht indient.
Dat is precies waarom LLM-evaluatie zo belangrijk is. Maar hier zit 'm de crux: traditionele softwaretests werken gewoon niet voor taalmodellen. Je kunt de output niet vergelijken met een hardcoded verwacht antwoord, want LLMs zijn probabilistisch. Dezelfde prompt levert bij elke aanroep een net iets ander antwoord op. Je hebt een fundamenteel andere testaanpak nodig.
In deze handleiding duiken we in DeepEval — het populairste open-source framework voor het testen van LLM-applicaties. Met meer dan 13.000 GitHub-sterren en 3 miljoen maandelijkse downloads is het in 2026 dé standaard geworden voor teams die serieus zijn over AI-kwaliteit. We bouwen stap voor stap een complete testpipeline op, van eenvoudige unit tests tot RAG-evaluatie en agent-testen. Alles met werkende Python-code die je direct kunt kopiëren en aanpassen.
Wat is DeepEval en Waarom Heb Je Het Nodig?
DeepEval is een open-source evaluatieframework voor Python dat eigenlijk werkt als een gespecialiseerde versie van Pytest — maar dan voor LLM-applicaties. Waar Pytest controleert of 1 + 1 == 2, controleert DeepEval of een LLM-antwoord relevant, feitelijk correct en vrij van hallucinaties is.
Het framework biedt meer dan 50 kant-en-klare metrics, allemaal onderbouwd door wetenschappelijk onderzoek. De meeste gebruiken LLM-as-a-judge: een techniek waarbij een apart LLM de output van je applicatie beoordeelt. Klinkt misschien wat vreemd om een LLM te gebruiken om een ander LLM te beoordelen, maar eerlijk gezegd werkt het verrassend goed — mits je de juiste evaluatiecriteria definieert.
Kernvoordelen van DeepEval
- Pytest-integratie — Past naadloos in bestaande Python-testworkflows en CI/CD-pipelines
- 50+ metrics — Van hallucinatiedetectie tot toxiciteitscontrole, van RAG-faithfulness tot agentevaluatie
- Component-level evaluatie — Test niet alleen de eindoutput, maar ook individuele stappen in je workflow
- Synthetische datasetgeneratie — Genereer automatisch testcases op basis van je documentatie
- Multi-turn ondersteuning — Evalueer volledige gespreksflows, niet alleen losse vraag-antwoord-paren
De nieuwste versie op moment van schrijven is 3.9.6 (april 2026), met recente toevoegingen zoals ArenaGEval voor vergelijkende evaluatie en verbeterde agent-metrics.
Installatie en Configuratie
Vereisten
- Python 3.9 of hoger
- Een API-key van OpenAI (standaard evaluatiemodel) of een alternatieve LLM-provider
- pip voor pakketbeheer
DeepEval Installeren
De installatie is zo simpel als het maar kan:
pip install deepeval
Stel vervolgens je OpenAI API-key in als omgevingsvariabele:
export OPENAI_API_KEY="jouw-openai-api-key"
Standaard gebruikt DeepEval GPT-4o als evaluatiemodel. Je kunt dit overschrijven naar elk ander model — daar komen we later op terug.
Projectstructuur
Zo ziet een typische projectstructuur voor LLM-tests eruit:
mijn-llm-app/
├── app/
│ ├── chatbot.py
│ └── rag_pipeline.py
├── tests/
│ ├── test_chatbot.py
│ ├── test_rag.py
│ └── test_agent.py
├── datasets/
│ └── golden_set.json
└── requirements.txt
Niets verrassends hier — het volgt de standaard Python-projectstructuur die je waarschijnlijk al kent.
Je Eerste LLM-Test: Unit Testing met DeepEval
Oké, laten we beginnen met de eenvoudigste mogelijke test. Stel, je hebt een chatbot en je wilt controleren of de antwoorden correct en relevant zijn. In DeepEval definieer je een test case met een input, de werkelijke output van je LLM, en optioneel een verwachte output:
import pytest
from deepeval import assert_test
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
def genereer_antwoord(vraag: str) -> str:
"""Simulatie van je LLM-applicatie."""
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": vraag}]
)
return response.choices[0].message.content
def test_correctheid_antwoord():
correctheid = GEval(
name="Correctheid",
criteria="Bepaal of de 'actual output' feitelijk correct is "
"op basis van de 'expected output'.",
evaluation_params=[
LLMTestCaseParams.ACTUAL_OUTPUT,
LLMTestCaseParams.EXPECTED_OUTPUT
],
threshold=0.5
)
test_case = LLMTestCase(
input="Wat is de hoofdstad van Nederland?",
actual_output=genereer_antwoord("Wat is de hoofdstad van Nederland?"),
expected_output="Amsterdam is de hoofdstad van Nederland."
)
assert_test(test_case, [correctheid])
Voer de test uit met:
deepeval test run tests/test_chatbot.py
Wat hier achter de schermen gebeurt: GEval is de meest veelzijdige metric van DeepEval. Het gebruikt chain-of-thought redeneringen om je LLM-output te beoordelen op basis van criteria die jij zelf definieert. De score loopt van 0 tot 1, en de threshold bepaalt wanneer de test slaagt. Best elegant, als je het mij vraagt.
Meerdere Metrics Combineren
In de praktijk wil je een antwoord op meerdere dimensies tegelijk evalueren. Hier combineren we correctheid met relevantie en een toxiciteitscheck:
from deepeval.metrics import GEval, AnswerRelevancyMetric, ToxicityMetric
from deepeval.test_case import LLMTestCaseParams
def test_chatbot_kwaliteit():
metrics = [
GEval(
name="Correctheid",
criteria="Is het antwoord feitelijk juist?",
evaluation_params=[
LLMTestCaseParams.ACTUAL_OUTPUT,
LLMTestCaseParams.EXPECTED_OUTPUT
],
threshold=0.5
),
AnswerRelevancyMetric(threshold=0.7),
ToxicityMetric(threshold=0.5)
]
test_case = LLMTestCase(
input="Leg uit hoe photosynthese werkt",
actual_output=genereer_antwoord("Leg uit hoe photosynthese werkt"),
expected_output="Photosynthese is het proces waarbij planten "
"zonlicht omzetten in energie."
)
assert_test(test_case, metrics)
RAG-Pipelines Evalueren: Faithfulness, Relevantie en Recall
Nu wordt het pas echt interessant. Voor RAG-applicaties is standaard testen niet genoeg. Je wilt niet alleen weten of het antwoord goed is, maar ook of de opgehaalde context relevant is en of het antwoord trouw blijft aan die context (en dus niet gaat hallucineren). DeepEval biedt hiervoor vier gespecialiseerde RAG-metrics.
De Vier RAG-Metrics
- Faithfulness — Is het antwoord feitelijk onderbouwd door de opgehaalde context? Dit is je hallucinatiedetector.
- Contextual Relevancy — Is de opgehaalde context relevant voor de gestelde vraag?
- Contextual Precision — Staan de meest relevante documenten bovenaan de resultaten?
- Contextual Recall — Bevat de opgehaalde context alle informatie die nodig is voor een correct antwoord?
In mijn ervaring is Faithfulness veruit de belangrijkste van de vier. Als je LLM informatie verzint die niet in de context staat, heb je een serieus probleem. Maar laten we ze allemaal in actie zien:
from deepeval import assert_test
from deepeval.metrics import (
FaithfulnessMetric,
ContextualRelevancyMetric,
ContextualPrecisionMetric,
ContextualRecallMetric
)
from deepeval.test_case import LLMTestCase
def test_rag_pipeline():
# Simuleer een RAG-aanroep
vraag = "Wat is het retourbeleid voor elektronica?"
opgehaalde_context = [
"Elektronica kan binnen 14 dagen worden geretourneerd met originele verpakking.",
"Retourzendingen zijn gratis voor bestellingen boven €50.",
"Beschadigde producten komen niet in aanmerking voor retour."
]
antwoord = "U kunt elektronica binnen 14 dagen retourneren, mits in originele " \
"verpakking. Retourzendingen boven €50 zijn gratis. Let op: beschadigde " \
"producten worden niet geaccepteerd."
test_case = LLMTestCase(
input=vraag,
actual_output=antwoord,
expected_output="Elektronica kan binnen 14 dagen geretourneerd worden "
"met originele verpakking. Gratis retour boven €50.",
retrieval_context=opgehaalde_context
)
metrics = [
FaithfulnessMetric(threshold=0.7),
ContextualRelevancyMetric(threshold=0.7),
ContextualPrecisionMetric(threshold=0.7),
ContextualRecallMetric(threshold=0.7)
]
assert_test(test_case, metrics)
Het cruciale verschil met gewone tests zit 'm in het retrieval_context-veld. Dit vertelt DeepEval welke documenten je RAG-pipeline heeft opgehaald, zodat het kan beoordelen of het antwoord trouw blijft aan deze bronnen. Als je LLM informatie verzint die niet in de context staat, scoort de Faithfulness-metric laag — en dat is precies wat je wilt detecteren.
Bulktesten met een Dataset
Eén testcase is natuurlijk niet genoeg voor een betrouwbare evaluatie. In de praktijk gebruik je een golden dataset — een verzameling van vraag-antwoord-paren waarvan je wéét dat ze correct zijn:
import pytest
from deepeval import assert_test
from deepeval.dataset import EvaluationDataset, Golden
from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase
# Definieer je golden dataset
goldens = [
Golden(
input="Wat zijn de openingstijden?",
expected_output="Wij zijn open van maandag t/m vrijdag, 9:00-17:00."
),
Golden(
input="Hoe kan ik mijn bestelling volgen?",
expected_output="U kunt uw bestelling volgen via de link in uw bevestigingsmail."
),
Golden(
input="Wat is de levertijd?",
expected_output="De standaard levertijd is 2-3 werkdagen."
)
]
dataset = EvaluationDataset(goldens=goldens)
# Vul elke golden aan met de werkelijke output van je RAG-app
for golden in dataset.goldens:
rag_response = jouw_rag_pipeline(golden.input) # Vervang met je eigen pipeline
dataset.add_test_case(LLMTestCase(
input=golden.input,
actual_output=rag_response["antwoord"],
expected_output=golden.expected_output,
retrieval_context=rag_response["bronnen"]
))
@pytest.mark.parametrize("test_case", dataset.test_cases)
def test_rag_golden_dataset(test_case: LLMTestCase):
metrics = [
FaithfulnessMetric(threshold=0.7),
AnswerRelevancyMetric(threshold=0.7)
]
assert_test(test_case, metrics)
De @pytest.mark.parametrize-decorator zorgt ervoor dat elke testcase afzonderlijk wordt uitgevoerd en gerapporteerd. Zo zie je direct welke specifieke vragen problematisch zijn — heel handig bij het debuggen.
AI-Agents Testen: Tool-Calling en Trajectevaluatie
Het testen van AI-agents is een stuk complexer dan een chatbot of RAG-pipeline testen. Een agent voert namelijk meerdere stappen uit: hij redeneert, roept tools aan, bekijkt de resultaten en besluit dan wat hij vervolgens doet. Dat maakt het evalueren ook lastiger. Gelukkig biedt DeepEval sinds versie 3.8 zes gespecialiseerde agentic metrics die de volledige trace van een agent kunnen evalueren.
Wat Kun Je Evalueren bij Agents?
- Tool Correctness — Worden de juiste tools aangeroepen voor de gegeven taak?
- Tool Argument Validation — Zijn de argumenten die aan tools worden meegegeven correct en gestructureerd?
- Task Completion — Heeft de agent de taak daadwerkelijk voltooid?
- Efficiency — Hoe efficiënt was het pad dat de agent nam? Waren er onnodige omwegen?
- Plan Following — Volgde de agent een logisch plan of maakte hij willekeurige keuzes?
from deepeval import assert_test
from deepeval.metrics import ToolCorrectnessMetric
from deepeval.test_case import LLMTestCase, ToolCall
def test_agent_tool_correctheid():
tool_correctheid = ToolCorrectnessMetric(threshold=0.7)
test_case = LLMTestCase(
input="Wat is het weer in Amsterdam vandaag?",
actual_output="Het is 18°C en bewolkt in Amsterdam.",
expected_tools=[
ToolCall(name="get_weather", arguments={"city": "Amsterdam"})
],
tools_called=[
ToolCall(name="get_weather", arguments={"city": "Amsterdam"})
]
)
assert_test(test_case, [tool_correctheid])
Het expected_tools-veld definieert welke tools je verwacht dat de agent aanroept, en tools_called bevat wat de agent daadwerkelijk heeft gedaan. Een belangrijk detail: DeepEval vergelijkt deze niet simpelweg letterlijk. Het gebruikt een LLM-judge om te beoordelen of de aangeroepen tools semantisch correct zijn voor de taak. Dat is een subtiel maar belangrijk verschil.
Aangepaste Evaluatiecriteria met G-Eval
Soms passen de standaard metrics gewoon niet bij jouw specifieke situatie. Misschien wil je controleren of antwoorden in een bepaalde toon zijn geschreven, of ze een maximale lengte respecteren, of ze voldoen aan domeinspecifieke regels. Daar is G-Eval voor — je kunt er willekeurige evaluatiecriteria mee definiëren in gewoon Nederlands (of elke andere taal).
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCaseParams
# Controleer of het antwoord geschikt is voor een zakelijke context
zakelijke_toon = GEval(
name="Zakelijke Toon",
criteria="Beoordeel of het antwoord een professionele, zakelijke toon hanteert. "
"Het mag geen informele taal, slang of emoji's bevatten. "
"Het moet beleefd maar direct zijn.",
evaluation_params=[LLMTestCaseParams.ACTUAL_OUTPUT],
threshold=0.7
)
# Controleer of technische uitleg begrijpelijk is voor niet-technici
begrijpelijkheid = GEval(
name="Begrijpelijkheid",
criteria="Beoordeel of de technische uitleg begrijpelijk is voor iemand "
"zonder technische achtergrond. Jargon moet worden uitgelegd, "
"en er moeten concrete voorbeelden worden gegeven.",
evaluation_params=[
LLMTestCaseParams.INPUT,
LLMTestCaseParams.ACTUAL_OUTPUT
],
threshold=0.6
)
Dit is eerlijk gezegd een van mijn favoriete features van DeepEval. G-Eval gebruikt chain-of-thought prompting om het evaluatiemodel stap voor stap door de beoordeling te leiden. Het resultaat is een score tussen 0 en 1 — simpel en effectief.
Alternatieve Evaluatiemodellen Gebruiken
Je bent absoluut niet beperkt tot OpenAI als evaluatiemodel. DeepEval ondersteunt via LiteLLM een breed scala aan providers. Handig als je kosten wilt drukken, een lokaal model wilt draaien, of gewoon een ander model als judge wilt inzetten:
from deepeval.metrics import AnswerRelevancyMetric
# Gebruik Claude als evaluatiemodel
metric_claude = AnswerRelevancyMetric(
threshold=0.7,
model="anthropic/claude-sonnet-4-6"
)
# Gebruik een lokaal Ollama-model
metric_lokaal = AnswerRelevancyMetric(
threshold=0.7,
model="ollama/llama3.1"
)
# Gebruik Google Gemini
metric_gemini = AnswerRelevancyMetric(
threshold=0.7,
model="gemini/gemini-2.5-pro"
)
Een tip: het evaluatiemodel hoeft niet hetzelfde te zijn als het model dat je applicatie gebruikt. Sterker nog, het is vaak beter om een sterker model als judge te gebruiken dan het model dat je evalueert. Gebruik bijvoorbeeld Claude of GPT-4o als judge voor een applicatie die draait op een kleiner model.
Integratie in CI/CD-Pipelines
De echte kracht van geautomatiseerde LLM-tests komt pas naar voren wanneer je ze integreert in je CI/CD-pipeline. Zo voorkom je dat een slechte promptwijziging of modelupdate ongemerkt in productie belandt — en dat is toch waar het uiteindelijk om draait.
GitHub Actions Voorbeeld
# .github/workflows/llm-tests.yml
name: LLM Evaluatie
on:
pull_request:
paths:
- "app/prompts/**"
- "app/rag_pipeline.py"
- "app/agent.py"
jobs:
evaluatie:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Python instellen
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Afhankelijkheden installeren
run: pip install -r requirements.txt
- name: LLM-tests uitvoeren
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: deepeval test run tests/ --verbose
Let op het paths-filter: de tests worden alleen uitgevoerd wanneer er wijzigingen zijn in je prompts, RAG-pipeline of agent-code. Slim, want zo voorkom je onnodige API-kosten bij elke willekeurige commit.
Regressietesten
DeepEval ondersteunt ook regressietesten door scores van eerdere runs bij te houden. Als een metric plotseling daalt na een wijziging, weet je precies wat er is misgegaan:
# Voer tests uit en vergelijk met de vorige baseline
deepeval test run tests/ --mark-as-baseline # Eerste keer: stel baseline in
deepeval test run tests/ # Volgende keer: vergelijk met baseline
Best Practices voor LLM-Evaluatie
1. Begin Klein, Groei Geleidelijk
Start met 20-50 zorgvuldig geselecteerde testcases die je belangrijkste use cases dekken. Breid pas uit als je goed begrijpt welke metrics het meest informatief zijn voor jouw applicatie. Te snel opschalen levert alleen maar ruis op.
2. Combineer Metrics
Geen enkele metric vertelt het hele verhaal. Een antwoord kan relevant zijn maar hallucineren, of feitelijk correct maar volstrekt onbegrijpelijk. Combineer altijd meerdere dimensies.
3. Gebruik Realistische Testdata
Synthetisch gegenereerde testcases zijn prima voor schaal, maar je golden dataset moet échte gebruikersvragen bevatten. Log productieverkeer en destilleer daaruit de meest voorkomende en kritische scenario's. Die edge cases die je gebruikers bedenken? Daar kom je zelf nooit op.
4. Stel Zinvolle Thresholds In
Een threshold van 0.7 is een prima startpunt voor de meeste metrics, maar pas aan op basis van je domein. Medische of juridische toepassingen vereisen hogere drempels voor faithfulness; creatieve toepassingen kunnen juist lagere thresholds voor exacte correctheid hebben.
5. Evalueer op Componentniveau
Test niet alleen de eindoutput van je pipeline. Evalueer afzonderlijk je retriever (haalt hij de juiste documenten op?), je reranker (sorteert hij ze goed?) en je generator (genereert hij een goed antwoord op basis van de context?). Zo weet je precies wáár het misgaat als er iets faalt.
Veelgestelde Vragen
Wat kost het om DeepEval te gebruiken?
DeepEval zelf is volledig gratis en open-source. Je betaalt alleen voor de LLM API-kosten van het evaluatiemodel. Een typische evaluatierun met GPT-4o als judge kost zo'n €0,01-0,05 per testcase, afhankelijk van het aantal metrics. Wil je kosten drukken? Gebruik een goedkoper model als judge of draai een lokaal model via Ollama.
Kan ik DeepEval gebruiken zonder OpenAI?
Absoluut. DeepEval ondersteunt via LiteLLM meer dan 100 LLM-providers, waaronder Anthropic Claude, Google Gemini, Mistral, AWS Bedrock en lokale modellen via Ollama. Je kunt het evaluatiemodel per metric configureren, dus je hebt volledige flexibiliteit.
Hoe verschilt DeepEval van RAGAS?
RAGAS is specifiek ontworpen voor RAG-evaluatie en biedt een beperkte set metrics gericht op retrieval-kwaliteit. DeepEval is breder: het ondersteunt RAG, agents, chatbots en eigenlijk alle LLM-applicaties die je kunt bedenken. Met 50+ metrics, native Pytest-integratie en CI/CD-ondersteuning is het een completer pakket. Bonus: DeepEval bevat alle RAGAS-metrics ook als ingebouwde opties, dus je mist niets.
Hoe bouw ik een goede golden dataset op?
Begin met het loggen van echte gebruikersvragen uit productie. Selecteer daaruit 20-50 representatieve voorbeelden die je belangrijkste scenario's dekken — inclusief die vervelende edge cases. Laat domeinexperts de verwachte antwoorden opstellen en valideren. Vul aan met synthetisch gegenereerde testcases via DeepEval's Synthesizer-klasse voor bredere dekking, maar review die altijd handmatig. Blindelings vertrouwen op synthetische data is een recept voor blinde vlekken.
Kan ik DeepEval gebruiken om streaming-antwoorden te evalueren?
Ja, maar met een kanttekening. DeepEval evalueert het volledige antwoord nadat de streaming is afgerond. In de praktijk buffer je de stream-chunks tot het complete antwoord beschikbaar is en geeft dat dan door aan de testcase. Real-time evaluatie tíjdens het streamen is momenteel niet ondersteund. Heb je dat wel nodig? Kijk dan eens naar Guardrails AI, dat output-validators tijdens het streamen kan toepassen.