Embeddings + pgvector
Embeddings permitem comparar entradas em um espaço vetorial e recuperar itens relacionados. Para usá-los em uma aplicação, é necessário entender a medida de comparação, o formato dos dados e o efeito de índices e filtros. Nesta semana você construirá uma busca pequena e saberá o que ela demonstra.
O caso é uma coleção de políticas de suporte de duas empresas. Documentos semanticamente próximos podem pertencer a escopos diferentes. A busca precisa encontrar conteúdo relevante dentro do conjunto autorizado, preservando origem e versão para a geração posterior.
JavaScriptPostgreSQLRAGAo terminar esta aula
- Embeddings exigem contrato de representação.
- Metadados complementam proximidade.
- Índices são escolhas operacionais que precisam de avaliação.
Antes de continuar: Laboratório: Tool design
Embeddings e dimensionalidade
RAGUm embedding é um vetor numérico produzido por um modelo para representar uma entrada. A dimensionalidade é a quantidade de componentes do vetor. Ela faz parte do contrato entre modelo e armazenamento: vetores de dimensões diferentes não podem ser comparados diretamente pela mesma operação. Trocar modelo geralmente exige planejar reindexação e avaliar qualidade, não apenas substituir um identificador na chamada. Não presuma que espaços de modelos diferentes são compatíveis, mesmo com a mesma quantidade de dimensões.
A utilidade depende de como o modelo foi treinado e da tarefa. Uma consulta curta e um documento longo podem ser representados de maneira que facilite recuperação, mas proximidade não comprova verdade nem vigência. Metadados complementam o vetor com identificador, documento, trecho, data, versão e escopo. O vetor serve à comparação; os metadados servem à seleção, rastreabilidade e autorização. Essa separação retoma a primeira semana e evita interpretar dimensões individuais como campos de negócio legíveis.
Similaridade vetorial e cosine similarity
FundamentosSimilaridade vetorial compara representações segundo uma função. Cosine similarity usa o cosseno do ângulo: produto escalar dividido pelo produto das normas. Em termos intuitivos, considera direção relativa, não apenas magnitude. Produto escalar e distância euclidiana têm propriedades distintas; a escolha precisa ser compatível com o modelo e a normalização. Vetor nulo não possui direção definida para o cosseno, portanto o código deve tratar esse caso.
Valores de similaridade são relativos ao espaço e à coleção. Um score alto não é uma probabilidade calibrada de que o documento responde corretamente. Ordene candidatos e avalie relevância com casos rotulados. Para duas políticas quase iguais, a diferença de escopo pode importar mais que a proximidade. Um limiar escolhido olhando apenas exemplos fáceis tende a falhar em perguntas ambíguas. Registre função, normalização e critério de seleção para repetir o experimento e comparar mudanças de embedding.
PostgreSQL e pgvector
PostgreSQLPostgreSQL armazena dados relacionais e pode usar a extensão pgvector para representar vetores e fazer busca por similaridade. Isso permite combinar metadados, relações e consulta vetorial no mesmo sistema. O exemplo conceitual é uma tabela de trechos com documentoId, tenantId, versão e vetor. O filtro de escopo continua uma responsabilidade do desenho de acesso; acrescentar um vetor não torna linhas automaticamente privadas.
Busca exata compara com todos os candidatos elegíveis e oferece referência para avaliar aproximações. Índices aproximados, como HNSW e IVFFlat no pgvector, trocam trabalho por compromissos de recuperação e manutenção. Parâmetros e filtros influenciam quantidade de candidatos encontrados. Não prometa ganho sem medir corpus, carga e distribuição. Uma consulta filtrada pode retornar menos itens do que o esperado conforme o plano e mecanismo de busca. Compare com a referência exata e registre cobertura, latência, memória e custo de atualização antes de escolher configuração.
Panorama de bancos e serviços vetoriais
FundamentosPinecone, Qdrant, Weaviate e Milvus oferecem abordagens de armazenamento e recuperação vetorial com contratos próprios. O panorama serve para identificar opções, não para afirmar que são intercambiáveis. Compare integração com metadados, filtros, atualização, modos de índice, operação, observabilidade e requisitos de implantação. Um serviço gerenciado reduz algumas tarefas operacionais, mas introduz dependência de conta e contrato. Um sistema autogerido oferece controle e exige manutenção correspondente.
↗ Pinecone Semantic search↗ Qdrant Points↗ Weaviate Hybrid search↗ Milvus Index Vector Fields
Qdrant representa pontos com vetores e payloads; outros sistemas possuem suas estruturas e APIs. Use documentação da versão escolhida para criar coleção e índice. Não copie configuração de um produto para outro. Para o curso, PostgreSQL com pgvector pode ser uma opção didática quando dados relacionais já existem, enquanto uma solução especializada pode atender outros requisitos. A decisão deve mencionar o caso, volume esperado e medidas ainda ausentes. Nome popular de produto não substitui evidência de adequação ao projeto.
↗ Pinecone Semantic search↗ Qdrant Points↗ Weaviate Hybrid search↗ Milvus Index Vector Fields
Índices, filtros e avaliação
AvaliaçãoFiltre por escopo autorizado, versão vigente e tipo de documento conforme a tarefa. Esses filtros precisam participar da recuperação correta, não apenas da apresentação final. Buscar globalmente e esconder linhas depois pode tanto expor conteúdo no contexto quanto deixar a resposta sem candidatos relevantes. Retome a engenharia de contexto: o conjunto enviado ao gerador é uma seleção de evidências, não um despejo dos vizinhos mais próximos.
Avalie com perguntas que possuam documentos relevantes definidos, incluindo termos exatos, paráfrases e perguntas sem resposta. Compare busca exata e índice aproximado em qualidade e operação. Preserve falsos positivos e ausências. Um índice rápido que perde a única exceção decisiva pode ser inadequado. Registre modelo de embedding, dimensionalidade, função, índice, filtros e corpus versionado. Esses campos permitem separar uma alteração de representação de uma alteração da coleção ou da consulta.
Exemplo comentado e limites
FundamentosOs vetores foram escolhidos manualmente para tornar a conta inspecionável. Não são embeddings produzidos por um modelo. O documento B é mais alinhado à consulta, mas pertence a outro escopo e é excluído antes da comparação. O exemplo mostra relevância condicionada à autorização.
function cos(a,b) {
if(a.length!==b.length) throw new Error("Dimensão incompatível");
const norma = v=>Math.sqrt(v.reduce((s,x)=>s+x*x,0));
const divisor=norma(a)*norma(b);
if(!divisor) return null;
return a.reduce((s,x,i)=>s+x*b[i],0)/divisor;
}
const consulta=[1,0];
const documentos=[{id:"a",tenant:"A",v:[1,0.2]},
{id:"b",tenant:"B",v:[1,0]}];
console.log(documentos.filter(x=>x.tenant==="A")
.map(x=>({id:x.id,score:cos(consulta,x.v)})));A função rejeita dimensão incompatível e retorna null para vetor sem direção. Em um pipeline real, vetores inválidos precisam de diagnóstico, não de um score inventado. O resultado numérico não permite afirmar que a política é vigente ou correta; origem e metadados continuam necessários.
Calcule o cosseno antes de confiar no índice
FundamentosUse consulta q=(1,2), candidato a=(2,1) e candidato b=(0,3). O produto escalar q·a=1×2+2×1=4; as normas de q e a são sqrt(5). Logo cos(q,a)=4/5=0,8. Para b, q·b=6 e a norma de b é 3; cos(q,b)=6/(3sqrt(5))=2/sqrt(5), aproximadamente 0,894. Pelo cosseno, b vem antes de a. São vetores didáticos, não embeddings semânticos de textos.
Se multiplicarmos b por dez, o produto e a norma crescem na mesma proporção: o cosseno continua 0,894. Pela distância euclidiana, essa mudança altera a ordem: a distância de q a a é sqrt(2), enquanto a de q a b é sqrt(2) no caso inicial; usando b=(0,30), ela passa a sqrt(785). Métricas medem propriedades diferentes. Esse cálculo explica por que normalização, operador de índice e distância de consulta devem ser compatíveis.
Um vetor zero tem norma zero: o cosseno usual fica indefinido, não igual a zero por uma garantia matemática. Sua implementação precisa escolher uma política explícita, como rejeitar o vetor e registrar erro de embedding. Não invente score válido para esconder entrada degenerada. Um índice aproximado acrescenta outro compromisso: mesmo usando a mesma métrica, pode perder vizinhos que a busca exata encontra.
Para uma nova tentativa, use q=(3,4), c=(6,8) e d=(4,-3). q·c=50 e as normas são 5 e 10: cosseno 1. q·d=0 e ambas as normas são 5: cosseno 0. Se d estiver autorizado e c não, somente d pode entrar no resultado; relevância não revoga o filtro de acesso. O score descreve geometria, não probabilidade de verdade nem autorização. Revise a unidade de álgebra da preparação se os passos não forem claros.
Exercício aplicado
Busque políticas relevantes apenas da empresa autorizada e mostre por que o score não é probabilidade de verdade.
- Tente ordenar candidatos e rotule relevância.
- Execute matemática e casos inválidos.
- Desenhe metadados, filtros e armazenamento.
- Compare opções e registre evidência por etapa.
Abrir resolução comentada
A solução mantém tenantId vindo de contexto confiável e compara somente candidatos elegíveis. A coleção real possui versão e referência ao documento original. Para avaliar índice, use busca exata como referência sobre o mesmo conjunto autorizado.
A escolha de banco inclui manutenção, filtros e integração além da busca. O relatório separa demonstração matemática local, geração real de embeddings e benchmark de armazenamento. Não afirme que um banco foi testado apenas porque o cálculo de cosseno executou.
A referência mostra filtro e cálculo. A entrega completa acrescenta coleção versionada, casos rotulados e decisão de armazenamento ligada ao projeto.
A resolução cobre todos os checks locais com asserts: dimensão, valores finitos, vetor nulo, filtro por tenant e vigência antes da seleção e casos rotulados. O desenho de armazenamento registra representação, metadata e referência exata. Os vetores manuais não medem qualidade de embeddings; a ADR depende de latência, recuperação e operação reais do banco. A etapa PostgreSQL e o benchmark de índice continuam explicitamente separados da execução matemática local.
import assert from "node:assert/strict";
function cosine(a,b){
if(a.length!==b.length||!a.length)throw new Error("DIMENSAO_INVALIDA");
if(![...a,...b].every(Number.isFinite))throw new Error("VETOR_INVALIDO");
const norma=v=>Math.sqrt(v.reduce((s,x)=>s+x*x,0));const divisor=norma(a)*norma(b);
return divisor?a.reduce((s,x,i)=>s+x*b[i],0)/divisor:null;
}
const corpus=[{id:"d1",tenant:"A",versao:2,vigente:true,vetor:[1,0],texto:"Ativação"},
{id:"d2",tenant:"B",versao:2,vigente:true,vetor:[1,0],texto:"Outra empresa"},
{id:"d3",tenant:"A",versao:1,vigente:false,vetor:[1,0],texto:"Política antiga"},
{id:"d4",tenant:"A",versao:2,vigente:true,vetor:[0,1],texto:"Contato"}];
function buscar(query,ctx,k){return corpus.filter(d=>d.tenant===ctx.tenant&&d.vigente)
.map(d=>({...d,score:cosine(query,d.vetor)})).filter(d=>d.score!==null)
.sort((a,b)=>b.score-a.score).slice(0,k);}
assert.equal(cosine([1,0],[1,0]),1);assert.equal(cosine([1,0],[0,1]),0);
assert.equal(cosine([0,0],[1,0]),null);
assert.throws(()=>cosine([1],[1,0]),/DIMENSAO_INVALIDA/);
assert.throws(()=>cosine([NaN,0],[1,0]),/VETOR_INVALIDO/);
const encontrados=buscar([1,0],{tenant:"A"},2);
assert.deepEqual(encontrados.map(x=>x.id),["d1","d4"]);
const casos=[{id:"q1",query:[1,0],relevantes:["d1"]},{id:"q2",query:[0,1],relevantes:["d4"]}];
const avaliacao=casos.map(c=>({id:c.id,retornado:buscar(c.query,{tenant:"A"},1)[0].id,
relevantes:c.relevantes}));assert.ok(avaliacao.every(x=>x.relevantes.includes(x.retornado)));
const armazenamento={dimensao:2,modelo:"vetores manuais, não embeddings aprendidos",
metadata:["id","tenant","versao","vigente","origem"],
referencia:"busca exata no corpus autorizado",indiceCandidato:"avaliar HNSW ou IVFFlat no banco",
decisao:"pgvector quando integração relacional é requisito; comparar serviço especializado no ambiente real",
medidasPendentes:["latência e recall com índice","consumo e manutenção","geração real de embeddings"]};
console.log({status:"aprovado",encontrados,avaliacao,armazenamento,
bancoExecutado:false,scoreEhProbabilidade:false});Como conferir seu resultado
- Escopo é aplicado antes da seleção.
- Dimensão e vetor nulo são tratados.
- Scores não são apresentados como verdade factual.
Aplique em um problema novo
Primeiro resolva sem consultar a resposta. Explique suas decisões e guarde a evidência. A conclusão de leitura é independente desta autoavaliação.
Confira seus pré-requisitos
- Calcular norma/produto escalar.
- Aplicar filtro confiável de tenant.
q=(1,0), A=(3,4) autorizada, B=(1,0) outro tenant. Calcule/selecionar; pode misturar modelos de mesma dimensão?
Conferir raciocínio e critérios de domínio
A:3/5=0,6; B:1.
B excluído; score não comprova verdade.
Mesma dimensão não alinha espaços; avaliar/reindexar modelo novo.
Evidências para autoavaliação ou revisão por pares
- Matemática: A:3/5=0,6; B:1.
- Escopo: B excluído; score não comprova verdade.
- Representação: Mesma dimensão não alinha espaços; avaliar/reindexar modelo novo.
Um erro frequente
Maior score global deve chegar ao gerador.
Relevância é selecionada dentro do escopo autorizado.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. Mesma dimensão torna dois modelos compatíveis?
Não.
Os espaços podem ter geometrias diferentes; trocar modelo exige avaliação e reindexação.
2. Score é probabilidade de verdade?
3. Índice aproximado garante todos os melhores candidatos?
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- Vector embeddings
OpenAI • consulta: 2026-10-06
OpenAIRAGEmbeddings, similaridade, dimensionalidade e busca semântica.
Limites: Dimensões e limites dependem do modelo; não misturar vetores de modelos diferentes no mesmo espaço.
- pgvector README
pgvector contributors • consulta: 2026-10-06
PostgreSQLPostgreSQL com vetores, distâncias cosine/L2, índices HNSW/IVFFlat, filtragem e busca híbrida.
Limites: README atual mostra versão 0.8.7; performance, recall e ordem de filtros exigem benchmark no dataset.
- Qdrant Points
Qdrant • consulta: 2026-10-06
FundamentosPontos com vetores, IDs, payloads e operações de armazenamento.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.
- OpenAI Retrieval
OpenAI • consulta: 2026-10-06
OpenAIIngestion, chunking/overlap, metadata/filtros, ranking e reescrita de consultas em vector stores.
Limites: Implementação gerenciada OpenAI; defaults não são melhores escolhas universais para pgvector.
- Pinecone Semantic search
Pinecone • consulta: 2026-10-06
FundamentosBusca semântica, top-k e resultados em índices vetoriais.
Limites: Serviço e pricing próprios; comparar com alternativas usando dataset e custos medidos.
- Weaviate Hybrid search
Weaviate • consulta: 2026-10-06
RAGCombinação de busca keyword/BM25 e vetorial; filtros e parâmetros de ranking.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.
- Milvus Index Vector Fields
Milvus • consulta: 2026-10-06
FundamentosÍndices vetoriais e opções de busca em Milvus.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.