Architecting Production-Ready RAG AI Agents with OpenAI & pgvector
How to build low-latency Retrieval-Augmented Generation (RAG) pipelines using PostgreSQL, pgvector cosine similarity, semantic search, and streaming responses.
Retrieval-Augmented Generation (RAG) enables Large Language Models (LLMs) to answer domain-specific queries accurately by grounding responses in private knowledge bases without fine-tuning model weights.
In projects like Try Rehearse AI and Nutrition AI App, I implemented low-latency vector similarity pipelines using PostgreSQL and the pgvector extension.
High-Level RAG Architecture
[ User Question ] ──▶ [ text-embedding-3-small ] ──▶ ( 1536-dim Vector )
│
▼
[ PostgreSQL / pgvector ]
Query: <=> Cosine Distance
│
▼
[ LLM Generation (GPT-4o) ] ◀── [ Top K Chunks + System Prompt ]1. Schema & Vector Indexing
-- Enable vector extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Documents table with vector embedding column
CREATE TABLE knowledge_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
document_id UUID REFERENCES documents(id) ON DELETE CASCADE,
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
embedding vector(1536) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- HNSW Index for sub-millisecond similarity search
CREATE INDEX idx_knowledge_embedding_hnsw
ON knowledge_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);2. Similarity Search Query
import { sql } from "drizzle-orm";
import { db } from "@/lib/db";
export async function findRelevantChunks(queryEmbedding: number[], limit = 4, threshold = 0.78) {
const embeddingString = `[${queryEmbedding.join(",")}]`;
const results = await db.execute(sql`
SELECT
id,
content,
metadata,
1 - (embedding <=> ${embeddingString}::vector) AS similarity
FROM knowledge_chunks
WHERE 1 - (embedding <=> ${embeddingString}::vector) > ${threshold}
ORDER BY similarity DESC
LIMIT ${limit};
`);
return results.rows;
}Key Best Practices
- Chunk Overlap: Use a recursive text splitter with 500-token chunks and 100-token overlap to maintain semantic continuity.
- Metadata Filtering: Filter by user ID or organization ID before performing vector calculations for multi-tenant isolation.
- Prompt Hardening: Instruct the model to strictly cite sources and state "I don't have enough information" when similarity scores fall below the threshold.