Schema-evolutie en achterwaartse compatibiliteit
Beheer niet-compatibele schemawijzigingen in langlopende extractiepijplijnen door schema's te versieseren, historische extracties te migreren en tijdens overgangen parallel te valideren.
Schema-evolutie en achterwaartse compatibiliteit 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 schema's in de loop van de tijd veranderen
Extractieschema's zijn niet statisch. Zakelijke vereisten veranderen, er verschijnen nieuwe documenttypen en je ontdekt velden die je vanaf het begin had moeten vastleggen. Een schema wijzigen in een actieve pijplijn veroorzaakt een probleem met achterwaartse compatibiliteit: bestaande geëxtraheerde records gebruiken het oude schema, terwijl nieuwe records het nieuwe gebruiken. Schema-evolutie gaat over het veilig beheren van deze overgang.
Je schema's van versies voorzien
Wijs aan elk schema een versienummer toe en sla dit op bij elk geëxtraheerd record. Verhoog het versienummer wanneer je het schema wijzigt. Zo kun je records op schema-versie opvragen, migraties uitvoeren op oude records en afzonderlijke validatielogica voor elke versie behouden. Een eenvoudig tekenreeksveld schema_version in elk uitvoermodel is voldoende.
from pydantic import BaseModel
from typing import Literal
class InvoiceV1(BaseModel):
schema_version: Literal['1.0'] = '1.0'
vendor: str
total_amount: float
class InvoiceV2(BaseModel):
schema_version: Literal['2.0'] = '2.0'
vendor: str
vendor_tax_id: str | None = None # new field
total_amount: float
currency: str = 'USD' # new field with defaultToevoegende versus ingrijpende wijzigingen
Toevoegende wijzigingen zijn veilig: een Optional-veld of een veld met een standaardwaarde toevoegen verbreekt oude extractiecode of oude records niet. Ingrijpende wijzigingen zijn riskant: de naam van een veld wijzigen, het type veranderen van string naar int of een veld verwijderen verbreekt downstreamgebruikers. Geef altijd de voorkeur aan toevoegende wijzigingen. Wanneer een ingrijpende wijziging onvermijdelijk is, maak je een nieuwe hoofdversie van het schema en migreer je gecontroleerd.
# Safe: additive change - add optional field
class ProductV2(BaseModel):
name: str
price: float
sku: str | None = None # NEW optional field - backward safe
category: str = 'general' # NEW with default - backward safe
# Risky: breaking change - rename or retype
# class ProductV2(BaseModel):
# product_name: str # RENAMED from name - breaks consumers
# price_cents: int # RETYPED from float - breaks dataDe schema-versie in de database opslaan
Neem de schema-versie op in je tabel met extractieresultaten, zodat je altijd weet welke versie elk record heeft geproduceerd. Een jsonb-kolom met de volledige geëxtraheerde gegevens plus een tekstkolom schema_version is een veelgebruikt patroon. Zo kun je versieafhankelijke zoekopdrachten schrijven en oudere records selectief migreren tijdens perioden met weinig verkeer.
-- PostgreSQL table design
CREATE TABLE extractions (
doc_id TEXT PRIMARY KEY,
schema_version TEXT NOT NULL,
extracted_data JSONB NOT NULL,
extracted_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_schema_version ON extractions(schema_version);
-- Query old records needing migration
SELECT doc_id, extracted_data
FROM extractions
WHERE schema_version = '1.0'
LIMIT 1000;Migratiescripts schrijven
Schrijf voor elke overgang tussen schema-versies een migratiescript dat oude records leest, ze omzet naar de nieuwe indeling en ze met de nieuwe versie terugschrijft. Voer migraties uit in kleine reeksen met transacties, zodat een fout de database niet in een gedeeltelijk gemigreerde toestand achterlaat. Houd het oude schema altijd beschikbaar totdat je hebt gecontroleerd dat de migratie is voltooid.
import asyncpg
import json
async def migrate_v1_to_v2(pool, batch_size=100):
async with pool.acquire() as conn:
rows = await conn.fetch(
'SELECT doc_id, extracted_data FROM extractions WHERE schema_version=$1 LIMIT $2',
'1.0', batch_size
)
for row in rows:
old = row['extracted_data']
new_data = {
'schema_version': '2.0',
'vendor': old['vendor'],
'vendor_tax_id': None, # unknown for old records
'total_amount': old['total_amount'],
'currency': 'USD' # assume USD for old records
}
await conn.execute(
'UPDATE extractions SET extracted_data=$1, schema_version=$2 WHERE doc_id=$3',
json.dumps(new_data), '2.0', row['doc_id']
)Parallel valideren tijdens overgangen
Voer tijdens een schemamigratie parallelle validatie uit: extraheer een steekproef van binnenkomende documenten gelijktijdig met zowel het oude als het nieuwe schema. Vergelijk de resultaten om te controleren of het nieuwe schema alles vastlegt wat het oude vastlegde, plus de nieuwe velden. Schakel het oude schema pas uit nadat parallelle validatie op een statistisch significante steekproef stabiele gelijkwaardigheid heeft aangetoond.
async def parallel_validate(text: str) -> dict:
v1_result, v2_result = await asyncio.gather(
extract_with_schema(text, InvoiceV1),
extract_with_schema(text, InvoiceV2)
)
discrepancy = (
v1_result.vendor != v2_result.vendor or
abs(v1_result.total_amount - v2_result.total_amount) > 0.01
)
if discrepancy:
log_discrepancy(text, v1_result, v2_result)
return {'v1': v1_result, 'v2': v2_result, 'discrepancy': discrepancy}Functievlaggen voor de uitrol van schema's
Gebruik functievlaggen om te bepalen wanneer je pijplijn overschakelt van het oude naar het nieuwe schema. Zo kun je het nieuwe schema geleidelijk naar een percentage van het verkeer uitrollen, foutpercentages bewaken en onmiddellijk terugdraaien als er iets misgaat — zonder code opnieuw te implementeren. Diensten voor functievlaggen zoals LaunchDarkly of een eenvoudige databaseregel werken allebei.
import os
def get_active_schema():
version = os.environ.get('EXTRACTION_SCHEMA_VERSION', '1.0')
schemas = {
'1.0': InvoiceV1,
'2.0': InvoiceV2,
}
return schemas.get(version, InvoiceV1)
async def extract_document(text: str):
SchemaClass = get_active_schema()
return await extract_with_schema(text, SchemaClass)Compatibiliteit voor gebruikers met unietypen
Downstreamgebruikers die geëxtraheerde gegevens lezen, moeten meerdere schema-versies goed kunnen verwerken. Gebruik in je code een onderscheiden unietype dat de juiste parserlogica selecteert op basis van het veld schema_version. Dit is robuuster dan voorwaardelijke if-else-ketens schrijven en eenvoudiger uit te breiden wanneer versie 3 verschijnt.
from pydantic import BaseModel
from typing import Union, Annotated
from typing import Literal
def parse_extraction(raw: dict) -> Union[InvoiceV1, InvoiceV2]:
version = raw.get('schema_version', '1.0')
if version == '1.0':
return InvoiceV1(**raw)
elif version == '2.0':
return InvoiceV2(**raw)
else:
raise ValueError(f'Unknown schema version: {version}')Schemawijzigingen testen vóór implementatie
Voer een nieuw schema vóór implementatie uit op je volledige regressietestset: een samengestelde verzameling representatieve documenten met bekende verwachte uitvoer. Vergelijk de F1-scores voor elk veld tussen het oude en nieuwe schema. Een achteruitgang in de F1-score van een veld betekent dat de nieuwe schemabeschrijving het model in verwarring heeft gebracht — verbeter de veldbeschrijving voordat je de wijziging uitbrengt.
def eval_schema_on_test_set(test_cases: list, SchemaClass) -> dict:
field_f1 = {}
for case in test_cases:
result = extract_with_schema(case['text'], SchemaClass)
for field in case['expected']:
expected = case['expected'][field]
actual = getattr(result, field, None)
# Update precision/recall counters
update_metrics(field_f1, field, expected, actual)
return {k: compute_f1(v) for k, v in field_f1.items()}Schema's uitfaseren
Zodra een schema-versie niet meer wordt gebruikt voor nieuwe extracties, kun je deze uitfaseren. Uitfaseren betekent: geen nieuwe records in die versie meer accepteren, oude records leesbaar houden en een einddatum plannen waarop oude records worden gemigreerd of gearchiveerd. Documenteer de uitfasering in een wijzigingslogboek, zodat alle gebruikers weten dat ze hun parsercode moeten bijwerken.
DEPRECATED_VERSIONS = {'1.0'}
SUNSET_DATE = '2026-09-01'
def warn_if_deprecated(version: str):
if version in DEPRECATED_VERSIONS:
import warnings
warnings.warn(
f'Schema version {version} is deprecated. '
f'It will be removed after {SUNSET_DATE}. '
'Migrate consumers to version 2.0.',
DeprecationWarning,
stacklevel=2
)Wijzigingslogboek en communicatie
Elke schemawijziging moet vergezeld gaan van een vermelding in het wijzigingslogboek waarin staat wat er is gewijzigd, waarom, hoe je migreert en wat de verwachte gevolgen zijn. Deel vermeldingen uit het wijzigingslogboek met alle teams die geëxtraheerde gegevens gebruiken voordat je de wijziging implementeert. Veel rampen bij schemamigraties ontstaan niet door technische fouten, maar doordat gebruikers niet waren geïnformeerd over een aanstaande wijziging.
# CHANGELOG.md entry format:
# ## Schema v2.0 (2026-07-01)
# ### Changes
# - ADDED: vendor_tax_id (Optional[str]) - VAT/EIN extracted from header
# - ADDED: currency (str, default='USD') - detected from symbol/code
# ### Migration
# Run: python scripts/migrate_v1_to_v2.py --batch-size=500
# ### Consumers
# - billing-service: update parse_extraction() to handle v2
# - audit-service: query now supports currency filterKorte controle
Test je begrip van schema-evolutie en achterwaartse compatibiliteit in extractiepijplijnen.
Samenvatting van de les
In deze les heb je geleerd dat schema-versiebeheer een versieaanduiding opslaat bij elk geëxtraheerd record, zodat je selectief kunt migreren, dat toevoegende wijzigingen veilig zijn terwijl het hernoemen of opnieuw typen van velden een zorgvuldige migratie vereist, en dat parallelle validatie je laat controleren of het nieuwe schema goed werkt voordat je het oude buiten gebruik stelt. Hierna meten we LLM-latentie met de metrieken TTFT en TPOT.
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 “Schema-evolutie en achterwaartse compatibiliteit” gratis?
Ja — de volledige tekst van “Schema-evolutie en achterwaartse compatibiliteit” 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 “Schema-evolutie en achterwaartse compatibiliteit”?
Beheer niet-compatibele schemawijzigingen in langlopende extractiepijplijnen door schema's te versieseren, historische extracties te migreren en tijdens overgangen parallel te valideren. 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 “Schema-evolutie en achterwaartse compatibiliteit”?
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
- Instructor: getypeerde extractie met Pydantic
- Omgaan met gedeeltelijke en ontbrekende gegevens
- Batchverwerking met async en wachtrijen
- Schema-evolutie en achterwaartse compatibiliteit