Oracle AI Vector Search-tutorial: Embeddings opslaan en bevragen met Python
Deze tutorial introduceert Oracle AI Vector Search, legt de kernfuncties uit en doorloopt een praktische lokale setup. Ook komen set-upeisen, semantisch zoeken, vectorindexering en veelvoorkomende troubleshooting aan bod.
In deze tutorial bouwen we een lokale demo voor semantisch zoeken met Oracle AI Vector Search, Python en Oracle Database Free 26ai.
We beginnen met handgeschreven driedimensionale vectoren zodat de afstandsberekening zichtbaar is, genereren daarna tekstembeddings en bevragen die met SQL vanuit Oracle Database.
Deze tutorial is voor Python- en SQL-ontwikkelaars die nieuw zijn met vector search en vertrouwd zijn met Docker, omgevingsvariabelen, Python-packages en een lokale databaseset-up.
AI-gedreven applicaties hebben search nodig die betekenis begrijpt, niet alleen exacte woorden. Een support-app, documentatieportaal of interne kennistool moet “databaseopslag voor AI-zoekopdrachten” kunnen vinden, ook als het best passende document zegt: “vector-embeddings opslaan in native kolommen.”
Vector-embeddings maken dat mogelijk door tekst als numerieke vectoren te representeren. Met Oracle AI Vector Search kunnen we die vectoren rechtstreeks in Oracle Database opslaan, met SQL bevragen en embeddings naast relationele applicatiedata bewaren.
Voor deze lokale workflow hebben we geen aparte vectordatabank nodig.
We draaien Oracle Database Free 26ai lokaal, verbinden vanuit Python met oracledb Thin-modus, slaan eerst handmatige vectoren op, vervolgens OpenAI-embeddings, voeren semantisch zoeken uit, vergelijken semantische retrieval met een eenvoudige exacte frase-predicate en maken een vectorindex die we valideren via USER_INDEXES.
Aan het eind hebben we een werkende Python-gestuurde semantische zoekworkflow die embeddings opslaat in Oracle Database en de meest vergelijkbare documents lokaal ophaalt.
Wat is Oracle AI Vector Search?
Oracle AI Vector Search is een set mogelijkheden in Oracle Database voor het opslaan, indexeren en bevragen van vector-embeddings. Een vector-embedding is een lijst met vaste lengte met getallen die de betekenis van tekst, afbeeldingen of andere data representeert in een vorm die een database wiskundig kan vergelijken.
Een embeddingmodel maakt de numerieke vectoren. Het neemt invoer zoals een zin, alinea, afbeeldingsbeschrijving of codefragment en geeft een vector met een vast aantal dimensies terug.
Vergelijkbare input zou vectoren moeten opleveren die dicht bij elkaar liggen, terwijl niet-gerelateerde input verder uit elkaar valt. We moeten daarom hetzelfde embeddingmodel gebruiken voor opgeslagen documents en inkomende queries, omdat afstanden alleen betekenis hebben als vectoren hetzelfde coördinatenstelsel delen.
In deze tutorial zijn de handmatige vectoren bewust klein zodat we de wiskunde kunnen inspecteren. De echte tekstembeddings zijn veel groter, omdat het model genoeg dimensies nodig heeft om subtielere relaties tussen woorden, frasen en onderwerpen te coderen.
Vector search rangschikt rijen op basis van de afstand tussen vectoren. Bij Euclidische en cosinusafstandsqueries betekent een kleinere afstand een dichterbijzijnde match. In deze tutorial beginnen we met een kleine VECTOR(3, FLOAT32)-kolom zodat we het afstandsgedrag direct kunnen zien, en gaan daarna naar VECTOR(1536, FLOAT32)-embeddings die uit tekst worden gegenereerd.
Figuur 1. Oracle AI Vector Search-flow
Oracle AI Vector Search slaat embeddings op in een native VECTOR-kolom en rangschikt resultaten op vectorafstand.
Oracle Database is handig wanneer embeddings naast relationele applicatiedata horen, zoals document-ID’s, titels, content, gebruikers, producten, tickets of metadata.
Sommige applicaties gebruiken een aparte vectordatabank of zoekmachine voor gespecialiseerde retrieval-workloads, maar voor de lokale semantische zoekworkflow in deze tutorial levert Oracle Database de vectoropslag en zoekfuncties die we nodig hebben.
Belangrijkste functies van Oracle AI Vector Search
We gebruiken vier Oracle AI Vector Search-functies in de demo: native vectoropslag, afstandsfuncties, vectorindexen en relationele integratie.
Native vectordatatype
Oracle Database ondersteunt native VECTOR-kolommen met expliciete dimensies en elementformaten. In de demo gebruiken we VECTOR(3, FLOAT32) voor handmatige vectoren en VECTOR(1536, FLOAT32) voor het standaard-embeddingmodel text-embedding-3-small.
Afstandfuncties en -operatoren
De uitvoerbare voorbeelden gebruiken VECTOR_DISTANCE() omdat daarmee de afstandsmaat expliciet in SQL blijft.
We gebruiken Euclidische afstand voor het voorbeeld met handmatige vectoren en cosinusafstand voor tekstembeddings.
Oracle Database bevat ook verkorte vectorafstand-operatoren en dotproduct-gerelateerd afstandsgedrag, maar deze tutorial houdt de uitvoerbare SQL op het expliciete pad met VECTOR_DISTANCE().
Verschillende afstandsmaatstaven beantwoorden net andere vragen over “nabijheid.”
Voor een kleine tutorial is cosinusafstand een goede standaard voor tekstembeddings, omdat deze vooral op richting focust, wat vaak goed overeenkomt met semantische gelijkenis.
Euclidische afstand is makkelijker te visualiseren met handgeschreven vectoren, en vergelijkingen in de stijl van dotproduct zijn nuttig in sommige retrievalsystemen wanneer vectorgrootte of genormaliseerde vectoren deel uitmaken van het modelontwerp.
Maatstaf
Wat wordt vergeleken
Goede toepassing
Let op
Cosinus
Vectorrichting
Tekstembeddings en semantische gelijkenis
Resultaten hangen af van hetzelfde embeddingmodel en consistente preprocessing
Euclidisch
Rechte-lijnafstand
Kleine voorbeelden, geometrische intuïtie, sommige numerieke featurevectoren
Grootte beïnvloedt de afstand, dus schaling kan uitmaken
Dotproduct
Richting en grootte samen
Workflows rond genormaliseerde vectoren of inner-product scoring
Score-richting en normalisatieregels moeten duidelijk zijn voor je resultaten vergelijkt
Vectorindexen
Exacte vector search is nuttig voor juistheid en kleine datasets. Naarmate datasets groeien, ondersteunen vectorindexen approximate nearest-neighbor-workflows.
Oracle AI Vector Search bevat in-memory neighbor graph-indexen, vaak geassocieerd met HNSW-zoekopdrachten, en neighbor-partitions-indexen, vaak geassocieerd met IVF-partitionering.
In deze lokale demo gebruiken we ORGANIZATION NEIGHBOR PARTITIONS en valideren de index met USER_INDEXES.
Approximate indexen ruilen een beetje uitputtende-zoek-zekerheid in voor snellere retrieval op schaal.
De juiste indexfamilie hangt af van de workload, datavolume, updatepatroon en recall-doel.
Deze tutorial gebruikt een IVF-achtige neighbor-partitions-index omdat dit de lokale set-up eenvoudig houdt en een concreet index-creatiestap biedt zonder er een index-tuninggids van te maken.
Indexfamilie
Basisidee
Sterke punten
Afwegingen
Wanneer je ’m zou gebruiken
IVF / neighbor partitions
Partitioneer de vectorruimte en doorzoek dan waarschijnlijke partities
Eenvoudig denkkader, praktisch voor veel batch-geladen datasets
Recall en snelheid hangen af van partitionering en zoekinstellingen
We willen een rechtlijnig approximate-zoekpad voor een groeiende dataset
HNSW / neighbor graph
Bouw een graaf die nabijgelegen vectoren koppelt voor snelle traversals
Sterk recall- en latentiebereik voor veel nearest-neighbor-workloads
Meer geheugen-georiënteerd en configuratie kan zwaarder wegen
We hebben lage latency nodig en kunnen geheugen en tuningbudget inzetten
Integratie met relationele queries
Een vectorkolom kan naast gewone relationele kolommen bestaan. Onze documents-tabel slaat titel, content en embedding samen op, zodat SQL zowel de gelijkenisscore als de originele documenttekst kan retourneren.
Aan de slag met Oracle AI Vector Search
We gebruiken één lokaal set-up-pad: Oracle Database Free 26ai in Docker, de FREEPDB1-service en een aparte applicatiegebruiker vector_demo.
De vector-searchconcepten zijn goed te overzien, maar de set-up is intermediate omdat we Docker, een databaseschema, Python-packages, omgevingsvariabelen en een embedding-API-sleutel gebruiken.
Vereisten
We hebben nodig:
Docker Desktop of Docker Engine.
Toegang tot Oracle Container Registry.
Lokale poorten 1521 en 5500 beschikbaar.
Python 3.10 of later.
Basiskennis Python en SQL.
Basiskennis Docker en omgevingsvariabelen.
Een OpenAI API-sleutel voor de embeddingstappen.
Deze demo vereist een Oracle Database-versie of -omgeving die de hier gebruikte vectorfuncties bevat, inclusief native VECTOR-kolommen, VECTOR_DISTANCE() en CREATE VECTOR INDEX.
Het lokale pad gebruikt Oracle Database Free 26ai met de onderstaande image-tag, en de DSN gebruikt de FREEPDB1 pluggable database-service.
De stappen met handmatige vectoren vereisen geen OpenAI API-sleutel. De semantische stappen sturen de voorbeelddocumenttekst en querytekst naar de geconfigureerde embeddingprovider, dus we gebruiken alleen voorbeeld- of niet-gevoelige tekst.
Deze tutorial gebruikt oracledb, de huidige Python-driver voor Oracle Database. python-oracledb draait standaard in Thin-modus, dus voor deze lokale demo zijn geen Oracle Client-libraries nodig. Thick-modus is nuttig in andere Oracle Database-implementaties, maar we roepen hier oracledb.init_oracle_client() niet aan.
Oracle Database Free 26ai lokaal starten
Maak een projectmap voor de scripts die we gaan bouwen.
mkdir oracle-ai-vector-search-python
cd oracle-ai-vector-search-pythonMogelijk gemaakt door
Start Oracle Database Free 26ai met de lokale containerimage.
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-amd64Mogelijk gemaakt door
Controleer de containerlogs en wacht tot de database meldt dat de start is voltooid.
FREEPDB1 is de pluggable database-service die door dit lokale pad met Oracle Database Free-container wordt gebruikt. Onze Python-DSN wordt localhost:1521/FREEPDB1.
Maak het vector_demo-schema in FREEPDB1
Gebruik SYS alleen voor de schemaset-upstap. Het wachtwoord in het sqlplus-commando is de ORACLE_PWD-waarde uit het docker run-commando; het wachtwoord in CREATE USER is het applicatiewachtwoord dat we exporteren als DB_PASSWORD.
Voer de set-up uit binnen de databasecontainer.
# 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
SQLMogelijk gemaakt door
Dit is een lokale ontwikkelsnelkoppeling voor de democontainer. CREATE SEQUENCE is nodig omdat de tabellen identity-kolommen gebruiken.
Voor productie zouden we de privileges met een databasebeheerder doornemen en least privilege toepassen voor precies de applicatieworkload.
Python-afhankelijkheden installeren
Maak en activeer een virtual environment.
python -m venv .venv
source .venv/bin/activate
python -m pip install--upgrade pipMogelijk gemaakt door
Installeer de Python-packages die door de demo worden gebruikt.
Sla databasegegevens en embeddinginstellingen op in omgevingsvariabelen in plaats van ze hard te coderen in Python-bestanden.
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"Mogelijk gemaakt door
OPENAI_API_KEY is alleen nodig voor de embedding- en semantische zoekstappen. EMBEDDING_DIM moet overeenkomen met het aantal dimensies dat door het geselecteerde embeddingmodel wordt geretourneerd.
Oracle AI Vector Search-demoproject
We bouwen de demo in acht checkpoints. Elk script voegt één concept toe en produceert uitvoer die we kunnen verifiëren voordat we verder gaan.
Het alleen-database-checkpoint is voltooid na Stappen 1–3. Op dat punt hebben we verbinding gemaakt met Oracle Database, handmatige vectoren opgeslagen, ze op afstand bevraagd en de semantische tabel gemaakt. De OpenAI API-sleutel wordt vereist in Stap 4.
Stap 1: Maak verbinding met de lokale database
We verifiëren eerst dat Python verbinding kan maken met Oracle Database als de vector_demo-applicatiegebruiker. Dit script leest DB_USER, DB_PASSWORD en DB_DSN uit de omgeving en print de drivermodus en databaseversie.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
De uitvoer moet bevestigen dat de verbinding werkt en dat de driver in Thin-modus staat.
Connected to Oracle Database.
Driver mode: thin
Database version: 23.26.1.0.0Mogelijk gemaakt door
We weten nu dat de lokale database, servicenaam, credentials en Python-driver werken voordat we vectortabellen aanmaken.
Stap 2: Bouw intuïtie op met handmatige vectoren
Voordat we embeddingmodellen introduceren, slaan we drie kleine vectoren op waar we logisch over kunnen redeneren. De aanroep array.array("f", values) maakt een 32-bits floating-pointarray die python-oracledb kan binden in een VECTOR(..., FLOAT32)-kolom.
Figuur 2. Handmatige vectoren en Euclidische afstand.
Het handmatige voorbeeld gebruikt Euclidische afstand. De apple-vector heeft een afstand van 0,0000 omdat deze overeenkomt met de queryvector. De banana-vector staat tweede omdat sqrt((1.0 - 0.9)^2 + (0.0 - 0.1)^2 + (0.0 - 0.0)^2) = 0,1414.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
De identieke vector verschijnt eerst met afstand 0,0000, en de nabije banana-vector verschijnt als tweede.
Created manual_vectors.
Inserted 3 manual vectors.
Nearest manual vectors:
1. apple distance=0.0000
2. banana distance=0.1414Mogelijk gemaakt door
Dit is het kernidee achter vector search: rijen worden gerangschikt op wiskundige nabijheid tot een queryvector. Embeddingmodellen genereren grotere vectoren, maar het databasegedrag blijft hetzelfde.
Stap 3: Maak de semantische documententabel
Nu we weten dat vectoren werken, maken we een echte tabel in applicatiestijl. Het belangrijke detail is dat de dimensie van de vectorkolom moet overeenkomen met de outputdimensie van het embeddingmodel.
De dimensie is onderdeel van het tabelcontract. Als een embeddingmodel 1.536 getallen teruggeeft, moet de kolom gedeclareerd zijn als VECTOR(1536, FLOAT32).
Als we later overstappen op een model met een andere outputlengte, moeten we de vectorkolom opnieuw maken of migreren, zodat inserts en queries compatibele vectoren blijven gebruiken.
Omdat DDL de vectordimensie niet kan binden als een reguliere SQL-bindvariabele, zet het script EMBEDDING_DIM om naar een integer voordat deze in de CREATE TABLE-instructie wordt gebruikt.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
De uitvoer moet het geconfigureerde embeddingmodel en de vectordimensie tonen.
Embedding model: text-embedding-3-small
Embedding dimension: 1536
Recreated documents table.Mogelijk gemaakt door
We hebben het alleen-databasegedeelte voltooid. Oracle Database kan lokaal vectoren opslaan en vergelijken; daarna vervangen we handgeschreven vectoren door embeddings die uit tekst zijn gegenereerd.
Stap 4: Verifieer de dimensie van het embeddingmodel
Voordat we embeddings invoegen, vragen we het embeddingmodel om één vector en verifiëren we de lengte. Dit voorkomt de meest voorkomende fout met vectortabellen: een vector invoegen waarvan de lengte niet overeenkomt met de dimensie van de VECTOR-kolom.
Een embeddingmodel is niet zomaar een tekst-naar-getal-converter; het bepaalt de betekenisspace voor de applicatie. Alle document- en query-embeddings in deze demo moeten uit hetzelfde model komen.
Door één model te gebruiken, zorgen we ervoor dat een kleine afstand vergelijkbare betekenis representeert in plaats van twee niet-gerelateerde vectoren die toevallig een vergelijkbare vorm hebben. Het model bepaalt ook de vectorlengte, daarom controleren we de geretourneerde dimensie voordat we data laden.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
Voor het standaardmodel en de standaarddimensie zou de uitvoer er zo uit moeten zien.
Embedding model: text-embedding-3-small
Returned embedding length: 1536
Configured EMBEDDING_DIM: 1536
Dimension check passed.Mogelijk gemaakt door
Als we later een ander embeddingmodel kiezen, moeten we EMBEDDING_MODEL bijwerken, EMBEDDING_DIM instellen op de geretourneerde vectorlengte en de documents-tabel opnieuw aanmaken.
Stap 5: Genereer en voeg documentembeddings in
Nu genereren we embeddings voor een kleine, zelfstandige dataset en voegen die in in Oracle Database.
Elke embedding wordt geconverteerd naar array.array("f", embedding) vóór het binden, zodat deze overeenkomt met de FLOAT32-vectorkolom.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
Het aantal rijen moet overeenkomen met de zeven inline documents.
Embedding model: text-embedding-3-small
Generated embeddings for 7 documents.
Inserted 7 documents.
documents row count: 7Mogelijk gemaakt door
We hebben nu tekst en embeddings samen opgeslagen in Oracle Database. De niet-gerelateerde documents over gitaar en soep zijn opgenomen, zodat de zoekresultaten duidelijke nabije en verre matches hebben.
Stap 6: Voer een semantische zoekquery uit
Vervolgens embedden we een natuurlijke-taalquery en vergelijken die met opgeslagen documentembeddings. Dit script gebruikt cosinusafstand, wat vaak wordt gebruikt voor tekstembeddings omdat het focust op vectorrichting in plaats van ruwe grootte.
Voor semantisch zoeken gaat de query door hetzelfde embeddingmodel als de documents. We vragen SQL niet om de Engelse zin direct te begrijpen.
We vragen het embeddingmodel om de zin in een vector om te zetten en vragen Oracle Database vervolgens om opgeslagen vectoren te rangschikken op hun afstand tot die queryvector.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
Exacte rangschikkingen en afstanden kunnen variëren als het embeddingmodel verandert. Toch zouden documents over Oracle AI Vector Search, semantisch zoeken, Python-databasecode en vectorindexering hoog moeten eindigen.
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...Mogelijk gemaakt door
Voor de Euclidische en cosinusafstandsqueries in deze tutorial duiden kleinere waarden op betere matches.
Dotproduct is een andere nuttige vergelijkingsmethode in veel vector-search-workflows, vooral wanneer grootte of genormaliseerde vectoren belangrijk zijn, maar score-richting en normalisatie vragen om zorgvuldige behandeling.
We houden de uitvoerbare code bij Euclidische en cosinusafstand zodat de resultaatinterpretatie eenvoudig blijft.
Als we in een toekomstige applicatie zelf embeddings normaliseren, moeten we zowel opgeslagen documentembeddings als query-embeddings consequent normaliseren; anders kunnen afstanden en rangschikkingen veranderen.
Stap 7: Vergelijk semantisch zoeken met een frase-match
Semantisch zoeken is nuttig omdat het niet vereist dat exact dezelfde frase in het document voorkomt.
Laten we de semantische query vergelijken met een eenvoudige predicate voor een exacte frase.
Dit is geen demo van een fulltext-zoekmachine; het is een kleine SQL-vergelijking die het verschil zichtbaar maakt tussen letterlijk matchen en betekenisgebaseerd rangschikken.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
Het semantische zoeken zou relevante documents moeten retourneren, ook al is de exacte keywordfrase niet aanwezig.
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 matchesMogelijk gemaakt door
Traditionele SQL-predicaten blijven belangrijk voor filters, joins, permissies en exact matchen. Vector search voegt een betekenisgebaseerd rangsignaal toe dat we met relationele data kunnen combineren wanneer een applicatie semantische retrieval nodig heeft.
Stap 8: Voeg een vectorindex toe en valideer die
Tot slot maken we een vectorindex en valideren we dat Oracle Database die rapporteert als een geldige index in het demoschema.
Deze stap demonstreert de workflow voor indexcreatie; onze piepkleine dataset is niet groot genoeg voor zinvolle prestatieconclusies.
Zonder index kan Oracle Database de queryvector exact vergelijken met elke opgeslagen vector. Die aanpak is geschikt voor heel kleine datasets en nuttig tijdens het leren.
Bij grotere datasets verkleinen approximate vectorindexen de zoekruimte, zodat queries snel kunnen terugkeren en toch nabije buren vinden.
Kies de indexfamilie na het overwegen van datagrootte, latentiedoelen, recall-eisen, geheugenbudget en hoe vaak vectoren veranderen.
De query aan het eind bevestigt dat semantisch zoeken nog steeds resultaten retourneert na het aanmaken van de index.
We gebruiken hier geen EXPLAIN PLAN of DBMS_XPLAN, omdat deze tutorial indexcreatie valideert met schemametadata, niet met queryplangedrag.
Maak het script
Sla de volgende code op als 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()Mogelijk gemaakt door
De uitvoer moet een rij bevatten voor DOCUMENT_EMBEDDING_IDX, met INDEX_TYPE ingesteld op VECTOR en STATUS op 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.Mogelijk gemaakt door
USER_INDEXES bevestigt dat de index bestaat en geldig is. Het bewijst niet dat een specifieke query de index gebruikte, en deze tutorial gebruikt geen uitvoeringsplanuitvoer als validatiemethode.
Voor productie-workloads zouden we testen met realistisch datavolume, querypatronen en prestatiedoelen.
Oracle AI Vector Search-tips en troubleshooting
De databasecontainer is nog aan het starten
Wacht tot de start is voltooid en voer daarna docker logs oracle-free-26ai-vector opnieuw uit. De database moet klaar zijn voordat Python kan verbinden met localhost:1521/FREEPDB1.
Poort 1521 is al in gebruik
Stop de conflicterende lokale service of wijzig de Docker-poortmapping. Werk DB_DSN bij als de hostpoort verandert.
De databaseverbinding faalt
Controleer DB_USER, DB_PASSWORD en DB_DSN. Gebruik FREEPDB1 in de DSN, en laat applicatiescripts verbinden als vector_demo, niet als SYS, SYSTEM of PDBADMIN.
De embedding-API-sleutel ontbreekt
Stappen 1-3 zijn alleen database. Stappen 4-8 vereisen OPENAI_API_KEY en kunnen API-kosten met zich meebrengen.
Een vectordimensie komt niet overeen
Voer 04_check_embedding_dimension.py uit, werk EMBEDDING_DIM bij, voer 03_create_documents_table.py opnieuw uit en laad de embeddings opnieuw met 05_insert_embeddings.py.
Een vectorbind faalt
Zorg dat elke FLOAT32-vectorbind array.array("f", values) gebruikt. De tutorial gebruikt dit formaat voor handmatige vectoren, opgeslagen documentembeddings en query-embeddings.
Semantische rangorden verschillen van het voorbeeld
Dat is te verwachten. Embeddingproviders kunnen modellen bijwerken, en floating-pointafstanden kunnen tussen runs variëren.
Aanmaken van een vectorindex faalt
Controleer of de documents-tabel bestaat, het vector_demo-schema eigenaar is, en DOCUMENT_EMBEDDING_IDX niet is achtergebleven van een gedeeltelijk uitgevoerde run.
Voorbereiden op productie
Gebruik oracledb.create_pool() voor connection pooling, benchmark realistische datavolumes, beoordeel security en geheimbeheer en tune indexen op echte querypatronen.
Stop en verwijder de container
Als de tutorial klaar is, stop en verwijder de lokale container.
docker stop oracle-free-26ai-vector
dockerrm oracle-free-26ai-vectorMogelijk gemaakt door
Conclusie
We bouwden een lokale workflow voor semantisch zoeken met Oracle AI Vector Search, Oracle Database Free 26ai en Python.
We begonnen met handgeschreven VECTOR(3, FLOAT32)-waarden, voegden modelgegenereerde embeddings in met array.array("f", values), bevraagden vergelijkbare documents met VECTOR_DISTANCE(), vergeleken semantische retrieval met een eenvoudige predicate voor een exacte frase en valideerden een vectorindex via USER_INDEXES.
Deze aanpak past goed wanneer embeddings naast relationele data horen en we opslag en zoekopdrachten zichtbaar in SQL willen, zonder voor de lokale workflow een aparte vectordatabank toe te voegen.
De demo is bewust klein: hij leert de bouwstenen, niet de productieschaal. Grotere applicaties moeten benchmarken met realistische data, security en privileges beoordelen, connection pooling gebruiken en indexkeuzes valideren onder echte querypatronen.
Oracle AI Vector Search LiveLabs biedt hands-on workshops voor vector-embeddings, exacte en approximate search, beeldzoeken en retrieval-augmented generation.
FAQs
Wat is Oracle AI Vector Search?⌄
Oracle AI Vector Search is een set mogelijkheden in Oracle Database voor het opslaan, indexeren en bevragen van vector-embeddings naast relationele data.
Heb ik een OpenAI API-sleutel nodig om de tutorial te voltooien?⌄
De stappen met handmatige vectoren en databaseset-up vereisen geen API-sleutel. Stappen 4-8 vereisen een embeddingprovider en de geconfigureerde OPENAI_API_KEY.
Waarom moet EMBEDDING_DIM overeenkomen met het embeddingmodel?⌄
De dimensie van de VECTOR-kolom moet gelijk zijn aan het aantal waarden dat door het embeddingmodel wordt geretourneerd. Een mismatch zorgt ervoor dat het invoegen van vectoren mislukt.
Welke afstandsmaatstaven gebruikt de tutorial?⌄
Het voorbeeld met handmatige vectoren gebruikt Euclidische afstand. De voorbeelden met semantisch zoeken gebruiken cosinusafstand.
Bewijst een geldige vectorindex dat een query de index heeft gebruikt?⌄
Nee. USER_INDEXES bevestigt dat de index bestaat en een geldige status heeft, maar het bevestigt niet dat een specifieke query die heeft gebruikt.
Mark Nelson is architect en developer evangelist bij Oracle. Hij werkt op het snijvlak van AI, microservices en databasetechnologie. Hij is een actieve blogger, gepubliceerd auteur, technisch reviewer bij Manning Publications, Section Leader bij Stanford Code in Place en mentor bij DeepLearning.ai. Hij spreekt regelmatig bij Java- en Oracle-gebruikersgroepen, AI-meetups en grote conferenties. Hij heeft een passie voor leren en lesgeven. Hij heeft meer dan dertig jaar ervaring in de industrie, bij IBM en Oracle.
Leer hoe je AI in softwareapplicaties kunt integreren met behulp van API's en open-sourcebibliotheken. Begin vandaag nog aan je reis om AI-ingenieur te worden!
In deze tutorial bouwen we een lokale demo voor semantisch zoeken met Oracle AI Vector Search, Python en Oracle Database Free 26ai.
We beginnen met handgeschreven driedimensionale vectoren zodat de afstandsberekening zichtbaar is, genereren daarna tekstembeddings en bevragen die met SQL vanuit Oracle Database.
Deze tutorial is voor Python- en SQL-ontwikkelaars die nieuw zijn met vector search en vertrouwd zijn met Docker, omgevingsvariabelen, Python-packages en een lokale databaseset-up.
AI-gedreven applicaties hebben search nodig die betekenis begrijpt, niet alleen exacte woorden. Een support-app, documentatieportaal of interne kennistool moet “databaseopslag voor AI-zoekopdrachten” kunnen vinden, ook als het best passende document zegt: “vector-embeddings opslaan in native kolommen.”
Vector-embeddings maken dat mogelijk door tekst als numerieke vectoren te representeren. Met Oracle AI Vector Search kunnen we die vectoren rechtstreeks in Oracle Database opslaan, met SQL bevragen en embeddings naast relationele applicatiedata bewaren.
Voor deze lokale workflow hebben we geen aparte vectordatabank nodig.
We draaien Oracle Database Free 26ai lokaal, verbinden vanuit Python met
oracledbThin-modus, slaan eerst handmatige vectoren op, vervolgens OpenAI-embeddings, voeren semantisch zoeken uit, vergelijken semantische retrieval met een eenvoudige exacte frase-predicate en maken een vectorindex die we valideren viaUSER_INDEXES.Aan het eind hebben we een werkende Python-gestuurde semantische zoekworkflow die embeddings opslaat in Oracle Database en de meest vergelijkbare
documentslokaal ophaalt.Wat is Oracle AI Vector Search?
Oracle AI Vector Search is een set mogelijkheden in Oracle Database voor het opslaan, indexeren en bevragen van vector-embeddings. Een vector-embedding is een lijst met vaste lengte met getallen die de betekenis van tekst, afbeeldingen of andere data representeert in een vorm die een database wiskundig kan vergelijken.
Een embeddingmodel maakt de numerieke vectoren. Het neemt invoer zoals een zin, alinea, afbeeldingsbeschrijving of codefragment en geeft een vector met een vast aantal dimensies terug.
Vergelijkbare input zou vectoren moeten opleveren die dicht bij elkaar liggen, terwijl niet-gerelateerde input verder uit elkaar valt. We moeten daarom hetzelfde embeddingmodel gebruiken voor opgeslagen documents en inkomende queries, omdat afstanden alleen betekenis hebben als vectoren hetzelfde coördinatenstelsel delen.
In deze tutorial zijn de handmatige vectoren bewust klein zodat we de wiskunde kunnen inspecteren. De echte tekstembeddings zijn veel groter, omdat het model genoeg dimensies nodig heeft om subtielere relaties tussen woorden, frasen en onderwerpen te coderen.
Vector search rangschikt rijen op basis van de afstand tussen vectoren. Bij Euclidische en cosinusafstandsqueries betekent een kleinere afstand een dichterbijzijnde match. In deze tutorial beginnen we met een kleine
VECTOR(3, FLOAT32)-kolom zodat we het afstandsgedrag direct kunnen zien, en gaan daarna naarVECTOR(1536, FLOAT32)-embeddings die uit tekst worden gegenereerd.Figuur 1. Oracle AI Vector Search-flow
Oracle AI Vector Search slaat embeddings op in een native VECTOR-kolom en rangschikt resultaten op vectorafstand.
Oracle Database is handig wanneer embeddings naast relationele applicatiedata horen, zoals document-ID’s, titels, content, gebruikers, producten, tickets of metadata.
Sommige applicaties gebruiken een aparte vectordatabank of zoekmachine voor gespecialiseerde retrieval-workloads, maar voor de lokale semantische zoekworkflow in deze tutorial levert Oracle Database de vectoropslag en zoekfuncties die we nodig hebben.
Belangrijkste functies van Oracle AI Vector Search
We gebruiken vier Oracle AI Vector Search-functies in de demo: native vectoropslag, afstandsfuncties, vectorindexen en relationele integratie.
Native vectordatatype
Oracle Database ondersteunt native
VECTOR-kolommen met expliciete dimensies en elementformaten. In de demo gebruiken weVECTOR(3, FLOAT32)voor handmatige vectoren enVECTOR(1536, FLOAT32)voor het standaard-embeddingmodeltext-embedding-3-small.Afstandfuncties en -operatoren
De uitvoerbare voorbeelden gebruiken
VECTOR_DISTANCE()omdat daarmee de afstandsmaat expliciet in SQL blijft.We gebruiken Euclidische afstand voor het voorbeeld met handmatige vectoren en cosinusafstand voor tekstembeddings.
Oracle Database bevat ook verkorte vectorafstand-operatoren en dotproduct-gerelateerd afstandsgedrag, maar deze tutorial houdt de uitvoerbare SQL op het expliciete pad met
VECTOR_DISTANCE().Verschillende afstandsmaatstaven beantwoorden net andere vragen over “nabijheid.”
Voor een kleine tutorial is cosinusafstand een goede standaard voor tekstembeddings, omdat deze vooral op richting focust, wat vaak goed overeenkomt met semantische gelijkenis.
Euclidische afstand is makkelijker te visualiseren met handgeschreven vectoren, en vergelijkingen in de stijl van dotproduct zijn nuttig in sommige retrievalsystemen wanneer vectorgrootte of genormaliseerde vectoren deel uitmaken van het modelontwerp.
Maatstaf
Wat wordt vergeleken
Goede toepassing
Let op
Cosinus
Vectorrichting
Tekstembeddings en semantische gelijkenis
Resultaten hangen af van hetzelfde embeddingmodel en consistente preprocessing
Euclidisch
Rechte-lijnafstand
Kleine voorbeelden, geometrische intuïtie, sommige numerieke featurevectoren
Grootte beïnvloedt de afstand, dus schaling kan uitmaken
Dotproduct
Richting en grootte samen
Workflows rond genormaliseerde vectoren of inner-product scoring
Score-richting en normalisatieregels moeten duidelijk zijn voor je resultaten vergelijkt
Vectorindexen
Exacte vector search is nuttig voor juistheid en kleine datasets. Naarmate datasets groeien, ondersteunen vectorindexen approximate nearest-neighbor-workflows.
Oracle AI Vector Search bevat in-memory neighbor graph-indexen, vaak geassocieerd met HNSW-zoekopdrachten, en neighbor-partitions-indexen, vaak geassocieerd met IVF-partitionering.
In deze lokale demo gebruiken we
ORGANIZATION NEIGHBOR PARTITIONSen valideren de index metUSER_INDEXES.Approximate indexen ruilen een beetje uitputtende-zoek-zekerheid in voor snellere retrieval op schaal.
De juiste indexfamilie hangt af van de workload, datavolume, updatepatroon en recall-doel.
Deze tutorial gebruikt een IVF-achtige neighbor-partitions-index omdat dit de lokale set-up eenvoudig houdt en een concreet index-creatiestap biedt zonder er een index-tuninggids van te maken.
Indexfamilie
Basisidee
Sterke punten
Afwegingen
Wanneer je ’m zou gebruiken
IVF / neighbor partitions
Partitioneer de vectorruimte en doorzoek dan waarschijnlijke partities
Eenvoudig denkkader, praktisch voor veel batch-geladen datasets
Recall en snelheid hangen af van partitionering en zoekinstellingen
We willen een rechtlijnig approximate-zoekpad voor een groeiende dataset
HNSW / neighbor graph
Bouw een graaf die nabijgelegen vectoren koppelt voor snelle traversals
Sterk recall- en latentiebereik voor veel nearest-neighbor-workloads
Meer geheugen-georiënteerd en configuratie kan zwaarder wegen
We hebben lage latency nodig en kunnen geheugen en tuningbudget inzetten
Integratie met relationele queries
Een vectorkolom kan naast gewone relationele kolommen bestaan. Onze documents-tabel slaat titel, content en embedding samen op, zodat SQL zowel de gelijkenisscore als de originele documenttekst kan retourneren.
Aan de slag met Oracle AI Vector Search
We gebruiken één lokaal set-up-pad: Oracle Database Free 26ai in Docker, de
FREEPDB1-service en een aparte applicatiegebruikervector_demo.De vector-searchconcepten zijn goed te overzien, maar de set-up is intermediate omdat we Docker, een databaseschema, Python-packages, omgevingsvariabelen en een embedding-API-sleutel gebruiken.
Vereisten
We hebben nodig:
Deze demo vereist een Oracle Database-versie of -omgeving die de hier gebruikte vectorfuncties bevat, inclusief native
VECTOR-kolommen,VECTOR_DISTANCE()enCREATE VECTOR INDEX.Het lokale pad gebruikt Oracle Database Free 26ai met de onderstaande image-tag, en de DSN gebruikt de
FREEPDB1pluggable database-service.De stappen met handmatige vectoren vereisen geen
OpenAIAPI-sleutel. De semantische stappen sturen de voorbeelddocumenttekst en querytekst naar de geconfigureerde embeddingprovider, dus we gebruiken alleen voorbeeld- of niet-gevoelige tekst.Deze tutorial gebruikt
oracledb, de huidige Python-driver voor Oracle Database.python-oracledbdraait standaard in Thin-modus, dus voor deze lokale demo zijn geen Oracle Client-libraries nodig. Thick-modus is nuttig in andere Oracle Database-implementaties, maar we roepen hieroracledb.init_oracle_client()niet aan.Oracle Database Free 26ai lokaal starten
Maak een projectmap voor de scripts die we gaan bouwen.
Start Oracle Database Free 26ai met de lokale containerimage.
Controleer de containerlogs en wacht tot de database meldt dat de start is voltooid.
FREEPDB1is de pluggable database-service die door dit lokale pad met Oracle Database Free-container wordt gebruikt. Onze Python-DSN wordtlocalhost:1521/FREEPDB1.Maak het vector_demo-schema in FREEPDB1
Gebruik
SYSalleen voor de schemaset-upstap. Het wachtwoord in het sqlplus-commando is de ORACLE_PWD-waarde uit het docker run-commando; het wachtwoord in CREATE USER is het applicatiewachtwoord dat we exporteren alsDB_PASSWORD.Voer de set-up uit binnen de databasecontainer.
Dit is een lokale ontwikkelsnelkoppeling voor de democontainer. CREATE SEQUENCE is nodig omdat de tabellen identity-kolommen gebruiken.
Voor productie zouden we de privileges met een databasebeheerder doornemen en least privilege toepassen voor precies de applicatieworkload.
Python-afhankelijkheden installeren
Maak en activeer een virtual environment.
Installeer de Python-packages die door de demo worden gebruikt.
Omgevingsvariabelen instellen
Sla databasegegevens en embeddinginstellingen op in omgevingsvariabelen in plaats van ze hard te coderen in Python-bestanden.
OPENAI_API_KEYis alleen nodig voor de embedding- en semantische zoekstappen.EMBEDDING_DIMmoet overeenkomen met het aantal dimensies dat door het geselecteerde embeddingmodel wordt geretourneerd.Oracle AI Vector Search-demoproject
We bouwen de demo in acht checkpoints. Elk script voegt één concept toe en produceert uitvoer die we kunnen verifiëren voordat we verder gaan.
Het alleen-database-checkpoint is voltooid na Stappen 1–3. Op dat punt hebben we verbinding gemaakt met Oracle Database, handmatige vectoren opgeslagen, ze op afstand bevraagd en de semantische tabel gemaakt. De
OpenAIAPI-sleutel wordt vereist in Stap 4.Stap 1: Maak verbinding met de lokale database
We verifiëren eerst dat Python verbinding kan maken met Oracle Database als de
vector_demo-applicatiegebruiker. Dit script leestDB_USER, DB_PASSWORDenDB_DSNuit de omgeving en print de drivermodus en databaseversie.Maak het script
Sla de volgende code op als
01_check_connection.py.Voer het script uit
Voer de verbindingscheck uit.
Verwachte output
De uitvoer moet bevestigen dat de verbinding werkt en dat de driver in Thin-modus staat.
We weten nu dat de lokale database, servicenaam, credentials en Python-driver werken voordat we vectortabellen aanmaken.
Stap 2: Bouw intuïtie op met handmatige vectoren
Voordat we embeddingmodellen introduceren, slaan we drie kleine vectoren op waar we logisch over kunnen redeneren. De aanroep
array.array("f", values)maakt een 32-bits floating-pointarray diepython-oracledbkan binden in eenVECTOR(..., FLOAT32)-kolom.Figuur 2. Handmatige vectoren en Euclidische afstand.
Het handmatige voorbeeld gebruikt Euclidische afstand. De apple-vector heeft een afstand van 0,0000 omdat deze overeenkomt met de queryvector. De banana-vector staat tweede omdat sqrt((1.0 - 0.9)^2 + (0.0 - 0.1)^2 + (0.0 - 0.0)^2) = 0,1414.
Maak het script
Sla de volgende code op als
02_manual_vectors.py.Voer het script uit
Voer het script met handmatige vectoren uit.
Verwachte output
De identieke vector verschijnt eerst met afstand 0,0000, en de nabije banana-vector verschijnt als tweede.
Dit is het kernidee achter vector search: rijen worden gerangschikt op wiskundige nabijheid tot een queryvector. Embeddingmodellen genereren grotere vectoren, maar het databasegedrag blijft hetzelfde.
Stap 3: Maak de semantische documententabel
Nu we weten dat vectoren werken, maken we een echte tabel in applicatiestijl. Het belangrijke detail is dat de dimensie van de vectorkolom moet overeenkomen met de outputdimensie van het embeddingmodel.
De dimensie is onderdeel van het tabelcontract. Als een embeddingmodel 1.536 getallen teruggeeft, moet de kolom gedeclareerd zijn als
VECTOR(1536, FLOAT32).Als we later overstappen op een model met een andere outputlengte, moeten we de vectorkolom opnieuw maken of migreren, zodat inserts en queries compatibele vectoren blijven gebruiken.
Omdat DDL de vectordimensie niet kan binden als een reguliere SQL-bindvariabele, zet het script
EMBEDDING_DIMom naar een integer voordat deze in de CREATE TABLE-instructie wordt gebruikt.Maak het script
Sla de volgende code op als
03_create_documents_table.py.Voer het script uit
Voer het script voor het maken van de tabel uit.
Verwachte output
De uitvoer moet het geconfigureerde embeddingmodel en de vectordimensie tonen.
We hebben het alleen-databasegedeelte voltooid. Oracle Database kan lokaal vectoren opslaan en vergelijken; daarna vervangen we handgeschreven vectoren door embeddings die uit tekst zijn gegenereerd.
Stap 4: Verifieer de dimensie van het embeddingmodel
Voordat we embeddings invoegen, vragen we het embeddingmodel om één vector en verifiëren we de lengte. Dit voorkomt de meest voorkomende fout met vectortabellen: een vector invoegen waarvan de lengte niet overeenkomt met de dimensie van de
VECTOR-kolom.Een embeddingmodel is niet zomaar een tekst-naar-getal-converter; het bepaalt de betekenisspace voor de applicatie. Alle document- en query-embeddings in deze demo moeten uit hetzelfde model komen.
Door één model te gebruiken, zorgen we ervoor dat een kleine afstand vergelijkbare betekenis representeert in plaats van twee niet-gerelateerde vectoren die toevallig een vergelijkbare vorm hebben. Het model bepaalt ook de vectorlengte, daarom controleren we de geretourneerde dimensie voordat we data laden.
Maak het script
Sla de volgende code op als
04_check_embedding_dimension.py.Voer het script uit
Voer de dimensiecheck uit.
Verwachte output
Voor het standaardmodel en de standaarddimensie zou de uitvoer er zo uit moeten zien.
Als we later een ander embeddingmodel kiezen, moeten we
EMBEDDING_MODELbijwerken,EMBEDDING_DIMinstellen op de geretourneerde vectorlengte en dedocuments-tabel opnieuw aanmaken.Stap 5: Genereer en voeg documentembeddings in
Nu genereren we embeddings voor een kleine, zelfstandige dataset en voegen die in in Oracle Database.
Elke embedding wordt geconverteerd naar
array.array("f", embedding)vóór het binden, zodat deze overeenkomt met deFLOAT32-vectorkolom.Maak het script
Sla de volgende code op als
05_insert_embeddings.py.Voer het script uit
Voer het insertscript uit.
Verwachte output
Het aantal rijen moet overeenkomen met de zeven inline
documents.We hebben nu tekst en embeddings samen opgeslagen in Oracle Database. De niet-gerelateerde
documentsover gitaar en soep zijn opgenomen, zodat de zoekresultaten duidelijke nabije en verre matches hebben.Stap 6: Voer een semantische zoekquery uit
Vervolgens embedden we een natuurlijke-taalquery en vergelijken die met opgeslagen documentembeddings. Dit script gebruikt cosinusafstand, wat vaak wordt gebruikt voor tekstembeddings omdat het focust op vectorrichting in plaats van ruwe grootte.
Voor semantisch zoeken gaat de query door hetzelfde embeddingmodel als de
documents. We vragen SQL niet om de Engelse zin direct te begrijpen.We vragen het embeddingmodel om de zin in een vector om te zetten en vragen Oracle Database vervolgens om opgeslagen vectoren te rangschikken op hun afstand tot die queryvector.
Maak het script
Sla de volgende code op als
06_semantic_search.py.Voer het script uit
Voer het script voor semantisch zoeken uit.
Verwachte output
Exacte rangschikkingen en afstanden kunnen variëren als het embeddingmodel verandert. Toch zouden
documentsover Oracle AI Vector Search, semantisch zoeken, Python-databasecode en vectorindexering hoog moeten eindigen.Voor de Euclidische en cosinusafstandsqueries in deze tutorial duiden kleinere waarden op betere matches.
Dotproduct is een andere nuttige vergelijkingsmethode in veel vector-search-workflows, vooral wanneer grootte of genormaliseerde vectoren belangrijk zijn, maar score-richting en normalisatie vragen om zorgvuldige behandeling.
We houden de uitvoerbare code bij Euclidische en cosinusafstand zodat de resultaatinterpretatie eenvoudig blijft.
Als we in een toekomstige applicatie zelf embeddings normaliseren, moeten we zowel opgeslagen documentembeddings als query-embeddings consequent normaliseren; anders kunnen afstanden en rangschikkingen veranderen.
Stap 7: Vergelijk semantisch zoeken met een frase-match
Semantisch zoeken is nuttig omdat het niet vereist dat exact dezelfde frase in het document voorkomt.
Laten we de semantische query vergelijken met een eenvoudige predicate voor een exacte frase.
Dit is geen demo van een fulltext-zoekmachine; het is een kleine SQL-vergelijking die het verschil zichtbaar maakt tussen letterlijk matchen en betekenisgebaseerd rangschikken.
Maak het script
Sla de volgende code op als
07_semantic_vs_keyword.py.Voer het script uit
Voer het vergelijkingsscript uit.
Verwachte output
Het semantische zoeken zou relevante
documentsmoeten retourneren, ook al is de exacte keywordfrase niet aanwezig.Traditionele SQL-predicaten blijven belangrijk voor filters, joins, permissies en exact matchen. Vector search voegt een betekenisgebaseerd rangsignaal toe dat we met relationele data kunnen combineren wanneer een applicatie semantische retrieval nodig heeft.
Stap 8: Voeg een vectorindex toe en valideer die
Tot slot maken we een vectorindex en valideren we dat Oracle Database die rapporteert als een geldige index in het demoschema.
Deze stap demonstreert de workflow voor indexcreatie; onze piepkleine dataset is niet groot genoeg voor zinvolle prestatieconclusies.
Zonder index kan Oracle Database de queryvector exact vergelijken met elke opgeslagen vector. Die aanpak is geschikt voor heel kleine datasets en nuttig tijdens het leren.
Bij grotere datasets verkleinen approximate vectorindexen de zoekruimte, zodat queries snel kunnen terugkeren en toch nabije buren vinden.
Kies de indexfamilie na het overwegen van datagrootte, latentiedoelen, recall-eisen, geheugenbudget en hoe vaak vectoren veranderen.
De query aan het eind bevestigt dat semantisch zoeken nog steeds resultaten retourneert na het aanmaken van de index.
We gebruiken hier geen EXPLAIN PLAN of DBMS_XPLAN, omdat deze tutorial indexcreatie valideert met schemametadata, niet met queryplangedrag.
Maak het script
Sla de volgende code op als
08_create_vector_index.py.Voer het script uit
Voer het indexscript uit.
Verwachte output
De uitvoer moet een rij bevatten voor
DOCUMENT_EMBEDDING_IDX, metINDEX_TYPEingesteld opVECTORenSTATUSopVALID.USER_INDEXESbevestigt dat de index bestaat en geldig is. Het bewijst niet dat een specifieke query de index gebruikte, en deze tutorial gebruikt geen uitvoeringsplanuitvoer als validatiemethode.Voor productie-workloads zouden we testen met realistisch datavolume, querypatronen en prestatiedoelen.
Oracle AI Vector Search-tips en troubleshooting
De databasecontainer is nog aan het starten
Wacht tot de start is voltooid en voer daarna
docker logs oracle-free-26ai-vectoropnieuw uit. De database moet klaar zijn voordat Python kan verbinden metlocalhost:1521/FREEPDB1.Poort 1521 is al in gebruik
Stop de conflicterende lokale service of wijzig de Docker-poortmapping. Werk
DB_DSNbij als de hostpoort verandert.De databaseverbinding faalt
Controleer
DB_USER, DB_PASSWORDenDB_DSN. GebruikFREEPDB1in de DSN, en laat applicatiescripts verbinden alsvector_demo, niet alsSYS, SYSTEMofPDBADMIN.De embedding-API-sleutel ontbreekt
Stappen 1-3 zijn alleen database. Stappen 4-8 vereisen
OPENAI_API_KEYen kunnen API-kosten met zich meebrengen.Een vectordimensie komt niet overeen
Voer
04_check_embedding_dimension.pyuit, werkEMBEDDING_DIMbij, voer03_create_documents_table.pyopnieuw uit en laad de embeddings opnieuw met05_insert_embeddings.py.Een vectorbind faalt
Zorg dat elke
FLOAT32-vectorbindarray.array("f", values)gebruikt. De tutorial gebruikt dit formaat voor handmatige vectoren, opgeslagen documentembeddings en query-embeddings.Semantische rangorden verschillen van het voorbeeld
Dat is te verwachten. Embeddingproviders kunnen modellen bijwerken, en floating-pointafstanden kunnen tussen runs variëren.
Aanmaken van een vectorindex faalt
Controleer of de
documents-tabel bestaat, hetvector_demo-schema eigenaar is, enDOCUMENT_EMBEDDING_IDXniet is achtergebleven van een gedeeltelijk uitgevoerde run.Voorbereiden op productie
Gebruik
oracledb.create_pool()voor connection pooling, benchmark realistische datavolumes, beoordeel security en geheimbeheer en tune indexen op echte querypatronen.Stop en verwijder de container
Als de tutorial klaar is, stop en verwijder de lokale container.
Conclusie
We bouwden een lokale workflow voor semantisch zoeken met Oracle AI Vector Search, Oracle Database Free 26ai en Python.
We begonnen met handgeschreven
VECTOR(3, FLOAT32)-waarden, voegden modelgegenereerde embeddings in metarray.array("f", values), bevraagden vergelijkbaredocumentsmetVECTOR_DISTANCE(), vergeleken semantische retrieval met een eenvoudige predicate voor een exacte frase en valideerden een vectorindex viaUSER_INDEXES.Deze aanpak past goed wanneer embeddings naast relationele data horen en we opslag en zoekopdrachten zichtbaar in SQL willen, zonder voor de lokale workflow een aparte vectordatabank toe te voegen.
De demo is bewust klein: hij leert de bouwstenen, niet de productieschaal. Grotere applicaties moeten benchmarken met realistische data, security en privileges beoordelen, connection pooling gebruiken en indexkeuzes valideren onder echte querypatronen.
Vervolg je implementatie met deze resources: