LLM Prompts Testen: Van Gokken naar Meetbare Kwaliteit
Hoe prompt kwaliteit systematisch getest en gemeten wordt. Evaluatiestrategieën, regressietests en scoring voor LLM-applicaties in productie.
Jean-Pierre Broeders
Freelance DevOps Engineer
LLM Prompts Testen: Van Gokken naar Meetbare Kwaliteit
Een prompt schrijven is makkelijk. Weten of die prompt ook daadwerkelijk goed werkt — dat is een heel ander verhaal. De meeste teams testen hun prompts door er handmatig een paar keer tegenaan te praten, te concluderen dat het "wel oké" lijkt, en het naar productie te deployen. Tot er klachten binnenkomen.
Het probleem zit hem niet in slechte prompts. Het probleem is dat er geen manier is om te weten of een wijziging de output beter of slechter maakt. Prompt development zonder tests is als software schrijven zonder unit tests — het werkt totdat het niet meer werkt, en dan gaat het flink mis.
Waarom Handmatig Testen Niet Schaalt
Bij drie use cases en een handjevol edge cases lukt het nog wel om even snel te checken of de output klopt. Maar zodra een applicatie tientallen prompt-varianten heeft, met verschillende user inputs en edge cases, wordt handmatig controleren een fulltime baan.
En dan is er nog het non-determinisme probleem. Dezelfde prompt met dezelfde input geeft niet altijd dezelfde output. Temperature op 0 zetten helpt, maar zelfs dan zijn er subtiele verschillen tussen API calls. Dat maakt "even snel checken" fundamenteel onbetrouwbaar als teststrategie.
Een Test Suite voor Prompts Opzetten
De aanpak is eigenlijk niet zo anders dan wat er al voor gewone software bestaat. Een test suite voor prompts bestaat uit drie onderdelen:
Test cases — een verzameling inputs met verwachte outputs of criteria waaraan de output moet voldoen. Niet per se een exacte match, maar wel meetbare eigenschappen.
Evaluatiefuncties — de logica die bepaalt of een output "goed" is. Soms simpel (bevat de output het juiste JSON-schema?), soms complex (is de toon professioneel maar niet te formeel?).
Een runner — iets dat alle test cases door de prompt haalt en de resultaten scoort.
In Python ziet dat er ongeveer zo uit:
import json
from openai import OpenAI
client = OpenAI()
test_cases = [
{
"input": "Mijn factuur klopt niet, er staat een verkeerd bedrag op",
"expected_category": "billing",
"expected_sentiment": "negative"
},
{
"input": "Kunnen jullie ook een dark mode toevoegen?",
"expected_category": "feature-request",
"expected_sentiment": "neutral"
},
{
"input": "De app crasht als ik op export klik",
"expected_category": "technical",
"expected_sentiment": "negative"
}
]
def run_prompt(user_input: str) -> dict:
response = client.chat.completions.create(
model="gpt-4o",
temperature=0,
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": """Classificeer het support ticket.
Geef JSON terug met: category (billing|technical|feature-request|other)
en sentiment (positive|neutral|negative)."""},
{"role": "user", "content": user_input}
]
)
return json.loads(response.choices[0].message.content)
def evaluate(test_case: dict, result: dict) -> dict:
return {
"category_correct": result["category"] == test_case["expected_category"],
"sentiment_correct": result["sentiment"] == test_case["expected_sentiment"]
}
Niks raketwetenschap. Gewoon inputs, verwachte outputs, en een check.
Scoring: Meer dan Pass/Fail
Binaire pass/fail werkt voor gestructureerde output — het JSON-schema klopt of het klopt niet. Maar voor vrije tekst is een genuanceerder systeem nodig.
| Evaluatietype | Wanneer gebruiken | Voorbeeld |
|---|---|---|
| Exact match | Classificatie, labels, categorieën | Output moet exact "billing" zijn |
| Contains check | Verplichte elementen in output | Samenvatting moet de bedrijfsnaam bevatten |
| Regex validatie | Formaat-checks | Datum moet in YYYY-MM-DD formaat staan |
| LLM-as-judge | Subjectieve kwaliteit | Beoordeel of de toon professioneel is (1-5) |
| Embedding similarity | Semantische overeenkomst | Output moet semantisch lijken op referentie-antwoord |
De LLM-as-judge aanpak is bijzonder handig. Een tweede model beoordeelt de output van het eerste. Klinkt circulair, maar in de praktijk werkt het verrassend goed — zeker als het beoordelingsmodel sterker is dan het model dat de output genereert.
def llm_judge(output: str, criteria: str) -> int:
response = client.chat.completions.create(
model="gpt-4o",
temperature=0,
messages=[
{"role": "system", "content": f"""Beoordeel de volgende tekst op: {criteria}
Geef een score van 1-5. Antwoord met alleen het cijfer."""},
{"role": "user", "content": output}
]
)
return int(response.choices[0].message.content.strip())
Regressietests: De Echte Winst
De grootste waarde van prompt tests zit niet in de initiële evaluatie. Het zit in regressietests. Elke keer dat een prompt wordt aangepast — een zin toevoegen, de instructies herschrijven, een ander model proberen — draait de hele suite opnieuw. Daardoor is direct zichtbaar of de wijziging de kwaliteit verbetert of verslechtert.
Dat past prima in een CI/CD pipeline:
# .github/workflows/prompt-tests.yml
name: Prompt Regression Tests
on:
pull_request:
paths:
- 'prompts/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run prompt tests
run: python -m pytest tests/prompts/ -v
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Check score threshold
run: |
python scripts/check_scores.py --min-accuracy 0.85
Bij elke PR die prompts wijzigt, draaien de tests automatisch. Zakt de accuracy onder de drempel? Dan blokkeert de pipeline. Geen discussies meer over of een prompt "beter voelt" — de cijfers spreken.
Praktische Tips
Begin klein. Vijf tot tien goede test cases per prompt zijn genoeg om mee te starten. Voeg cases toe als er bugs opduiken in productie — net als bij gewone software.
Log alles. Elke prompt call in productie verdient logging: de input, de volledige output, het model, de temperature, en eventueel de latency. Dat zijn de test cases van morgen.
Versie je prompts. Prompts horen in version control, niet in een database of hardcoded in de applicatie. Een prompt wijzigen is een code change en verdient dezelfde review.
Test met echte data. Synthetische test cases zijn een goed startpunt, maar de echte edge cases komen uit productiedata. Anonimiseer waar nodig en bouw een golden dataset op van geverifieerde input-output paren.
Pas op met overfitting. Een prompt die perfect scoort op de test suite maar faalt op nieuwe inputs is net zo waardeloos als een overfit ML-model. Houd een aparte holdout set aan die niet wordt gebruikt tijdens prompt development.
De Investering Loont
Prompt testing opzetten kost een middag. Misschien twee als de evaluatiefuncties complexer zijn. Maar die investering verdient zichzelf dubbel en dwars terug bij de eerste keer dat een "kleine aanpassing" aan een prompt de hele output breekt — en de test suite dat opvangt voordat het productie haalt.
Het is uiteindelijk dezelfde discipline als unit testing. Niet sexy, niet spannend, maar het verschil tussen een robuuste applicatie en eentje die regelmatig in de kreukels ligt.
