Tworzenie ciągłego potoku ewaluacji
Zintegruj ewaluację LLM-as-judge z potokiem CI/CD, aby każda zmiana promptu lub modelu była automatycznie oceniana względem zestawu testów regresji przed wdrożeniem.
Tworzenie ciągłego potoku ewaluacji to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Dlaczego ocena musi być ciągła
Jednorazowa ocena podczas wdrożenia nie wystarcza. Jakość LLM pogarsza się niezauważenie: dostawcy modeli aktualizują swoje modele, zmiany w promptach systemowych mogą zostać niepostrzeżenie wprowadzone, jakość wyszukiwania zmienia się wraz z rozrostem korpusu dokumentów, a rozkład zapytań użytkowników zmienia się w czasie. Ciągły proces oceny uruchamia ten sam zestaw ocen przy każdej zmianie i zgodnie z harmonogramem, dzięki czemu regresje jakości są wykrywane w ciągu godzin, a nie tygodni.
Podstawowe elementy procesu
Ciągły potok ewaluacji składa się z pięciu komponentów: zbioru testowego (wyselekcjonowanych pytań z oczekiwanymi wynikami), mechanizmu uruchamiającego system (wywołującego potok LLM dla każdego pytania testowego), modułu oceniającego (punktującego każdą odpowiedź), magazynu wyników (bazy danych lub magazynu szeregów czasowych przechowującego historyczne metryki) oraz warstwy raportowania (paneli i alertów). Każdy komponent można niezależnie aktualizować.
# 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 notificationStruktura zbioru testowego
Zbiór testowy do ewaluacji należy przechowywać jako wersjonowany plik JSON lub YAML w repozytorium. Każdy wpis zawiera pytanie, kategorię (faktyczne, proceduralne, wykraczające poza zakres) oraz opcjonalnie odpowiedź referencyjną. Zbiór testowy należy wersjonować niezależnie od kodu — dodawanie nowych przypadków testowych jest zmianą kompatybilną wstecz, natomiast usuwanie przypadków może ukrywać regresje. Należy dążyć do 200–500 przypadków obejmujących wszystkie istotne kategorie.
# 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
# },
# ...
# ]
# }Uruchamianie zestawu ewaluacyjnego
Mechanizm uruchamiający ewaluację wywołuje system produkcyjny (lub wersję stagingową) dla każdego przypadku testowego i zapisuje odpowiedź oraz metadane. Każde uruchomienie ewaluacji należy oznaczyć unikalnym identyfikatorem uruchomienia, skrótem SHA commita, sygnaturą czasową oraz wersją zbioru testowego. Dzięki temu można dokładnie porównywać uruchomienia i ustalić, która zmiana w kodzie spowodowała regresję.
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}Przechowywanie i odpytywanie historycznych metryk
Każdy wynik uruchomienia ewaluacji należy zapisywać w bazie danych. Wystarczy prosta tabela eval_results z polami run_id, commit_sha, case_id i score. Należy odpytywać zagregowane wyniki według run_id, aby obliczać metryki dla poszczególnych uruchomień. Bieżące uruchomienie należy porównywać z ostatnim pomyślnym uruchomieniem na gałęzi main, aby wykrywać regresje. Baza szeregów czasowych, taka jak InfluxDB, dobrze sprawdza się w ciągłym monitorowaniu.
-- 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);Automatyczne wykrywanie regresji
Po każdym uruchomieniu ewaluacji należy porównać zagregowane wyniki z wartością bazową (ostatnim uruchomieniem z gałęzi main, które zostało ręcznie zatwierdzone). Regresję definiuje się jako spadek dowolnego wymiaru wyniku o więcej niż 5% poniżej wartości bazowej lub spadek średniego wyniku dowolnej kategorii poniżej ustalonego minimum. Regresje powinny blokować wdrożenie i generować alert dla zespołu. Ulepszenia można zatwierdzać automatycznie.
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}Integracja z CI/CD
Należy dodać zestaw ewaluacyjny jako krok CI uruchamiany przy każdym pull requeście. Potok CI wywołuje system stagingowy, uruchamia moduł oceniający, zapisuje wyniki i sprawdza regresje. Jeśli zostanie wykryta regresja, krok CI kończy się niepowodzeniem i blokuje scalanie PR-a. Należy dodać go jako wymagane sprawdzenie statusu w GitHubie lub GitLabie, aby nikt nie mógł go pominąć. Czas uruchomienia ewaluacji należy utrzymywać poniżej 10 minut, wykorzystując do sprawdzania PR-ów podzbiór 50–100 przypadków.
# .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_IDPlanowane pełne uruchomienia ewaluacji
Oprócz sprawdzania PR-ów należy codziennie uruchamiać pełny zestaw ewaluacyjny (wszystkie ponad 300 przypadków) względem systemu produkcyjnego. Pozwala to wykrywać stopniowe pogarszanie jakości, którego nie powoduje pojedyncza zmiana — na przykład spadek czułości bazy wektorowej po dodaniu większej liczby dokumentów lub cichą aktualizację modelu przez dostawcę LLM. Codzienne pełne uruchomienia dostarczają szeregu czasowego jakości, dzięki któremu trendy stają się widoczne.
# 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
}
}Alerty dotyczące pogarszania jakości
Należy skonfigurować alerty uruchamiane po przekroczeniu progów ostrzegawczych i krytycznych przez trendy metryk. Spadek średniej poprawności o 3% w ciągu ostatnich 7 dni powinien wywołać ostrzeżenie. Spadek o 10% w pojedynczym uruchomieniu powinien wywołać natychmiastowy alert. Ostrzeżenia należy kierować do zespołowego kanału Slack, a alerty krytyczne do PagerDuty. Każdy komunikat alertu powinien zawierać analizę regresji, odnośnik do panelu ewaluacji oraz wynik git blame dla ostatnich zmian.
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})Zarządzanie rozszerzaniem zbioru testowego
Zbiór testowy należy stale rozszerzać na podstawie rzeczywistych błędów w systemie produkcyjnym. Gdy użytkownik zgłosi niepoprawną odpowiedź, należy dodać to pytanie (w razie potrzeby po anonimizacji) do zbioru testowego wraz z oczekiwaną odpowiedzią zweryfikowaną przez człowieka. Dzięki temu zestaw ewaluacyjny odzwierciedla rzeczywiste potrzeby użytkowników, a nie hipotetyczne przypadki. Zbiór testowy należy traktować jako żywy dokument i co kwartał przeglądać go pod kątem usunięcia nieaktualnych przypadków.
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)Wizualizacja trendów jakości w czasie
Należy utworzyć prosty panel jakości przedstawiający w czasie kluczowe metryki: średni wynik poprawności, współczynnik trafień w pamięci podręcznej, opóźnienie p95 oraz koszt zapytania. Do wygładzenia szumu wynikającego z małych próbek należy użyć tygodniowej średniej kroczącej. Wykres trendu natychmiast pokazuje stopniowe pogarszanie jakości — stopniowy spadek o 3% w ciągu sześciu tygodni jest niewidoczny w raportach poszczególnych uruchomień, ale oczywisty na wykresie szeregu czasowego. Grafana lub nawet prosty skrypt Python z użyciem matplotlib dobrze się do tego nadaje.
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')Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat potoków ciągłej ewaluacji aplikacji LLM.
Podsumowanie lekcji
W tej lekcji nauczyłeś się, że potoki ciągłej ewaluacji wykonują automatyczne kontrole jakości przy każdym PR-ze oraz codziennie, aby wcześnie wykrywać regresje, wykrywanie regresji porównuje bieżące wyniki z wartością bazową i blokuje wdrożenie, gdy jakość spada, a rozszerzanie zbioru testowego na podstawie rzeczywistych błędów sprawia, że zestaw ewaluacyjny pozostaje oparty na rzeczywistych potrzebach użytkowników. Następnie sklasyfikujemy tryby awarii agentów i zaprojektujemy strategie odzyskiwania.
Ucz się Python dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 30
- Lekcje
- 120
Często zadawane pytania
Czy lekcja „Tworzenie ciągłego potoku ewaluacji” jest bezpłatna?
Tak — pełny tekst „Tworzenie ciągłego potoku ewaluacji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Tworzenie ciągłego potoku ewaluacji”?
Zintegruj ewaluację LLM-as-judge z potokiem CI/CD, aby każda zmiana promptu lub modelu była automatycznie oceniana względem zestawu testów regresji przed wdrożeniem. Ćwiczysz AI Engineering Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Engineering Academy?
Nie wymagamy żadnego doświadczenia. AI Engineering Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Tworzenie ciągłego potoku ewaluacji”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Engineering Academy?
Tak. Każda lekcja AI Engineering Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wzorzec LLM-as-Judge
- Ewaluacja punktowa i porównawcza
- Kalibracja modeli-sędziów względem ludzi
- Tworzenie ciągłego potoku ewaluacji