Implementar pesquisa vetorial e RAG com PostgreSQL e pgvector
Voltar para a trilha AI-200
AI-200Capítulo 13

Estudo para a Certificação Microsoft AI-200

Implementar pesquisa vetorial e RAG com PostgreSQL e pgvector

Armazene embeddings no Banco de Dados do Azure para PostgreSQL, escolha métricas de distância e índices ANN, mantenha vetores em evolução, crie recuperação semântica e híbrida e fundamente respostas RAG com citações rastreáveis.

Tempo de estudo sugerido: 130 minutos • Nível intermediário • Reescrita autoral completa com versão resumida de cada tópico, avaliação comentada e laboratório guiado de pesquisa vetorial

Escudo neon Microsoft Certified AI-200 com vetores PostgreSQL, índices pgvector, recuperação semântica e pipeline RAG

1. Transformar um PostgreSQL existente em recuperador de IA

Imagine um sistema jurídico que já mantém de documentos e clientes no . Advogados precisam localizar casos, cláusulas e precedentes pelo significado, mesmo quando a pergunta e a fonte usam palavras diferentes. Manter embeddings junto aos dados relacionais elimina outro banco vetorial e a sincronização entre sistemas, sem impedir ingestões diárias e consultas em escala com baixa latência.

  • Armazenar e consultar embeddings com pgvector.
  • Escolher a métrica e executar pesquisa por similaridade.
  • Selecionar e ajustar índices de vizinhos mais próximos aproximados.
  • Atualizar vetores e migrar modelos de embedding com segurança.
  • Criar recuperação semântica, híbrida e RAG com citações e qualidade mensurável.

Resumo do tópico

O pgvector leva recuperação semântica aos dados PostgreSQL existentes e reduz componentes e sincronizações adicionais.

2. Habilitar pgvector e projetar esquemas vetoriais

No servidor flexível do , inclua primeiro a extensão na lista de permissões do servidor, confirme com SHOW .extensions e crie-a em cada banco que a utilizará. A comunidade diz pgvector, mas o binário e o nome SQL são vector. Normalmente a operação exige o administrador do servidor ou participação em azure_pg_admin.

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE knowledge_chunks (
  id BIGSERIAL PRIMARY KEY,
  source_id BIGINT NOT NULL,
  chunk_no INTEGER NOT NULL,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  category TEXT,
  token_count INTEGER,
  embedding vector(1536),
  embedding_stale BOOLEAN NOT NULL DEFAULT false,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (source_id, chunk_no)
);

A dimensão de vector(n) deve coincidir exatamente com a saída do modelo. Vetores de 384, 1.536 e 3.072 dimensões não podem compartilhar uma coluna restrita sem transformação. Guarde com o vetor os usados para filtrar e exibir; separe textos muito grandes somente quando a redução de tráfego compensar o JOIN.

Colunas distintas atendem embeddings de título e corpo ou modelos diferentes. INSERT, INSERT de várias linhas e COPY carregam vetores; ao mudar o conteúdo, o embedding correspondente precisa ser regenerado.

O conteúdo vira embedding, é armazenado com metadados PostgreSQL e comparado ao vetor da consulta por distância L2, de cosseno ou produto interno.
Dimensão do esquema, saída do modelo e operador de consulta devem representar o mesmo espaço vetorial.

Resumo do tópico

Autorize e crie vector por banco e associe cada coluna à dimensão e à finalidade de um único espaço de embeddings.

3. Escolher vector, halfvec ou sparsevec

Tipos de armazenamento do pgvector.
TipoRepresentaçãoQuando usar
vectorPontos flutuantes de 32 bits; cerca de 6 KB em 1.536 dimensões.Padrão para embeddings densos e bom equilíbrio entre precisão e espaço.
halfvecPontos flutuantes de 16 bits; aproximadamente metade do armazenamento.Depois de testes confirmarem que a precisão menor preserva a relevância.
sparsevecSomente valores diferentes de zero e suas posições.Saídas de alta dimensão realmente esparsas.

Comece com vector para embeddings densos. Valide halfvec com métricas de qualidade antes da economia de espaço. O HNSW sobre sparsevec aceita no máximo 1.000 elementos não nulos; acima disso, reduza dimensões ou selecione outra estratégia.

Resumo do tópico

Use vector como padrão, halfvec após validação de qualidade e sparsevec somente para representações genuinamente esparsas.

4. Alinhar operadores de distância ao modelo

-- Euclidean/L2: smaller means nearer
SELECT id, title, embedding <-> $1::vector AS distance
FROM knowledge_chunks ORDER BY embedding <-> $1::vector LIMIT 8;

-- Cosine distance: common for text embeddings
SELECT id, title, embedding <=> $1::vector AS distance
FROM knowledge_chunks ORDER BY embedding <=> $1::vector LIMIT 8;

-- Negative inner product: smaller means a larger dot product
SELECT id, title, embedding <#> $1::vector AS distance
FROM knowledge_chunks ORDER BY embedding <#> $1::vector LIMIT 8;
Semântica das distâncias.
OperadorMétricaInterpretação
<->L2 / euclidianaDistância em linha reta; a magnitude pode importar.
<=>Distância de cossenoÂngulo entre vetores; comum em pesquisa semântica de texto.
<#>Produto interno negativoProduto escalar negado para manter os menores valores primeiro.

Nos três operadores, menor significa mais próximo. Siga a recomendação do modelo. Vetores normalizados podem aproveitar produto interno com eficiência, enquanto cosseno é um padrão frequente para texto. Envie o vetor como parâmetro, sem concatená-lo ao SQL.

Resumo do tópico

A métrica precisa refletir a geometria do modelo, e todas as distâncias do pgvector são ordenadas do menor para o mais semelhante.

5. Entender pesquisa exata, ANN, recall e DiskANN

Sem índice, o PostgreSQL compara o vetor de consulta com todas as linhas e encontra os vizinhos exatos. O recall é perfeito, mas o custo cresce linearmente; pode ser aceitável abaixo de aproximadamente dez mil linhas e lento em milhões.

A pesquisa ANN examina um subconjunto estruturado. Recall mede a parcela dos vizinhos exatos presente no resultado aproximado; muitos sistemas aceitam 95–99% para obter milissegundos. O também oferece DiskANN por pg_diskann, com alto recall e throughput, escala orientada a disco, compilações rápidas, quantização de produto e, em versões recentes, dimensões maiores que HNSW/IVFFlat.

Resumo do tópico

Pesquisa exata maximiza recall; ANN troca uma pequena parcela dele por grande redução de latência, e DiskANN acrescenta uma opção para grande escala.

6. Criar e ajustar IVFFlat

Na criação, IVFFlat usa k-means e separa vetores em lists ao redor de centroides. A consulta encontra os centroides próximos e pesquisa o número de listas indicado por probes; o trabalho aproximado é (linhas / lists) × probes.

  • Carregue dados representativos antes do índice; uma tabela vazia não treina úteis.
  • Até cerca de um milhão de linhas, comece com linhas / 1.000 para lists; acima disso, use aproximadamente a raiz quadrada.
  • Comece probes próximo de sqrt(lists); elevar melhora recall e aumenta latência.
  • Reconstrua se uma carga grande ou de outro domínio tornar os antigos pouco representativos.

Resumo do tópico

IVFFlat economiza memória e compila rapidamente, mas depende de dados de treinamento e do equilíbrio entre lists e probes.

7. Criar e ajustar HNSW

HNSW constrói um grafo de proximidade em camadas. A busca parte de uma camada superior esparsa, segue conexões promissoras e desce até candidatos próximos. Diferente do IVFFlat, pode nascer em uma tabela vazia e evoluir com inserções.

CREATE INDEX chunks_embedding_hnsw_idx
ON knowledge_chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 96);

SET LOCAL hnsw.ef_search = 100;

-- Alternative after representative data exists
CREATE INDEX chunks_embedding_ivfflat_idx
ON knowledge_chunks USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

SET LOCAL ivfflat.probes = 10;

m limita conexões por nó: valores maiores podem elevar recall, memória e tempo de compilação. ef_construction amplia candidatos durante a criação e melhora o grafo às custas de tempo. ef_search amplia a exploração na consulta; aumente-o somente quando o recall medido exigir.

Resumo do tópico

HNSW costuma entregar melhor relação velocidade/recall, pagando com mais memória, criação mais lenta e inserções moderadamente custosas.

8. Escolher o índice e provar seu uso

Seleção de índice ANN.
FatorIVFFlatHNSW
Velocidade/recallBomGeralmente melhor
CompilaçãoMais rápidaMais lenta
MemóriaMenorMaior
Tabela vaziaNão é útilCompatível
InserçõesRápidasModeradas

Prefira HNSW quando baixa latência e alto recall dominarem e houver memória. Prefira IVFFlat quando compilação, memória ou recargas em lote forem prioritárias. A classe deve casar com o operador: vector_l2_ops com <->, vector_cosine_ops com <=> e vector_ip_ops com <#>. Uma divergência impede o índice de atender à ordenação.

EXPLAIN (ANALYZE, VERBOSE, BUFFERS)
SELECT id, title
FROM knowledge_chunks
ORDER BY embedding <=> $1::vector
LIMIT 10;

Em tabela grande com ORDER BY de distância e LIMIT, procure Index Scan. Seq Scan pode ser correto em tabela pequena. Confirme ainda validade do índice, estatísticas atualizadas e presença de LIMIT.

Pesquisa exata, IVFFlat, HNSW e DiskANN comparados por recall, latência, memória, criação e sinais de manutenção.
A escolha de índice é uma decisão medida e revisável.

Resumo do tópico

Escolha com dados da carga, alinhe classe e operador e confira o plano real em vez de presumir uso do índice.

9. Monitorar, reconstruir e recuperar espaço

pg_stat_user_indexes mostra varreduras e tamanho; zero usos pode revelar operador incompatível ou decisão do planejador. Acompanhe EXPLAIN ANALYZE e recall de consultas representativas. pg_stat_progress_create_index exibe fases e progresso da criação.

Latência crescente sem volume equivalente, qualidade menor ou aproximadamente 20–30% de dados novos de outro domínio sinalizam reconstrução. Sem indisponibilidade, crie substituto com CREATE INDEX CONCURRENTLY, valide, remova o antigo e renomeie. REINDEX é mais simples se uma interrupção de gravação for aceitável.

Estime vector como dimensões × 4 bytes × linhas, mais cerca de 1,5–2 vezes esse volume para HNSW ou 1–1,5 vez para IVFFlat. MVCC deixa tuplas mortas após atualizações: VACUUM reaproveita espaço; VACUUM FULL devolve mais ao disco, mas bloqueia. Tabelas muito atualizadas podem precisar de limites menores de autovacuum.

Resumo do tópico

Estatísticas, planos, recall, substituição concorrente e vacuum mantêm índices vetoriais saudáveis.

10. Atualizar embeddings sem bloquear conteúdo

O embedding fica obsoleto quando o significado da fonte muda. Em alterações raras, conteúdo e novo vetor podem ser confirmados juntos, mas isso acopla a gravação à de embeddings. Em alta frequência, marque linhas obsoletas, processe lotes assíncronos, gere vetores em grupo e limpe o sinalizador apenas após gravar.

-- Content writes stay fast and mark the vector as stale
UPDATE knowledge_chunks
SET content = $1, embedding_stale = true, updated_at = now()
WHERE id = $2;

-- A worker claims a bounded batch without colliding with peers
SELECT id, content
FROM knowledge_chunks
WHERE embedding_stale
ORDER BY updated_at
FOR UPDATE SKIP LOCKED
LIMIT 250;

-- The worker writes the regenerated vector
UPDATE knowledge_chunks
SET embedding = $1::vector, embedding_stale = false
WHERE id = $2;

Uma atualização integral agendada corrige falhas e normaliza mudanças de configuração. Priorize linhas antigas, respeite limites da , use transações controladas—em grandes backfills, muitas vezes 1.000–5.000 linhas—e monitore replicação, bloqueios, WAL e crescimento de índices.

Resumo do tópico

Use atualização atômica para poucos eventos e sinalizadores com workers em lote para corpora dinâmicos.

11. Migrar modelos com colunas paralelas

Vetores de modelos ou dimensões diferentes não pertencem ao mesmo espaço. Sobrescrever a coluna ativa mistura semânticas incompatíveis. Adicione uma segunda coluna, crie o índice correspondente, preencha em lotes, compare versões em avaliação rotulada, altere as leituras de uma vez e mantenha o caminho antigo até não precisar de .

ALTER TABLE knowledge_chunks ADD COLUMN embedding_v2 vector(3072);

CREATE INDEX CONCURRENTLY chunks_embedding_v2_idx
ON knowledge_chunks USING hnsw (embedding_v2 vector_cosine_ops);

-- Backfill in bounded batches, compare recall and latency, then switch reads.
-- Keep the original column until the new model passes acceptance tests.

Calcule o prazo por quantidade de linhas, throughput do lote, cotas da e tentativas. Durante a migração, duas colunas e dois índices exigem capacidade temporária adicional.

Resumo do tópico

Colunas paralelas evitam espaços misturados, permitem comparar qualidade e preservam .

12. Combinar similaridade, e limiares

SELECT id, title, content, category,
       embedding <=> $1::vector AS distance
FROM knowledge_chunks
WHERE category = $2
  AND embedding <=> $1::vector < $3
ORDER BY embedding <=> $1::vector
LIMIT $4;

Índices B-tree em filtros frequentes, inclusive compostos, reduzem candidatos. Filtros muito seletivos podem levar o planejador aos índices relacionais; filtros amplos favorecem o índice vetorial. ANALYZE e EXPLAIN ANALYZE revelam a escolha.

LIMIT sempre devolve até N linhas, mesmo ruins. Um limiar de distância define qualidade mínima e pode retornar vazio corretamente. Derive-o de pares relevantes e irrelevantes rotulados. Traga título, conteúdo, citação e distância em uma ida ao banco, sem transferir o texto inteiro quando um resumo basta.

Resumo do tópico

limitam o escopo, limiares impõem relevância mínima e planos mostram como o PostgreSQL combina acessos.

13. Tratar consultas multivetoriais e híbridas

Faça a média de vetores de exemplos quando todos expressarem um único conceito. Mantenha vetores separados quando houver requisitos independentes e combine a evidência de candidatos recuperados para cada aspecto.

Semântica pode subestimar nomes exatos, códigos ou jargão. A pesquisa de texto completo do PostgreSQL fornece classificação lexical, acelerada por GIN sobre tsvector armazenado ou gerado. A recuperação híbrida une candidatos. A fusão recíproca de classificação (RRF) combina posições sem fingir que distância vetorial e relevância textual usam a mesma escala.

WITH semantic AS (
  SELECT id, row_number() OVER (ORDER BY embedding <=> $1::vector) AS rank
  FROM knowledge_chunks ORDER BY embedding <=> $1::vector LIMIT 40
), lexical AS (
  SELECT id, row_number() OVER (
    ORDER BY ts_rank_cd(to_tsvector('simple', content), websearch_to_tsquery('simple', $2)) DESC
  ) AS rank
  FROM knowledge_chunks
  WHERE to_tsvector('simple', content) @@ websearch_to_tsquery('simple', $2)
  LIMIT 40
)
SELECT k.id, k.title,
       coalesce(1.0 / (60 + s.rank), 0) + coalesce(1.0 / (60 + l.rank), 0) AS rrf_score
FROM knowledge_chunks k
LEFT JOIN semantic s ON s.id = k.id
LEFT JOIN lexical l ON l.id = k.id
WHERE s.id IS NOT NULL OR l.id IS NOT NULL
ORDER BY rrf_score DESC LIMIT 10;

Resumo do tópico

Use média para um conceito, recuperação separada para conceitos distintos e RRF quando significado e termos exatos forem importantes.

14. Projetar o modelo de documentos e para RAG

RAG transforma a pergunta em vetor, recupera evidências e orienta o modelo de linguagem com esse contexto. Documentos inteiros são amplos demais; separe da fonte de pesquisáveis.

CREATE TABLE source_documents (
  id BIGSERIAL PRIMARY KEY,
  title TEXT NOT NULL,
  source_url TEXT,
  document_type TEXT,
  version INTEGER NOT NULL DEFAULT 1,
  ingested_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE document_chunks (
  id BIGSERIAL PRIMARY KEY,
  document_id BIGINT NOT NULL REFERENCES source_documents(id) ON DELETE CASCADE,
  chunk_no INTEGER NOT NULL,
  section_title TEXT,
  page_number INTEGER,
  content TEXT NOT NULL,
  token_count INTEGER NOT NULL,
  embedding vector(1536),
  UNIQUE (document_id, chunk_no)
);

CREATE INDEX chunks_source_order_idx ON document_chunks(document_id, chunk_no);
Estratégias de segmentação.
EstratégiaForçaRisco / uso
Tamanho fixo previsíveis e simples.Pode cortar ideias; útil sem estrutura clara.
Limites semânticosPreserva parágrafos, seções, cláusulas ou respostas.Tamanhos variáveis; ideal para material estruturado.
SobreposiçãoPreserva conceitos na fronteira.Aumenta espaço e evidências duplicadas.

Guarde seção, página, offsets e para reconstruir contexto e citações. Envie embeddings e inserts em lote. Uma substituição pode excluir antigos por cascata; quando histórico importa, mantenha versões e filtre a ativa.

Resumo do tópico

Separe fontes de , preserve rastreabilidade e defina limites conforme a estrutura e as perguntas do corpus.

15. Montar janela de contexto, orçamento e citações

Top-k basta para autônomos. Conteúdo narrativo pode exigir vizinhos do mesmo documento. Expanda apenas ali, elimine duplicatas e some para reservar espaço às instruções, pergunta e resposta.

WITH seeds AS (
  SELECT id, document_id, chunk_no, embedding <=> $1::vector AS distance
  FROM document_chunks
  ORDER BY embedding <=> $1::vector
  LIMIT 4
), expanded AS (
  SELECT DISTINCT c.*, s.distance
  FROM seeds s
  JOIN document_chunks c ON c.document_id = s.document_id
   AND c.chunk_no BETWEEN s.chunk_no - 1 AND s.chunk_no + 1
), budgeted AS (
  SELECT e.*, d.title, d.source_url,
         sum(e.token_count) OVER (ORDER BY e.distance, e.chunk_no) AS tokens_used
  FROM expanded e JOIN source_documents d ON d.id = e.document_id
)
SELECT content, title, source_url, section_title, page_number, distance
FROM budgeted WHERE tokens_used <= 3200
ORDER BY distance, chunk_no;

Retorne título, ou ID estável, seção, página e distância. Agrupe vários da mesma fonte em uma citação com vários trechos. Em áreas de alto risco, cada afirmação deve ser verificável e correspondências fracas precisam de revisão humana.

Pipeline RAG segmenta e vetoriza fontes, recupera candidatos semânticos e lexicais, aplica filtros e RRF, expande contexto dentro do orçamento e entrega evidências citadas ao modelo.
Uma resposta RAG confiável começa por recuperação rastreável, limitada e relevante.

Resumo do tópico

Expanda contexto apenas quando necessário, imponha orçamento de e devolva verificáveis.

16. Avaliar recuperação separadamente da geração

Métricas centrais.
MétricaPerguntaAjuste típico
PrecisãoQuantos retornados são relevantes?Limiar mais rígido, menos , segmentação focada.
RecallQuantos relevantes foram encontrados?Mais candidatos, limiar flexível, ef_search ou probes maior.
MRRQuão alto aparece o primeiro relevante?Embeddings, pré-processamento, reclassificação ou fusão melhores.

Comece com 20–50 perguntas representativas, recupere 10–20 candidatos e peça a especialistas que rotulem relevância. Automatize precision@k, recall@k e MRR. menores podem elevar precisão e fragmentar fatos; sobreposição preserva continuidade e duplica dados; busca ANN mais ampla eleva recall e latência.

Resumo do tópico

Perguntas rotuladas e métricas tornam o ajuste de modelo, , limiar e índice baseado em evidências.

17. Laboratório guiado: similaridade de produtos com Flask

O exercício de origem reserva cerca de 30 minutos para criar um aplicativo web de produtos, padrão reutilizável em recomendações, pesquisa semântica e RAG.

  1. Prepare assinatura com permissão, , atual, Python 3.12 ou posterior e psql.
  2. Baixe o projeto inicial e configure o script de implantação.
  3. Implante servidor flexível do com .
  4. Complete o aplicativo Flask enquanto o servidor é criado.
  5. Autorize e habilite vector e crie a tabela de produtos com embedding.
  6. Carregue exemplos, pesquise similaridade e examine ordem e distâncias.
  7. Inclua produtos e observe a mudança dos vizinhos.
  8. Exclua os recursos temporários ao concluir.

Resumo do tópico

O laboratório une provisionamento seguro, esquema pgvector, Flask e resultados reais de similaridade.

18. Revisão da avaliação e checklist final

  1. Para similaridade semântica com embeddings unitários, a resposta esperada é distância de cosseno (<=>); a documentação do modelo pode justificar produto interno em implementações otimizadas.
  2. Para cinco milhões de embeddings, cargas ocasionais e sem inserções em tempo real, a avaliação escolhe IVFFlat com lists adequadas.
  3. No HNSW, m controla o máximo de conexões por nó; ef_construction controla a exploração na criação.
  4. Para 50 mil vetores regenerados, transações de aproximadamente 1.000–5.000 linhas perturbam menos que uma única transação gigante.
  5. RRF equilibra classificações híbridas sem multiplicar escalas incompatíveis.
  • Alinhe dimensão, modelo, operador e classe.
  • Meça recall e latência antes de escolher exata, HNSW, IVFFlat ou DiskANN.
  • Monitore planos, usos, criação, bloat e mudanças de distribuição.
  • Atualize de forma assíncrona em alta frequência e migre modelos com colunas paralelas.
  • Filtre e aplique limiar; adicione sinal lexical quando termos exatos importarem.
  • Projete RAG para íntegros, limite de , citações e qualidade mensurável.

Referências oficiais

  1. Habilitar e usar pgvector no servidor flexível
  2. Otimizar o desempenho ao usar pgvector
  3. Habilitar e usar DiskANN
  4. Integrar recursos de IA do ao
  5. Criar pesquisa semântica com OpenAI

Resumo do tópico

Recuperação vetorial de produção combina espaço de embeddings coerente, índices verificados, atualização sustentável, filtros relacionais e evidências RAG rastreáveis.