Skip to main content

Supabase Easy RAG

License: MIT Python 3.10+ PostgreSQL 17+ pgvector

A modular, lightweight Hybrid RAG engine built natively on PostgreSQL & Supabase.

Why Supabase Easy RAG?

  • 🎯 High-Accuracy Hybrid Search: Combines semantic vector search with keyword matching — catches both conceptual questions and exact IDs/terms.
  • 📖 Parent-Context Expansion: Searches precise 400-token chunks for high retrieval precision (89%+ Document Top-1, 92%+ Fact Recall), while feeding the full parent section to your LLM.
  • 🔒 Native Multi-Tenant Security: Out-of-the-box Row-Level Security (RLS) via Supabase Auth (auth.uid()) — users only see documents they own or are shared with them.
  • ⚡ High-Speed Parallel Ingestion: Automatic change detection (SHA-256) verifies 700+ docs/sec incrementally, with multi-threaded embedding generation.
  • 🌍 Battle-Tested Multilingual: Evaluated across 11 languages with automatic text search dictionary fallbacks.
  • 🔌 Zero Framework Overhead: Clean Python SDK and pure PostgreSQL RPCs. No heavy dependencies.

📊 Comprehensive Multilingual Benchmark (TyDi QA)

Evaluated against the complete Google Research TyDi QA gold-standard validation corpus (4,488 authentic Wikipedia articles, 5,077 real human questions across 11 typologically diverse languages) with 400-character chunking and Reciprocal Rank Fusion (RRF).

1. Global Information Retrieval (IR) Quality Metrics

Benchmark Metric Score Description
Document Hit Rate @ 1 (Top-1) 88.46% Ground-truth relevant document is ranked #1 (Strict Document Match)
Document Hit Rate @ 3 (Top-3) 91.61% Ground-truth relevant document in Top-3 retrieved chunks
Document Hit Rate @ 5 (Top-5) 92.34% Ground-truth relevant document in Top-5 retrieved chunks
Document Hit Rate @ 10 (Top-10) 92.75% Ground-truth relevant document in Top-10 retrieved chunks
Document MRR (Mean Reciprocal Rank) 0.9012 Average reciprocal rank on ground-truth document retrieval
Answer Span Recall @ 5 91.90% Exact fact-answer span is contained in the top-5 retrieved chunks
Incremental Verification Speed 651.5 docs/sec 4,488 documents verified via SHA-256 in 6.9 seconds (16 parallel workers)

[!NOTE] Metric Rigor:

  • Document Hit Rate @ K strictly requires the retrieved chunk to belong to the target ground-truth document.
  • Answer Span Recall @ K verifies that the exact answer span is present in the retrieved chunk content for QA generation.
  • Full benchmark is 100% reproducible via python eval/corpora/fetch_tydiqa.py and python eval/benchmark.py.

2. Multilingual Breakdown Across 11 Languages

Language Language Family Evaluated Queries Doc Hit @ 1 Doc Hit @ 5 Doc MRR Answer Recall @ 5
Arabic Afroasiatic (Semitic) 964 89.2% 92.8% 0.908 92.0%
Finnish Uralic (Agglutinative) 920 90.0% 93.0% 0.913 92.9%
Russian Indo-European (Slavic) 828 91.5% 93.8% 0.926 93.2%
Telugu Dravidian 668 89.1% 92.8% 0.906 93.1%
Indonesian Austronesian 499 89.4% 91.8% 0.903 91.6%
Swahili Niger-Congo (Bantu) 475 87.4% 92.6% 0.895 91.6%
English Germanic 278 87.1% 89.9% 0.883 91.0%
Korean Koreanic 194 75.8% 85.0% 0.795 83.0%
Japanese Japonic 139 82.0% 89.2% 0.854 88.5%
Bengali Indo-Aryan 111 76.6% 91.9% 0.834 90.1%
Thai Kra-Dai 1 100.0% 100.0% 1.000 100.0%

Quick Start

1. Installation

pip install supabase-easy-rag

2. Apply Database Migrations to Supabase

Export and run the SQL migrations:

easy-rag init-sql --output ./migrations --dimensions 1536

Apply 01_schema.sql and 02_functions.sql to your Supabase project (via Supabase CLI supabase db query --file ... or SQL Editor).

3. Configure Environment Variables

SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_SERVICE_ROLE_KEY="your-service-role-key"

# Embedding Provider (OpenAI or Azure OpenAI)
OPENAI_API_KEY="sk-..."
# or Azure:
AZURE_OPENAI_API_KEY="your-azure-key"
AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com"
AZURE_OPENAI_EMBEDDING_DEPLOYMENT="text-embedding-3-large"

💻 Python SDK Usage

1. Hybrid Search with Parent-Context Expansion

from supabase_easy_rag import EasyRagClient
from supabase_easy_rag.providers.azure import AzureEmbeddingProvider

# Initialize provider & client
provider = AzureEmbeddingProvider(
    api_key="...",
    endpoint="https://your-resource.openai.azure.com",
    model="text-embedding-3-large",
)
client = EasyRagClient(embedding_provider=provider)

# Search by dense chunk, expand to full parent section for LLM context
results = client.search_hybrid(
    query="When was the Ottoman Empire established?",
    match_count=5,
    candidate_count=50,
    rrf_k=60,
    expand_context="section",  # "section" or "document"
)

for item in results:
    print(f"[{item.final_score:.4f}] {item.document_title} > {item.section_title}")
    # Effective text contains the full parent section text
    print(item.effective_text[:200] + "...")

2. High-Throughput Parallel Directory Ingestion

# Sync a directory of Markdown documents with 8 parallel workers
sync_stats = client.sync_directory(
    directory_path="./knowledgebase_docs",
    batch_size=30,
    max_workers=8,
    enable_chunking=True,
    chunk_size=800,
    chunk_overlap=100,
)

print(f"Synced {sync_stats['total_files']} files in parallel.")

3. Asynchronous Client (FastAPI / High-Concurrency)

from supabase_easy_rag import AsyncEasyRagClient

async_client = AsyncEasyRagClient(embedding_provider=provider)

results = await async_client.search_hybrid(
    query="PostgreSQL connection pooling guidelines",
    match_count=3,
    expand_context="section",
)

🛠️ CLI Commands

# Export migration files
easy-rag init-sql --dimensions 1536 --output ./migrations

# Sync directory of documents
easy-rag sync ./docs --workers 8

# Execute test query with diagnostics
easy-rag query "What is distributed erasure coding?" --mode hybrid --count 5

# Manage backend API access tokens
easy-rag create-token "Production Ingestion Worker"
easy-rag list-tokens

⚙️ Architecture & Implementation Details

  • Two-Stage Hybrid Fusion: Independent candidate pools are retrieved via indexed scans (HNSW for vector distance, GIN for full-text match) and fused using Reciprocal Rank Fusion: $$RRF_Score = \frac{w_v}{k + rank_v} + \frac{w_t}{k + rank_t}$$ This avoids arbitrary score normalization issues between cosine similarities and BM25/FTS weights.
  • Weighted Lexical Search: Uses PostgreSQL native setweight() indexing where document titles receive Weight A ($1.0$), section headings receive Weight B ($0.4$), and chunk text receives Weight D ($0.1$).
  • Candidate Pre-filtering: Full-text candidate scans limit initial matches to Top-200 before applying ts_rank to minimize CPU cycles on frequent keywords.
  • Multi-Tenant Security: Enforces database-level isolation via Supabase Auth (auth.uid()) using Row-Level Security (RLS) policies on documents and chunks.

📄 License

Distributed under the MIT License. See LICENSE for details.

Metadata

Release files for supabase-easy-rag 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for supabase-easy-rag 0.1.2
File Size Uploaded
supabase_easy_rag-0.1.2.tar.gz 101.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for supabase-easy-rag 0.1.2
File Interpreter ABI Platform
supabase_easy_rag-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 142.9 kB

Release files / supabase_easy_rag-0.1.2.tar.gz

Download URL supabase_easy_rag-0.1.2.tar.gz
Size 101.9 kB
Tags Source
SHA-256 checksum
How to use checksums
6a3964f0eedc8805ec5bed8447f563aa86f5cf27491626220af4512a8e5d39e3
BLAKE2b-256 checksum
How to use checksums
3dd7cd9c4b37b791a5e9dd426aca425e761359eaf0369851d6799645a6908630
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / supabase_easy_rag-0.1.2-py3-none-any.whl

Download URL supabase_easy_rag-0.1.2-py3-none-any.whl
Size 41.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b00c31800c76a4d5368f383c2e48fe61e06e14beaee218a7897f8f46fadb61c
BLAKE2b-256 checksum
How to use checksums
b09326e71a68ca32a41f3acfb70bfeb186a2dc7eb923bc2c455a29bead283c38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page