IA Avanzada

RAG con Supabase pgvector: tutorial completo

Por Ricardo Gutierrez · · 9 min lectura

Supabase Rag Tutorial

Por qué Supabase para RAG

Si ya usas Supabase (auth, base de datos, storage), no necesitas un servicio vectorial separado. pgvector es una extensión de PostgreSQL que añade soporte para vectores y búsqueda por similitud. Una base de datos, todo incluido.

Activar pgvector

-- En Supabase SQL Editor
create extension if not exists vector;

-- Crear tabla para chunks de documentos
create table documents (
  id bigserial primary key,
  content text not null,
  embedding vector(768),  -- nomic-embed-text: 768 dims
  metadata jsonb default '{}'::jsonb,
  created_at timestamptz default now()
);

-- Crear indice para búsqueda rapida
create index on documents using ivfflat (embedding vector_cosine_ops)
  with (lists = 100);

Generar embeddings

import requests
from supabase import create_client

supabase = create_client(SUPABASE_URL, SUPABASE_KEY)

def get_embedding(text):
    resp = requests.post("http://localhost:11434/api/embeddings",
        json={"model": "nomic-embed-text", "prompt": text})
    return resp.json()["embedding"]

# Indexar documento
chunks = split_document("manual.pdf", chunk_size=500)
for chunk in chunks:
    embedding = get_embedding(chunk)
    supabase.table("documents").insert({
        "content": chunk,
        "embedding": embedding
    }).execute()

Búsqueda semántica

-- Función RPC para búsqueda
create or replace function match_documents(
  query_embedding vector(768),
  match_threshold float default 0.7,
  match_count int default 5
) returns table (id bigint, content text, similarity float) as $$
  select id, content, 1 - (embedding <=> query_embedding) as similarity
  from documents
  where 1 - (embedding <=> query_embedding) > match_threshold
  order by embedding <=> query_embedding
  limit match_count;
$$ language sql;

Pipeline RAG completo

def rag_query(question):
    # 1. Embedding de la pregunta
    q_emb = get_embedding(question)

    # 2. Buscar chunks similares
    results = supabase.rpc("match_documents", {
        "query_embedding": q_emb, "match_count": 3
    }).execute()

    # 3. Generar respuesta con contexto
    context = "\n".join([r["content"] for r in results.data])
    response = client.chat.completions.create(
        model="qwen3:8b",
        messages=[
            {"role": "system", "content": f"Responde basándote en: {context}"},
            {"role": "user", "content": question}
        ]
    )
    return response.choices[0].message.content

Ventajas vs Qdrant/Pinecone

Un servicio menos: si ya usas Supabase, pgvector está incluido. No necesitas gestionar otro servicio.

RLS: Row Level Security permite RAG multi-tenant nativo. Cada usuario solo busca en sus documentos.

Precio: incluido en Supabase. Qdrant/Pinecone son servicios adicionales con coste propio.

Aprende más en IAcademy

Los 3 primeros módulos son gratis. 151 módulos cubriendo Claude API, LangChain, Ollama, fine-tuning y más.

Empieza gratis

Curso completo: 151 módulos de IA aplicada

13 especializaciones. Claude API, LangChain, Ollama, fine-tuning. Dashboard con progreso. Desde 399 EUR.

Ver precios Acceder al portal