Skip to main content

Progettare un flusso ETL RAG economico su AWS

Di Thomas Vignoli·Pubblicato il 15 settembre 2024

I sistemi RAG in produzione richiedono ETL affidabili e osservabili. Dopo aver implementato pipeline per gruppi bancari, aziende sanitarie ed e-commerce che processano milioni di documenti mensilmente, ho distillato i pattern che garantiscono comportamento deterministico sotto carichi imprevedibili mantenendo costi prevedibili.

Architettura di Riferimento & Contratti Dati

Iniziamo con regole Amazon EventBridge che rispondono a nuovi oggetti in S3 o eventi webhook da sistemi di ticketing. Ogni evento attiva una Lambda che valida il payload contro uno schema JSON memorizzato in AWS Glue Data Catalog. Contratti rigorosi prevengono documenti malformati che intaserebbero lo stream. Quando il payload è valido, Step Functions orchestra una pipeline multi-stage: estrazione, arricchimento, embedding e caricamento.

Il layer di validazione è critico. Ho visto pipeline fallire perché un singolo PDF malformato corrompeva l'intero batch. La nostra Lambda di validazione controlla struttura del documento, limiti di dimensione file (capiamo a 50MB per documento), tipi MIME e campi metadati richiesti. Payload non validi vengono immediatamente instradati a una dead-letter queue con contesto di errore dettagliato, permettendo ai team operativi di fare triage senza scavare nei log CloudWatch.

import json
import boto3
from jsonschema import validate, ValidationError
from typing import Dict, Any

s3 = boto3.client('s3')
glue = boto3.client('glue')

def validate_payload(event: Dict[str, Any]) -> Dict[str, Any]:
    """Valida il payload del documento contro lo schema Glue."""
    schema = glue.get_schema(
        SchemaId={'SchemaName': 'rag-document-schema', 'RegistryName': 'rag-registry'}
    )
    
    try:
        validate(instance=event, schema=json.loads(schema['SchemaDefinition']))
        
        # Regole di business aggiuntive
        if event['fileSize'] > 50 * 1024 * 1024:  # Limite 50MB
            raise ValueError(f"Dimensione file {event['fileSize']} supera il limite di 50MB")
        
        if event['mimeType'] not in ['application/pdf', 'text/plain', 'text/markdown']:
            raise ValueError(f"Tipo MIME non supportato: {event['mimeType']}")
        
        return {'valid': True, 'payload': event}
    except ValidationError as e:
        return {'valid': False, 'error': str(e), 'payload': event}

Strategia di Processing & Embedding

Documenti ricchi di contenuto passano attraverso Textract (estrazione tabelle) e modelli multimodali Bedrock Titan per rapida summarizzazione. La normalizzazione linguistica avviene in Amazon Comprehend. Gli embedding si affidano a un SageMaker Serverless Endpoint con warm pool auto-scaling, evitando picchi di cold-start durante le ore lavorative.

La strategia di embedding conta enormemente per costi e qualità. Usiamo chunking con overlap (tipicamente 200 token con overlap di 50 token) per preservare contesto tra i confini. Per documenti strutturati come PDF con tabelle, estraiamo le tabelle separatamente e le embediamo come chunk distinti, preservando integrità referenziale attraverso link nei metadati.

Casi d'Uso Reali & Lezioni di Produzione

Caso studio #1: Una fintech europea aggrega 200k PDF di disclosure giornalieri attraverso multiple giurisdizioni regolatorie. La sfida: requisiti di data residency significavano che documenti da clienti EU non potevano lasciare l'EU, ma serviva un'esperienza di ricerca unificata. Soluzione: Abbiamo diviso il carico di lavoro su tre regioni (eu-west-1, eu-central-1, eu-north-1) usando bucket S3 regionali, ma centralizzato la collezione OpenSearch Serverless in eu-west-1 usando replicazione cross-region. I job Glue scrivono artefatti Parquet + Snappy su S3, e manteniamo finestre rolling di 30 giorni in hot storage mentre archiviamo embedding più vecchi su Glacier Instant Retrieval. Risultato: 41% di risparmio storage ($2,300/mese di riduzione) e latenza di ricerca conforme SLA sotto 200ms p95.

L'insight chiave qui è stato usare lo stato Map di Step Functions per parallelizzare il processing regionale mantenendo una singola fonte di verità. Ogni branch regionale processa documenti indipendentemente, ma tutti scrivono nella stessa collezione OpenSearch attraverso VPC endpoints, garantendo bassa latenza rispettando i confini di compliance.

Controlli Costi, Scaling e Osservabilità

Due regole mantengono le bollette prevedibili: micro-batching (max 5 minuti di payload per run) e tagging aggressivo. Ogni risorsa porta tag `env`, `rag-etl`, `customer` e `cost-center` così AWS Cost Explorer può fare pivot per feature. La reserved concurrency di Lambda protegge da stampede causate da webhook di terze parti. Per il vector store, iniziate con OpenSearch Serverless (2 OCU baseline) e migrate ad Aurora PostgreSQL + pgvector quando servono join relazionali o isolamento tenant.

L'ottimizzazione dei costi è una disciplina continua. Usiamo AWS Cost Anomaly Detection per alertare quando la spesa giornaliera supera il baseline del 20%. Ogni funzione Lambda ha alarm CloudWatch per durata e uso memoria, e regolarmente right-size basandoci su metriche reali. Per workload ad alto volume, considerate provisioned concurrency per funzioni Lambda critiche (a $0.015 per GB-secondo) per eliminare cold start, ma solo dopo che il profiling mostra che i cold start impattano effettivamente l'SLA.

Pattern Avanzati: Multi-Tenancy & Sicurezza

Per provider SaaS che servono multiple clienti, l'isolamento tenant è non negoziabile. Implementiamo row-level security in OpenSearch usando document-level access control (DLAC) o instradiamo ogni tenant a un indice separato. L'approccio latter scala meglio ma richiede automazione di gestione indici. Per industrie compliance-heavy (sanità, finanza), aggiungiamo encryption at rest usando KMS customer-managed keys e abilitiamo VPC endpoints per assicurare che il traffico non lasci mai la rete AWS.

Best practice di sicurezza includono: (1) ruoli IAM con accesso least-privilege, (2) Secrets Manager per API keys e credenziali database, (3) VPC endpoints per tutte le chiamate servizio AWS per evitare egress internet, (4) logging CloudTrail per tutte le chiamate API, e (5) audit di sicurezza regolari usando AWS Security Hub. Implementiamo anche scanning data loss prevention (DLP) usando Amazon Macie per rilevare dati sensibili prima dell'indicizzazione.

Performance Tuning & Monitoring

Pipeline RAG di produzione richiedono tuning accurato delle performance. Metriche chiave da monitorare: (1) latenza end-to-end (target: <5 minuti per documento 10MB), (2) tasso generazione embedding (target: >100 documenti/minuto), (3) throughput indicizzazione OpenSearch (target: >1000 docs/secondo), e (4) tasso errore (target: <0.1%). Usiamo dashboard CloudWatch con alarm automatizzati che triggerano alert PagerDuty quando le soglie sono violate.

Colli di bottiglia comuni: (1) processing Textract per PDF grandi (mitigare con processing async e notifiche eventi S3), (2) cold start endpoint SageMaker (mitigare con provisioned concurrency o script warm-up), (3) colli di bottiglia indicizzazione OpenSearch (mitigare con bulk API e strategia sharding appropriata), e (4) limiti memoria Lambda (right-size basandosi su query CloudWatch Insights che mostrano uso memoria effettivo).

© 2026 Thomas Vignoli. Tutti i diritti riservati.