Vector databases: o que são, como funcionam e quando usar com LLMs
1. O problema que os bancos vetoriais resolvem
1.1. Limitações das buscas tradicionais com LLMs
Modelos de linguagem de grande escala (LLMs) possuem conhecimento limitado ao seu corte temporal e não conseguem acessar bases de dados privadas ou atualizadas em tempo real. Quando um usuário pergunta sobre um documento interno da empresa ou sobre um evento recente, o LLM simplesmente não tem essa informação. Buscas tradicionais por palavra-chave (como SQL LIKE ou Elasticsearch) falham em capturar significado semântico: uma busca por "carro elétrico" não retorna resultados sobre "veículo movido a bateria".
1.2. A necessidade de representar significado semântico
A busca semântica exige que o sistema entenda o significado por trás das palavras, não apenas a correspondência literal. É aqui que os bancos vetoriais entram: eles armazenam representações matemáticas densas (vetores) que capturam o sentido de textos, imagens ou áudios. Dois textos com significados similares geram vetores próximos no espaço multidimensional, mesmo que usem palavras diferentes.
1.3. Contexto na arquitetura de RAG e agentes
Os bancos vetoriais são o coração do padrão Retrieval-Augmented Generation (RAG). Em um sistema RAG típico:
1. Documentos são divididos em chunks e convertidos em embeddings
2. Esses embeddings são armazenados em um banco vetorial
3. Quando chega uma pergunta, ela também é convertida em embedding
4. O banco retorna os chunks mais similares semanticamente
5. O LLM usa esses chunks como contexto para gerar a resposta
Agentes autônomos (como os construídos com LangGraph) usam bancos vetoriais como memória de longo prazo, permitindo recuperar informações de interações passadas.
2. Fundamentos: embeddings e vetores
2.1. O que é um embedding vetorial
Um embedding é um vetor de números reais (por exemplo, 1536 dimensões no modelo text-embedding-ada-002 da OpenAI). Cada dimensão captura um aspecto semântico latente do texto. Vetores densos significam que a maioria das dimensões tem valores não-zero, ao contrário de representações esparsas como bag-of-words.
2.2. Como LLMs geram embeddings
Modelos de embedding são treinados para produzir vetores onde textos similares ficam próximos. Exemplos populares:
- OpenAI: text-embedding-3-small (512 ou 1536 dimensões)
- HuggingFace: BAAI/bge-base-en-v1.5 (768 dimensões)
- Google: text-embedding-gecko (768 dimensões)
2.3. Métricas de similaridade
As três métricas mais comuns para comparar vetores:
# Similaridade por cosseno (mais comum)
similaridade = cos(θ) = (A · B) / (||A|| * ||B||)
# Distância euclidiana (L2)
distancia = sqrt(Σ(Ai - Bi)²)
# Produto escalar (dot product)
produto = Σ(Ai * Bi)
A similaridade por cosseno é a mais usada por ser invariante à magnitude dos vetores, focando apenas na direção (significado).
3. Arquitetura interna de um banco vetorial
3.1. Indexação: algoritmos de aproximação
Para busca eficiente em milhões de vetores, usam-se índices aproximados (ANN - Approximate Nearest Neighbors):
- HNSW (Hierarchical Navigable Small World): Cria múltiplas camadas de grafos, permitindo busca logarítmica. Alta precisão, mas maior consumo de memória.
- IVF (Inverted File Index): Divide o espaço em clusters (Voronoi). Rápido, mas menos preciso que HNSW.
- PQ (Product Quantization): Comprime vetores para reduzir memória. Útil para datasets muito grandes.
Trade-off principal: precisão vs. velocidade vs. memória. HNSW oferece ~99% de recall com latências de milissegundos.
3.2. Operações fundamentais
# Inserção de vetor
INSERT INTO vectordb (id, embedding, metadata)
VALUES ('doc1', [0.12, 0.45, ..., 0.89], '{"titulo": "Relatório 2024"}')
# Busca por similaridade (k-NN)
SELECT id, metadata, cosine_similarity(embedding, query_embedding) AS score
FROM vectordb
ORDER BY score DESC
LIMIT 5
# Filtragem híbrida
SELECT id, metadata, cosine_similarity(embedding, query_embedding) AS score
FROM vectordb
WHERE metadata->>'ano' = '2024'
ORDER BY score DESC
LIMIT 5
4. Principais soluções do mercado
4.1. Bancos dedicados
| Solução | Prós | Contras |
|---|---|---|
| Pinecone | Gerenciado, escalável, baixa latência | Caro em escala |
| Weaviate | Open-source, schema flexível | Configuração mais complexa |
| Qdrant | Rust, performance alta | Ecossistema menor |
| Milvus | Suporte a GPU, bilhões de vetores | Operação complexa |
4.2. Extensões em bancos relacionais
- pgvector (PostgreSQL): Permite usar PostgreSQL como banco vetorial com índices IVFFlat e HNSW. Ideal para quem já usa PostgreSQL.
- MongoDB Atlas Vector Search: Integração nativa com MongoDB, suporta filtros híbridos.
4.3. Critérios de escolha
- Volume de dados: até 100k vetores → pgvector; até 10M → Qdrant/Weaviate; acima → Milvus/Pinecone
- Latência: aplicações em tempo real → HNSW com banco em memória
- Gerenciamento: equipe pequena → Pinecone (serverless); equipe experiente → Milvus auto-hospedado
5. Integrando bancos vetoriais com LLMs na prática
5.1. Pipeline típico
1. Chunking: Dividir documentos em partes de ~500 tokens com overlap de 50 tokens
2. Embedding: Converter cada chunk em vetor usando modelo de embedding
3. Inserção: Armazenar vetor + chunk + metadados no banco vetorial
4. Consulta: Embedding da pergunta → busca k-NN → recuperação dos chunks
5. Geração: Contexto (chunks) + pergunta → LLM → resposta final
5.2. Exemplo de fluxo RAG (pseudocódigo conceitual)
# 1. Preparação dos dados
documentos = carregar_pdfs("relatorios/")
chunks = chunk_documentos(documentos, tamanho=500, overlap=50)
# 2. Criação dos embeddings
modelo_embedding = carregar_modelo("BAAI/bge-base-en-v1.5")
vetores = modelo_embedding.embed(chunks)
# 3. Inserção no banco vetorial (Qdrant)
for chunk, vetor in zip(chunks, vetores):
banco.inserir(
id=chunk.id,
vetor=vetor,
payload={"texto": chunk.texto, "fonte": chunk.arquivo}
)
# 4. Consulta do usuário
pergunta = "Qual foi o faturamento em 2024?"
vetor_pergunta = modelo_embedding.embed([pergunta])
# 5. Busca semântica
resultados = banco.buscar(
vetor=vetor_pergunta[0],
limite=3,
filtro={"ano": "2024"}
)
# 6. Geração com contexto
contexto = "\n".join([r.payload["texto"] for r in resultados])
resposta = llm.gerar(f"Contexto:\n{contexto}\n\nPergunta: {pergunta}")
5.3. Desafios comuns
- Tamanho do contexto: chunks muito grandes excedem o limite de tokens do LLM
- Atualização de embeddings: ao trocar o modelo, todos os vetores precisam ser recalculados
- Filtragem por metadados: bancos vetoriais puros têm suporte limitado; soluções híbridas (pgvector) são melhores
6. Quando usar (e quando evitar) bancos vetoriais com LLMs
6.1. Casos de uso ideais
- Chatbots com base de conhecimento: suporte técnico, FAQ interno, manuais de produtos
- Pesquisa em documentos: contratos, artigos científicos, relatórios financeiros
- Sistemas de recomendação semântica: recomendar artigos baseados em conteúdo similar
- Memória para agentes: agentes que precisam lembrar de interações anteriores
6.2. Cenários onde não são recomendados
- Dados puramente tabulares: buscas exatas em colunas (SQL resolve melhor)
- Baixo volume de dados: menos de 1000 documentos → uma busca simples com embeddings em memória é suficiente
- Busca por metadados complexa: consultas SQL com múltiplos joins são mais eficientes em bancos relacionais
6.3. Alternativas
- Busca híbrida (BM25 + vetorial): combina busca lexical e semântica (ex: Elasticsearch com plugin de embeddings)
- Bancos relacionais com índices simples: para dados estruturados com poucos registros
7. Boas práticas e armadilhas comuns
7.1. Escolha do modelo de embedding
Para datasets pequenos (< 100k documentos), modelos com 384-768 dimensões (como all-MiniLM-L6-v2) oferecem bom custo-benefício. Para datasets grandes, modelos maiores (1536 dimensões) capturam mais nuances, mas aumentam custo de armazenamento.
7.2. Estratégias de chunking
# Chunking com overlap
tamanho_chunk = 500 tokens
overlap = 50 tokens
# Exemplo de chunks de um documento de 1200 tokens:
# Chunk 1: tokens 0-500
# Chunk 2: tokens 450-950
# Chunk 3: tokens 900-1200
O overlap evita que informações importantes sejam cortadas no meio de um chunk.
7.3. Monitoramento em produção
- Drift de embeddings: verifique periodicamente se a distribuição dos vetores mudou (pode indicar mudança no domínio dos dados)
- Latência: buscas devem levar < 100ms para aplicações interativas
- Custo de armazenamento: vetores 1536-dim em float32 ocupam ~6KB cada; para 1M documentos, são ~6GB
8. Tendências futuras
8.1. Embeddings multimodais
Modelos como CLIP e ImageBind geram embeddings que representam texto, imagem e áudio no mesmo espaço. Bancos vetoriais estão se adaptando para buscas multimodais: "encontre imagens que combinem com este texto descritivo".
8.2. Integração com agentes LangGraph
Agentes com loops de feedback podem usar bancos vetoriais como memória episódica, armazenando embeddings de ações e resultados para melhorar decisões futuras.
8.3. Relação com temas vizinhos
Bancos vetoriais são fundamentais para RAG avançado, busca semântica e vibe coding (onde o código é gerado a partir de descrições em linguagem natural). Eles formam a ponte entre a compreensão semântica dos LLMs e dados estruturados e não estruturados.
Referências
- Pinecone Documentation - What are Vector Databases? — Guia completo sobre conceitos, arquitetura e casos de uso de bancos vetoriais
- pgvector GitHub Repository — Documentação oficial da extensão vetorial para PostgreSQL, com exemplos de instalação e uso
- Qdrant Documentation - Overview — Visão técnica da arquitetura HNSW e operações de busca vetorial
- Weaviate Blog - What is a Vector Database? — Artigo introdutório com comparações entre soluções e explicações sobre embeddings
- OpenAI Embeddings Guide — Documentação oficial sobre modelos de embedding, parâmetros e melhores práticas
- Milvus Documentation - Vector Index — Guia técnico sobre algoritmos de indexação (IVF, HNSW, PQ) e trade-offs de performance
- LangChain RAG Tutorial — Tutorial prático de implementação de RAG com bancos vetoriais e LLMs