Construire un pipeline d’évaluation continue
Intégrez l’évaluation par un LLM-évaluateur à votre pipeline CI/CD afin que chaque modification d’invite ou de modèle soit automatiquement évaluée par rapport à une suite de tests de régression avant le déploiement.
Construire un pipeline d’évaluation continue est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Why Evaluation Must Be Continuous
One-time evaluation at deployment is not enough. LLM quality degrades silently: model providers update their models, system prompt changes slip in, retrieval quality shifts as the document corpus grows, and user query distribution changes over time. A continuous evaluation pipeline runs the same suite of evaluations on every change and on a schedule so quality regressions are caught within hours, not weeks.
Core Components of the Pipeline
A continuous evaluation pipeline has five components: a test dataset (curated questions with expected outputs), a system runner (calls your LLM pipeline for each test question), a judge (scores each response), a results store (database or time-series store for historical metrics), and a reporting layer (dashboards and alerts). Each component is independently upgradeable.
# Pipeline architecture:
#
# test_dataset.json
# |
# v
# system_runner.py --> calls your LLM pipeline
# |
# v
# judge.py --> scores each (question, answer) pair
# |
# v
# results_db --> stores timestamped metric history
# |
# v
# dashboard + alert --> Grafana / Slack notificationStructuring the Test Dataset
Store your evaluation test set as a versioned JSON or YAML file in your repository. Each entry contains a question, the category (factual, procedural, out-of-scope), and optionally a reference answer. Version the test set separately from the code — adding new test cases is a backward-compatible change, while removing cases may hide regressions. Aim for 200-500 cases across all relevant categories.
# eval/test_set_v3.json
# {
# 'version': '3.0',
# 'created': '2026-06-01',
# 'cases': [
# {
# 'id': 'faq_001',
# 'category': 'factual',
# 'question': 'What is the cancellation policy?',
# 'reference': 'Cancellations must be made 24 hours in advance.',
# 'min_correctness': 4
# },
# ...
# ]
# }Running the Evaluation Suite
The evaluation runner calls your production system (or a staging version) for each test case and records the response and metadata. Tag each evaluation run with a unique run ID, the commit SHA that triggered it, the timestamp, and the test set version. This makes it possible to compare runs exactly and diagnose which code change caused a regression.
import asyncio
import uuid
from datetime import datetime
async def run_eval_suite(system, test_set: list, commit_sha: str) -> dict:
run_id = str(uuid.uuid4())
results = []
for case in test_set:
response = await system.answer(case['question'])
score = await judge(case['question'], response, case.get('reference'))
results.append({
'run_id': run_id,
'commit_sha': commit_sha,
'case_id': case['id'],
'category': case['category'],
'response': response,
'score': score.model_dump(),
'evaluated_at': datetime.utcnow().isoformat()
})
return {'run_id': run_id, 'results': results}Storing and Querying Historical Metrics
Persist every eval run result to a database. A simple eval_results table with run_id, commit_sha, case_id, and score fields is sufficient. Query aggregate scores by run_id to compute per-run metrics. Compare the current run against the last successful run on main branch to detect regressions. A time-series database like InfluxDB works well for continuous monitoring.
-- PostgreSQL schema
CREATE TABLE eval_runs (
run_id UUID PRIMARY KEY,
commit_sha TEXT NOT NULL,
test_set_version TEXT NOT NULL,
triggered_by TEXT, -- 'ci', 'scheduled', 'manual'
started_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE eval_results (
id SERIAL PRIMARY KEY,
run_id UUID REFERENCES eval_runs(run_id),
case_id TEXT NOT NULL,
category TEXT,
correctness INT,
overall INT,
response TEXT
);
CREATE INDEX idx_run_id ON eval_results(run_id);Detecting Regressions Automatically
After each evaluation run, compare aggregate scores to the baseline (the last run from the main branch that was manually approved). A regression is defined as: any score dimension dropping more than 5% below baseline, or any category's mean score dropping below a hard minimum. Regressions should block deployment and alert the team. Improvements can be auto-approved.
def detect_regression(current: dict, baseline: dict, threshold_pct: float = 5.0) -> dict:
regressions = []
for metric in ['correctness', 'helpfulness', 'clarity']:
delta_pct = (current[metric] - baseline[metric]) / baseline[metric] * 100
if delta_pct < -threshold_pct:
regressions.append({
'metric': metric,
'baseline': baseline[metric],
'current': current[metric],
'delta_pct': round(delta_pct, 1)
})
return {'has_regression': len(regressions) > 0, 'regressions': regressions}Integrating with CI/CD
Add the evaluation suite as a CI step that runs on every pull request. The CI pipeline calls your staging system, runs the judge, stores results, and checks for regressions. If a regression is detected, the CI step fails and blocks the PR merge. Add this as a required status check in GitHub or GitLab so no one can bypass it. Keep the eval run time under 10 minutes by using a subset of 50-100 cases for PR checks.
# .github/workflows/eval.yml
# name: LLM Quality Evaluation
# on: [pull_request]
# jobs:
# eval:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Run eval suite
# run: python eval/run_suite.py --commit $GITHUB_SHA --mode pr
# env:
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# - name: Check for regressions
# run: python eval/check_regression.py --run-id $EVAL_RUN_IDScheduled Full Evaluation Runs
Beyond PR checks, run the full evaluation suite (all 300+ cases) on a daily schedule against production. This catches gradual quality drift that no single change introduces — for example, if the vector database's recall degrades as more documents are added, or if the LLM provider silently updates their model. Daily full runs give you a quality time series that makes trends visible.
# Separate eval modes:
EVAL_CONFIGS = {
'pr_check': {
'test_cases': 'eval/test_set_core_100.json',
'target': 'staging',
'max_runtime_min': 8
},
'nightly': {
'test_cases': 'eval/test_set_full_350.json',
'target': 'production',
'max_runtime_min': 30
},
'weekly_deep': {
'test_cases': 'eval/test_set_full_350.json',
'target': 'production',
'include_pairwise': True,
'max_runtime_min': 90
}
}Alerting on Quality Degradation
Configure alerts when metric trends cross warning and critical thresholds. A 3% drop in mean correctness over the past 7 days triggers a warning. A 10% drop in a single run triggers an immediate alert. Route warnings to a team Slack channel and critical alerts to PagerDuty. Include the regression analysis, a link to the eval dashboard, and the git blame for recent changes in every alert message.
import httpx
def send_regression_alert(regression_report: dict, webhook_url: str):
regressions = regression_report['regressions']
blocks = [{
'type': 'section',
'text': {'type': 'mrkdwn', 'text': '*LLM Quality Regression Detected*'}
}]
for r in regressions:
blocks.append({
'type': 'section',
'text': {'type': 'mrkdwn',
'text': f'*{r["metric"]}*: {r["baseline"]} -> {r["current"]} ({r["delta_pct"]}%)'}
})
httpx.post(webhook_url, json={'blocks': blocks})Managing Test Set Expansion
Continuously grow your test set based on real production failures. When a user reports a bad response, add that question (anonymized if needed) to the test set with a human-verified expected answer. This ensures your evaluation suite reflects actual user needs rather than hypothetical cases. Treat the test set as a living document and review it quarterly to remove stale cases.
def add_to_test_set(question: str, reference_answer: str, category: str,
source: str, test_set_path: str):
import json, uuid
with open(test_set_path, 'r') as f:
test_set = json.load(f)
test_set['cases'].append({
'id': f'user_report_{uuid.uuid4().hex[:8]}',
'category': category,
'question': question,
'reference': reference_answer,
'source': source, # 'user_report', 'regression', 'manual'
'added': '2026-06-21'
})
with open(test_set_path, 'w') as f:
json.dump(test_set, f, indent=2)Visualizing Quality Trends Over Time
Build a simple quality dashboard that plots your key metrics over time: mean correctness score, cache hit rate, p95 latency, and cost per query. Use a weekly moving average to smooth out noise from small sample sizes. A trend chart makes quality drift immediately visible — a gradual 3% decline over six weeks is invisible in individual run reports but obvious on a time-series chart. Grafana or even a simple Python matplotlib script works well for this.
import matplotlib.pyplot as plt
import pandas as pd
def plot_quality_trend(eval_history: list):
df = pd.DataFrame(eval_history)
df['date'] = pd.to_datetime(df['evaluated_at'])
df = df.sort_values('date')
# 7-day rolling average
df['score_ma7'] = df['mean_correctness'].rolling(window=7).mean()
plt.figure(figsize=(12, 4))
plt.plot(df['date'], df['mean_correctness'], alpha=0.3, label='Daily')
plt.plot(df['date'], df['score_ma7'], label='7-day avg', linewidth=2)
plt.axhline(y=4.0, color='r', linestyle='--', label='Min threshold')
plt.legend()
plt.title('LLM Answer Quality Over Time')
plt.savefig('quality_trend.png')Quick Check
Test your understanding of continuous evaluation pipelines for LLM applications.
Lesson Recap
In this lesson you learned: continuous evaluation pipelines run automated quality checks on every PR and on a daily schedule to catch regressions early, regression detection compares current scores to a baseline and blocks deployment if quality drops, and test set expansion from real failures keeps your evaluation suite grounded in actual user needs. Next up we classify agent failure modes and design recovery strategies.
Questions Fréquemment Posées
La leçon « Construire un pipeline d’évaluation continue » est-elle gratuite ?
Oui — le texte complet de « Construire un pipeline d’évaluation continue » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Construire un pipeline d’évaluation continue » ?
Intégrez l’évaluation par un LLM-évaluateur à votre pipeline CI/CD afin que chaque modification d’invite ou de modèle soit automatiquement évaluée par rapport à une suite de tests de régression avant… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?
Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Construire un pipeline d’évaluation continue » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?
Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Le modèle du LLM évaluateur
- Évaluation point par point et par paires
- Étalonner les modèles évaluateurs par rapport aux humains
- Construire un pipeline d’évaluation continue