-- Migration 002 — busca hibrida e leitura cirurgica no schema `tigre`. -- -- Motivo (medido em 02/09/2026, 346 chunks / 190 arquivos): -- 1. O indice ivfflat com lists=100 sobre 346 linhas da ~3,5 linhas por -- lista. Com o padrao ivfflat.probes=1 a busca varre ~3 de 346 linhas, -- e varias consultas voltavam VAZIAS. recall@5 do conjunto dourado -- (rag/bench.py): 33%. Trocamos por HNSW, que nao particiona. -- 2. A busca densa pura erra nomes exatos de tipo (`FCPXMLValidator` nao -- aparecia no top-5 do proprio arquivo). Adicionamos `symbols` + -- indices GIN trgm para o lado lexico da fusao. -- 3. Os chunks nao guardavam faixa de linhas, entao o agente lia o -- arquivo inteiro depois da busca. `start_line`/`end_line` permitem -- ler so a janela relevante. -- -- Idempotente: seguro rodar mais de uma vez. -- -- COMO RODAR (precisa ser rag_admin — o rag_tigre_indexer nao tem DDL): -- -- rag/ensure_tunnel.sh -- psql -h 127.0.0.1 -p 55435 -U rag_admin -d rag_tigre \ -- -f rag/migrations/002-tigre-search.sql -- -- A senha do rag_admin esta em admin/VPS-ACCESS.md. -- -- DEPOIS DE RODAR: reindexar do zero e obrigatorio. -- rag/reindex_tigre.sh --full -- Os embeddings passam a usar o prefixo `search_document: ` exigido pelo -- nomic-embed-text; vetores antigos e novos nao sao comparaveis entre si. BEGIN; -- --------------------------------------------------------------------- -- 1. Indice vetorial: ivfflat -> HNSW -- --------------------------------------------------------------------- DROP INDEX IF EXISTS tigre.code_chunks_embedding_idx; CREATE INDEX IF NOT EXISTS code_chunks_embedding_hnsw_idx ON tigre.code_chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64); -- --------------------------------------------------------------------- -- 2. Metadados de chunk: faixa de linhas, simbolos, modulo, tipo -- --------------------------------------------------------------------- ALTER TABLE tigre.code_chunks ADD COLUMN IF NOT EXISTS start_line int; ALTER TABLE tigre.code_chunks ADD COLUMN IF NOT EXISTS end_line int; ALTER TABLE tigre.code_chunks ADD COLUMN IF NOT EXISTS symbols text; ALTER TABLE tigre.code_chunks ADD COLUMN IF NOT EXISTS module text; -- kind: 'decl' (declaracao Swift), 'header' (imports + doc do tipo), -- 'window' (fallback por janela de linhas, usado fora do Swift) ALTER TABLE tigre.code_chunks ADD COLUMN IF NOT EXISTS kind text; -- --------------------------------------------------------------------- -- 3. Indices lexicos (pg_trgm) — o lado keyword da busca hibrida -- --------------------------------------------------------------------- CREATE INDEX IF NOT EXISTS code_chunks_file_path_trgm_idx ON tigre.code_chunks USING gin (file_path gin_trgm_ops); CREATE INDEX IF NOT EXISTS code_chunks_symbols_trgm_idx ON tigre.code_chunks USING gin (symbols gin_trgm_ops); -- Filtro de escopo por modulo (--module TigreAI). CREATE INDEX IF NOT EXISTS code_chunks_module_idx ON tigre.code_chunks (module); -- --------------------------------------------------------------------- -- 4. Mapa de arquivos — 1 linha por arquivo, para responder "onde fica X" -- sem trazer nenhum corpo de codigo. -- --------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS tigre.file_index ( file_path text PRIMARY KEY, module text, main_type text, public_symbols text[], summary text, n_lines int, content_hash text, updated_at timestamp DEFAULT now() ); CREATE INDEX IF NOT EXISTS file_index_module_idx ON tigre.file_index (module); CREATE INDEX IF NOT EXISTS file_index_path_trgm_idx ON tigre.file_index USING gin (file_path gin_trgm_ops); -- --------------------------------------------------------------------- -- 5. Permissoes do usuario de indexacao/busca -- --------------------------------------------------------------------- GRANT SELECT, INSERT, UPDATE, DELETE ON tigre.file_index TO rag_tigre_indexer; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA tigre TO rag_tigre_indexer; COMMIT; -- Conferencia rapida (rode a mao depois): -- \d tigre.code_chunks -- SELECT indexname FROM pg_indexes WHERE schemaname = 'tigre';