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 gratisCurso completo: 151 módulos de IA aplicada
13 especializaciones. Claude API, LangChain, Ollama, fine-tuning. Dashboard con progreso. Desde 399 EUR.