#ImpolyzerDataStudio© #AI #Text to SQL #ETL #RAG
POSTED BY GIULIANO PAGNINI, 24 GIU 2025
Dal RAG allo Schema-Guided SQL Generation: Evoluzione dei Sistemi per la Generazione Strutturata di Query e regole di import/export
Introduzione
I moderni sistemi di generazione di codice SQL stanno adottando tecniche avanzate di Intelligenza Artificiale per tradurre richieste in linguaggio naturale in query precise e ottimizzate. Tra questi, il Retrieval-Augmented Generation (RAG) è emerso come un approccio potente, combinando recupero di informazioni contestuali e generazione dinamica.
Tuttavia, in contesti specializzati come la generazione di query SQL per database strutturati (es. Firebird, PostgreSQL,Oracle,Interbase,ect), è possibile definire un’evoluzione più mirata del RAG: un Domain-constrained SQL generation framework (o alternativamente, Prompt-guided structured generation system).
Ma cosa distingue questo sistema da un RAG tradizionale? E perché è particolarmente efficace per l’interazione con database complessi?
1. RAG Classico vs. Schema-Guided SQL Generation
Retrieval-Augmented Generation (RAG)
Il RAG standard combina due fasi:
Retrieval: Recupera informazioni da una knowledge base esterna (es. documenti, articoli).
Generation: Genera una risposta basata sui dati recuperati e sul contesto della domanda.
Esempio:
Schema-Guided SQL Generation (SGSG)
Nel nostro caso, il sistema specializzato opera in modo più strutturato:
Retrieval vincolato: Invece di cercare in documenti generici, accede a uno schema di database predefinito (tabelle, campi, relazioni).
Generazione guidata da regole: Produce SQL seguendo vincoli precisi (sintassi del DBMS, assenza di alias non supportati, ecc.).
Mappatura semantica: Traduce termini naturali (es. "contribuente") in campi DB (es. H531UTENTI.IDUTENTE
).
Esempio:
2. Perché è Più di un Semplicistico RAG?
Mentre il RAG tradizionale è general-purpose, il nostro sistema introduce:
a) Vincoli di Dominio Forti
Schema-aware: Non cerca informazioni in modo aperto, ma naviga una struttura DB nota.
DBMS-specific: Rispetta i limiti del DB attivo (es. Firebird 3.0+)
b) Prompt Engineering Specializzato
c) Controllo Strutturato dell’Output
Non genera testo libero, ma solo SQL valido per lo schema fornito.
Evita allucinazioni (es. non inventa campi inesistenti).
3. Nomenclatura: Quale Termine Usare?
Ecco alcune definizioni alternative, con pro e contro:
Termine | Vantaggi | Svantaggi |
---|
Domain-constrained SQL generation framework | Precisa il dominio (SQL) e i vincoli. Ottimo per tecnici. | Un po’ lungo. |
Prompt-guided structured generation system | Enfatizza il ruolo del prompt. Più generale. | Non specifica il contesto SQL. |
Schema-Guided SQL Generator (SGSG) | Breve, tecnico, intuitivo. | Meno noto. |
La nostra scelta: Domain-constrained SQL generation framework cattura meglio la natura ibrida (IA + regole di dominio).
4. Caso d’Uso: Generazione di Query Complesse
Il sistema eccelle in scenari come:
Traduzione di richieste amministrative (es. "lista contribuenti morosi").
Adattamento a DB legacy (Firebird, Oracle,Interbase,SQLLite,ect) con sintassi specifiche.
Mantenimento della compliance: Query sempre allineate allo schema DB.
Esempio di output generato:
SELECT
U.IDUTENTE,
U.RAGIONE_SOCIALE,
SUM(R.IMPORTO) AS TOTALE_CANONE_2025
FROM
H531UTENTI U
JOIN
H531EREGISTRO2025 R ON U.IDUTENTE = R.IDUTENTE
WHERE
R.IDCODIFICA IN (SELECT COD FROM H531ECODIFICA2025 WHERE TIPOCOD = 1)
AND R.DATAINIZIO >= '2025-01-01'
AND R.DATAFINE <= '2025-12-31'
GROUP BY
U.IDUTENTE, U.RAGIONE_SOCIALE
Nel sistema che hai presentato, la chiave filters
non è inclusa tra quelle standard, ma può essere implementata in due modi, a seconda delle esigenze:
Uso Alternativo di semantic_mapping
per Filtri
Se per "filters" intendi condizioni SQL predefinite, queste possono essere inserite direttamente nel semantic_mapping
:
"semantic_mapping": {
"occupazione": "REGISTRO.IDCODIFICA IN (SELECT COD FROM {{dynamic_codifica}} WHERE TIPOCOD = 1)",
"attivo": "STATO = 'ATTIVO'"
},
"placeholders": {
"dynamic_codifica": "[[COMUNE]]CODIFICA{{ANNO}}",
},
Esempio di utilizzo:
Se la domanda è "mostra i contribuenti attivi", il sistema tradurrà "attivo"
nella condizione SQL associata.
La Chiave Custom filters
Per filtri complessi, si può estender lo schema JSON:
{
"filters": {
"filtro_occupazione": "TIPOCOD = 1 AND DATAFINE >= CURRENT_DATE",
"filtro_moroso": "PAGATO = 0 AND SCADENZA < CURRENT_DATE"
}
}
Vantaggi:
Differenza tra filters
e constraints
Esempio Completo con filters
Personalizzata
{
"question": "totale canoni occupazione non pagati nel 2025",
"constraints": ["NO alias", "Usa sintassi Firebird 3.0+"],
"tables": { ... },
"semantic_mapping": {
"canone": "REGISTRO.IMPORTO",
"occupazione": "[[FILTRO_OCCUPAZIONE]]"
},
"filters": {
"FILTRO_OCCUPAZIONE": "IDCODIFICA IN (SELECT COD FROM H531ECODIFICA2025 WHERE TIPOCOD = 1)",
"FILTRO_NON_PAGATO": "ID NOT IN (SELECT IDPAGAMENTO FROM PAGAMENTI)"
}
}
SQL Generato:
SELECT SUM(IMPORTO)
FROM H531EREGISTRO2025
WHERE IDCODIFICA IN (SELECT COD FROM H531ECODIFICA2025 WHERE TIPOCOD = 1)
AND ID NOT IN (SELECT IDPAGAMENTO FROM PAGAMENTI)
Se vuoi standardizzare il sistema
Approccio Conservativo: Usa solo semantic_mapping
per i filtri (come nell'esempio iniziale).
Approccio Esteso: Aggiungi filters
come chiave opzionale per condizioni riutilizzabili.
Raccomandazione: Se lavori in un contesto con molti filtri ricorrenti (es. "moroso", "storico", "in scadenza"), la chiave filters
migliora la manutenibilità.
Conclusioni: ImpolyzerDataStudio verso Sistemi Ibridi AI + Rules
Questo framework rappresenta un ponte tra NLP e database strutturati, superando i limiti del RAG generico:
Maggiore accuratezza: Niente allucinazioni su schemi DB.
Mantenibilità: Aggiornando lo schema, si aggiorna il generatore.
Adattabilità: Può essere esteso a altri DBMS (tutti i DB Firedac e CDATA,CSV, Access, Excel,memTable,ect).