cd /news/artificial-intelligence/transparent-rag-pipelines-with-oracl… · home topics artificial-intelligence article
[ARTICLE · art-104393] src=blog.devgenius.io ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Transparent RAG Pipelines with Oracle AI Database + Langchain.js:

Oracle has released a sample TypeScript application demonstrating a transparent RAG pipeline using Oracle AI Database 26ai, LangChain.js, and OCI Generative AI, with code available on GitHub. The app loads text files, summarizes and chunks them, embeds them via the ALL_MINILM_L12_V2 ONNX model, stores vectors in Oracle AI Vector Search, retrieves evidence, and prints both the retrieved context and the final prompt to make the retrieval-augmentation-generation stages visible. The walkthrough includes SQL commands to load the ONNX model and grant privileges, and requires Node.js, npm, and Oracle AI Database 26ai with the model loaded.

read9 min views3 publishedAug 20, 2026

On the back of the launch of our LangChain.js Integration for Oracle AI Database, this blog presents a practical, end-to-end walkthrough of a sample TypeScript application that showcases the individual retrieval, augmentation, and generation stages instead of hiding RAG behind a black box.

The complete sample application is available** ** here. This sample application uses

RAG is usually summarized in one sentence: retrieve relevant information, add it to a prompt, and ask a language model to answer. That definition is correct, but it hides the engineering decisions that determine whether an answer is actually grounded.

This sample application keeps those decisions visible. Two ordinary text files are loaded from disk, summarized, split into overlapping chunks, embedded inside Oracle AI Database, stored in Oracle AI Vector Search, retrieved for a question, inserted into a constrained prompt, and finally sent to OCI Generative AI. The program prints both the retrieved evidence and the completed prompt, so you can see what shaped the answer.

This application would require the latest Node.js and npm installation first and foremost.

We would need the latest Oracle AI Database 26ai setup with the required LLM model loaded for the generation of vector embeddings.

For this sample, we use the ALL_MINILM_L12_V2 ONNX LLM model to generate embeddings. It can be downloaded here. Download the LLM files to any directory that can be accessed by Oracle Database (say /opt/oracle/onnx ).

You would also need to give the corresponding roles and permissions to the application user ( say testuser ) to access and work with the loaded LLM in the database.

Now login to Oracle Database (using your favorite SQL client) and run the following SQL commands as a SYSDBA user and grant the LLM privileges to the application user:

CREATE OR REPLACE DIRECTORY model_dir AS '/opt/oracle/onnx/';EXECUTE dbms_data_mining.drop_model(model_name => 'database', force => true);GRANT READ, WRITE ON DIRECTORY model_dir TO testuser;GRANT DB_DEVELOPER_ROLE, CREATE MINING MODEL TO testuser;ALTER USER testuser QUOTA UNLIMITED ON USERS;GRANT CREATE ANY DIRECTORY TO testuser;

Exit the SQL client and re-login as the application user testuser again to load the LLM for embeddings in Oracle AI Database:

BEGINDBMS_VECTOR.LOAD_ONNX_MODEL(directory  => 'MODEL_DIR',file_name  => 'all_MiniLM_L12_v2.onnx',model_name => 'ALL_MINILM_L12_V2',metadata  => JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));END;/

Now run the following SQL to check if the LLM is properly loaded:

SELECT model_name, algorithm, mining_function FROM user_mining_models WHERE model_name='ALL_MINILM_L12_V2';

You should see an output similar to the following:

MODEL_NAME--------------------------------------------------------------------------------ALGORITHM                MINING_FUNCTION------------------------------ ------------------------------ALL_MINILM_L12_V2ONNX                     EMBEDDING

Now exit the SQL client.

The sample project uses ES modules and has the following dependencies as indicated by the package.json file here:

...  "dependencies": {    "@langchain/core": "^1.1.26",    "@oracle/langchain-oracledb": "^1.0.0",    "oci-common": "^2.139.0",    "oci-generativeaiinference": "^2.139.0"  },  "devDependencies": {    "@types/node": "^25.3.0",    "@types/oracledb": "^6.10.1",    "ts-node": "^10.9.2",    "typescript": "^5.9.3"  }...

The sample also imports node-oracledb directly, so ensure the oracledb package is installed or otherwise available.

Make sure all the above modules are installed and ready to go.

The following environment variables are used by the sample application:

The environment variables related to the OCI Generative AI service (defined by OCI_* ) is specific to the service and the OCI profile being used.

Note that OCI_MODEL_ID needs to be updated to one of the available models as older models are continuously replaced by newer models in the OCI Generative AI service. Keep database passwords, OCI configuration, and compartment identifiers outside source control.

The sample application must have access to an OCI Generative AI service with the dedicated AI cluster (OCI_COMPARTMENT_ID), OCI Generative AI inference endpoint (OCI_ENDPOINT) and the latest LLMs.

The access to the service is usually configured via the OCI configuration file (OCI_CONFIG_FILE) and the profile information (OCI_CONFIG_PROFILE) in the configuration file. This file must be easily accessible by the application.

The corpus (or data source documents) is deliberately small. There are two data files — movies.txt and technology.txt.

The movies.txt file covers cinema topics such as silent films, talkies, CGI, streaming, IMAX, Oppenheimer, and Dune. The *technology.txt *file covers LLMs, Transformers, attention masks, quantum computing, vector databases, embeddings, context, and hallucinations.

This makes retrieval behavior easy to reason about: a question about Transformer attention masks should favor the technology document and a question about cinema topics should favor the movies document.

The application logic is available in the oracle-rag-full-pipeline.ts file.

The pipeline opens a node-oracledb connection and constructs four database-backed helpers: OracleDoc, OracleTextSplitter, OracleEmbeddings, and OracleSummary. The splitter is configured for word-based chunks with a maximum of 30 words, a five-word overlap, and normalization enabled.

const  = new OracleDoc(conn, { dir: DOCUMENTS_FOLDER });const splitter = new OracleTextSplitter(conn, { by: "words", max: 30, overlap: 5, normalize: "all"});const embedder = new OracleEmbeddings(conn, {provider: "database", model: EMBEDDING_MODEL});const summarizer = new OracleSummary(conn, { provider: "database", gLevel: "P" });

Each chunk receives metadata containing sourceFile, chunkId, and a summarySnippet. The code then derives deterministic IDs such as technology_txt_chk_1. Deterministic identifiers make repeated ingestion predictable.

const rawDocs = await .load();const chunks: Document[] = [];for (const doc of rawDocs) {  const summary = await summarizer.getSummary(doc.pageContent);  const textParts = await splitter.splitText(doc.pageContent);  const fileName = doc.metadata.source?.split("/").pop() || "doc";  textParts.forEach((part, idx) => {    chunks.push(      new Document({        pageContent: part.trim(),        metadata: {          sourceFile: fileName,          chunkId: idx + 1,          summarySnippet: summary ? `${summary.slice(0, 60)}...` : "N/A",        },      })    );   });}const deterministicIds = chunks.map(  (c) => `${c.metadata.sourceFile.replace(".", "_")}_chk_${c.metadata.chunkId}`);

Chunking is a retrieval design decision, not a universal constant. Thirty-word chunks make the demo easy to inspect. However with real-time workloads, the user should tune chunk size and overlap against the documents, question patterns, latency targets, and retrieval evaluations.

For repeatability, the sample first purges the FULL_RAG_DEMO_TBL table first. OracleVS.fromDocuments() then writes chunks and embeddings to Oracle Database using the cosine distance technique. The code creates an IVF index named IDX_FULL_RAG_IVF with *32 *neighbor partitions and a target accuracy of 90.

const vectorStore = await OracleVS.fromDocuments(chunks, embedder,{ client: pool, tableName: "FULL_RAG_DEMO_TBL",distanceStrategy: DistanceStrategy.COSINE, query: "Initialization query" },{ ids: deterministicIds, mutateOnDuplicate: true });await createIndex(conn, vectorStore, {idxName: "IDX_FULL_RAG_IVF", idxType: "IVF", neighborPart: 32, accuracy: 90});

The application then runs a similarity search on a user query and requests the top two matches from the designated corpus. In the proposed walkthrough output, both matches come from technology.txt, which is exactly the retrieval behavior this tiny corpus is designed to demonstrate.

    const userQuery = "How do Transformer models use attention masks?";    const searchResults = await vectorStore.similaritySearchWithScore(userQuery, 2);    const tableRows = searchResults.map(([doc, score], idx) => ({      Rank: idx + 1,      "Relevance Match": `${Math.max(0, (1 - Math.abs(score)) * 100).toFixed(1)}%`,      Source: `${doc.metadata.sourceFile} (Chunk #${doc.metadata.chunkId})`,      "Content Snippet": doc.pageContent.replace(/\n/g, " "),    }));

The displayed “Relevance Match” is a demo-friendly transformation: Math.max(0, (1 — Math.abs(score)) * 100). It should not be treated as a universal confidence score. Distance semantics depend on the embedding model, distance strategy, and vector-store implementation; production thresholds should be based on evaluation data.

Retrieval is only the first half of grounding. The application concatenates the retrieved passages as Context 1 and Context 2, then formats a PromptTemplate that explicitly limits the answer to those passages.

You are a helpful AI assistant answering user questions using only the provided context.If the context does not contain enough information to answer, state that clearly.Context:{context}Question: {question}Answer:

Printing the completed prompt is a small but important observability feature. When an answer is weak, you can inspect whether the failure began with document preparation, retrieval, or prompt construction before blaming the model.

The chatWithOci() helper uses OCI TypeScript SDK APIs to send a non-streaming generic chat request with pre-defined AI configuration settings (temperature, topP, maxTokens). The response handler keeps TEXT content, joins the returned parts, and raises explicit errors for empty or unexpected response shapes.

const generatedResponse = await chatWithOci(formattedPrompt, ociConfig);

The important architectural point is that the LLM does not receive the whole source folder. It receives the passages selected at query time and an instruction to stay within that evidence. That is what makes the final response a RAG answer rather than a general model answer.

Run the application as follows:

npx tsx oracle-rag-full-pipeline.ts

What the @oracle/langchain-oracledb integration is doing

OracleDoc: loads source documents from the configured directory.

OracleTextSplitter: performs database-backed text splitting with the chosen word, overlap, and normalization settings.

OracleSummary: creates a short summary used here as chunk metadata.

OracleEmbeddings: generates vectors using the embedding model configured in Oracle Database.

OracleVS: persists documents and embeddings, then performs semantic similarity search.

createIndex: creates the IVF vector index used by the sample.

Together, these abstractions keep the TypeScript orchestration compact while Oracle AI Database provides the vector-search foundation.

Run the pipeline application as supplied, inspect the two retrieved chunks, and compare them with the generated answer. Then ask a cinema question such as “Why do audiences still value IMAX for action-heavy films?” and verify that retrieval moves toward movies.txt. Finally, change the chunk size, overlap, or top-k value in the application code and observe how the retrieved evidence and augmented prompt change.

Those small experiments are the fastest way to make RAG trade-offs tangible: the quality of the final answer begins with the quality of the evidence you retrieve.

Why use Oracle AI Database 26ai for RAG?

It lets the application store and search vector embeddings alongside enterprise data, while this integration exposes document processing, embeddings, vector storage, and indexing through TypeScript-friendly LangChain abstractions.

Where are embeddings generated in this sample?

OracleEmbeddings is configured with provider: “database” and an embedding model. The embedding generation is database-backed.

Does LangChain.js call OCI Generative AI in this example?

Not for the final generation call. LangChain.js drives the database access along with document and prompt abstractions, while the sample calls OCI Generative AI directly through the OCI TypeScript SDKs (oci-common ,oci-generativeaiinference).

Is the displayed relevance percentage a confidence score?

No. It is a readable transformation of the returned score for demonstration. Its meaning is not universal across embedding models or distance metrics.

Why does the sample drop the vector table?

To make each walkthrough run deterministic and self-cleaning. A production system would normally retain the table and update vectors incrementally.

What is the next improvement to make this application production-ready?

Return source citations from sourceFile and chunkId, then add retrieval evaluation, authorization filtering, and production-grade observability.

A useful RAG demo should show more than a final answer. It should show how documents become searchable evidence, why particular passages were retrieved, what the model actually received, and where you would harden the design for production.

This TypeScript example does exactly that. Oracle AI Vector Search supplies the retrieval foundation, @oracle/langchain-oracledb supplies the document and vector abstractions, PromptTemplate makes augmentation explicit, and OCI Generative AI produces the final response. The result is a small pipeline you can inspect end to end — and a practical base for building larger grounded AI applications on Oracle AI Database 26ai.

Transparent RAG Pipelines with Oracle AI Database + Langchain.js: was originally published in Dev Genius on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @oracle 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/transparent-rag-pipe…] indexed:0 read:9min 2026-08-20 ·