Oracle e' il piu' noto e diffuso database relazionale commerciale.
L'Oracle AI Vector Search, introdotta nelle ultime versioni,
e' progettata per l'Artificial Intelligence (AI)
e consente di interrogare i dati con ricerche basate sulla semantica
oltre che con chiavi e valori come avviene su una base dati relazionale.
In questa paginetta proveremo, con esempi pratici e sfruttando
solo componenti gratuiti e/o Open Source, alcune delle funzionalita' avanzate AI
di Oracle AI Database 26ai
che utilizzano gli LLMs (Large Language Models).
Per presentare in modo interessante le funzioni presenti proveremo ad
eseguire un percorso che ci portera' dalla configurazione inziale
alla creazione di tutti i componenti che servono ad un semplice RAG (Retrieval Augmented Generation).
Per ragioni di spazio gli argomenti sono presentati in modo sintetico e
per un pubblico adulto ovvero sufficientemente preparato dal punto di vista tecnico
sul database Oracle.
Gli argomenti sono raccolti
nei seguenti capitoli:
Prerequisiti,
Interrogare un LLM,
Ottenere gli embedding,
Creare la base dati,
Ricerche semantiche,
RAG,
...
Varie ed Eventuali,
Quanta memoria ho? Poca, dimentico sempre tutto... ma per queste prove consiglio almeno 16GB: Oracle 26ai Free non puo' utilizzare piu' di 2GB di RAM, ma gli servono tutti ed un paio di GB in piu' al OS vanno lasciati; i modelli che che utilizzeremo sono 7b o 8b... insomma 16MB sono fortemente consigliati. Poi se di dispone di computer potente e sopratutto di una GPU con molta memoria i tempi di risposta saranno migliori. Ma per provare basta questo.
Sceglieremo strumenti ed ambienti che possiamo installare gratuitamente e localmente sul nostro PC Windows/Linux/Mac [NdA in effetti i Mac, grazie all'UMA (Unified Memory Architecture), presentano qualche vantaggio ma con l'hardware adeguato o con molta pazienza si possono ottenere comunque risultati utili]. Abbiamo bisogno di un'installazione Oracle con la versione piu' recente che possa accedere ad un moderno LLM (Large Language Model). Vediamo i dettagli e seguite i link se non conoscete gli oggetti.
Per ospitare gli LLM utilizzeremo Ollama
che installeremo localmente con HomeBrew
[NdA poiche' credo nell'evoluzione e quindi utilizzo Darwin].
Per le prove si possono scaricare innumerevoli modelli differenti,
nel seguito useremo llama3.1:8b, mistral:7b e qllama/bge-large-en-v1.5.
Per Oracle utilizziamo la piu' recente Oracle AI Database 26ai disponibile Free;
tra le diverse modalita' di installazione utilizzeremo un container:
Docker o Podman praticamente non hanno differenze perche' utilizzano gli stessi comandi.
Non possiamo utilizzare la versione lite di Oracle e quindi il dowload richiedera' un po' di tempo
[NdA quasi 10GB],
inoltre per utilizzare gli indici vector i memoria dobbiamo modificare la configurazione.
Parole, parole, parole, ... passiamo ai fatti!
Abbiamo installato un LLM locale ed un database Oracle. Riusciremo a farli comunicare?
Oracle 26ai puo' richiamare gli LLM locali o di terze parti utilizzando gli opportuni package.
Per caso di prova che abbiamo scelto useremo Mistral un LLM francese perche' e' noto che sono appassionati di vela oceanica. Dovendo raggiungere un servizio installato sul nostro PC da un container faremo riferimento ad un hostname riservato: host.docker.internal. L'accesso all'LLM verra' effettuato con una query SQL lanciata da linea di comando che richiamera' la funzione utl_to_generate_text del package dbms_vector.
Naturalmente e' possibile chiedere qualsiasi cosa... Dall'esempio e' chiaro che riusciamo ad interrogare un LLM con una SELECT, che l'LLM capisce la nostra domanda, ci risponde in italiano in modo coerente anche se, come un appassionato di vela potrebbe notare, con qualche allucinazione. In effetti se provassimo a chiedere chi ha vinto la regata nel 2019 o un pronostico su chi potrebbe vincere nel 2025 l'LLM darebbe una risposta ancora piu' imprecisa: risponderebbe in modo verosimile ma inventando gran parte del testo! Stiamo interrogando in locale un modello di dimensioni ridotte: non puo' sapere tutto. Ed anche i modelli di dimensioni maggiori vengono aggiornati solo periodicamente e possono ottenere informazioni solo da quanto pubblicato su internet o comunque utilizzato nel training.
Sicuramente potremmo abbassare la temperatura per ridurre le allucinazioni [NdA e' il modo tecnicamente corretto] ma non otterremmo comunque una risposta precisa ed aggiornata. Per farlo dobbiamo fornire piu' informazioni al modello... i database sono adatti proprio a gestire le informazioni ma ci servono gli emebedding.
Per fornire all'LLM la conoscenza aggiuntiva sugli argomenti che ci interessano
servono due cose: le informazioni e gli embedding.
Sulle base dati e' normale avere le informazioni, sono fatte per gestire grandi quantita' di dati!
La novita' sono gli embeddings...
Ci sono molti modi di porre una domanda: chi ha vinto la regata nel 2019?
come e' andata sei anni fa? mi interessano i risultati del ...
come facciamo ad associare queste domande alle informazioni?
Potremmo farlo comprendendo il significato della domanda
e confrontandolo con il significato dei documenti, ma e' possibile?
E' possibile con gli embedding che catturano il significato di
una frase, di un testo o di un documento in una rappresentazione
numerica multidimensionale. Confrontando gli embedding tra loro
i piu' vicini avranno significati simili.
Parole, parole, parole, ... passiamo ai fatti!
Usiamo la funzione utl_to_embedding del package dbms_vector
richiamando un modello adatto;
abbiamo scelto bge-large-en-v1.5 che e' un
embedding model che trasforma il testo in una rappresentazione
semantica densa e ne cattura il significato.
Anche la generazione degli embedding, cosi' come interrogare un LLM, e' molto semplice da SQL o PL/SQL con Oracle 26ai.
Ora che possiamo estrarre il significato della domanda dobbiamo catalogare la nostra conoscenza nel database Oracle ed utilizzeremo i VECTOR.
Oracle 26ai dispone di un nuovo datatype VECTOR che e' stato creato appositamente per memorizzare gli embedding e per eseguire ricerche efficienti su di essi. Utilizzando i VECTOR possiamo memorizzare gli embedding sulla base dati: in questo capitolo creiamo le tabelle e gli indici necessari alle ricerche RAG.
I contenuti della knowledge base sono molto importanti e le origini dei dati possono essere differenti. Nel nostro esempio partiamo da file in formato markdown di modeste dimensioni. E' una scelta tattica usata molto spesso perche' il formato markdown e' facilmente leggibile dagli umani e trattabile direttamente come testo. Una volta caricati i dati possimo utilizzare la funzione utl_to_embedding per aggiornare la colonna che contiene l'embedding:
Abbiamo creato una tabella e l'abbiamo popolata ora possiamo interrogarla... continuate a leggere!
L'aspetto importante e' che le ricerche semantiche non sono svolte confrontando il testo o parole chiave ma comprendendo il significato della richiesta utente, confrontandolo con quello dei documenti presenti nella base dati e scegliendo quelli piu' vicini [NdA KNN: algoritmo k-nearest neighbors che e' un classificatore di apprendimento supervisionato non parametrico utilizzato sia per la classificazione che per la regressione... in parole povere: i risultati piu' vicini].
Oracle consente ricerche semantiche utilizzando la funzione VECTOR_DISTANCE
applicata su dati di tipo VECTOR.
Per estrarre i 5 documenti piu' simili alla richiesta dell'utente:
Per estrarre i 10 documenti con argomento simile e con i tag previsti ordinati per priorita' e per similarita':
Dovrebbe essere chiaro che le possibilita' di interrogazione sono molteplici e dipendono dalle esigenze progettuali...
In una tipica implementazione di un RAG (Retrieval Augmented Generation)
la base dati viene utilizzata solo per effettuare le ricerche semantiche
per estrarre i testi da aggiungere al prompt inviato all'LLM e ottenere
cosi' risposte che tengono conto di una conoscenza arricchita dal contesto.
Il linguaggio di programmazione piu' utilizzato e' il Python,
le basi dati utilizzate sono quelle che supportano i vettori
e le ricerche per prossimita'.
Oracle 26ai supporta il datatype VECTOR e puo' eseguire ricerche semantiche,
quindi puo' essere utilizzato in questo tipo di architetture.
Ma nei capitoli precedenti abbiamo visto che Oracle puo' fare molto di piu'
perche' da SQL e' possibile calcolare l'embedding della richiesta
utente e richiamare un LLM esterno.
L'intera catena di elaborazione puo' essere realizzata in PL/SQL:
Con un RAG in pratica anziche' interrogare un LLM in modo generico, prima ricerchiamo in una base dati interna quali ulteriori informazioni possono essere fornite e quindi le utilizziamo per aumentare il contesto della richiesta. La ricerca sulla base dati si puo' eseguire con normali condizioni ma anche, e questa e' la parte innovativa, per significato. Per fare questo ogni documento viene valutato ottenendo un vettore che ne descrive il significato: l'embedding. Quindi la ricerca avviene con una normale query SQL che confronta la richiesta iniziale con gli embedding dei documenti disponibili.
Il primo passo e' stato quello di definire la tabella sail_kb
che contiene i documenti utili ad arricchire la conoscenza
di un LLM generico.
Oracle 26ai supporta il datatype vector che puo' essere utilizzato
per memorizzare gli embedding.
La base dati va quindi caricata con le informazioni della RAG
e per ciascun documento deve essere catturato il significato,
che praticamente si traduce nella valorizzazione del vettore di embedding.
La scelta dei documenti, la loro trasformazione in testo,
la separazione in chunk, la generazione degli embedding e la memorizzazione sulla base dati
sono ovviamente molto importanti... ma li consideriamo tecnicismi!
Il risultato ottenuto dalle query viene poi inserito nel contesto
ed inviato all'LLM per ottenere la risposta finale.
Tipicamente l'LLM e' esterno e vieni richiamato su OCI o su Cloud,
nel nostro esempio abbiamo utilizzato Ollama che viene richiamato
come se fosse un servizio esterno.
Ho cercato di rendere pratica e sintetica questa paginetta,
in realta' ci sono parecchi ulteriori dettagli da presentare.
Perche' non l'hai detto subito? Perche' era troppo noioso!
Ma se avete avuto la pazienza di leggere fino a qui ora potete sorbirvi tutti i dettagli che non sono stati descritti in precedenza.
Gli embedding consentono di rappresentare il significato di un testo o di un immagine. La teoria su cui si appoggiano gli LLM, i concetti di distanza, ... tutti argomenti interessanti ed importanti che non abbiamo presentato.
Sono fondamentali i concetti di token, chunk, context, ...
negli esempi abbiamo utilizzato richieste che non raggiungevano i limiti di contesto
e non richiedevano di dividere in chunk i testi ma e' importante conoscerli nei progetti reali.
Altrettanto importanti dal punto di vista pratico sono altri dettagli tecnici
come la scelta tra le diversi dimensioni di un modello, la temperatura, la quantizzazione, ...
Non li abbiamo descritti in dettaglio ma tutti questi elementi sono presenti anche
nell'implementazione di Oracle.
E' possibile caricare nella base dati Oracle i modelli LLM, se disponibili in formato ONNX, e far eseguire dalla base dati stessa i modelli. Ma nella maggior parte dei casi si preferisce accedere a servizi esterni che e' possibile richiamare direttamente dal PL/SQL. Sono supportati i principali fornitori di servizi: OpenAI, Anthropic, Cohere, Mistral AI, Google AI e, naturalmente, Oracle Cloud Infrastructure Generative AI. Il richiamo avviene attraverso una chiamata REST sulla terza parte remota (eg. Google AI, Hugging Face, OpenAI, Vertex AI) o locale (Ollama).
Il datatype VECTOR consente di memorizzare gli embedding in Oracle. Oracle, dalla versione 26ai, fornisce funzioni ed indici specifici per ottimizzare le ricerche sui VECTOR e costruire catene dal dato grezzo fino all'informazione finale. L'indicazione della versione e' volutamente imprecisa perche' non e' semplice individuare il momento in cui e' stata raggiunta la maturita' necessaria per un uso concreto delle funzionalita' di AI.
I package
DBMS_VECTOR, DBMS_VECTOR_CHAIN, DBMS_HYBRID_VECTOR
forniscono le funzionalita' per trattare i dati semantici in Oracle.
ONNX! Chi era costui?
ONNX (Open Neural Network Exchange) e' un formato con cui vengono memorizzati i pesi delle reti neurali
degli LLM.
Non e' l'unico formato disponibile e quindi puo' essere utile questa tabella che riporta
i piu' diffusi:
DBMS_VECTOR (cfr. documentazione ufficiale)
fornisce le funzioni di base
DBMS_VECTOR_CHAIN (cfr. documentazione ufficiale)
fornisce le funzioni avanzate
DBMS_HYBRID_VECTOR (cfr. documentazione ufficiale)
fornisce le funzioni per gestire
ONNX
| Modello | Utilizzo | Note |
|---|---|---|
| Safetensors | Training, PyTorch, MLX | Sicuro, veloce da caricare, contiene pesi "puri" da caricare in RAM senza modifiche (Zero-Copy). Creato da Hugging Face per sostituire i vecchi file .bin (Pickle) che erano potenzialmente pericolosi... |
| GGUF GPT-Generated Unified Format | Ollama, llama.cpp | Lossy, orientato alla quantizzazione che e' molto flessibile (eg. Q4_K_M). Tutto-in-uno, perfetto per CPU/GPU consumer. |
| ONNX Open Neural Network Exchange | Produzione, Mobile, Edge | Rivolto all'interoperabilita'. Sviluppato inizialmente da Microsoft. Contiene anche la logica (grafo), non solo i pesi. Puo' essere Loseness ma generalmente usa INT8 o FP16. |
Esistono molti altri modelli (eg. NVIDIA TensorRT), formati (eg. AWQ: Activation-aware Weight Quantization) e la quantizzazione puo' essere molto spinta:
| Formato | Bit | Note |
|---|---|---|
| FP32 | 32 | Massimo dettaglio. Usato principalmente per il training. |
| FP16 / BF16 | 16 | Standard per l'addestramento moderno e l'inferenza ad alta fedelta'. |
| INT8 | 8 | Primo step di compressione massiccia. Perdita di precisione generalmente impercettibile. |
| Q4_K_M | ~4.5 | Ottimo equilibrio tra memoria e intelligenza. E' il default su GGUF/Ollama. |
| NF4 (Normal Float) | 4 | Formato speciale che usa una distribuzione normale per mappare i pesi. Molto efficace nei modelli Llama. |
| IQ2 / EXL2 | 2 | Estremo. Il modello inizia a "farneticare" o perdere coerenza logica complessa (Perplexity). |
| Ternario | 1.58 | Utilizza i valori: -1, 0, 1. Il calcolo non richiede moltiplicazioni, ma solo addizioni. Adatto solo a casi particolari ma velocissimo. |
Ma direi che e' sufficiente!
Per accedere ad Oracle ho impostato una password banale
ed ho utilizzato un utenza amministrativa.
Ovviamente non va fatto cosi' ma e' un dettaglio.
Non ho utilizzato un volume per ospitare il database,
in questo modo i dati non persistono.
Le installazioni con Oracle 26ai sono sempre multitenant.
Negli esempi abbiamo utilizzato il CDB ma e' buona norma utilizzare un PDB.
Il linguaggio piu' utilizzato nell'AI e' il Python in questa pagina abbiamo utilizzato solo SQL e PL/SQL. E' ovviamente possibile utilizzare Oracle ed il suo SQL da Python.
Sono i limiti sul numero di token, la separazione del testo in chunck, la dimensione massima del contesto negli esempi abbiamo usati sono stati aggirati con alcune scelte tattiche. Le funzioni Oracle consentono il controllo e la gestione di questi aspetti che sono fondamentali per la robustezza del sistema.
Sicuramente e' interessante il confronto delle funzionalita' vettoriali di
Oracle 26ai rispetto all'extension pgvector
di PostgreSQL che era disponibile gia' dal 2021.
Le differenze sono molte perche' PostgreSQL oltre alle funzioni
fornisce operatori per i confronti di distanza,
quindi le query SQL risultano diverse anche se i concetti di base sono gli stessi.
Inoltre PostgreSQL non prevede richiami diretti o integrazioni con gli LLM.
Titolo: Oracle Database 26ai - Utilizzo funzionalita' AI
Livello: Avanzato
Data:
31 Ottobre 2024 🎃
Versione: 1.1.0 - 31 Ottobre 2025 🎃
Autore: mail [AT] meo.bogliolo.name