Configurando o Supabase para RAG

Para utilizar a funcionalidade de Retrieval-Augmented Generation (RAG), seu projeto no Supabase precisa ser configurado. Execute os scripts SQL abaixo no seu SQL Editor para preparar seu banco de dados.

1Habilitar a extensão pgvector

A extensão pgvector é essencial para trabalhar com embeddings e realizar buscas por similaridade.

-- Habilita a extensão para cálculos vetoriais
create extension if not exists vector;

2Criar a tabela de documentos

Esta tabela irá armazenar o conteúdo dos seus documentos, metadados e os vetores de embedding.

-- Cria a tabela para armazenar os documentos e seus embeddings
create table if not exists documents (
  id bigint primary key generated always as identity,
  filename text,
  content text,
  metadata jsonb,
  fts tsvector generated always as (to_tsvector('english', content)) stored,
  embedding vector(1536)
);

3Criar índices para otimização

Índices são cruciais para garantir que as buscas na tabela `documents` sejam rápidas e eficientes.

-- Cria um índice GIN para busca full-text
create index if not exists idx_documents_fts on documents using gin(fts);

-- Cria um índice HNSW para busca vetorial por similaridade
create index if not exists idx_documents_embedding on documents using hnsw (embedding vector_ip_ops);

4Criar a função de busca híbrida

Esta função combina a busca por palavra-chave (full-text) com a busca por similaridade semântica (vetorial) para retornar os resultados mais relevantes.

-- Cria a função que combina busca semântica e full-text
create or replace function hybrid_search(
  query_text text,
  query_embedding vector(1536),
  match_count int,
  full_text_weight float = 1,
  semantic_weight float = 1,
  rrf_k int = 50
)
returns setof documents
language sql
as $$
with full_text as (
  select
    id,
    row_number() over(order by ts_rank_cd(fts, websearch_to_tsquery(query_text)) desc) as rank_ix
  from
    documents
  where
    fts @@ websearch_to_tsquery(query_text)
  order by rank_ix
  limit least(match_count, 30) * 2
),
semantic as (
  select
    id,
    row_number() over (order by embedding <#> query_embedding) as rank_ix
  from
    documents
  order by rank_ix
  limit least(match_count, 30) * 2
)
select
  documents.*
from
  full_text
  full outer join semantic
    on full_text.id = semantic.id
  join documents
    on coalesce(full_text.id, semantic.id) = documents.id
order by
  coalesce(1.0 / (rrf_k + full_text.rank_ix), 0.0) * full_text_weight +
  coalesce(1.0 / (rrf_k + semantic.rank_ix), 0.0) * semantic_weight
  desc
limit
  least(match_count, 30)
$$;