LangChain Python Integration
Use LangChain with Oracle AI Database to build RAG, semantic search, hybrid retrieval, semantic caching, chat history, and memory-augmented Python applications.
Contents
- Choose the Package
- Migrate from langchain-community
- Quick Start
- Connect to Oracle AI Database
- Load Documents
- Split Text
- Generate Embeddings
- Use the OracleVS Vector Store
- Create HNSW and IVF Indexes
- Use Semantic Search
- Use Full-Text Search
- Use Hybrid Search
- Filter by Metadata
- Use Async Patterns
- Cache LLM Responses
- Store Chat Message History
- Build Agentic RAG with LangGraph
- Store Agent Memory
- Summarize Documents
- Troubleshoot Common Issues
- Review Reference Links
Choose the Package
The Oracle LangChain ecosystem has two packages that serve different roles. Install one or both packages depending on your use case.
# Database features: vector store, document loading, text splitting, embeddings, and retrievers
pip install -qU langchain-oracledb
# OCI cloud features: LLMs and cloud-hosted embeddings through OCI Generative AI
pip install -qU langchain-oci
# End-to-end RAG on Oracle
pip install -qU langchain-oracledb langchain-oci
# Optional embedding provider used by examples in this guide
pip install -qU langchain-huggingface
| Package | What It Provides | When to Use |
|---|---|---|
langchain-oracledb |
OracleVS, DistanceStrategy, OracleDocLoader, OracleTextSplitter, OracleEmbeddings, OracleSummary, OracleSemanticCache, OracleChatMessageHistory, OracleHybridSearchRetriever, OracleTextSearchRetriever |
Store vectors, load and chunk documents, generate in-database embeddings, cache LLM responses, persist chat history, and use retrieval strategies. |
langchain-oci |
ChatOCIGenAI, OCIGenAI, OCIGenAIEmbeddings, ChatOCIModelDeployment |
Use chat models, completion models, and cloud embeddings through OCI Generative AI. |
Both packages can run side by side, and pip resolves dependencies automatically. This guide focuses on langchain-oracledb. For langchain-oci usage, see the OCI Generative AI LangChain documentation.
Migrate from langchain-community
The langchain-oracledb package replaces the older Oracle integrations that lived in the langchain-community package. If you upgrade an existing project, update your imports.
Old Import (langchain-community) |
New Import (langchain-oracledb) |
|---|---|
from langchain_community.vectorstores.oraclevs import OracleVS |
from langchain_oracledb.vectorstores.oraclevs import OracleVS |
from langchain_community.vectorstores import oraclevs |
from langchain_oracledb.vectorstores import oraclevs |
from langchain_community.document_loaders.oracleai import OracleDocLoader |
from langchain_oracledb.document_loaders.oracleai import OracleDocLoader |
from langchain_community.document_loaders.oracleai import OracleTextSplitter |
from langchain_oracledb.document_loaders.oracleai import OracleTextSplitter |
from langchain_community.embeddings.oracleai import OracleEmbeddings |
from langchain_oracledb.embeddings import OracleEmbeddings |
from langchain_community.utilities.oracleai import OracleSummary |
from langchain_oracledb.utilities.oracleai import OracleSummary |
from langchain_community.vectorstores.utils import DistanceStrategy |
from langchain_oracledb.vectorstores import DistanceStrategy |
The class names and constructor signatures remain the same. For the vector store constants, import DistanceStrategy from langchain_oracledb.vectorstores.
The langchain-oracledb package also adds components that are not available in the community package, including OracleSemanticCache, OracleChatMessageHistory, OracleHybridSearchRetriever, OracleTextSearchRetriever, and OracleVectorizerPreference.
Quick Start
Create a minimal end-to-end pipeline that connects, embeds, stores, and searches documents.
import oracledb
from langchain_core.documents import Document
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_oracledb.vectorstores import DistanceStrategy
from langchain_oracledb.vectorstores.oraclevs import OracleVS
# 1. Connect.
connection = oracledb.connect(
user="myuser",
password="mypass",
dsn="localhost:1521/FREEPDB1",
)
# 2. Prepare documents.
docs = [
Document(
page_content="Oracle AI Database supports vector search natively.",
metadata={"source": "docs"},
),
Document(
page_content="HNSW indexes accelerate approximate nearest-neighbor queries.",
metadata={"source": "docs"},
),
]
# 3. Create embeddings and a vector store.
model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
vs = OracleVS.from_documents(
docs,
model,
client=connection,
table_name="QUICKSTART",
distance_strategy=DistanceStrategy.COSINE,
)
# 4. Search.
results = vs.similarity_search("How does vector search work?", k=2)
for result in results:
print(result.page_content)
Tip: For production workloads, use OracleEmbeddings with a database-resident ONNX model to keep embedding computation inside the database.
For a full implementation, see oracle_langchain_example.ipynb.
Connect to Oracle AI Database
The python-oracledb driver supports two modes. Thin mode is the default and connects without Oracle Client libraries. Thick mode enables additional features when Oracle Client libraries are present.
See the python-oracledb feature comparison to decide which mode you need.
import oracledb
username = "<username>"
password = "<password>"
dsn = "<hostname>:<port>/<service_name>"
connection = oracledb.connect(user=username, password=password, dsn=dsn)
print("Connection successful!")
Connect to Oracle Autonomous AI Database with a Wallet
For Oracle Autonomous AI Database connections that use mutual TLS (mTLS), provide wallet details.
connection = oracledb.connect(
user=username,
password=password,
dsn=tns_name,
config_dir="/path/to/wallet",
wallet_location="/path/to/wallet",
wallet_password="wallet_password",
)
With TLS authentication, wallet_location and wallet_password are not required.
The OracleAutonomousDatabaseLoader source documents these connection patterns.
Use Docker for Local Development
Run Oracle AI Database Free locally for development.
docker run -d --name oracle-free \
-p 1521:1521 -p 5500:5500 \
-e ORACLE_PASSWORD='OraclePwd_2025' \
ghcr.io/gvenzl/oracle-free:23.26.0
Then connect to the database.
connection = oracledb.connect(
user="sys",
password="OraclePwd_2025",
dsn="127.0.0.1:1521/FREEPDB1",
)
For a full Docker setup walkthrough, see the Docker setup section in agent_with_memory.ipynb.
Load Documents
Use OracleDocLoader and OracleAutonomousDatabaseLoader to load files, directories, database table content, or query results as LangChain Document objects.
Load Files, Directories, or Database Tables
OracleDocLoader supports more than 150 file formats, including PDF, DOCX, HTML, and TXT, through Oracle Text document processing. You do not need separate loaders for each file format.
from langchain_oracledb.document_loaders.oracleai import OracleDocLoader
# Load from a local file.
loader = OracleDocLoader(conn=connection, params={"file": "/path/to/document.pdf"})
docs = loader.load()
# Load from a directory.
loader = OracleDocLoader(conn=connection, params={"dir": "/path/to/documents/"})
docs = loader.load()
# Load from an Oracle Database table.
loader = OracleDocLoader(
conn=connection,
params={
"owner": "<owner>",
"tablename": "demo_tab",
"colname": "data",
},
)
docs = loader.load()
print(f"Loaded {len(docs)} documents")
For implementation details, see oracleai.py.
Load SQL Query Results as Documents
OracleAutonomousDatabaseLoader runs SQL, including SQL with bind variables, and returns results as LangChain Document objects.
from langchain_oracledb.document_loaders import OracleAutonomousDatabaseLoader
SQL_QUERY = """
SELECT channel_id, channel_desc
FROM sh.channels
WHERE channel_desc = :1
FETCH FIRST 5 ROWS ONLY
"""
doc_loader = OracleAutonomousDatabaseLoader(
query=SQL_QUERY,
user=username,
password=password,
schema=schema,
dsn=dsn,
parameters=["Direct Sales"],
)
docs = doc_loader.load()
For implementation details, see oracleadb_loader.py.
Split Text
OracleTextSplitter uses Oracle AI Database text processing to chunk documents by characters, words, or sentences.
from langchain_oracledb.document_loaders.oracleai import OracleDocLoader
from langchain_oracledb.document_loaders.oracleai import OracleTextSplitter
# Load documents first.
loader = OracleDocLoader(
conn=connection,
params={
"owner": "<owner>",
"tablename": "demo_tab",
"colname": "data",
},
)
docs = loader.load()
# Split by characters. Use a maximum of 500 characters per chunk.
splitter_params = {"split": "chars", "max": 500, "normalize": "all"}
# Split by words. Use a maximum of 100 words per chunk.
# splitter_params = {"split": "words", "max": 100, "normalize": "all"}
# Split by sentences. Use a maximum of 20 sentences per chunk.
# splitter_params = {"split": "sentence", "max": 20, "normalize": "all"}
# Use the default split.
# splitter_params = {"normalize": "all"}
splitter = OracleTextSplitter(conn=connection, params=splitter_params)
all_chunks = []
for doc in docs:
chunks = splitter.split_text(doc.page_content)
all_chunks.extend(chunks)
print(f"Total chunks: {len(all_chunks)}")
For implementation details, see oracleai.py.
Generate Embeddings
OracleEmbeddings supports database-resident and third-party embedding providers through one class.
For implementation details, see embeddings/oracleai.py.
Constructor
Use the conn, params, and optional proxy arguments to configure an embeddings provider.
OracleEmbeddings(conn=connection, params={"provider": "...", "model": "..."}, proxy=None)
| Parameter | Type | Description |
|---|---|---|
conn |
oracledb.Connection |
Oracle AI Database connection. |
params |
dict |
Provider configuration. |
proxy |
str |
Optional HTTP proxy URL for outbound requests, such as "proxy.corp.example.com:80". |
Use a Database-Resident ONNX Model
Load an ONNX model into Oracle AI Database and generate embeddings without network round trips.
The load_onnx_model static method takes four positional arguments: the connection, an Oracle Directory name, the ONNX file name, and a model label.
from langchain_oracledb.embeddings import OracleEmbeddings
# Prerequisites:
# GRANT CREATE MINING MODEL, CREATE PROCEDURE, CREATE ANY DIRECTORY TO <user>;
# CREATE OR REPLACE DIRECTORY ONNX_DIR AS '/path/to/onnx/files';
# One-time load of an ONNX model into the database.
OracleEmbeddings.load_onnx_model(
connection,
"ONNX_DIR",
"all-minilm-l12-v2.onnx",
"ALL_MINILM_L12_V2",
)
# Use the database-resident model.
embeddings = OracleEmbeddings(
conn=connection,
params={"provider": "database", "model": "ALL_MINILM_L12_V2"},
)
Use OCI Generative AI Embeddings
Configure OracleEmbeddings to call OCI Generative AI through database credentials.
embeddings = OracleEmbeddings(
conn=connection,
params={
"provider": "ocigenai",
"credential_name": "OCI_CRED",
"url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText",
"model": "cohere.embed-english-light-v3.0",
},
)
Use Hugging Face Inference API Embeddings
Configure OracleEmbeddings to call Hugging Face through database credentials.
embeddings = OracleEmbeddings(
conn=connection,
params={
"provider": "huggingface",
"credential_name": "HF_CRED",
"url": "https://api-inference.huggingface.co/pipeline/feature-extraction/",
"model": "sentence-transformers/all-MiniLM-L6-v2",
},
proxy="proxy.corp.example.com:80",
)
Note: For OCI and Hugging Face providers, first create credentials in Oracle AI Database by using the DBMS_VECTOR_CHAIN helper procedures. See the Oracle AI Vector Search Guide.
Generate Query and Document Embeddings
Use embed_query for one query and embed_documents for batches of documents.
# Single query embedding.
vector = embeddings.embed_query("How does vector search work?")
print(f"Dimension: {len(vector)}")
# Batch document embeddings.
vectors = embeddings.embed_documents(
[
"First document text",
"Second document text",
"Third document text",
]
)
print(f"Embedded {len(vectors)} documents")
Note: OracleEmbeddings internally sets oracledb.defaults.fetch_lobs = False to return strings and bytes instead of LOB locators. If shared code depends on LOB locators, use a separate connection or restore the setting after embedding calls.
Use Third-Party Embeddings Directly
You can also use any LangChain-compatible embedding model outside the database.
from langchain_huggingface import HuggingFaceEmbeddings
model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
Note: Hybrid search requires OracleEmbeddings, not third-party embeddings, so that the vectorizer preference matches the embedding configuration.
Use the OracleVS Vector Store
OracleVS is the LangChain vector store integration for Oracle AI Vector Search. It stores document text, metadata, and embedding vectors in one Oracle table.
For implementation details, see oraclevs.py and utils.py.
Understand the Table Schema
When you call OracleVS.from_documents(), it creates a table with this structure.
| Column | Type | Description |
|---|---|---|
id |
VARCHAR2 |
Unique document identifier, generated as a UUID. |
text |
CLOB |
Document text content from page_content. |
metadata |
CLOB |
Document metadata stored as JSON. |
embedding |
VECTOR |
Embedding vector. |
You can inspect the vector store table directly with SQL.
SELECT id, DBMS_LOB.SUBSTR(text, 100, 1) AS preview, metadata
FROM MY_VECTORS
FETCH FIRST 5 ROWS ONLY;
Create a Vector Store
Create a vector store from documents, or instantiate a vector store over an existing table.
from langchain_oracledb.vectorstores import DistanceStrategy
from langchain_oracledb.vectorstores.oraclevs import OracleVS
# Create from documents. This call creates the table automatically.
vs = OracleVS.from_documents(
documents,
embeddings,
client=connection,
table_name="MY_VECTORS",
distance_strategy=DistanceStrategy.COSINE,
)
# Instantiate over an existing table.
vs = OracleVS(connection, table_name="MY_VECTORS", embedding_function=embeddings)
Choose a Distance Strategy
Set the distance strategy to match the embedding model and retrieval response that your application needs.
| Strategy | Constant | Best For |
|---|---|---|
| Cosine similarity | DistanceStrategy.COSINE |
Normalized embeddings. |
| Dot product | DistanceStrategy.DOT_PRODUCT |
Embeddings where magnitude matters. |
| Euclidean distance | DistanceStrategy.EUCLIDEAN_DISTANCE |
Absolute distance comparison. |
Add and Delete Documents
Add raw text with metadata or add LangChain Document objects.
# Add raw texts with metadata.
texts = ["Rohan", "Shailendra"]
metadata = [
{"id": "100", "link": "Document Example Test 1"},
{"id": "101", "link": "Document Example Test 2"},
]
vs.add_texts(texts, metadata)
# Add LangChain Document objects.
from langchain_core.documents import Document
new_docs = [
Document(page_content="New content here", metadata={"id": "200", "source": "api"}),
]
vs.add_documents(new_docs)
# Delete by metadata ID value.
vs.delete(["100"])
Tip: Initialize the vector store with from_documents() for the first batch, then use add_texts() or add_documents() to add more documents incrementally.
For a full implementation, see oracle_langchain_example.ipynb.
Create HNSW and IVF Indexes
Indexes accelerate similarity search over large collections. Oracle AI Vector Search supports HNSW and IVF vector indexes. See Manage Different Categories of Vector Indexes for detailed guidance.
from langchain_oracledb.vectorstores import oraclevs
Create HNSW Indexes
HNSW, or Hierarchical Navigable Small World, is best for high-recall, low-latency approximate nearest-neighbor search.
# Default HNSW index. Uses 8 parallel workers and default accuracy.
oraclevs.create_index(
connection,
vs,
params={"idx_name": "hnsw_idx1", "idx_type": "HNSW"},
)
# HNSW index with target accuracy and parallelism.
oraclevs.create_index(
connection,
vs,
params={
"idx_name": "hnsw_idx2",
"idx_type": "HNSW",
"accuracy": 97,
"parallel": 16,
},
)
# HNSW index with power-user parameters.
oraclevs.create_index(
connection,
vs,
params={
"idx_name": "hnsw_idx3",
"idx_type": "HNSW",
"neighbors": 64,
"efConstruction": 100,
},
)
Create IVF Indexes
IVF, or inverted file index, is best for very large datasets where memory efficiency matters.
# Default IVF index. Uses 8 parallel workers and default accuracy.
oraclevs.create_index(
connection,
vs,
params={"idx_name": "ivf_idx1", "idx_type": "IVF"},
)
# IVF index with target accuracy and parallelism.
oraclevs.create_index(
connection,
vs,
params={
"idx_name": "ivf_idx2",
"idx_type": "IVF",
"accuracy": 90,
"parallel": 32,
},
)
# IVF index with a partition count.
oraclevs.create_index(
connection,
vs,
params={"idx_name": "ivf_idx3", "idx_type": "IVF", "neighbor_part": 64},
)
Review Index Parameters
Use these parameters to configure HNSW and IVF indexes.
| Parameter | HNSW | IVF | Description |
|---|---|---|---|
idx_name |
Yes | Yes | Index name. |
idx_type |
"HNSW" |
"IVF" |
Index algorithm. |
accuracy |
Yes | Yes | Target accuracy percentage. |
parallel |
Yes | Yes | Number of parallel build workers. The default is 8. |
neighbors |
Yes | No | HNSW graph degree, also known as the M parameter. |
efConstruction |
Yes | No | HNSW build-time search width. |
neighbor_part |
No | Yes | IVF partition count. |
For implementations of all six index variants, see oracle_langchain_example.ipynb.
Use Semantic Search
Semantic search finds documents based on meaning rather than exact keyword matches. OracleVS provides similarity search and max marginal relevance search methods.
Understand Filtering with Vector Search
Oracle AI Vector Search supports three filtering stages that work with similarity search.
- Pre-filtering uses traditional SQL filters to reduce the dataset before vector similarity search runs.
- In-filtering uses the vector index to perform similarity search through optimized algorithms.
- Post-filtering uses additional SQL filters to refine results after vector similarity search.
Oracle AI Database automatically determines which filtering strategy to use based on the query, index type, and data distribution. Apply filters through the filter parameter, and Oracle AI Database handles the execution strategy.
Run Basic Similarity Search
Use similarity_search to return matching documents.
results = vs.similarity_search("How are LOBs stored in Oracle Database?", k=2)
for doc in results:
print(doc.page_content)
Run Similarity Search with Scores
Use similarity_search_with_score to return documents and their distance or relevance scores.
results = vs.similarity_search_with_score("How are LOBs stored?", k=2)
for doc, score in results:
print(f"Score: {score:.4f} | {doc.page_content[:80]}...")
Run Max Marginal Relevance Search
Max marginal relevance balances relevance with diversity. Use it when you want varied results instead of only the top nearest neighbors.
results = vs.max_marginal_relevance_search(
"Oracle Database storage",
k=2,
fetch_k=20,
lambda_mult=0.5,
)
Apply Metadata Filters to Search
All search methods support metadata filters.
doc_filter = {"id": "101", "link": "Document Example Test 2"}
results = vs.similarity_search("query", k=2, filter=doc_filter)
results = vs.similarity_search_with_score("query", k=2, filter=doc_filter)
results = vs.max_marginal_relevance_search(
"query",
k=2,
fetch_k=20,
lambda_mult=0.5,
filter=doc_filter,
)
See Filter by Metadata for the full filter syntax.
Use OracleVS as a LangChain Retriever
Convert OracleVS into a retriever for use in chains and agents.
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
retriever = vs.as_retriever(search_kwargs={"k": 5})
llm = ChatOpenAI(model="gpt-4o-mini")
qa = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
answer = qa.run("What is a tablespace in Oracle Database?")
For a full implementation, see oracle_langchain_example.ipynb.
Use Full-Text Search
Full-text search uses the Oracle Text CONTAINS operator for keyword-based retrieval. Use full-text search when users search for specific terms, error codes, product names, or exact phrases.
For implementation details, see text_search.py.
Create a Text Index
Create an Oracle Text index over the built-in text column of an OracleVS table or over another table and column.
from langchain_oracledb.retrievers.text_search import (
OracleTextSearchRetriever,
create_text_index,
)
# Index the built-in text column of an existing OracleVS table.
create_text_index(
connection,
idx_name="IDX_DOCS_TEXT",
vector_store=vs,
)
# Index an arbitrary table and column.
create_text_index(
connection,
idx_name="IDX_MYDOCS_TEXT",
table_name="MYDOCS",
column_name="CONTENT",
)
Build and Use the Text Search Retriever
Use OracleTextSearchRetriever with an OracleVS table or a raw database table.
# When targeting an OracleVS table, returned_columns defaults to ["metadata"].
retriever = OracleTextSearchRetriever(
vector_store=vs,
k=5,
fuzzy=True,
return_scores=True,
)
docs = retriever.invoke("refund policy")
for doc in docs:
print(doc.page_content, doc.metadata.get("score"))
When you target a raw table, use client, table_name, and column_name. You can include extra columns through returned_columns.
retriever = OracleTextSearchRetriever(
client=connection,
table_name="MYDOCS",
column_name="CONTENT",
returned_columns=["title", "author"],
k=5,
)
Choose a Text Search Mode
Default literal mode treats input as literal text, tokenizes on non-word characters, and rewrites the query as an ACCUM expression. With fuzzy=True, each token is wrapped as FUZZY("token") to handle misspellings.
# Fuzzy matching can find "refund policy" from misspelled input.
docs = retriever.invoke("refnd polcy")
Operator mode passes an Oracle Text expression unchanged. It supports NEAR, ABOUT, AND, OR, NOT, WITHIN, and other Oracle Text operators. In this mode, fuzzy is ignored.
retriever_ops = OracleTextSearchRetriever(
vector_store=vs,
operator_search=True,
return_scores=True,
)
docs = retriever_ops.invoke("NEAR((policy, refund), 2, TRUE)")
For more information, see Oracle Text CONTAINS Query Operators and Fuzzy Matching and Stemming.
Use Hybrid Search
Hybrid search combines keyword and semantic signals in one retrieval call. It can produce higher-quality results than either strategy alone.
Note: Hybrid search requires Oracle Database 26ai or later.
For implementation details, see hybrid_search.py.
Understand the Hybrid Search Architecture
The hybrid search pipeline uses three components.
OracleVectorizerPreferencecreates a database-side vectorizer preference withDBMS_VECTOR_CHAIN.create_hybrid_indexbuilds aHYBRID VECTOR INDEXon the table.OracleHybridSearchRetrievercallsDBMS_HYBRID_VECTOR.SEARCHwith configurable search modes.
Set Up Hybrid Search
Hybrid search requires OracleEmbeddings, not third-party embeddings, so that the vectorizer preference matches the embedding configuration.
from langchain_core.documents import Document
from langchain_oracledb.embeddings import OracleEmbeddings
from langchain_oracledb.retrievers.hybrid_search import (
OracleHybridSearchRetriever,
OracleVectorizerPreference,
create_hybrid_index,
)
from langchain_oracledb.vectorstores.oraclevs import OracleVS
# Use OracleEmbeddings. This example uses a database-resident model.
embeddings = OracleEmbeddings(
conn=connection,
params={"provider": "database", "model": "DB_MODEL"},
)
# Create or load your vector store.
vs = OracleVS(connection, table_name="DOCS", embedding_function=embeddings)
Create a Vectorizer Preference and Hybrid Index
Create a named vectorizer preference, then build the hybrid index.
# Create a named vectorizer preference.
pref = OracleVectorizerPreference.create_preference(
vector_store=vs,
preference_name="PREF_DOCS",
)
# Build the hybrid index.
create_hybrid_index(
connection,
idx_name="IDX_DOCS_HYB",
vectorizer_preference=pref,
)
You can also let create_hybrid_index manage a temporary vectorizer preference. Pass vector_store instead of vectorizer_preference.
create_hybrid_index(
connection,
idx_name="IDX_DOCS_HYB2",
vector_store=vs,
params={"parallel": 8},
)
Search with a Hybrid Retriever
Use OracleHybridSearchRetriever to run hybrid, keyword, or semantic search.
retriever = OracleHybridSearchRetriever(
vector_store=vs,
idx_name="IDX_DOCS_HYB",
search_mode="hybrid",
k=5,
return_scores=True,
)
docs = retriever.invoke("refund policy for premium plan")
for doc in docs:
print(
doc.page_content,
doc.metadata.get("score"),
doc.metadata.get("text_score"),
doc.metadata.get("vector_score"),
)
Choose a Hybrid Search Mode
Choose a search mode based on the signal that the user query needs.
| Mode | Signal | When to Use |
|---|---|---|
"hybrid" |
Keyword and vector combined | Default mode for overall recall and precision. |
"keyword" |
Full-text only | Users search for exact terms, codes, or names. |
"semantic" |
Vector only | Users ask conceptual or natural-language questions. |
Tune and Clean Up Hybrid Search
Pass DBMS_HYBRID_VECTOR parameters through the retriever params argument to control score fusion and weighting.
When you no longer need a named vectorizer preference, drop it.
pref.drop_preference()
For more information, see these Oracle AI Vector Search topics:
For a full implementation, see agentic_rag_langchain_oracledb_demo.ipynb.
Filter by Metadata
Oracle AI Vector Search supports pre-filtering, in-filtering, and post-filtering to constrain results before, during, and after similarity search.
Use Filter Operators
Use filter operators to compare metadata values.
| Operator | Description | Example |
|---|---|---|
$eq |
Equals (=) |
{"status": "active"} |
$ne |
Not equals (!=) |
{"status": {"$ne": "archived"}} |
$gt |
Greater than (>) |
{"age": {"$gt": 30}} |
$gte |
Greater than or equal (>=) |
{"age": {"$gte": 30}} |
$lt |
Less than (<) |
{"price": {"$lt": 100}} |
$lte |
Less than or equal (<=) |
{"price": {"$lte": 100}} |
$in |
Value in array | {"category": {"$in": ["A", "B"]}} |
$nin |
Value not in array | {"category": {"$nin": ["C"]}} |
$between |
Between two values, inclusive | {"score": {"$between": [0.5, 1.0]}} |
$exists |
Field exists | {"email": {"$exists": true}} |
$startsWith |
Starts with string | {"name": {"$startsWith": "Ora"}} |
$hasSubstring |
Contains substring | {"desc": {"$hasSubstring": "vector"}} |
$instr |
Contains substring alias | {"desc": {"$instr": "vector"}} |
$regex |
Regular expression | {"code": {"$regex": "^ORA-\\d+"}} |
$like |
SQL LIKE pattern |
{"name": {"$like": "%search%"}} |
$all |
Array contains all items | {"tags": {"$all": ["ai", "db"]}} |
Use Logical Operators
Use logical operators to combine or negate metadata filters.
| Operator | Description |
|---|---|
$and |
Logical AND. |
$or |
Logical OR. |
$nor |
Logical NOR. |
$not |
Negates a comparison operator. |
Apply a Metadata Filter
Apply a metadata filter to any supported vector search method.
db_filter = {
"$and": [
{"id": "101"},
{
"$or": [
{"status": "approved"},
{"link": "Document Example Test 2"},
{
"$and": [
{"status": "approved"},
{"link": "Document Example Test 2"},
]
},
]
},
]
}
results = vs.similarity_search("How are LOBs stored?", k=2, filter=db_filter)
results = vs.similarity_search_with_score("How are LOBs stored?", k=2, filter=db_filter)
results = vs.max_marginal_relevance_search(
"How are LOBs stored?",
k=2,
fetch_k=20,
lambda_mult=0.5,
filter=db_filter,
)
Use Shorthand Filter Syntax
Omit $and when all conditions must be met. These filters are equivalent.
# Explicit.
{"$and": [{"name": {"$startsWith": "Fred"}}, {"salary": {"$gt": 10000, "$lte": 20000}}]}
# Implicit.
{"name": {"$startsWith": "Fred"}, "salary": {"$gt": 10000, "$lte": 20000}}
Use $not to negate a comparison operator.
{"address.zip": {"$not": {"$eq": "90001"}}}
Use field: value as shorthand for field: {"$eq": value}.
{"animal": "cat"}
For more examples, see the filter test specification.
Use Async Patterns
Key langchain-oracledb components support async operations. Use oracledb.connect_async() for the underlying connection.
Create an Async Connection
Create an async connection before calling async index and retrieval operations.
import oracledb
async_connection = await oracledb.connect_async(
user=username,
password=password,
dsn=dsn,
)
Create Indexes Asynchronously
Use async index creation helpers for Oracle Text and hybrid indexes.
from langchain_oracledb.retrievers.hybrid_search import (
OracleVectorizerPreference,
acreate_hybrid_index,
)
from langchain_oracledb.retrievers.text_search import acreate_text_index
# Async text index.
await acreate_text_index(async_connection, idx_name="IDX_TEXT_ASYNC", vector_store=vs)
# Async hybrid index.
pref = await OracleVectorizerPreference.acreate_preference(
vs,
preference_name="PREF_ASYNC",
)
await acreate_hybrid_index(
async_connection,
idx_name="IDX_HYB_ASYNC",
vectorizer_preference=pref,
)
Retrieve Asynchronously
Call ainvoke to retrieve documents asynchronously.
# Text search.
docs = await text_retriever.ainvoke("search query")
# Hybrid search.
docs = await hybrid_retriever.ainvoke("search query")
Note: OracleVS similarity search methods inherit async variants from the LangChain base VectorStore class where available.
Cache LLM Responses
Use OracleSemanticCache to cache LLM generations in Oracle AI Database and retrieve prior responses by semantic similarity instead of exact string matching. The cache stores prompts in an Oracle vector table, stores serialized LangChain generations in metadata, and isolates entries by the LangChain llm_string value so different model configurations do not share responses.
For implementation details, see cache.py.
Create a Semantic Cache
Create the cache with an Oracle connection, a LangChain-compatible embedding model, and an optional vector index.
from langchain_oracledb.vectorstores import DistanceStrategy
from langchain_core.globals import set_llm_cache
from langchain_oracledb import OracleSemanticCache
# Reuse the same embedding model you use for semantic search.
cache = OracleSemanticCache(
client=connection,
embedding=embeddings,
table_name="LANGCHAIN_SEMANTIC_CACHE",
distance_strategy=DistanceStrategy.COSINE,
create_index_if_missing=True,
index_name="IDX_LANGCHAIN_SEMANTIC_CACHE",
score_threshold=0.02,
)
# Install the cache for LangChain LLM calls in this Python process.
set_llm_cache(cache)
Oracle AI Database returns vector distance scores, so lower scores are better. score_threshold is the maximum distance allowed for a cache match. Use a lower value for exact replay, and a higher value when you intentionally want paraphrased prompts to reuse cached answers.
Note: If you install the cache globally for multi-turn agents, start with a tight score_threshold. LangChain cache lookups use the serialized message list, not only the latest user question, so different agent turns can look similar when they share a system prompt and history.
Use the Cache API Directly
Use lookup() and update() directly when you want to cache at the application layer, such as by normalizing the user’s latest question and choosing your own model key.
from langchain_core.outputs import Generation
prompt = "What is Oracle AI Database?"
llm_key = "model=gpt-4o-mini;temperature=0"
cache.update(
prompt,
llm_key,
[Generation(text="Oracle AI Database includes built-in AI and vector features.")],
)
cached = cache.lookup("Explain Oracle AI Database.", llm_key)
if cached is not None:
print(cached[0].text)
Attach the Cache to a Specific Chat Model
In multi-component applications, attach the cache to a specific chat model instead of installing it globally with set_llm_cache(). Per-model attachment lets you cache a user-facing FAQ chain while leaving an agent’s intermediate LLM calls uncached.
from langchain_openai import ChatOpenAI
from langchain_oracledb import OracleSemanticCache
cache = OracleSemanticCache(
client=connection,
embedding=embeddings,
table_name="LANGCHAIN_SEMANTIC_CACHE",
score_threshold=0.05,
)
# Cached: a user-facing question-answer chain.
faq_model = ChatOpenAI(model="gpt-4o-mini", cache=cache)
# Not cached: an agent loop whose prompts change every turn.
agent_model = ChatOpenAI(model="gpt-4o-mini")
Per-model attachment is the recommended pattern for agents because cache lookups use the serialized message list, not only the latest user question. Different agent turns can look semantically similar when they share a system prompt and history, which produces false-positive cache matches.
Measure Cache Effectiveness
Verify that the cache is wired correctly with a timed two-call demo on the same prompt. The first call goes to the LLM and writes a cache entry. The second call looks up by embedding similarity and returns the stored response without contacting the LLM.
import time
from langchain_openai import ChatOpenAI
from langchain_oracledb import OracleSemanticCache
cache = OracleSemanticCache(
client=connection,
embedding=embeddings,
table_name="LANGCHAIN_SEMANTIC_CACHE",
score_threshold=0.05,
)
cache_demo_model = ChatOpenAI(model="gpt-4o-mini", cache=cache, max_tokens=120)
PROMPT = "In one sentence, what is Oracle AI Database?"
t0 = time.perf_counter()
r1 = cache_demo_model.invoke(PROMPT)
miss = time.perf_counter() - t0
t0 = time.perf_counter()
r2 = cache_demo_model.invoke(PROMPT)
hit = time.perf_counter() - t0
assert r1.content == r2.content
print(f"miss: {miss:.2f}s, hit: {hit:.2f}s, speedup: {miss / max(hit, 0.001):.1f}x")
The assertion confirms the cache returned the stored response on the second call. If the cache were not connected, the LLM would generate a different response on the second invocation and the assertion would fail.
Manage Cache Entries
Clear all cache entries, or clear only entries for an exact prompt or model configuration.
# Clear one prompt for every model key.
cache.clear(prompt=prompt)
# Clear every prompt for one model key.
cache.clear(llm_string=llm_key)
# Clear the whole cache table.
cache.clear()
# Drop the backing table when you decommission the cache.
OracleSemanticCache.drop_table(connection, "LANGCHAIN_SEMANTIC_CACHE")
Understand the Semantic Cache Table
OracleSemanticCache uses the same underlying vector-table shape as OracleVS. The prompt text is stored as the searchable text, and cache-specific metadata stores hashes and the serialized return value.
| Metadata Key | Description |
|---|---|
prompt_hash |
SHA-256 hash of the exact prompt text. |
llm_string_hash |
SHA-256 hash of the LangChain model configuration string. |
return_val |
Serialized LangChain Generation objects returned on a cache match. |
Store Chat Message History
Use OracleChatMessageHistory to persist LangChain chat messages in Oracle AI Database. The class implements LangChain’s BaseChatMessageHistory, stores one row per message, preserves insertion order with an identity column, and separates conversations by session_id.
For implementation details, see chat_message_histories.py.
Create a Chat History Table
The constructor creates the backing table and session index by default. For production applications, provision the table once with create_tables(), then instantiate per-session history objects with create_table=False and create_index=False.
from langchain_oracledb import OracleChatMessageHistory
OracleChatMessageHistory.create_tables(
connection,
"LANGCHAIN_CHAT_HISTORY",
)
The default table schema is:
| Column | Type | Description |
|---|---|---|
id |
NUMBER identity primary key |
Preserves message order. |
session_id |
VARCHAR2(255) |
Application-defined conversation identifier. |
message |
CLOB |
Serialized LangChain message payload. |
created_at |
TIMESTAMP WITH TIME ZONE |
Message insert time. |
Add, Read, and Clear Messages
Create a history object for each conversation session. Use history_size to return only the most recent messages while keeping older rows in the table.
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_oracledb import OracleChatMessageHistory
history = OracleChatMessageHistory(
session_id="customer-42",
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
history_size=20,
)
history.add_messages(
[
SystemMessage(content="You are a support assistant."),
HumanMessage(content="My order is late."),
AIMessage(content="I can help check the order status."),
]
)
messages = history.messages
history.clear()
Use RunnableWithMessageHistory
Wrap a chat model or chain with LangChain’s RunnableWithMessageHistory so each invocation automatically loads and writes messages for the configured session.
from langchain_core.messages import HumanMessage
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain_oracledb import OracleChatMessageHistory
def get_session_history(session_id: str) -> OracleChatMessageHistory:
return OracleChatMessageHistory(
session_id=session_id,
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
history_size=20,
)
llm = ChatOpenAI(model="gpt-4o-mini")
chat = RunnableWithMessageHistory(llm, get_session_history)
response = chat.invoke(
[HumanMessage(content="Summarize my last support request.")],
config={"configurable": {"session_id": "customer-42"}},
)
Run a Multi-Turn Conversation
Persistence is durable across application restarts. The next time you open the same session_id, the prior turns are still there. Use this pattern to verify that the table is wired correctly.
from langchain_core.messages import AIMessage, HumanMessage
from langchain_oracledb import OracleChatMessageHistory
SESSION_ID = "planner-priya-2026Q3"
# Turn 1: write a question + answer pair.
history = OracleChatMessageHistory(
session_id=SESSION_ID,
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
)
history.add_messages([
HumanMessage(content="What was our latest soccer merchandise buy recommendation?"),
AIMessage(content="Conservative volumes on cleats, evening promo support."),
])
# Simulate an application restart by opening the same session anew.
reopened = OracleChatMessageHistory(
session_id=SESSION_ID,
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
)
print(f"Recovered {len(reopened.messages)} turns:")
for message in reopened.messages:
print(f" [{type(message).__name__}] {message.content}")
# Turn 2: add a follow-up. Order is preserved by the identity column.
reopened.add_messages([
HumanMessage(content="And the hydration SKU push?"),
AIMessage(content="No standing recommendation yet — fresh planner ran an exploratory query."),
])
Each OracleChatMessageHistory instance reads only the rows for its session_id, so multiple sessions can share one table without filtering on the application side.
Manage Sessions
Use plain SQL through the underlying connection to list active sessions or clean up old conversations. The history table has a session index (create_index=True by default) that keeps these queries fast.
# List the distinct sessions stored in the table.
cur = connection.cursor()
cur.execute(
'SELECT session_id, COUNT(*) AS turns FROM "LANGCHAIN_CHAT_HISTORY" '
'GROUP BY session_id ORDER BY turns DESC'
)
for session_id, turns in cur.fetchall():
print(f" {session_id}: {turns} turns")
# Clear messages for one session.
history_for_session = OracleChatMessageHistory(
session_id="customer-42",
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
)
history_for_session.clear()
# Bulk cleanup: drop conversations older than 30 days.
cur.execute(
'DELETE FROM "LANGCHAIN_CHAT_HISTORY" '
"WHERE created_at < SYSTIMESTAMP - INTERVAL '30' DAY"
)
connection.commit()
Use OracleChatMessageHistory.drop_table(connection, "LANGCHAIN_CHAT_HISTORY") to decommission the table entirely.
Combine Cache and Chat History
A real chat application typically uses both primitives together. OracleSemanticCache short-circuits the LLM call when a similar prompt has already been answered. OracleChatMessageHistory persists the conversation so the next session can resume where the user left off. Both layers reside in the same Oracle AI Database, share the same connection, and participate in the same transactions.
from langchain_core.messages import HumanMessage
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain_oracledb import OracleChatMessageHistory, OracleSemanticCache
# Cache: same connection, same embedder.
cache = OracleSemanticCache(
client=connection,
embedding=embeddings,
table_name="LANGCHAIN_SEMANTIC_CACHE",
score_threshold=0.05,
)
# Chat model: attach the cache to this specific instance.
chat_model = ChatOpenAI(model="gpt-4o-mini", cache=cache)
def get_session_history(session_id: str) -> OracleChatMessageHistory:
return OracleChatMessageHistory(
session_id=session_id,
client=connection,
table_name="LANGCHAIN_CHAT_HISTORY",
create_table=False,
create_index=False,
history_size=20,
)
# History: load and write messages around each chat invocation.
chat = RunnableWithMessageHistory(chat_model, get_session_history)
# First turn: cache miss + LLM call + write to history.
response_1 = chat.invoke(
[HumanMessage(content="What is supply-chain demand planning?")],
config={"configurable": {"session_id": "planner-priya"}},
)
# Same question, same session: cache hit, no LLM call, history still appended.
response_2 = chat.invoke(
[HumanMessage(content="What is supply-chain demand planning?")],
config={"configurable": {"session_id": "planner-priya"}},
)
Both LANGCHAIN_SEMANTIC_CACHE and LANGCHAIN_CHAT_HISTORY are plain Oracle tables. You can join them with your own application tables, back them up with RMAN, and run SQL analytics over them — all the same operational tooling that protects the rest of your data.
Build Agentic RAG with LangGraph
Use LangGraph to build a ReAct agent that dynamically chooses vector, keyword, or hybrid retrieval.
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
@tool
def vector_search(query: str) -> str:
"""Search documents by semantic meaning."""
docs = vs.similarity_search(query, k=3)
return "\n".join([doc.page_content for doc in docs])
@tool
def keyword_search(query: str) -> str:
"""Search documents by exact keyword match."""
docs = text_retriever.invoke(query)
return "\n".join([doc.page_content for doc in docs])
@tool
def hybrid_search(query: str) -> str:
"""Search documents using keyword and semantic signals."""
docs = hybrid_retriever.invoke(query)
return "\n".join([doc.page_content for doc in docs])
llm = ChatOpenAI(model="gpt-4o-mini")
agent = create_react_agent(llm, tools=[vector_search, keyword_search, hybrid_search])
response = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "What is the refund policy for premium plans?",
}
]
}
)
For a full implementation, see agentic_rag_langchain_oracledb_demo.ipynb.
Store Agent Memory
Oracle AI Database provides ACID-compliant, semantically searchable storage for agent memory.
Store Memory in Vector Tables
Use OracleVS to store different memory types in separate vector-enabled tables.
from langchain_oracledb.vectorstores import DistanceStrategy
from langchain_oracledb.vectorstores import oraclevs
from langchain_oracledb.vectorstores.oraclevs import OracleVS
# Knowledge base. Stores semantic search over documents.
knowledge_vs = OracleVS.from_documents(
knowledge_docs,
embeddings,
client=connection,
table_name="AGENT_KNOWLEDGE",
distance_strategy=DistanceStrategy.COSINE,
)
oraclevs.create_index(
connection,
knowledge_vs,
params={"idx_name": "idx_knowledge", "idx_type": "HNSW"},
)
# Summary memory. Stores compressed conversation summaries.
summary_vs = OracleVS.from_documents(
[],
embeddings,
client=connection,
table_name="AGENT_SUMMARIES",
distance_strategy=DistanceStrategy.COSINE,
)
Store Conversation History with OracleChatMessageHistory
Use OracleChatMessageHistory for ordered, session-scoped conversation turns. One table can store many sessions, and history_size limits the number of messages returned to the agent without deleting older rows.
from langchain_core.messages import AIMessage, HumanMessage
from langchain_oracledb import OracleChatMessageHistory
history = OracleChatMessageHistory(
session_id="thread-1001",
client=connection,
table_name="AGENT_CONVERSATION_HISTORY",
history_size=12,
)
history.add_messages(
[
HumanMessage(content="Which supplier is at risk?"),
AIMessage(content="Supplier A is at risk because lead time increased."),
]
)
recent_messages = history.messages
For details, see Store Chat Message History.
Compare Database Memory with Filesystem Memory
Database-backed agent memory provides stronger guarantees than filesystem-backed memory.
| Dimension | Filesystem | Oracle AI Database |
|---|---|---|
| Concurrency | Race conditions and no database locking. | ACID transactions. |
| Search | Filename and path search. | Semantic, keyword, and hybrid search. |
| Scale | Single computer. | Clustered and distributed deployments. |
| Durability | Local disk failure can cause data loss. | Write-ahead logging, backups, and replication. |
| Access control | Operating system permissions. | Row-level security and encryption. |
For full implementations, see these notebooks:
- 6 Types of Persistent Agent Memory
- Filesystem vs. Database Memory Benchmarks
- Memory and Context Engineering for Agents
Summarize Documents
OracleSummary provides document summarization directly within the database by using Oracle text processing or external providers.
The get_summary() method accepts str, Document, list[str], or list[Document] input.
Use the Database Provider
Use the database provider to summarize document text.
from langchain_oracledb.utilities.oracleai import OracleSummary
summarizer = OracleSummary(
conn=connection,
params={
"provider": "database",
"glevel": "paragraph",
"numParagraphs": 2,
},
)
summary = summarizer.get_summary("Long document text goes here...")
print(summary)
Use an External Provider
Use an external provider, such as Cohere, through database credentials.
summarizer = OracleSummary(
conn=connection,
params={
"provider": "cohere",
"credential_name": "COHERE_CRED",
"url": "https://api.cohere.com/v1/summarize",
"model": "command",
},
proxy="proxy.corp.example.com:80",
)
summary = summarizer.get_summary("Long document text goes here...")
Summarize Batches
Use get_summary() with lists for batch summarization.
from langchain_core.documents import Document
# Summarize a list of strings.
summaries = summarizer.get_summary(["First document text", "Second document text"])
# Summarize a list of Documents.
summaries = summarizer.get_summary(
[
Document(page_content="First document text"),
Document(page_content="Second document text"),
]
)
Note: For external providers, such as Cohere and OCI Generative AI, first create credentials in Oracle AI Database by using DBMS_VECTOR_CHAIN helper procedures.
Troubleshoot Common Issues
Use these troubleshooting patterns for common local development, indexing, and runtime issues.
Docker Container Is Not Ready
Oracle AI Database can take 30 to 60 seconds to initialize after docker run. If a connection fails immediately after you start the container, wait and retry.
import time
import oracledb
def connect_with_retry(user, password, dsn, max_retries=5, delay=10):
for attempt in range(max_retries):
try:
return oracledb.connect(user=user, password=password, dsn=dsn)
except oracledb.OperationalError:
if attempt < max_retries - 1:
print(f"Waiting for database... (attempt {attempt + 1}/{max_retries})")
time.sleep(delay)
else:
raise
Duplicate Key Errors on add_texts
Calling add_texts() with the same metadata id values on a table that enforces uniqueness raises an error. Delete existing records first or catch the exception.
try:
vs.add_texts(texts, metadata)
except Exception as ex:
print(f"Duplicate detected: {ex}")
Oracle Text Index Errors
If create_text_index fails, check the Oracle Text error log.
SELECT * FROM ctx_user_index_errors ORDER BY err_timestamp DESC;
macOS ARM64 and Thick Mode
If you need Oracle Client libraries on Apple Silicon, note that Oracle does not provide native ARM64 Instant Client for macOS. Thin mode is the default, does not require these libraries, and works on all platforms.
Only switch to thick mode when you need features listed in the python-oracledb feature comparison.
ORA-01805 Date and Time Errors
The ORA-01805: possible error in date/time operation error can occur with LangChain SQL agents when timezone settings do not match. Set the session timezone explicitly.
cursor = connection.cursor()
cursor.execute("ALTER SESSION SET TIME_ZONE = 'UTC'")
fetch_lobs Side Effects
OracleEmbeddings internally sets oracledb.defaults.fetch_lobs = False. If shared code depends on LOB locators, use a separate connection for embeddings or reset the flag after embedding calls.
oracledb.defaults.fetch_lobs = True
Review Reference Links
Use these links for package documentation, source code, Oracle AI Vector Search documentation, and notebooks.
Package and API Documentation
Review the package and API documentation for langchain-oracledb, langchain-oci, and the python-oracledb driver.
| Resource | Link |
|---|---|
PyPI: langchain-oracledb |
pypi.org/project/langchain-oracledb |
PyPI: langchain-oci |
pypi.org/project/langchain-oci |
Source: langchain-oracle repository |
github.com/oracle/langchain-oracle |
Source: langchain-oracledb package |
github.com/oracle/langchain-oracle/tree/main/libs/oracledb |
| LangChain integration documentation | docs.langchain.com/…/vectorstores/oracle |
| OCI Generative AI integration documentation | docs.langchain.com/…/providers/oci |
python-oracledb driver |
python-oracledb.readthedocs.io |
Source Code
Review the source code for the main langchain-oracledb components.
| Module | Link |
|---|---|
OracleVS vector store |
oraclevs.py |
| Vector store utilities | utils.py |
OracleHybridSearchRetriever |
hybrid_search.py |
OracleTextSearchRetriever |
text_search.py |
OracleSemanticCache |
cache.py |
OracleChatMessageHistory |
chat_message_histories.py |
OracleEmbeddings |
embeddings/oracleai.py |
OracleDocLoader and OracleTextSplitter |
document_loaders/oracleai.py |
OracleAutonomousDatabaseLoader |
document_loaders/oracleadb_loader.py |
| Filter test specification | test_oraclevs.py |
Oracle AI Vector Search Documentation
Review the Oracle AI Vector Search documentation for vector indexes, hybrid search, and Oracle Text.
| Resource | Link |
|---|---|
| Vector index types | Manage Different Categories of Vector Indexes |
| Understand Hybrid Search | Understand Hybrid Search |
CREATE_PREFERENCE |
CREATE_PREFERENCE |
CREATE_HYBRID_VECTOR_INDEX |
CREATE_HYBRID_VECTOR_INDEX |
DBMS_HYBRID_VECTOR.SEARCH |
DBMS_HYBRID_VECTOR.SEARCH |
Oracle Text CONTAINS operators |
Oracle Text CONTAINS Query Operators |
| Fuzzy matching and stemming | Fuzzy Matching and Stemming |
| Thin and thick mode feature comparison | python-oracledb feature comparison |
Notebooks
Review Oracle and LangChain notebooks for complete examples.
| Notebook | Description |
|---|---|
oracle_langchain_example.ipynb |
End-to-end ingest, index, search, and filter workflow. |
agentic_rag_langchain_oracledb_demo.ipynb |
Agentic RAG with vector, keyword, and hybrid retrieval through LangGraph. |
agent_with_memory.ipynb |
Persistent agent memory patterns. |
fs_vs_dbs.ipynb |
Filesystem and database memory benchmarks with ACID concurrency tests. |
memory_context_engineering_agents.ipynb |
Memory and context engineering patterns for AI agents. |
| End-to-End RAG Pipeline | Complete RAG pipeline from the LangChain cookbook. |
| Oracle AI Developer Hub | Repository of notebooks, applications, and reference materials. |
Community and Learning Resources
Review these resources for labs, articles, and related learning material.
| Resource | Link |
|---|---|
| Oracle LiveLabs AI Agent Workshop | livelabs.oracle.com Workshop 4185 |
| Multi-Agent RAG with A2A Protocol | Oracle Developer Blog |
| DeepLearning.AI Agent Memory Course | Agent Memory: Building Memory-Aware Agents |