Evolución de esquemas y compatibilidad con versiones anteriores
Gestione cambios incompatibles en esquemas dentro de pipelines de extracción de larga duración mediante el versionado de esquemas, la migración de extracciones históricas y la validación en paralelo durante las transiciones.
Evolución de esquemas y compatibilidad con versiones anteriores es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.
Por qué cambian los esquemas con el tiempo
Los esquemas de extracción no son estáticos. Los requisitos empresariales evolucionan, aparecen nuevos tipos de documentos y usted descubre campos que debería haber capturado desde el principio. Cambiar un esquema en una canalización activa crea un problema de compatibilidad con versiones anteriores: los registros extraídos existentes usan el esquema antiguo, mientras que los nuevos usan el esquema nuevo. Gestionar esta transición de forma segura es en lo que consiste la evolución de esquemas.
Control de versiones de los esquemas
Asigne un número de versión a cada esquema y guárdelo junto a cada registro extraído. Cuando cambie el esquema, incremente la versión. Esto le permite consultar registros por versión del esquema, ejecutar migraciones en registros antiguos y mantener una lógica de validación independiente para cada versión. Un simple campo de cadena schema_version en cada modelo de salida es suficiente.
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 defaultCambios aditivos frente a cambios incompatibles
Los cambios aditivos son seguros: añadir un campo Optional o un campo con un valor predeterminado no rompe el código de extracción antiguo ni los registros existentes. Los cambios incompatibles son arriesgados: cambiar el nombre de un campo, cambiar su tipo de string a int o eliminarlo romperá los consumidores posteriores. Prefiera siempre los cambios aditivos. Cuando no se pueda evitar un cambio incompatible, cree una nueva versión principal del esquema y realice la migración de forma controlada.
# 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 dataAlmacenamiento de la versión del esquema en la base de datos
Incluya la versión del esquema en la tabla de resultados de extracción para saber siempre qué versión produjo cada registro. Una columna jsonb que almacene todos los datos extraídos, junto con una columna de texto schema_version, es un patrón habitual. Esto le permite escribir consultas que tengan en cuenta la versión y migrar de forma selectiva los registros antiguos durante periodos de poco tráfico.
-- 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;Escritura de scripts de migración
Escriba un script de migración para cada transición entre versiones del esquema. El script debe leer los registros antiguos, transformarlos al formato nuevo y volver a escribirlos con la nueva versión. Ejecute las migraciones en lotes pequeños y dentro de transacciones para que un fallo no deje la base de datos en un estado parcialmente migrado. Mantenga siempre disponible el esquema antiguo hasta verificar que la migración se ha completado.
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']
)Validación paralela durante las transiciones
Durante una migración de esquema, realice una validación paralela: extraiga datos con el esquema antiguo y el nuevo simultáneamente para una muestra de los documentos entrantes. Compare los resultados para verificar que el esquema nuevo captura todo lo que capturaba el antiguo, además de los campos nuevos. Retire el esquema antiguo únicamente después de que la validación paralela muestre una paridad estable en una muestra estadísticamente significativa.
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}Indicadores de funcionalidades para el despliegue del esquema
Use indicadores de funcionalidades para controlar cuándo su canalización cambia del esquema antiguo al nuevo. Esto le permite desplegar gradualmente el esquema nuevo para un porcentaje del tráfico, supervisar las tasas de error y revertirlo al instante si algo sale mal, sin volver a desplegar el código. Funcionan tanto servicios de indicadores como LaunchDarkly como una simple fila en la base de datos.
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)Compatibilidad de los consumidores con tipos unión
Los consumidores posteriores que leen datos extraídos deben gestionar correctamente varias versiones del esquema. Use una unión discriminada en el código del consumidor que seleccione la lógica de análisis adecuada basándose en el campo schema_version. Esto es más sólido que escribir cadenas condicionales de if-else y resulta más fácil de ampliar cuando llegue la versión 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}')Prueba de los cambios de esquema antes del despliegue
Antes de desplegar un esquema nuevo, ejecútelo con todo su conjunto de pruebas de regresión: una colección seleccionada de documentos representativos con resultados esperados conocidos. Compare las puntuaciones F1 de cada campo entre el esquema antiguo y el nuevo. Una regresión en la puntuación F1 de cualquier campo significa que la descripción del esquema nuevo confundió al modelo; corrija la descripción del campo antes de ponerlo en producción.
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()}Gestión de la obsolescencia de esquemas
Cuando una versión del esquema deje de utilizarse para nuevas extracciones, puede marcarla como obsoleta. La obsolescencia significa dejar de aceptar registros nuevos en esa versión, mantener los registros antiguos legibles y programar una fecha de retirada en la que los registros antiguos se migrarán o archivarán. Documente la obsolescencia en un registro de cambios para que todos los consumidores sepan que deben actualizar su código de análisis.
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
)Registro de cambios y comunicación
Cada cambio de esquema debe ir acompañado de una entrada en el registro de cambios que describa qué ha cambiado, por qué, las instrucciones de migración y el impacto previsto. Comparta las entradas del registro de cambios con todos los equipos que consumen datos extraídos antes de desplegar el cambio. Muchos desastres de migración de esquemas no se deben a fallos técnicos, sino a que los consumidores no fueron informados de que se acercaba un cambio.
# 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 filterComprobación rápida
Compruebe su comprensión de la evolución de esquemas y la compatibilidad con versiones anteriores en las canalizaciones de extracción.
Resumen de la lección
En esta lección ha aprendido que el control de versiones de esquemas almacena un identificador de versión junto a cada registro extraído para poder migrarlos de forma selectiva; los cambios aditivos son seguros, mientras que cambiar el nombre o el tipo de los campos requiere una migración cuidadosa; y la validación paralela permite verificar el esquema nuevo antes de retirar el antiguo. A continuación, mediremos la latencia de los LLM con las métricas TTFT y TPOT.
Preguntas frecuentes
¿La lección «Evolución de esquemas y compatibilidad con versiones anteriores» es gratis?
Sí — el texto completo de «Evolución de esquemas y compatibilidad con versiones anteriores» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Evolución de esquemas y compatibilidad con versiones anteriores»?
Gestione cambios incompatibles en esquemas dentro de pipelines de extracción de larga duración mediante el versionado de esquemas, la migración de extracciones históricas y la validación en paralelo… Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Engineering Academy?
No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Evolución de esquemas y compatibilidad con versiones anteriores»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?
Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Instructor: extracción tipada con Pydantic
- Gestión de datos parciales y ausentes
- Procesamiento por lotes con asincronía y colas
- Evolución de esquemas y compatibilidad con versiones anteriores