Evoluzione degli schemi e compatibilità con le versioni precedenti
Gestisca le modifiche incompatibili agli schemi nelle pipeline di estrazione di lunga durata versionando gli schemi, migrando le estrazioni storiche ed eseguendo la validazione in parallelo durante le transizioni.
Evoluzione degli schemi e compatibilità con le versioni precedenti è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Perché gli schemi cambiano nel tempo
Gli schemi di estrazione non sono statici. I requisiti aziendali cambiano, compaiono nuovi tipi di documenti e si scoprono campi che sarebbe stato opportuno acquisire fin dall'inizio. La modifica di uno schema in una pipeline attiva crea un problema di compatibilità con le versioni precedenti: i record estratti esistenti usano il vecchio schema, mentre i nuovi record usano quello nuovo. La gestione sicura di questa transizione è ciò che si intende per evoluzione dello schema.
Gestire le versioni degli schemi
Assegni un numero di versione a ogni schema e lo memorizzi insieme a ogni record estratto. Quando modifica lo schema, incrementi la versione. In questo modo può interrogare i record in base alla versione dello schema, eseguire migrazioni sui record precedenti e mantenere una logica di convalida separata per ogni versione. È sufficiente un semplice campo stringa schema_version in ogni modello di output.
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 defaultModifiche additive e modifiche incompatibili
Le modifiche additive sono sicure: aggiungere un campo Optional o un campo con un valore predefinito non interrompe il vecchio codice di estrazione né i vecchi record. Le modifiche incompatibili sono rischiose: rinominare un campo, cambiarne il tipo da string a int o rimuoverlo interromperà i consumer downstream. Preferisca sempre le modifiche additive. Quando una modifica incompatibile è inevitabile, crei una nuova versione principale dello schema ed esegua la migrazione in modo controllato.
# 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 dataMemorizzare la versione dello schema nel database
Includa la versione dello schema nella tabella dei risultati dell'estrazione, così saprà sempre quale versione ha prodotto ogni record. Una colonna jsonb che memorizza tutti i dati estratti, insieme a una colonna di testo schema_version, è un modello comune. Questo consente di scrivere query consapevoli della versione e di migrare selettivamente i record più vecchi durante le finestre di basso traffico.
-- 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;Scrivere script di migrazione
Scriva uno script di migrazione per ogni transizione tra versioni dello schema: lo script deve leggere i record precedenti, trasformarli nel nuovo formato e riscriverli con la nuova versione. Esegua le migrazioni in piccoli batch con transazioni, così un errore non lascerà il database in uno stato parzialmente migrato. Mantenga sempre disponibile il vecchio schema finché non avrà verificato il completamento della migrazione.
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']
)Convalida parallela durante le transizioni
Durante una migrazione dello schema, esegua una convalida parallela: esegua l'estrazione contemporaneamente con il vecchio e il nuovo schema su un campione di documenti in arrivo. Confronti i risultati per verificare che il nuovo schema acquisisca tutto ciò che acquisiva il vecchio, oltre ai nuovi campi. Dismetta il vecchio schema solo dopo che la convalida parallela avrà mostrato una parità stabile su un campione statisticamente significativo.
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}Usare i feature flag per il rilascio dello schema
Usi i feature flag per controllare quando la pipeline passa dal vecchio schema al nuovo. In questo modo può distribuire gradualmente il nuovo schema a una percentuale del traffico, monitorare i tassi di errore e ripristinare immediatamente la versione precedente se qualcosa va storto, senza ridistribuire il codice. Sono adatti sia servizi di feature flag come LaunchDarkly sia una semplice riga nel database.
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)Compatibilità dei consumer con i tipi union
I consumer downstream che leggono i dati estratti devono gestire correttamente più versioni dello schema. Usi una union discriminata nel codice del consumer, che selezioni la logica di analisi corretta in base al campo schema_version. Questa soluzione è più robusta della scrittura di catene condizionali if-else e più facile da estendere quando arriverà la versione 3.
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}')Testare le modifiche allo schema prima del deployment
Prima di distribuire un nuovo schema, lo esegua sull'intero set di test di regressione: una raccolta curata di documenti rappresentativi con output attesi noti. Confronti i punteggi F1 di ogni campo tra il vecchio e il nuovo schema. Una regressione dell'F1 per qualsiasi campo indica che la descrizione del nuovo schema ha confuso il modello: corregga la descrizione del campo prima del rilascio.
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()}Gestire la dismissione degli schemi
Quando una versione dello schema non viene più usata per le nuove estrazioni, può deprecarla. La dismissione significa: smettere di accettare nuovi record in quella versione, mantenere leggibili i record esistenti e pianificare una data di fine utilizzo entro la quale i vecchi record verranno migrati o archiviati. Documenti la dismissione in un changelog, così tutti i consumer sapranno di dover aggiornare il proprio codice di analisi.
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
)Changelog e comunicazione
Ogni modifica dello schema deve essere accompagnata da una voce nel changelog che descriva cosa è cambiato, perché, le istruzioni per la migrazione e l'impatto previsto. Condivida le voci del changelog con tutti i team che utilizzano i dati estratti prima di distribuire la modifica. Molti disastri nelle migrazioni degli schemi non sono causati da problemi tecnici, ma da consumer che non erano stati informati dell'imminente modifica.
# 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 filterVerifica rapida
Verifichi la propria comprensione dell'evoluzione degli schemi e della compatibilità con le versioni precedenti nelle pipeline di estrazione.
Riepilogo della lezione
In questa lezione ha imparato che il versioning degli schemi memorizza un identificatore di versione insieme a ogni record estratto, consentendo migrazioni selettive, che le modifiche additive sono sicure, mentre rinominare o modificare il tipo dei campi richiede una migrazione accurata, e che la convalida parallela consente di verificare il nuovo schema prima di dismettere quello precedente. Ora misureremo la latenza degli LLM con le metriche TTFT e TPOT.
Impara Python con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 30
- Lezioni
- 120
Domande Frequenti
La lezione «Evoluzione degli schemi e compatibilità con le versioni precedenti» è gratuita?
Sì — il testo completo di «Evoluzione degli schemi e compatibilità con le versioni precedenti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Evoluzione degli schemi e compatibilità con le versioni precedenti»?
Gestisca le modifiche incompatibili agli schemi nelle pipeline di estrazione di lunga durata versionando gli schemi, migrando le estrazioni storiche ed eseguendo la validazione in parallelo durante l… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Evoluzione degli schemi e compatibilità con le versioni precedenti»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Instructor: estrazione tipizzata con Pydantic
- Gestire dati parziali e mancanti
- Elaborazione batch con async e code
- Evoluzione degli schemi e compatibilità con le versioni precedenti