AI Engineering Academy · Les

Uw gefinetunede model evalueren en implementeren

Voer kwantitatieve evaluaties uit waarin het basismodel en het gefinetunede model worden vergeleken op achtergehouden testgevallen, converteer naar GGUF voor lokale inferentie en bied het model aan via llama.cpp of vLLM.

Les 4 van 413 stappen

Uw gefinetunede model evalueren en implementeren is een gratis AI Engineering Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject AI Engineering Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus AI Engineering Academy bevat in totaal 4 lessen.

Waarom evaluatie vóór implementatie moet plaatsvinden

Een verfijnd model dat goed presteert op trainingsgegevens kan slechter presteren dan het basismodel voor jouw daadwerkelijke gebruikssituatie in productie. De enige manier om dat vast te stellen is grondige evaluatie. Fine-tuning kan leiden tot catastrofaal vergeten (het verliezen van mogelijkheden die het basismodel had), overspecialisatie (goed presteren op jouw taak maar slechter op verwante taken) of subtiele achteruitgang in veiligheidsgedrag. Implementeer een verfijnd model nooit zonder het op een representatieve testset te evalueren tegen het basismodel.

Een achtergehouden testset samenstellen

Je testset moet volledig gescheiden zijn van de trainings- en validatiegegevens — het moeten voorbeelden zijn die het model tijdens geen enkele trainingsfase heeft gezien. De testset moet de volledige verdeling van productie-invoer vertegenwoordigen: veelvoorkomende gevallen, randgevallen en vijandige invoer. Neem voor taken waarbij instructies moeten worden gevolgd voorbeelden op die vereisen dat alle aspecten van de instructie worden gevolgd, niet alleen de meest voorkomende. Een testset van 100–500 voorbeelden is doorgaans voldoende voor een betrouwbare evaluatie.

import json
from typing import TypedDict

class TestCase(TypedDict):
    input: str                 # the user message
    expected_output: str       # the ideal response
    category: str              # e.g., 'format', 'accuracy', 'edge_case'
    evaluation_method: str     # 'exact_match', 'json_schema', 'llm_judge'

# Load test set (never used during training)
def load_test_set(path: str) -> list[TestCase]:
    cases = []
    with open(path) as f:
        for line in f:
            data = json.loads(line.strip())
            cases.append({
                'input': data['messages'][-2]['content'],  # user message
                'expected_output': data['messages'][-1]['content'],  # assistant response
                'category': data.get('metadata', {}).get('category', 'general'),
                'evaluation_method': data.get('metadata', {}).get('eval_method', 'llm_judge')
            })
    return cases

test_set = load_test_set('test.jsonl')
print(f'Test set loaded: {len(test_set)} examples')

Kwantitatieve meetwaarden voor taakspecifieke evaluatie

Kies evaluatiemaatstaven die bij jouw taak passen. Meet voor JSON-extractie het nalevingspercentage van het schema en de nauwkeurigheid per veld. Meet voor classificatie de nauwkeurigheid, precisie en recall per klasse. Gebruik voor tekstgeneratie scoring door een LLM als beoordelaar voor de kwaliteit. Meet voor indelingsnaleving het exacte nalevingspercentage van de indeling. Voer elke maatstaf uit op zowel het basismodel als het verfijnde model, zodat je de verbetering kunt meten.

import json

def evaluate_json_extraction(model_output: str, expected: str, schema: dict) -> dict:
    metrics = {'valid_json': False, 'schema_compliant': False, 'field_accuracy': 0.0}
    
    try:
        parsed = json.loads(model_output.strip())
        metrics['valid_json'] = True
        
        # Check schema compliance
        required_fields = schema.get('required', [])
        all_present = all(field in parsed for field in required_fields)
        correct_types = all(
            isinstance(parsed.get(field), schema['properties'][field]['expected_type'])
            for field in required_fields if field in parsed
        )
        metrics['schema_compliant'] = all_present and correct_types
        
        # Field-level accuracy against expected output
        expected_parsed = json.loads(expected)
        correct_fields = sum(1 for k in expected_parsed if parsed.get(k) == expected_parsed[k])
        metrics['field_accuracy'] = correct_fields / len(expected_parsed) if expected_parsed else 0.0
    
    except json.JSONDecodeError:
        pass  # valid_json stays False
    
    return metrics

Evaluatie met een LLM als beoordelaar

Gebruik voor open generatieopdrachten een LLM als beoordelaar om de uitvoer van het verfijnde model te scoren ten opzichte van de verwachte uitvoer. Geef GPT-4o de opdracht om als beoordelaar op te treden, verstrek de invoer, de verwachte uitvoer en de uitvoer van het model, en vraag het om juistheid, volledigheid en naleving van de indeling te beoordelen op een schaal van 1–5. Bereken het gemiddelde van de scores over de testset voor een algemene kwaliteitsbeoordeling. Vergelijk de score van het verfijnde model met die van het basismodel op dezelfde testset.

from openai import OpenAI

client = OpenAI()

def llm_judge_score(instruction: str, expected: str, actual: str) -> dict:
    judge_prompt = f'''Evaluate the quality of an AI assistant response.

Instruction given to assistant:
{instruction}

Expected ideal response:
{expected}

Actual response from model being evaluated:
{actual}

Rate the actual response on these criteria (1=poor, 5=excellent):
1. Correctness: Is the information accurate?
2. Format compliance: Does it follow the expected output format?
3. Completeness: Does it address all parts of the instruction?

Return JSON: {{"correctness": N, "format": N, "completeness": N, "overall": N, "reason": "brief explanation"}}'''
    
    response = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': judge_prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(response.choices[0].message.content)

De vergelijkende evaluatie uitvoeren

Voer een rechtstreekse evaluatie uit waarin je het basismodel, het verfijnde model en eventueel een sterke promptbasislijn vergelijkt op alle testgevallen. Genereer voor elk testgeval uitvoer van elk model en scoor vervolgens alle uitvoer met je evaluatiemaatstaven. Maak een vergelijkingstabel met de scores, standaardafwijkingen en voorbeelden van gevallen waarin het verfijnde model beter of slechter presteert dan de basislijn.

def run_full_evaluation(test_set: list, models: dict, system_prompt: str) -> dict:
    results = {name: {'scores': [], 'errors': 0} for name in models}
    
    for i, test_case in enumerate(test_set):
        print(f'Evaluating test case {i+1}/{len(test_set)}')
        
        for model_name, model_fn in models.items():
            try:
                output = model_fn(test_case['input'], system_prompt)
                score = llm_judge_score(
                    test_case['input'],
                    test_case['expected_output'],
                    output
                )
                results[model_name]['scores'].append(score['overall'])
            except Exception as e:
                results[model_name]['errors'] += 1
                results[model_name]['scores'].append(0)
    
    # Summarize
    summary = {}
    for name, data in results.items():
        scores = data['scores']
        summary[name] = {
            'mean_score': sum(scores) / len(scores),
            'errors': data['errors']
        }
        print(f'{name}: mean={summary[name]["mean_score"]:.2f}, errors={data["errors"]}')
    return summary

Regressietesten voor catastrofaal vergeten

Fine-tuning kan de algemene mogelijkheden van het model verslechteren; dit verschijnsel heet catastrofaal vergeten. Voer een regressietestsuite uit op zowel het basis- als het verfijnde model, met taken die je belangrijk vindt naast je doeltaak: algemene vraagbeantwoording, redeneren, codegeneratie en het volgen van instructies. Als het verfijnde model op deze taken aanzienlijk lager scoort, is je LoRA-rang mogelijk te hoog of heb je te veel epochs getraind.

REGRESSION_TEST_CASES = [
    # General QA
    {'input': 'What is the capital of France?', 'expected_substring': 'Paris'},
    {'input': 'What is 17 * 23?', 'expected_substring': '391'},
    # Instruction following
    {'input': 'List 3 planets. Format as: 1. Planet Name', 'expected_pattern': r'^1\. '},
    # Reasoning
    {'input': 'If all A are B and all B are C, are all A also C?', 'expected_substring': 'yes'},
]

def run_regression_tests(model_fn, test_cases: list) -> float:
    passed = 0
    for test in test_cases:
        output = model_fn(test['input'], '')
        if 'expected_substring' in test:
            if test['expected_substring'].lower() in output.lower():
                passed += 1
        elif 'expected_pattern' in test:
            import re
            if re.search(test['expected_pattern'], output):
                passed += 1
    
    rate = passed / len(test_cases)
    print(f'Regression test pass rate: {rate:.1%} ({passed}/{len(test_cases)})')
    return rate

Converteren naar GGUF voor lokale inferentie

Converteer voor lokale implementatie zonder dure GPU-infrastructuur je samengevoegde model naar GGUF-indeling en voer inferentie uit met llama.cpp. GGUF ondersteunt verschillende kwantisatieniveaus: Q4_K_M (4-bits, goede balans tussen kwaliteit en snelheid), Q8_0 (8-bits, bijna volledige kwaliteit) en Q2_K (2-bits, zeer snel maar met lagere kwaliteit). Een met Q4 gekwantiseerd 7B-model heeft slechts ongeveer 4 GB RAM nodig en kan op een CPU draaien met 1–5 tokens per seconde.

# Step 1: Convert merged HuggingFace model to GGUF
# git clone https://github.com/ggerganov/llama.cpp
# python llama.cpp/convert_hf_to_gguf.py ./merged-model --outtype f16 --outfile model-f16.gguf

# Step 2: Quantize to 4-bit
# ./llama.cpp/llama-quantize model-f16.gguf model-q4.gguf Q4_K_M

# Step 3: Run inference with llama.cpp Python bindings
# pip install llama-cpp-python
from llama_cpp import Llama

llm = Llama(
    model_path='./model-q4.gguf',
    n_ctx=4096,         # context window
    n_threads=8,        # CPU threads
    n_gpu_layers=0      # set > 0 to offload layers to GPU
)

output = llm.create_chat_completion(
    messages=[{'role': 'user', 'content': 'What is the capital of France?'}],
    temperature=0.1
)
print(output['choices'][0]['message']['content'])

Serveren met vLLM voor productie

Voor het op schaal serveren van een verfijnd model in productie is vLLM momenteel de standaard. vLLM gebruikt PagedAttention om meerdere verzoeken efficiënt samen te voegen in batches, waardoor de GPU-doorvoer sterk toeneemt. Het ondersteunt API-eindpunten die compatibel zijn met OpenAI, waardoor het een directe vervanging voor de OpenAI-API is. Eén A100-GPU waarop vLLM met een verfijnd 7B-model draait, kan honderden verzoeken per minuut afhandelen.

# Start vLLM server (run from command line)
# pip install vllm
# python -m vllm.entrypoints.openai.api_server \
#     --model ./merged-model \
#     --host 0.0.0.0 \
#     --port 8000 \
#     --max-model-len 4096 \
#     --tensor-parallel-size 1

# Use with OpenAI client (drop-in replacement)
from openai import OpenAI

client = OpenAI(
    base_url='http://localhost:8000/v1',
    api_key='not-needed'  # vLLM doesn't require auth by default
)

response = client.chat.completions.create(
    model='merged-model',  # model name matches the path you passed to vLLM
    messages=[{'role': 'user', 'content': 'Extract JSON from: "Alice, 30, NYC"'}]
)
print(response.choices[0].message.content)

A/B-testen van het verfijnde model

Voer voordat je volledig overstapt op het verfijnde model in productie een A/B-test uit: stuur een percentage van het productie‍verkeer (begin met 5–10%) naar het verfijnde model, terwijl de meerderheid nog het basismodel of de bestaande promptbenadering gebruikt. Bewaak voor beide groepen de kwaliteitsscores, latentie en meetwaarden voor gebruikerstevredenheid. Vergroot het aandeel verkeer naar het verfijnde model alleen als de A/B-test na een statistisch significant aantal verzoeken een verbetering bevestigt.

import random

class ModelRouter:
    def __init__(self, fine_tuned_traffic_fraction=0.1):
        self.ft_fraction = fine_tuned_traffic_fraction
        self.metrics = {'base': {'count': 0, 'quality_sum': 0}, 'fine_tuned': {'count': 0, 'quality_sum': 0}}

    def route(self, user_id: str, request: str) -> dict:
        # Deterministic routing by user_id (same user always goes to same model)
        use_fine_tuned = (hash(user_id) % 100) < (self.ft_fraction * 100)
        model_group = 'fine_tuned' if use_fine_tuned else 'base'
        
        response = call_model(request, use_fine_tuned=use_fine_tuned)
        return {'response': response, 'model_group': model_group}

    def record_quality(self, model_group: str, quality_score: float):
        self.metrics[model_group]['count'] += 1
        self.metrics[model_group]['quality_sum'] += quality_score

    def ab_test_summary(self) -> dict:
        summary = {}
        for group, data in self.metrics.items():
            avg = data['quality_sum'] / data['count'] if data['count'] > 0 else 0
            summary[group] = {'avg_quality': avg, 'n': data['count']}
        return summary

Verfijnde modellen in de loop van de tijd onderhouden

Verfijnde modellen vereisen voortdurend onderhoud. Wanneer het basismodel wordt bijgewerkt (een nieuwe GPT-4o-versie, een nieuwe Mistral-release), zijn je adaptergewichten mogelijk niet compatibel en moet je wellicht opnieuw trainen. Wanneer de vereisten voor je taak veranderen, moet je de trainingsgegevens bijwerken en opnieuw trainen. Wanneer je nieuwe foutmodi in productie ontdekt, voeg je voorbeelden toe aan je trainingsset. Plan periodieke hertraining als onderdeel van je workflow voor ML-operaties in productie.

Beslismatrix voor implementatie

Het kiezen van een implementatiestrategie voor je verfijnde model hangt af van je schaal en beperkingen van je infrastructuur. Voor lage volumes (minder dan 1000 aanvragen per dag) is de fine-tuning-API van OpenAI het eenvoudigst. Overweeg voor gemiddelde volumes (1000–100.000 per dag) vLLM op één GPU-instantie. Gebruik voor hoge volumes of latentiegevoelige toepassingen vLLM met meerdere GPU's, overweeg tensorparallelisme en voeg een cachinglaag aan de voorkant toe. Host privacygevoelige gegevens zelf op je eigen infrastructuur met GGUF/llama.cpp of vLLM.

Korte controle

Test je begrip van het evalueren en implementeren van verfijnde modellen uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat grondige evaluatie vóór implementatie, waarbij een verfijnd model wordt vergeleken met het basismodel op achtergehouden testgevallen, absoluut noodzakelijk is; dat regressietests catastrofaal vergeten van algemene mogelijkheden door overspecialisatie detecteren; en dat implementatieopties variëren van de beheerde fine-tuning-API van OpenAI voor eenvoud tot vLLM voor verwerking met hoge doorvoer in productie en GGUF/llama.cpp voor lokale inferentie op de CPU. Gefeliciteerd met het voltooien van het traject AI Engineering!

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Uw gefinetunede model evalueren en implementeren” gratis?

Ja — de volledige tekst van “Uw gefinetunede model evalueren en implementeren” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus AI Engineering Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus AI Engineering Academy bevat in totaal 4 lessen.

Wat leer ik in “Uw gefinetunede model evalueren en implementeren”?

Voer kwantitatieve evaluaties uit waarin het basismodel en het gefinetunede model worden vergeleken op achtergehouden testgevallen, converteer naar GGUF voor lokale inferentie en bied het model aan v… Je oefent met AI Engineering Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met AI Engineering Academy te beginnen?

Ervaring vooraf is niet nodig. AI Engineering Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Uw gefinetunede model evalueren en implementeren”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over AI Engineering Academy?

Ja. Elke les over AI Engineering Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Wanneer fine-tuning beter werkt dan prompting
  2. Een hoogwaardige trainingsdataset voorbereiden
  3. LoRA-fine-tuning met Hugging Face PEFT
  4. Uw gefinetunede model evalueren en implementeren
← Terug naar AI Engineering Academy