Tutorial Oracle AI Vector Search: archivia e interroga embedding con Python
Questo tutorial introduce Oracle AI Vector Search, ne spiega le funzionalità principali e guida un progetto pratico locale. Copre anche i requisiti di setup, la ricerca semantica, l’indicizzazione vettoriale e i passaggi di troubleshooting più comuni.
In questo tutorial, costruiremo una demo locale di ricerca semantica con Oracle AI Vector Search, Python e Oracle Database Free 26ai.
Partiremo con vettori tridimensionali scritti a mano per rendere visibile il calcolo della distanza, poi genereremo embedding testuali e li interrogheremo da Oracle Database con SQL.
Questo tutorial è per sviluppatori Python e SQL nuovi alla vector search e a proprio agio con Docker, variabili d'ambiente, pacchetti Python e setup di database locali.
Le applicazioni basate sull'AI hanno bisogno di una ricerca che capisca il significato, non solo le parole esatte. Un'app di supporto, un portale di documentazione o uno strumento di knowledge interno dovrebbero saper trovare “archiviazione database per ricerca AI” anche quando il documento migliore dice “archivia embedding vettoriali in colonne native”.
I vettori embedding rendono tutto ciò possibile rappresentando il testo come vettori numerici. Oracle AI Vector Search ci permette di archiviare questi vettori direttamente in Oracle Database, interrogarli con SQL e tenere gli embedding accanto ai dati applicativi relazionali.
Per questo flusso di lavoro locale, non serve un database vettoriale separato.
Eseguiremo Oracle Database Free 26ai in locale, ci connetteremo da Python con la modalità Thin di oracledb, archivieremo prima i vettori manuali, poi gli embedding OpenAI, eseguiremo la ricerca semantica, confronteremo il recupero semantico con un semplice predicato di frase esatta e creeremo un indice vettoriale validato tramite USER_INDEXES.
Alla fine, avremo un flusso di lavoro di ricerca semantica in Python funzionante che archivia gli embedding in Oracle Database e recupera i documents più simili in locale.
Che cos'è Oracle AI Vector Search?
Oracle AI Vector Search è un insieme di funzionalità di Oracle Database per archiviare, indicizzare e interrogare embedding vettoriali. Un embedding vettoriale è un elenco a dimensione fissa di numeri che rappresenta il significato di testo, immagini o altri dati in una forma che un database può confrontare matematicamente.
Un modello di embedding crea i vettori numerici. Prende in input, ad esempio, una frase, un paragrafo, la descrizione di un'immagine o uno snippet di codice e restituisce un vettore con un numero fisso di dimensioni.
Input simili dovrebbero produrre vettori vicini tra loro, mentre input non correlati dovrebbero risultare più distanti. Dobbiamo quindi usare lo stesso modello di embedding per i documents archiviati e per le query in arrivo, perché le distanze hanno senso solo quando i vettori condividono lo stesso sistema di coordinate.
In questo tutorial, i vettori manuali sono volutamente piccoli così possiamo ispezionarne la matematica. Gli embedding testuali reali sono molto più grandi perché il modello ha bisogno di abbastanza dimensioni per codificare relazioni più sottili tra parole, frasi e argomenti.
La vector search ordina le righe in base alla distanza tra vettori. Per le query a distanza euclidea e coseno, distanze più piccole significano corrispondenze più vicine. In questo tutorial, inizieremo con una piccola colonna VECTOR(3, FLOAT32) per vedere direttamente il comportamento della distanza, poi passeremo a embedding VECTOR(1536, FLOAT32) generati dal testo.
Figura 1. Flusso Oracle AI Vector Search
Oracle AI Vector Search archivia gli embedding in una colonna VECTOR nativa e classifica i risultati in base alla distanza vettoriale.
Oracle Database è utile quando gli embedding devono stare accanto a dati applicativi relazionali come ID documento, titoli, contenuti, utenti, prodotti, ticket o metadati.
Alcune applicazioni usano un database vettoriale o un motore di ricerca separato per carichi di lavoro di retrieval specializzati, ma per il flusso di lavoro locale di ricerca semantica di questo tutorial, Oracle Database fornisce le funzionalità di archiviazione e ricerca vettoriale di cui abbiamo bisogno.
Funzionalità chiave di Oracle AI Vector Search
Useremo quattro funzionalità di Oracle AI Vector Search nella demo: archiviazione vettoriale nativa, funzioni di distanza, indici vettoriali e integrazione relazionale.
Tipo di dato vettoriale nativo
Oracle Database supporta colonne VECTOR native con dimensioni esplicite e formati degli elementi. Nella demo useremo VECTOR(3, FLOAT32) per i vettori manuali e VECTOR(1536, FLOAT32) per il modello di embedding predefinito text-embedding-3-small.
Funzioni e operatori di distanza
Gli esempi eseguibili usano VECTOR_DISTANCE() perché mantiene esplicita la metrica di distanza in SQL.
Useremo la distanza euclidea per l'esempio con vettori manuali e la distanza coseno per gli embedding testuali.
Oracle Database include anche operatori abbreviati di distanza vettoriale e comportamenti legati al prodotto scalare, ma questo tutorial mantiene l'SQL eseguibile sul percorso esplicito VECTOR_DISTANCE().
Metriche di distanza diverse rispondono a domande leggermente diverse sulla “vicinanza”.
Per un piccolo tutorial, la distanza coseno è una buona scelta predefinita per gli embedding testuali perché si concentra sulla direzione, che spesso si mappa bene sulla similarità semantica.
La distanza euclidea è più facile da visualizzare con vettori scritti a mano, e confronti in stile prodotto scalare sono utili in alcuni sistemi di retrieval quando la magnitudine o la normalizzazione dei vettori fanno parte del design del modello.
Metrica
Cosa confronta
Buon utilizzo
Attenzione a
Coseno
Direzione del vettore
Embedding testuali e similarità semantica
I risultati dipendono dall'uso dello stesso modello di embedding e da un preprocessing coerente
Euclidea
Distanza in linea retta
Piccoli esempi, intuizione geometrica, alcuni vettori di feature numeriche
La magnitudine influisce sulla distanza, quindi lo scaling può contare
Prodotto scalare
Direzione e magnitudine insieme
Workflow basati su vettori normalizzati o scoring a prodotto interno
Direzione del punteggio e regole di normalizzazione vanno comprese prima di confrontare i risultati
Indici vettoriali
La ricerca vettoriale esatta è utile per correttezza e piccoli dataset. Con la crescita dei dataset, gli indici vettoriali supportano workflow di approximate nearest neighbor.
Oracle AI Vector Search include indici in-memory a grafo di vicinato, spesso associati alla ricerca in stile HNSW, e indici a partizioni di vicinato, spesso associati al partizionamento in stile IVF.
In questa demo locale usiamo ORGANIZATION NEIGHBOR PARTITIONS e validiamo l'indice con USER_INDEXES.
Gli indici approssimati scambiano una piccola parte della certezza della ricerca esaustiva per un recupero più veloce su larga scala.
La famiglia di indici giusta dipende dal carico di lavoro, volume di dati, pattern di aggiornamento e obiettivo di recall.
Questo tutorial usa un indice a partizioni di vicinato in stile IVF perché mantiene il setup locale semplice e fornisce un passaggio concreto di creazione dell'indice senza trasformare il tutorial in una guida al tuning degli indici.
Famiglia di indici
Idea di base
Punti di forza
Trade-off
Quando potremmo usarla
IVF / neighbor partitions
Partizionare lo spazio vettoriale, poi cercare nelle partizioni probabili
Modello mentale semplice, pratico per molti dataset caricati in batch
Recall e velocità dipendono da partizionamento e impostazioni di ricerca
Vogliamo un percorso semplice di ricerca approssimata per un dataset in crescita
HNSW / grafo di vicinato
Costruire un grafo che collega vettori vicini per una traversata rapida
Ottimo profilo di recall e latenza per molti workload di nearest neighbor
Più orientato alla memoria, e la configurazione può contare di più
Serve ricerca a bassa latenza e possiamo dedicare memoria e sforzi di tuning
Integrazione con query relazionali
Una colonna vettoriale può convivere accanto a colonne relazionali ordinarie. La nostra tabella documents memorizzerà insieme titolo, contenuto ed embedding, così SQL può restituire sia lo score di similarità sia il testo originale del documento.
Come iniziare con Oracle AI Vector Search
Useremo un unico percorso di setup locale: Oracle Database Free 26ai in Docker, il servizio FREEPDB1 e un utente applicativo dedicato vector_demo.
I concetti di vector search sono accessibili, ma il setup è intermedio perché usiamo Docker, uno schema database, pacchetti Python, variabili d'ambiente e una chiave API per gli embedding.
Prerequisiti
Ci serviranno:
Docker Desktop o Docker Engine.
Accesso a Oracle Container Registry.
Porte locali 1521 e 5500 disponibili.
Python 3.10 o successivo.
Conoscenze di base di Python e SQL.
Familiarità di base con Docker e variabili d'ambiente.
Una chiave API OpenAI per i passaggi con gli embedding.
Questa demo richiede una versione o un ambiente Oracle Database che includa le funzionalità vettoriali usate qui, incluse le colonne VECTOR native, VECTOR_DISTANCE() e CREATE VECTOR INDEX.
Il percorso locale usa Oracle Database Free 26ai con il tag dell'immagine mostrato sotto, e il DSN usa il servizio del database pluggable FREEPDB1.
I passaggi con i vettori manuali non richiedono una chiave API OpenAI. I passaggi semantici inviano il testo campione del documento e il testo della query al provider di embedding configurato, quindi useremo solo testo campione o non sensibile.
Questo tutorial usa oracledb, l'attuale driver Python per Oracle Database. python-oracledb gira in modalità Thin per impostazione predefinita, quindi questa demo locale non richiede le librerie Oracle Client. La modalità Thick è utile in altri deployment Oracle Database, ma qui non chiameremo oracledb.init_oracle_client().
Avvia Oracle Database Free 26ai in locale
Crea una directory di progetto per gli script che costruiremo.
mkdir oracle-ai-vector-search-python
cd oracle-ai-vector-search-pythonOfferto da
Avvia Oracle Database Free 26ai con l'immagine del container locale.
docker run --name oracle-free-26ai-vector \--detach\--publish1521:1521 \--publish5500:5500 \
--shm-size=1g \--envORACLE_PWD="replace-with-a-strong-password"\
container-registry.oracle.com/database/free:23.26.1.0-lite-amd64Offerto da
Controlla i log del container e attendi finché il database non segnala che l'avvio è completo.
FREEPDB1 è il servizio del database pluggable usato da questo percorso con Oracle Database Free in container locale. Il nostro DSN Python sarà localhost:1521/FREEPDB1.
Crea lo schema vector_demo in FREEPDB1
Usa SYS solo per il passaggio di setup dello schema. La password nel comando sqlplus è il valore ORACLE_PWD del comando docker run; la password in CREATE USER è la password dell'applicazione che esporteremo come DB_PASSWORD.
Esegui il setup all'interno del container del database.
# Create the application user and grant the privileges needed for the demo.dockerexec-i oracle-free-26ai-vector \
sqlplus -s'sys/"replace-with-oracle-pwd"@FREEPDB1 as sysdba'<<'SQL'
WHENEVER SQLERROR EXIT SQL.SQLCODE
CREATE USER vector_demo IDENTIFIED BY "replace-with-vector-demo-password";
GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, UNLIMITED TABLESPACE TO vector_demo;
EXIT
SQLOfferto da
Questa è una scorciatoia di sviluppo locale per il container della demo. CREATE SEQUENCE è necessario perché le tabelle usano colonne identity.
In produzione, rivedremmo i privilegi con un amministratore del database e applicheremmo il principio del minimo privilegio per l'esatto carico applicativo.
Archivia le credenziali del database e le impostazioni per gli embedding in variabili d'ambiente invece di inserirle in hard-code nei file Python.
exportDB_USER="vector_demo"exportDB_PASSWORD="replace-with-vector-demo-password"exportDB_DSN="localhost:1521/FREEPDB1"exportOPENAI_API_KEY="replace-with-your-api-key"exportEMBEDDING_MODEL="text-embedding-3-small"exportEMBEDDING_DIM="1536"Offerto da
OPENAI_API_KEY è richiesta solo per i passaggi di embedding e ricerca semantica. EMBEDDING_DIM deve corrispondere al numero di dimensioni restituite dal modello di embedding selezionato.
Progetto demo Oracle AI Vector Search
Costruiremo la demo in otto checkpoint. Ogni script aggiunge un concetto e produce output che possiamo verificare prima di proseguire.
Il checkpoint solo-database è completo dopo i Passi 1–3. A quel punto ci saremo connessi a Oracle Database, avremo archiviato vettori manuali, li avremo interrogati per distanza e creato la tabella semantica. La chiave API OpenAI diventa necessaria al Passo 4.
Passo 1: Connettiti al database locale
Per prima cosa verificheremo che Python possa connettersi a Oracle Database come utente applicativo vector_demo. Questo script legge DB_USER, DB_PASSWORD e DB_DSN dall'ambiente e stampa la modalità del driver e la versione del database.
Crea lo script
Salva il seguente codice come 01_check_connection.py.
import os
import oracledb
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defmain():# Load required database settings from environment variables.
user = required_env("DB_USER")
password = required_env("DB_PASSWORD")
dsn = required_env("DB_DSN")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")# Open a Thin-mode connection with the application user.with oracledb.connect(user=user, password=password, dsn=dsn)as connection:
mode ="thin"if oracledb.is_thin_mode()else"thick"print("Connected to Oracle Database.")print(f"Driver mode: {mode}")print(f"Database version: {connection.version}")if __name__ =="__main__":
main()Offerto da
L'output dovrebbe confermare che la connessione funziona e che il driver è in modalità Thin.
Connected to Oracle Database.
Driver mode: thin
Database version: 23.26.1.0.0Offerto da
Ora sappiamo che il database locale, il nome del servizio, le credenziali e il driver Python funzionano prima di creare qualsiasi tabella vettoriale.
Passo 2: Fai esperienza con vettori manuali
Prima di introdurre i modelli di embedding, archivieremo tre piccoli vettori su cui possiamo ragionare. La chiamata array.array("f", values) crea un array a virgola mobile a 32 bit che python-oracledb può associare a una colonna VECTOR(..., FLOAT32).
Figura 2. Vettori manuali e distanza euclidea.
L'esempio manuale usa la distanza euclidea. Il vettore apple ha distanza 0,0000 perché coincide con il vettore di query. Il vettore banana è secondo perché sqrt((1.0 - 0.9)^2 + (0.0 - 0.1)^2 + (0.0 - 0.0)^2) = 0,1414.
Crea lo script
Salva il seguente codice come 02_manual_vectors.py.
import array
import os
import oracledb
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")# Define three small vectors so the distance calculation is easy to inspect.
rows =[("apple", array.array("f",[1.0,0.0,0.0])),("banana", array.array("f",[0.9,0.1,0.0])),("car", array.array("f",[0.0,1.0,0.0])),]with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:# Recreate the table so the script can be run repeatedly.
cursor.execute("""
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE manual_vectors PURGE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE <> -942 THEN
RAISE;
END IF;
END;
""")
cursor.execute("""
CREATE TABLE manual_vectors (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
label VARCHAR2(100),
embedding VECTOR(3, FLOAT32)
)
""")# Bind each vector as a 32-bit floating-point array.
cursor.executemany("""
INSERT INTO manual_vectors (label, embedding)
VALUES (:1, :2)
""",
rows,)
connection.commit()# Rank rows by Euclidean distance from the query vector.
cursor.execute("""
SELECT label,
VECTOR_DISTANCE(
embedding,
:query_vector,
EUCLIDEAN
) AS distance
FROM manual_vectors
ORDER BY distance
FETCH EXACT FIRST 2 ROWS ONLY
""",
query_vector=array.array("f",[1.0,0.0,0.0]),)print("Created manual_vectors.")print("Inserted 3 manual vectors.")print("\nNearest manual vectors:")for rank,(label, distance)inenumerate(cursor, start=1):print(f"{rank}. {label:<6} distance={float(distance):.4f}")if __name__ =="__main__":
main()Offerto da
Il vettore identico appare per primo con distanza 0,0000, e il vettore banana vicino appare secondo.
Created manual_vectors.
Inserted 3 manual vectors.
Nearest manual vectors:
1. apple distance=0.0000
2. banana distance=0.1414Offerto da
Questa è l'idea alla base della vector search: le righe vengono classificate per vicinanza matematica a un vettore di query. I modelli di embedding genereranno vettori più grandi, ma il comportamento del database è lo stesso.
Passo 3: Crea la tabella dei documenti semantici
Ora che sappiamo che i vettori funzionano, creeremo una vera tabella in stile applicativo. Il dettaglio importante è che la dimensione della colonna vettoriale deve corrispondere alla dimensione in uscita del modello di embedding.
La dimensione fa parte del contratto della tabella. Se un modello di embedding restituisce 1.536 numeri, la colonna deve essere dichiarata come VECTOR(1536, FLOAT32).
Se in seguito passiamo a un modello con una lunghezza di output diversa, dobbiamo ricreare o migrare la colonna vettoriale affinché insert e query continuino a usare vettori compatibili.
Poiché il DDL non può associare la dimensione del vettore come una normale bind variable SQL, lo script converte EMBEDDING_DIM in intero prima di usarla nella CREATE TABLE.
Crea lo script
Salva il seguente codice come 03_create_documents_table.py.
import os
import oracledb
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defconfigured_dimension():try:
dimension =int(required_env("EMBEDDING_DIM"))except ValueError as exc:raise SystemExit("EMBEDDING_DIM must be an integer.")from exc
if dimension <=0:raise SystemExit("EMBEDDING_DIM must be a positive integer.")return dimension
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")# Validate the configured model name and vector dimension.
model_name = required_env("EMBEDDING_MODEL")
dimension = configured_dimension()with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:# Recreate the documents table so the script is repeatable.
cursor.execute("""
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE documents PURGE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE <> -942 THEN
RAISE;
END IF;
END;
""")
cursor.execute(f"""
CREATE TABLE documents (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR2(200) NOT NULL,
content VARCHAR2(1000) NOT NULL,
embedding VECTOR({dimension}, FLOAT32)
)
""")print(f"Embedding model: {model_name}")print(f"Embedding dimension: {dimension}")print("Recreated documents table.")if __name__ =="__main__":
main()Offerto da
L'output dovrebbe mostrare il modello di embedding configurato e la dimensione del vettore.
Embedding model: text-embedding-3-small
Embedding dimension: 1536
Recreated documents table.Offerto da
Abbiamo completato la parte solo database. Oracle Database può archiviare e confrontare vettori in locale; ora sostituiremo i vettori scritti a mano con embedding generati dal testo.
Passo 4: Verifica la dimensione del modello di embedding
Prima di inserire gli embedding, chiederemo al modello di embedding un vettore e ne verificheremo la lunghezza. Questo previene l'errore più comune nelle tabelle vettoriali: inserire un vettore la cui lunghezza non corrisponde alla dimensione della colonna VECTOR.
Un modello di embedding non è solo un convertitore testo-numeri; definisce lo spazio di significato per l'applicazione. Tutti gli embedding di documenti e query in questa demo devono provenire dallo stesso modello.
Usare un unico modello garantisce che una distanza piccola rappresenti un significato simile, piuttosto che due vettori non correlati che casualmente hanno forme simili. Il modello determina anche la lunghezza del vettore, motivo per cui controlliamo la dimensione restituita prima di caricare i dati.
Crea lo script
Salva il seguente codice come 04_check_embedding_dimension.py.
import os
from openai import OpenAI
defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defconfigured_dimension():try:returnint(required_env("EMBEDDING_DIM"))except ValueError as exc:raise SystemExit("EMBEDDING_DIM must be an integer.")from exc
defmain():
required_env("OPENAI_API_KEY")
model_name = required_env("EMBEDDING_MODEL")
expected_dimension = configured_dimension()# Request one embedding to confirm the model output dimension.
client = OpenAI()
response = client.embeddings.create(
model=model_name,input="Oracle AI Vector Search dimension check",)
returned_dimension =len(response.data[0].embedding)print(f"Embedding model: {model_name}")print(f"Returned embedding length: {returned_dimension}")print(f"Configured EMBEDDING_DIM: {expected_dimension}")# Stop before loading data if the table dimension is incompatible.if returned_dimension != expected_dimension:raise SystemExit("Dimension check failed. Update EMBEDDING_DIM, rerun ""03_create_documents_table.py, and try again.")print("Dimension check passed.")if __name__ =="__main__":
main()Offerto da
Per il modello e la dimensione predefiniti, l'output dovrebbe essere simile a questo.
Embedding model: text-embedding-3-small
Returned embedding length: 1536
Configured EMBEDDING_DIM: 1536
Dimension check passed.Offerto da
Se in futuro scegliamo un modello di embedding diverso, dovremmo aggiornare EMBEDDING_MODEL, impostare EMBEDDING_DIM alla lunghezza del vettore restituito e ricreare la tabella documents.
Passo 5: Genera e inserisci gli embedding dei documenti
Ora genereremo gli embedding per un piccolo dataset autonomo e li inseriremo in Oracle Database.
Ogni embedding viene convertito in array.array("f", embedding) prima del binding così da corrispondere alla colonna vettoriale FLOAT32.
Crea lo script
Salva il seguente codice come 05_insert_embeddings.py.
import array
import os
import oracledb
from openai import OpenAI
DOCUMENTS =[("Oracle AI Vector Search","Oracle Database can store vector embeddings in native VECTOR ""columns and query them with SQL similarity search.",),("Semantic Search for Applications","Semantic search ranks results by meaning, helping applications ""find related content even when exact words differ.",),("Vector Index Workflow","Vector indexes help approximate nearest-neighbor search scale ""when datasets grow beyond small examples.",),("Local Docker Development","Docker containers make it practical to run a local database for ""development and repeatable tutorials.",),("Python Database Code","Python applications can connect to Oracle Database with the ""oracledb driver and use environment variables for credentials.",),("Acoustic Guitar Practice","Daily guitar practice improves timing, chord transitions, and ""confidence when learning new songs.",),("Weeknight Vegetable Soup","A simple soup can combine onions, carrots, beans, herbs, and ""broth for an easy weeknight meal.",),]
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defconfigured_dimension():try:returnint(required_env("EMBEDDING_DIM"))except ValueError as exc:raise SystemExit("EMBEDDING_DIM must be an integer.")from exc
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")
required_env("OPENAI_API_KEY")
model_name = required_env("EMBEDDING_MODEL")
expected_dimension = configured_dimension()# Generate embeddings for all sample documents in one API request.
client = OpenAI()
response = client.embeddings.create(
model=model_name,input=[content for _, content in DOCUMENTS],)# Restore the response order using each item's index.
embeddings =[
item.embedding
for item insorted(
response.data,
key=lambda item: item.index,)]ifany(len(embedding)!= expected_dimension for embedding in embeddings):raise SystemExit("An embedding length did not match EMBEDDING_DIM. ""Rerun 04_check_embedding_dimension.py.")# Bind each embedding as a 32-bit floating-point array.
rows =[(title, content, array.array("f", embedding))for(title, content), embedding inzip(DOCUMENTS, embeddings)]# Replace the sample rows and commit the transaction.with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:
cursor.execute("DELETE FROM documents")
cursor.executemany("""
INSERT INTO documents (title, content, embedding)
VALUES (:1, :2, :3)
""",
rows,)
cursor.execute("SELECT COUNT(*) FROM documents")
row_count = cursor.fetchone()[0]
connection.commit()print(f"Embedding model: {model_name}")print(f"Generated embeddings for {len(DOCUMENTS)} documents.")print(f"Inserted {len(DOCUMENTS)} documents.")print(f"documents row count: {row_count}")if __name__ =="__main__":
main()Offerto da
Il conteggio righe dovrebbe corrispondere ai sette documents inline.
Embedding model: text-embedding-3-small
Generated embeddings for 7 documents.
Inserted 7 documents.
documents row count: 7Offerto da
Ora abbiamo testo ed embedding archiviati insieme in Oracle Database. I documents non correlati su chitarra e zuppa sono inclusi, così i risultati di ricerca hanno corrispondenze vicine e lontane evidenti.
Passo 6: Esegui una query di ricerca semantica
Successivamente, effettueremo l'embedding di una query in linguaggio naturale e la confronteremo con gli embedding dei documenti archiviati. Questo script usa la distanza coseno, comunemente usata per gli embedding testuali perché si concentra sulla direzione del vettore più che sulla magnitudine grezza.
Per la ricerca semantica, la query passa attraverso lo stesso modello di embedding dei documents. Non stiamo chiedendo a SQL di capire direttamente la frase inglese.
Chiediamo al modello di embedding di trasformare la frase in un vettore, poi chiediamo a Oracle Database di ordinare i vettori archiviati in base alla loro distanza da quel vettore di query.
Crea lo script
Salva il seguente codice come 06_semantic_search.py.
import array
import os
import oracledb
from openai import OpenAI
QUERY_TEXT ="Where should an AI app keep meaning-based search data?"
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")
required_env("OPENAI_API_KEY")# Generate an embedding for the natural-language query.
client = OpenAI()
response = client.embeddings.create(
model=required_env("EMBEDDING_MODEL"),input=QUERY_TEXT,)
query_vector = array.array("f", response.data[0].embedding)with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:# Rank stored documents by cosine distance from the query vector.
cursor.execute("""
SELECT title,
content,
VECTOR_DISTANCE(
embedding,
:query_vector,
COSINE
) AS distance
FROM documents
ORDER BY distance
FETCH EXACT FIRST 5 ROWS ONLY
""",
query_vector=query_vector,)
rows = cursor.fetchall()ifnot rows:raise SystemExit("No documents found. Run 05_insert_embeddings.py first.")print(f"Query: {QUERY_TEXT}")print("\nTop 5 results:")for rank,(title, content, distance)inenumerate(rows, start=1):print(f"{rank}. {title}")print(f" distance: {float(distance):.6f}")print(f" {content[:90]}...")if __name__ =="__main__":
main()Offerto da
Classifiche e distanze esatte possono variare quando cambia il modello di embedding. Tuttavia, i documents su Oracle AI Vector Search, ricerca semantica, codice database Python e indicizzazione vettoriale dovrebbero posizionarsi in alto.
Query: Where should an AI app keep meaning-based search data?
Top 5 results:
1. Oracle AI Vector Search
distance: <cosine distance from your run>
Oracle Database can store vector embeddings in native VECTOR columns and query them with SQL...
2. Semantic Search for Applications
distance: <cosine distance from your run>
Semantic search ranks results by meaning, helping applications find related content even when...
3. Python Database Code
distance: <cosine distance from your run>
Python applications can connect to Oracle Database with the oracledb driver and use environment...
4. Vector Index Workflow
distance: <cosine distance from your run>
Vector indexes help approximate nearest-neighbor search scale when datasets grow beyond small...
5. Local Docker Development
distance: <cosine distance from your run>
Docker containers make it practical to run a local database for development and repeatable...Offerto da
Per le query a distanza euclidea e coseno in questo tutorial, valori più piccoli indicano corrispondenze più vicine.
Il prodotto scalare è un altro utile approccio di confronto in molti workflow di vector search, specialmente quando magnitudine o vettori normalizzati contano, ma direzione del punteggio e normalizzazione richiedono attenzione.
Terremo il codice eseguibile su distanza euclidea e coseno così l'interpretazione dei risultati resta semplice.
Se in una futura applicazione normalizziamo gli embedding, dovremo normalizzare in modo coerente sia gli embedding dei documenti archiviati sia quelli delle query; altrimenti, distanze e classifiche possono cambiare.
Passo 7: Confronta ricerca semantica con match di frase
La ricerca semantica è utile perché non richiede che la stessa frase esatta compaia nel documento.
Confrontiamo la query semantica con un semplice predicato di frase esatta.
Questa non è una demo di motore di ricerca full-text; è un piccolo confronto SQL che rende visibile la differenza tra matching letterale e ranking basato sul significato.
Crea lo script
Salva il seguente codice come 07_semantic_vs_keyword.py.
import array
import os
import oracledb
from openai import OpenAI
SEMANTIC_QUERY ="Where should an AI app keep meaning-based search data?"
KEYWORD_PHRASE ="meaning-based search data"
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")
required_env("OPENAI_API_KEY")# Generate an embedding for the semantic query.
client = OpenAI()
response = client.embeddings.create(
model=required_env("EMBEDDING_MODEL"),input=SEMANTIC_QUERY,)
query_vector = array.array("f", response.data[0].embedding)with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:# Rank documents by semantic similarity.
cursor.execute("""
SELECT title,
VECTOR_DISTANCE(embedding, :query_vector, COSINE)
FROM documents
ORDER BY VECTOR_DISTANCE(embedding, :query_vector, COSINE)
FETCH EXACT FIRST 3 ROWS ONLY
""",
query_vector=query_vector,)
semantic_rows = cursor.fetchall()# Compare semantic results with an exact phrase predicate.
cursor.execute("""
SELECT title
FROM documents
WHERE LOWER(title || ' ' || content)
LIKE '%' || :phrase || '%'
ORDER BY title
FETCH FIRST 3 ROWS ONLY
""",
phrase=KEYWORD_PHRASE.lower(),)
keyword_rows = cursor.fetchall()print(f"Semantic query: {SEMANTIC_QUERY}")print(f"Keyword phrase: {KEYWORD_PHRASE}")print("\nSemantic results:")for rank,(title, distance)inenumerate(semantic_rows, start=1):print(f"{rank}. {title}")print(f" distance: {float(distance):.6f}")print("\nKeyword results:")if keyword_rows:for rank,(title,)inenumerate(keyword_rows, start=1):print(f"{rank}. {title}")else:print("0 exact phrase matches")if __name__ =="__main__":
main()Offerto da
La ricerca semantica dovrebbe restituire documents rilevanti anche se la frase chiave esatta non è presente.
Semantic query: Where should an AI app keep meaning-based search data?
Keyword phrase: meaning-based search data
Semantic results:
1. Oracle AI Vector Search
distance: <cosine distance from your run>
2. Semantic Search for Applications
distance: <cosine distance from your run>
3. Python Database Code
distance: <cosine distance from your run>
Keyword results:
0 exact phrase matchesOfferto da
I tradizionali predicati SQL restano importanti per filtri, join, permessi e matching esatto. La vector search aggiunge un segnale di ranking basato sul significato che possiamo combinare con dati relazionali quando un'applicazione richiede retrieval semantico.
Passo 8: Aggiungi e valida un indice vettoriale
Infine, creeremo un indice vettoriale e valideremo che Oracle Database lo riporti come indice valido di proprietà dello schema della demo.
Questo passaggio dimostra il workflow di creazione dell'indice; il nostro dataset minuscolo non è abbastanza grande per trarre conclusioni significative sulle performance.
Senza indice, Oracle Database può confrontare esattamente il vettore di query con ciascun vettore archiviato. Questo approccio è adatto a dataset minuscoli ed è utile in fase di apprendimento.
Con dataset più grandi, gli indici vettoriali approssimati riducono lo spazio di ricerca così che le query possano tornare rapidamente pur trovando vicini prossimi.
Scegli la famiglia di indici dopo aver considerato dimensione dei dati, obiettivi di latenza, requisiti di recall, budget di memoria e frequenza di modifica dei vettori.
La query finale conferma che la ricerca semantica restituisce ancora risultati dopo la creazione dell'indice.
Non useremo EXPLAIN PLAN o DBMS_XPLAN perché questo tutorial valida la creazione dell'indice con metadati dello schema, non con il piano di esecuzione.
Crea lo script
Salva il seguente codice come 08_create_vector_index.py.
import array
import os
import oracledb
from openai import OpenAI
INDEX_NAME ="DOCUMENT_EMBEDDING_IDX"
QUERY_TEXT ="Where should an AI app keep meaning-based search data?"
ADMIN_USERS ={"SYS","SYSTEM","PDBADMIN"}defrequired_env(name):
value = os.getenv(name)ifnot value:raise SystemExit(f"Set {name} before running this script.")return value
defmain():
user = required_env("DB_USER")if user.upper()in ADMIN_USERS:raise SystemExit("Use the vector_demo application user, not an admin user.")
required_env("OPENAI_API_KEY")# Generate the query vector used for the validation search.
client = OpenAI()
response = client.embeddings.create(
model=required_env("EMBEDDING_MODEL"),input=QUERY_TEXT,)
query_vector = array.array("f", response.data[0].embedding)with oracledb.connect(
user=user,
password=required_env("DB_PASSWORD"),
dsn=required_env("DB_DSN"),)as connection:with connection.cursor()as cursor:# Remove a prior index so the script can be rerun safely.try:
cursor.execute(f"DROP INDEX {INDEX_NAME}")except oracledb.DatabaseError as exc:
error = exc.args[0]if error.code !=1418:raise# Create an approximate neighbor-partitions vector index.
cursor.execute("""
CREATE VECTOR INDEX document_embedding_idx
ON documents (embedding)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95
""")# Confirm that Oracle reports the vector index as valid.
cursor.execute("""
SELECT index_name, index_type, status
FROM user_indexes
WHERE index_name = :index_name
""",
index_name=INDEX_NAME,)
index_row = cursor.fetchone()# Confirm that semantic search still returns rows after index creation.
cursor.execute("""
SELECT title
FROM documents
ORDER BY VECTOR_DISTANCE(embedding, :query_vector, COSINE)
FETCH EXACT FIRST 3 ROWS ONLY
""",
query_vector=query_vector,)
rows = cursor.fetchall()ifnot index_row:raise SystemExit("Vector index was not found in USER_INDEXES.")print("Created vector index DOCUMENT_EMBEDDING_IDX.")print("\nIndex validation:")print(f"Index name: {index_row[0]}")print(f"Index type: {index_row[1]}")print(f"Status: {index_row[2]}")
result_count =len(rows)print("\nSemantic search still returns "f"{result_count} results after index creation.")if __name__ =="__main__":
main()Offerto da
L'output dovrebbe includere una riga per DOCUMENT_EMBEDDING_IDX, con INDEX_TYPE impostato a VECTOR e STATUS impostato a VALID.
Created vector index DOCUMENT_EMBEDDING_IDX.
Index validation:
Index name: DOCUMENT_EMBEDDING_IDX
Index type: VECTOR
Status: VALID
Semantic search still returns 3 results after index creation.Offerto da
USER_INDEXES conferma che l'indice esiste ed è valido. Non prova che una specifica query abbia usato l'indice, e questo tutorial non usa l'output del piano di esecuzione come metodo di validazione.
Per carichi di lavoro di produzione, testeremmo con volumi di dati realistici, pattern di query e obiettivi di performance.
Suggerimenti e troubleshooting per Oracle AI Vector Search
Il container del database si sta ancora avviando
Attendi finché l'avvio non è completo, poi esegui di nuovo docker logs oracle-free-26ai-vector. Il database deve essere pronto prima che Python possa connettersi a localhost:1521/FREEPDB1.
La porta 1521 è già in uso
Arresta il servizio locale in conflitto o modifica il mapping delle porte di Docker. Aggiorna DB_DSN se cambia la porta dell'host.
La connessione al database fallisce
Verifica DB_USER, DB_PASSWORD e DB_DSN. Usa FREEPDB1 nel DSN e collega gli script applicativi come vector_demo, non come SYS, SYSTEM o PDBADMIN.
Manca la chiave API per gli embedding
I Passi 1-3 sono solo database. I Passi 4-8 richiedono OPENAI_API_KEY e possono comportare costi API.
Una dimensione vettoriale non corrisponde
Esegui 04_check_embedding_dimension.py, aggiorna EMBEDDING_DIM, riesegui 03_create_documents_table.py e ricarica gli embedding con 05_insert_embeddings.py.
Un bind vettoriale fallisce
Assicurati che ogni bind di vettori FLOAT32 usi array.array("f", values). Il tutorial usa questo formato per vettori manuali, embedding dei documenti archiviati e embedding delle query.
Le classifiche semantiche differiscono dall'esempio
È previsto. I provider di embedding possono aggiornare i modelli e le distanze in virgola mobile possono variare tra le esecuzioni.
La creazione dell'indice vettoriale fallisce
Conferma che la tabella documents esiste, che lo schema vector_demo ne è il proprietario e che DOCUMENT_EMBEDDING_IDX non sia rimasto da un'esecuzione parziale.
Prepararsi alla produzione
Usa oracledb.create_pool() per il connection pooling, esegui benchmark con volumi di dati realistici, rivedi sicurezza e gestione dei segreti e ottimizza gli indici in base a pattern di query reali.
Arresta e rimuovi il container
Quando il tutorial è completato, arresta e rimuovi il container locale.
docker stop oracle-free-26ai-vector
dockerrm oracle-free-26ai-vectorOfferto da
Conclusione
Abbiamo costruito un flusso di lavoro di ricerca semantica locale con Oracle AI Vector Search, Oracle Database Free 26ai e Python.
Siamo partiti da valori VECTOR(3, FLOAT32) scritti a mano, abbiamo inserito embedding generati dal modello con array.array("f", values), interrogato documents simili con VECTOR_DISTANCE(), confrontato il recupero semantico con un semplice predicato di frase esatta e validato un indice vettoriale tramite USER_INDEXES.
Questo approccio si adatta bene quando gli embedding devono stare accanto ai dati relazionali e vogliamo archiviazione e ricerca visibili in SQL senza aggiungere un database vettoriale separato per il workflow locale.
La demo è volutamente piccola: insegna le primitive, non la scalabilità in produzione. Applicazioni più grandi dovrebbero eseguire benchmark con dati realistici, rivedere sicurezza e privilegi, usare connection pooling e validare le scelte di indicizzazione su pattern di query reali.
Poi possiamo approfondire l'implementazione con queste risorse:
Oracle AI Vector Search User’s Guide è il riferimento principale per archiviazione vettoriale, ricerca, indicizzazione e funzionalità SQL correlate.
Oracle AI Vector Search LiveLabs offre workshop pratici su embedding vettoriali, ricerca esatta e approssimata, ricerca di immagini e retrieval-augmented generation.
FAQs
Che cos'è Oracle AI Vector Search?⌄
Oracle AI Vector Search è un insieme di funzionalità di Oracle Database per archiviare, indicizzare e interrogare embedding vettoriali insieme ai dati relazionali.
Ho bisogno di una chiave API OpenAI per completare il tutorial?⌄
I passaggi con vettori manuali e setup del database non richiedono una chiave API. I Passi 4-8 richiedono un provider di embedding e la OPENAI_API_KEY configurata.
Perché EMBEDDING_DIM deve corrispondere al modello di embedding?⌄
La dimensione della colonna VECTOR deve essere uguale al numero di valori restituiti dal modello di embedding. Una mancata corrispondenza fa fallire l'inserimento del vettore.
Quali metriche di distanza usa il tutorial?⌄
L'esempio con vettori manuali usa la distanza euclidea. Gli esempi di ricerca semantica usano la distanza coseno.
Un indice vettoriale valido dimostra che una query ha usato l'indice?⌄
No. USER_INDEXES conferma che l'indice esiste ed è in stato valido, ma non conferma che una specifica query lo abbia utilizzato.
Mark Nelson è un architetto ed evangelist per sviluppatori in Oracle. Lavora all’incrocio tra AI, microservizi e tecnologie database. È un blogger attivo, autore pubblicato, revisore tecnico per Manning Publications, Section Leader a Stanford Code in Place e mentor presso DeepLearning.ai. Interviene regolarmente presso Java e Oracle User Group, meetup sull’AI e grandi conferenze. Ha una passione per l’apprendimento e l’insegnamento. Vanta oltre trent’anni di esperienza nel settore, in IBM e Oracle.
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Scopri come integrare l'intelligenza artificiale nelle applicazioni software utilizzando API e librerie open-source. Inizia oggi il tuo percorso per diventare un ingegnere AI!
In questo tutorial, costruiremo una demo locale di ricerca semantica con Oracle AI Vector Search, Python e Oracle Database Free 26ai.
Partiremo con vettori tridimensionali scritti a mano per rendere visibile il calcolo della distanza, poi genereremo embedding testuali e li interrogheremo da Oracle Database con SQL.
Questo tutorial è per sviluppatori Python e SQL nuovi alla vector search e a proprio agio con Docker, variabili d'ambiente, pacchetti Python e setup di database locali.
Le applicazioni basate sull'AI hanno bisogno di una ricerca che capisca il significato, non solo le parole esatte. Un'app di supporto, un portale di documentazione o uno strumento di knowledge interno dovrebbero saper trovare “archiviazione database per ricerca AI” anche quando il documento migliore dice “archivia embedding vettoriali in colonne native”.
I vettori embedding rendono tutto ciò possibile rappresentando il testo come vettori numerici. Oracle AI Vector Search ci permette di archiviare questi vettori direttamente in Oracle Database, interrogarli con SQL e tenere gli embedding accanto ai dati applicativi relazionali.
Per questo flusso di lavoro locale, non serve un database vettoriale separato.
Eseguiremo Oracle Database Free 26ai in locale, ci connetteremo da Python con la modalità Thin di
oracledb, archivieremo prima i vettori manuali, poi gli embedding OpenAI, eseguiremo la ricerca semantica, confronteremo il recupero semantico con un semplice predicato di frase esatta e creeremo un indice vettoriale validato tramiteUSER_INDEXES.Alla fine, avremo un flusso di lavoro di ricerca semantica in Python funzionante che archivia gli embedding in Oracle Database e recupera i
documentspiù simili in locale.Che cos'è Oracle AI Vector Search?
Oracle AI Vector Search è un insieme di funzionalità di Oracle Database per archiviare, indicizzare e interrogare embedding vettoriali. Un embedding vettoriale è un elenco a dimensione fissa di numeri che rappresenta il significato di testo, immagini o altri dati in una forma che un database può confrontare matematicamente.
Un modello di embedding crea i vettori numerici. Prende in input, ad esempio, una frase, un paragrafo, la descrizione di un'immagine o uno snippet di codice e restituisce un vettore con un numero fisso di dimensioni.
Input simili dovrebbero produrre vettori vicini tra loro, mentre input non correlati dovrebbero risultare più distanti. Dobbiamo quindi usare lo stesso modello di embedding per i documents archiviati e per le query in arrivo, perché le distanze hanno senso solo quando i vettori condividono lo stesso sistema di coordinate.
In questo tutorial, i vettori manuali sono volutamente piccoli così possiamo ispezionarne la matematica. Gli embedding testuali reali sono molto più grandi perché il modello ha bisogno di abbastanza dimensioni per codificare relazioni più sottili tra parole, frasi e argomenti.
La vector search ordina le righe in base alla distanza tra vettori. Per le query a distanza euclidea e coseno, distanze più piccole significano corrispondenze più vicine. In questo tutorial, inizieremo con una piccola colonna
VECTOR(3, FLOAT32)per vedere direttamente il comportamento della distanza, poi passeremo a embeddingVECTOR(1536, FLOAT32)generati dal testo.Figura 1. Flusso Oracle AI Vector Search
Oracle AI Vector Search archivia gli embedding in una colonna VECTOR nativa e classifica i risultati in base alla distanza vettoriale.
Oracle Database è utile quando gli embedding devono stare accanto a dati applicativi relazionali come ID documento, titoli, contenuti, utenti, prodotti, ticket o metadati.
Alcune applicazioni usano un database vettoriale o un motore di ricerca separato per carichi di lavoro di retrieval specializzati, ma per il flusso di lavoro locale di ricerca semantica di questo tutorial, Oracle Database fornisce le funzionalità di archiviazione e ricerca vettoriale di cui abbiamo bisogno.
Funzionalità chiave di Oracle AI Vector Search
Useremo quattro funzionalità di Oracle AI Vector Search nella demo: archiviazione vettoriale nativa, funzioni di distanza, indici vettoriali e integrazione relazionale.
Tipo di dato vettoriale nativo
Oracle Database supporta colonne
VECTORnative con dimensioni esplicite e formati degli elementi. Nella demo useremoVECTOR(3, FLOAT32)per i vettori manuali eVECTOR(1536, FLOAT32)per il modello di embedding predefinitotext-embedding-3-small.Funzioni e operatori di distanza
Gli esempi eseguibili usano
VECTOR_DISTANCE()perché mantiene esplicita la metrica di distanza in SQL.Useremo la distanza euclidea per l'esempio con vettori manuali e la distanza coseno per gli embedding testuali.
Oracle Database include anche operatori abbreviati di distanza vettoriale e comportamenti legati al prodotto scalare, ma questo tutorial mantiene l'SQL eseguibile sul percorso esplicito
VECTOR_DISTANCE().Metriche di distanza diverse rispondono a domande leggermente diverse sulla “vicinanza”.
Per un piccolo tutorial, la distanza coseno è una buona scelta predefinita per gli embedding testuali perché si concentra sulla direzione, che spesso si mappa bene sulla similarità semantica.
La distanza euclidea è più facile da visualizzare con vettori scritti a mano, e confronti in stile prodotto scalare sono utili in alcuni sistemi di retrieval quando la magnitudine o la normalizzazione dei vettori fanno parte del design del modello.
Metrica
Cosa confronta
Buon utilizzo
Attenzione a
Coseno
Direzione del vettore
Embedding testuali e similarità semantica
I risultati dipendono dall'uso dello stesso modello di embedding e da un preprocessing coerente
Euclidea
Distanza in linea retta
Piccoli esempi, intuizione geometrica, alcuni vettori di feature numeriche
La magnitudine influisce sulla distanza, quindi lo scaling può contare
Prodotto scalare
Direzione e magnitudine insieme
Workflow basati su vettori normalizzati o scoring a prodotto interno
Direzione del punteggio e regole di normalizzazione vanno comprese prima di confrontare i risultati
Indici vettoriali
La ricerca vettoriale esatta è utile per correttezza e piccoli dataset. Con la crescita dei dataset, gli indici vettoriali supportano workflow di approximate nearest neighbor.
Oracle AI Vector Search include indici in-memory a grafo di vicinato, spesso associati alla ricerca in stile HNSW, e indici a partizioni di vicinato, spesso associati al partizionamento in stile IVF.
In questa demo locale usiamo
ORGANIZATION NEIGHBOR PARTITIONSe validiamo l'indice conUSER_INDEXES.Gli indici approssimati scambiano una piccola parte della certezza della ricerca esaustiva per un recupero più veloce su larga scala.
La famiglia di indici giusta dipende dal carico di lavoro, volume di dati, pattern di aggiornamento e obiettivo di recall.
Questo tutorial usa un indice a partizioni di vicinato in stile IVF perché mantiene il setup locale semplice e fornisce un passaggio concreto di creazione dell'indice senza trasformare il tutorial in una guida al tuning degli indici.
Famiglia di indici
Idea di base
Punti di forza
Trade-off
Quando potremmo usarla
IVF / neighbor partitions
Partizionare lo spazio vettoriale, poi cercare nelle partizioni probabili
Modello mentale semplice, pratico per molti dataset caricati in batch
Recall e velocità dipendono da partizionamento e impostazioni di ricerca
Vogliamo un percorso semplice di ricerca approssimata per un dataset in crescita
HNSW / grafo di vicinato
Costruire un grafo che collega vettori vicini per una traversata rapida
Ottimo profilo di recall e latenza per molti workload di nearest neighbor
Più orientato alla memoria, e la configurazione può contare di più
Serve ricerca a bassa latenza e possiamo dedicare memoria e sforzi di tuning
Integrazione con query relazionali
Una colonna vettoriale può convivere accanto a colonne relazionali ordinarie. La nostra tabella documents memorizzerà insieme titolo, contenuto ed embedding, così SQL può restituire sia lo score di similarità sia il testo originale del documento.
Come iniziare con Oracle AI Vector Search
Useremo un unico percorso di setup locale: Oracle Database Free 26ai in Docker, il servizio
FREEPDB1e un utente applicativo dedicatovector_demo.I concetti di vector search sono accessibili, ma il setup è intermedio perché usiamo Docker, uno schema database, pacchetti Python, variabili d'ambiente e una chiave API per gli embedding.
Prerequisiti
Ci serviranno:
Questa demo richiede una versione o un ambiente Oracle Database che includa le funzionalità vettoriali usate qui, incluse le colonne
VECTORnative,VECTOR_DISTANCE()eCREATE VECTOR INDEX.Il percorso locale usa Oracle Database Free 26ai con il tag dell'immagine mostrato sotto, e il DSN usa il servizio del database pluggable
FREEPDB1.I passaggi con i vettori manuali non richiedono una chiave API
OpenAI. I passaggi semantici inviano il testo campione del documento e il testo della query al provider di embedding configurato, quindi useremo solo testo campione o non sensibile.Questo tutorial usa
oracledb, l'attuale driver Python per Oracle Database.python-oracledbgira in modalità Thin per impostazione predefinita, quindi questa demo locale non richiede le librerie Oracle Client. La modalità Thick è utile in altri deployment Oracle Database, ma qui non chiameremooracledb.init_oracle_client().Avvia Oracle Database Free 26ai in locale
Crea una directory di progetto per gli script che costruiremo.
Avvia Oracle Database Free 26ai con l'immagine del container locale.
Controlla i log del container e attendi finché il database non segnala che l'avvio è completo.
FREEPDB1è il servizio del database pluggable usato da questo percorso con Oracle Database Free in container locale. Il nostro DSN Python saràlocalhost:1521/FREEPDB1.Crea lo schema vector_demo in FREEPDB1
Usa
SYSsolo per il passaggio di setup dello schema. La password nel comando sqlplus è il valore ORACLE_PWD del comando docker run; la password in CREATE USER è la password dell'applicazione che esporteremo comeDB_PASSWORD.Esegui il setup all'interno del container del database.
Questa è una scorciatoia di sviluppo locale per il container della demo. CREATE SEQUENCE è necessario perché le tabelle usano colonne identity.
In produzione, rivedremmo i privilegi con un amministratore del database e applicheremmo il principio del minimo privilegio per l'esatto carico applicativo.
Installa le dipendenze Python
Crea e attiva un virtual environment.
Installa i pacchetti Python usati dalla demo.
Imposta le variabili d'ambiente
Archivia le credenziali del database e le impostazioni per gli embedding in variabili d'ambiente invece di inserirle in hard-code nei file Python.
OPENAI_API_KEYè richiesta solo per i passaggi di embedding e ricerca semantica.EMBEDDING_DIMdeve corrispondere al numero di dimensioni restituite dal modello di embedding selezionato.Progetto demo Oracle AI Vector Search
Costruiremo la demo in otto checkpoint. Ogni script aggiunge un concetto e produce output che possiamo verificare prima di proseguire.
Il checkpoint solo-database è completo dopo i Passi 1–3. A quel punto ci saremo connessi a Oracle Database, avremo archiviato vettori manuali, li avremo interrogati per distanza e creato la tabella semantica. La chiave API
OpenAIdiventa necessaria al Passo 4.Passo 1: Connettiti al database locale
Per prima cosa verificheremo che Python possa connettersi a Oracle Database come utente applicativo
vector_demo. Questo script leggeDB_USER, DB_PASSWORDeDB_DSNdall'ambiente e stampa la modalità del driver e la versione del database.Crea lo script
Salva il seguente codice come
01_check_connection.py.Esegui lo script
Esegui il controllo della connessione.
Output atteso
L'output dovrebbe confermare che la connessione funziona e che il driver è in modalità Thin.
Ora sappiamo che il database locale, il nome del servizio, le credenziali e il driver Python funzionano prima di creare qualsiasi tabella vettoriale.
Passo 2: Fai esperienza con vettori manuali
Prima di introdurre i modelli di embedding, archivieremo tre piccoli vettori su cui possiamo ragionare. La chiamata
array.array("f", values)crea un array a virgola mobile a 32 bit chepython-oracledbpuò associare a una colonnaVECTOR(..., FLOAT32).Figura 2. Vettori manuali e distanza euclidea.
L'esempio manuale usa la distanza euclidea. Il vettore apple ha distanza 0,0000 perché coincide con il vettore di query. Il vettore banana è secondo perché sqrt((1.0 - 0.9)^2 + (0.0 - 0.1)^2 + (0.0 - 0.0)^2) = 0,1414.
Crea lo script
Salva il seguente codice come
02_manual_vectors.py.Esegui lo script
Esegui lo script dei vettori manuali.
Output atteso
Il vettore identico appare per primo con distanza 0,0000, e il vettore banana vicino appare secondo.
Questa è l'idea alla base della vector search: le righe vengono classificate per vicinanza matematica a un vettore di query. I modelli di embedding genereranno vettori più grandi, ma il comportamento del database è lo stesso.
Passo 3: Crea la tabella dei documenti semantici
Ora che sappiamo che i vettori funzionano, creeremo una vera tabella in stile applicativo. Il dettaglio importante è che la dimensione della colonna vettoriale deve corrispondere alla dimensione in uscita del modello di embedding.
La dimensione fa parte del contratto della tabella. Se un modello di embedding restituisce 1.536 numeri, la colonna deve essere dichiarata come
VECTOR(1536, FLOAT32).Se in seguito passiamo a un modello con una lunghezza di output diversa, dobbiamo ricreare o migrare la colonna vettoriale affinché insert e query continuino a usare vettori compatibili.
Poiché il DDL non può associare la dimensione del vettore come una normale bind variable SQL, lo script converte
EMBEDDING_DIMin intero prima di usarla nella CREATE TABLE.Crea lo script
Salva il seguente codice come
03_create_documents_table.py.Esegui lo script
Esegui lo script di creazione della tabella.
Output atteso
L'output dovrebbe mostrare il modello di embedding configurato e la dimensione del vettore.
Abbiamo completato la parte solo database. Oracle Database può archiviare e confrontare vettori in locale; ora sostituiremo i vettori scritti a mano con embedding generati dal testo.
Passo 4: Verifica la dimensione del modello di embedding
Prima di inserire gli embedding, chiederemo al modello di embedding un vettore e ne verificheremo la lunghezza. Questo previene l'errore più comune nelle tabelle vettoriali: inserire un vettore la cui lunghezza non corrisponde alla dimensione della colonna
VECTOR.Un modello di embedding non è solo un convertitore testo-numeri; definisce lo spazio di significato per l'applicazione. Tutti gli embedding di documenti e query in questa demo devono provenire dallo stesso modello.
Usare un unico modello garantisce che una distanza piccola rappresenti un significato simile, piuttosto che due vettori non correlati che casualmente hanno forme simili. Il modello determina anche la lunghezza del vettore, motivo per cui controlliamo la dimensione restituita prima di caricare i dati.
Crea lo script
Salva il seguente codice come
04_check_embedding_dimension.py.Esegui lo script
Esegui il controllo della dimensione.
Output atteso
Per il modello e la dimensione predefiniti, l'output dovrebbe essere simile a questo.
Se in futuro scegliamo un modello di embedding diverso, dovremmo aggiornare
EMBEDDING_MODEL, impostareEMBEDDING_DIMalla lunghezza del vettore restituito e ricreare la tabelladocuments.Passo 5: Genera e inserisci gli embedding dei documenti
Ora genereremo gli embedding per un piccolo dataset autonomo e li inseriremo in Oracle Database.
Ogni embedding viene convertito in
array.array("f", embedding)prima del binding così da corrispondere alla colonna vettorialeFLOAT32.Crea lo script
Salva il seguente codice come
05_insert_embeddings.py.Esegui lo script
Esegui lo script di insert.
Output atteso
Il conteggio righe dovrebbe corrispondere ai sette
documentsinline.Ora abbiamo testo ed embedding archiviati insieme in Oracle Database. I
documentsnon correlati su chitarra e zuppa sono inclusi, così i risultati di ricerca hanno corrispondenze vicine e lontane evidenti.Passo 6: Esegui una query di ricerca semantica
Successivamente, effettueremo l'embedding di una query in linguaggio naturale e la confronteremo con gli embedding dei documenti archiviati. Questo script usa la distanza coseno, comunemente usata per gli embedding testuali perché si concentra sulla direzione del vettore più che sulla magnitudine grezza.
Per la ricerca semantica, la query passa attraverso lo stesso modello di embedding dei
documents. Non stiamo chiedendo a SQL di capire direttamente la frase inglese.Chiediamo al modello di embedding di trasformare la frase in un vettore, poi chiediamo a Oracle Database di ordinare i vettori archiviati in base alla loro distanza da quel vettore di query.
Crea lo script
Salva il seguente codice come
06_semantic_search.py.Esegui lo script
Esegui lo script di ricerca semantica.
Output atteso
Classifiche e distanze esatte possono variare quando cambia il modello di embedding. Tuttavia, i
documentssu Oracle AI Vector Search, ricerca semantica, codice database Python e indicizzazione vettoriale dovrebbero posizionarsi in alto.Per le query a distanza euclidea e coseno in questo tutorial, valori più piccoli indicano corrispondenze più vicine.
Il prodotto scalare è un altro utile approccio di confronto in molti workflow di vector search, specialmente quando magnitudine o vettori normalizzati contano, ma direzione del punteggio e normalizzazione richiedono attenzione.
Terremo il codice eseguibile su distanza euclidea e coseno così l'interpretazione dei risultati resta semplice.
Se in una futura applicazione normalizziamo gli embedding, dovremo normalizzare in modo coerente sia gli embedding dei documenti archiviati sia quelli delle query; altrimenti, distanze e classifiche possono cambiare.
Passo 7: Confronta ricerca semantica con match di frase
La ricerca semantica è utile perché non richiede che la stessa frase esatta compaia nel documento.
Confrontiamo la query semantica con un semplice predicato di frase esatta.
Questa non è una demo di motore di ricerca full-text; è un piccolo confronto SQL che rende visibile la differenza tra matching letterale e ranking basato sul significato.
Crea lo script
Salva il seguente codice come
07_semantic_vs_keyword.py.Esegui lo script
Esegui lo script di confronto.
Output atteso
La ricerca semantica dovrebbe restituire
documentsrilevanti anche se la frase chiave esatta non è presente.I tradizionali predicati SQL restano importanti per filtri, join, permessi e matching esatto. La vector search aggiunge un segnale di ranking basato sul significato che possiamo combinare con dati relazionali quando un'applicazione richiede retrieval semantico.
Passo 8: Aggiungi e valida un indice vettoriale
Infine, creeremo un indice vettoriale e valideremo che Oracle Database lo riporti come indice valido di proprietà dello schema della demo.
Questo passaggio dimostra il workflow di creazione dell'indice; il nostro dataset minuscolo non è abbastanza grande per trarre conclusioni significative sulle performance.
Senza indice, Oracle Database può confrontare esattamente il vettore di query con ciascun vettore archiviato. Questo approccio è adatto a dataset minuscoli ed è utile in fase di apprendimento.
Con dataset più grandi, gli indici vettoriali approssimati riducono lo spazio di ricerca così che le query possano tornare rapidamente pur trovando vicini prossimi.
Scegli la famiglia di indici dopo aver considerato dimensione dei dati, obiettivi di latenza, requisiti di recall, budget di memoria e frequenza di modifica dei vettori.
La query finale conferma che la ricerca semantica restituisce ancora risultati dopo la creazione dell'indice.
Non useremo EXPLAIN PLAN o DBMS_XPLAN perché questo tutorial valida la creazione dell'indice con metadati dello schema, non con il piano di esecuzione.
Crea lo script
Salva il seguente codice come
08_create_vector_index.py.Esegui lo script
Esegui lo script dell'indice.
Output atteso
L'output dovrebbe includere una riga per
DOCUMENT_EMBEDDING_IDX, conINDEX_TYPEimpostato aVECTOReSTATUSimpostato aVALID.USER_INDEXESconferma che l'indice esiste ed è valido. Non prova che una specifica query abbia usato l'indice, e questo tutorial non usa l'output del piano di esecuzione come metodo di validazione.Per carichi di lavoro di produzione, testeremmo con volumi di dati realistici, pattern di query e obiettivi di performance.
Suggerimenti e troubleshooting per Oracle AI Vector Search
Il container del database si sta ancora avviando
Attendi finché l'avvio non è completo, poi esegui di nuovo
docker logs oracle-free-26ai-vector. Il database deve essere pronto prima che Python possa connettersi alocalhost:1521/FREEPDB1.La porta 1521 è già in uso
Arresta il servizio locale in conflitto o modifica il mapping delle porte di Docker. Aggiorna
DB_DSNse cambia la porta dell'host.La connessione al database fallisce
Verifica
DB_USER, DB_PASSWORDeDB_DSN. UsaFREEPDB1nel DSN e collega gli script applicativi comevector_demo, non comeSYS, SYSTEMoPDBADMIN.Manca la chiave API per gli embedding
I Passi 1-3 sono solo database. I Passi 4-8 richiedono
OPENAI_API_KEYe possono comportare costi API.Una dimensione vettoriale non corrisponde
Esegui
04_check_embedding_dimension.py, aggiornaEMBEDDING_DIM, riesegui03_create_documents_table.pye ricarica gli embedding con05_insert_embeddings.py.Un bind vettoriale fallisce
Assicurati che ogni bind di vettori
FLOAT32usiarray.array("f", values). Il tutorial usa questo formato per vettori manuali, embedding dei documenti archiviati e embedding delle query.Le classifiche semantiche differiscono dall'esempio
È previsto. I provider di embedding possono aggiornare i modelli e le distanze in virgola mobile possono variare tra le esecuzioni.
La creazione dell'indice vettoriale fallisce
Conferma che la tabella
documentsesiste, che lo schemavector_demone è il proprietario e cheDOCUMENT_EMBEDDING_IDXnon sia rimasto da un'esecuzione parziale.Prepararsi alla produzione
Usa
oracledb.create_pool()per il connection pooling, esegui benchmark con volumi di dati realistici, rivedi sicurezza e gestione dei segreti e ottimizza gli indici in base a pattern di query reali.Arresta e rimuovi il container
Quando il tutorial è completato, arresta e rimuovi il container locale.
Conclusione
Abbiamo costruito un flusso di lavoro di ricerca semantica locale con Oracle AI Vector Search, Oracle Database Free 26ai e Python.
Siamo partiti da valori
VECTOR(3, FLOAT32)scritti a mano, abbiamo inserito embedding generati dal modello conarray.array("f", values), interrogatodocumentssimili conVECTOR_DISTANCE(), confrontato il recupero semantico con un semplice predicato di frase esatta e validato un indice vettoriale tramiteUSER_INDEXES.Questo approccio si adatta bene quando gli embedding devono stare accanto ai dati relazionali e vogliamo archiviazione e ricerca visibili in SQL senza aggiungere un database vettoriale separato per il workflow locale.
La demo è volutamente piccola: insegna le primitive, non la scalabilità in produzione. Applicazioni più grandi dovrebbero eseguire benchmark con dati realistici, rivedere sicurezza e privilegi, usare connection pooling e validare le scelte di indicizzazione su pattern di query reali.
Poi possiamo approfondire l'implementazione con queste risorse: