🧠 Janela de Contexto
A janela de contexto (context window) e a quantidade maxima de tokens que um LLM consegue processar de uma vez. Tudo que entra no prompt - instrucoes, dados, historico - compete por esse espaco. Estourar a janela significa perder informacao ou truncar dados criticos.
🎯 Conceito: Tokens e Limites
Modelos modernos variam de 8K a 2M tokens de contexto, mas mais contexto nao significa melhor resultado. O modelo perde precisao no "meio" de janelas muito grandes (problema do "lost in the middle"). A estrategia e colocar apenas o que e relevante.
- • Token: Unidade minima de texto. ~1 token = ~4 caracteres em ingles, ~3 em portugues
- • Compressao: Resumir documentos longos antes de enviar ao modelo
- • Sumarizacao hierarquica: Resumir blocos, depois resumir os resumos
- • Priorizacao por relevancia: Usar busca semantica para selecionar os trechos mais importantes
💡 Dica Pratica
Para aplicacoes de dados, a regra e: nao jogue o banco inteiro no prompt. Use RAG para buscar apenas os trechos relevantes, comprima documentos longos e reserve pelo menos 30% da janela para a resposta do modelo. Custo escala com tokens (input + output). 5 chunks bem selecionados superam 50 paginas inteiras.
🔎 RAG - Retrieval-Augmented Generation
RAG e a tecnica que conecta LLMs aos seus dados. Em vez de depender apenas do conhecimento interno do modelo, RAG busca informacoes relevantes na sua base e injeta no prompt antes de gerar a resposta. E assim que chatbots "conhecem" dados internos da empresa.
🔄 Pipeline RAG Completo
1. Chunking
Dividir documentos em pedacos de ~500-1000 tokens com overlap
2. Embeddings
Converter cada chunk em vetor numerico que captura significado semantico
3. Indexacao
Armazenar vetores em banco vetorial com indice para busca rapida
4. Query
Converter a pergunta do usuario em vetor e buscar chunks similares
5. Reranking
Reordenar resultados com modelo cross-encoder para maior precisao
6. Generation
Montar prompt com contexto recuperado e gerar resposta com o LLM
# Pipeline RAG completo em Python
docs = split_into_chunks(load_corpus(), tokens=600)
vecs = embed(docs)
index = build_vector_index(vecs)
query = embed("Como normalizar tabelas?")
tops = index.search(query, k=5)
prompt = compose(system, user, context=tops)
answer = llm.generate(prompt)
📊 Numeros de Referencia
- Chunk size tipico: 500-1000 tokens com 10-20% de overlap
- Embeddings populares: text-embedding-3-small (1536 dims), BGE, E5
- Top-k tipico: 3-10 chunks dependendo do tamanho da janela
- Reranking melhora precisao em 10-25% vs busca vetorial pura
🐘 pgvector no PostgreSQL
pgvector adiciona o tipo VECTOR ao PostgreSQL, permitindo busca por similaridade direto no banco relacional que voce ja conhece. Sem infra extra, sem novo banco. Ideal para ate ~1 milhao de vetores com boa performance.
-- Habilitar a extensao
CREATE EXTENSION IF NOT EXISTS vector;
-- Criar tabela com coluna vetorial
CREATE TABLE doc_chunk (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding VECTOR(1536)
);
-- Buscar os 5 chunks mais similares (distancia cosseno)
SELECT id, content
FROM doc_chunk
ORDER BY embedding <=> '[0.010, -0.020, ...]'::vector
LIMIT 5;
💡 Performance: ivfflat e HNSW
Sem indice, pgvector faz busca exata (seq scan). Para tabelas grandes, crie um indice aproximado:
- • ivfflat: Divide vetores em
lists(clusters). Na busca, consulta apenasprobesclusters proximos. Regra:lists = sqrt(n),probes = sqrt(lists). - • HNSW: Grafo hierarquico navegavel. Mais rapido que ivfflat para busca, mais lento para construir. Melhor para producao com alta QPS.
- • Comece com ivfflat e migre para HNSW quando precisar de mais velocidade de busca.
🎯 Operadores de Distancia
<=> Cosseno
Mais usado. Compara direcao dos vetores, ignora magnitude.
<-> L2 (Euclidiana)
Distancia geometrica. Sensivel a magnitude dos vetores.
<#> Produto Interno
Maximiza similaridade. Usado com vetores normalizados.
🌊 Weaviate
Weaviate e um banco vetorial com busca hibrida nativa: combina busca semantica (vetores) com busca por palavras-chave (BM25). Busca puramente semantica pode perder termos exatos. O hibrido resolve isso combinando os dois rankings.
import weaviate
client = weaviate.Client("http://localhost:8080")
# Busca semantica (nearVector)
result = client.query.get("Document", ["content", "source"]) \
.with_near_vector({"vector": query_vec}) \
.with_limit(5) \
.do()
# Busca hibrida (vetor + BM25)
result = client.query.get("Document", ["content", "source"]) \
.with_hybrid(query="normalizacao tabelas", alpha=0.5) \
.with_limit(5) \
.do()
# alpha=1.0 = puramente vetorial
# alpha=0.0 = puramente BM25
# alpha=0.5 = metade de cada
🔍 Diferenciais do Weaviate
- • Hybrid search: Parametro alpha controla o balanco entre semantica e BM25
- • Modules: Modulos integrados para embedding automatico (text2vec-openai, text2vec-cohere)
- • Multi-tenancy: Isola dados por tenant sem duplicar infra. Bom para SaaS
- • GraphQL API: Interface de consulta expressiva e bem documentada
⚡ Milvus
Milvus e um banco vetorial open source projetado para bilhoes de vetores. Quando pgvector nao escala mais, Milvus e a opcao mais madura. Suporta GPU acceleration, sharding distribuido e multiplos tipos de indice.
from pymilvus import (
connections, FieldSchema, CollectionSchema,
DataType, Collection
)
# Conectar
connections.connect("default", host="localhost", port="19530")
# Definir schema
fields = [
FieldSchema(name="id", dtype=DataType.INT64,
is_primary=True, auto_id=True),
FieldSchema(name="content", dtype=DataType.VARCHAR,
max_length=2000),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR,
dim=1536)
]
schema = CollectionSchema(fields, description="RAG docs")
collection = Collection("documents", schema)
# Criar indice IVF_FLAT
index_params = {
"metric_type": "COSINE",
"index_type": "IVF_FLAT",
"params": {"nlist": 256}
}
collection.create_index("embedding", index_params)
collection.load()
# Buscar
results = collection.search(
data=[query_vector],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"nprobe": 16}},
limit=5,
output_fields=["content"]
)
🎯 Quando Milvus Brilha
Escala
Bilhoes de vetores distribuidos em cluster. Sharding automatico, replicas de leitura.
GPU Acceleration
Suporte nativo a GPU para indexacao e busca. Ordens de magnitude mais rapido.
Zilliz Cloud
Versao gerenciada (SaaS) do Milvus. Sem ops, escala sob demanda.
🎯 Qdrant e Redis Vetorial
Qdrant armazena vetores com payloads filtraveis - ideal para buscas semanticas com filtros complexos. Redis com o modulo RediSearch adiciona busca vetorial ao cache que muitos ja usam em producao. Duas abordagens, dois cenarios diferentes.
# Qdrant com qdrant-client
from qdrant_client import QdrantClient
from qdrant_client.models import (
VectorParams, Distance, PointStruct
)
client = QdrantClient("localhost", port=6333)
# Criar collection com distancia cosseno
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(
size=1536,
distance=Distance.COSINE
)
)
# Inserir com payload (metadados filtraveis)
client.upsert(
collection_name="documents",
points=[
PointStruct(
id=1,
vector=[0.012, -0.034, ...],
payload={
"content": "Normalizacao ate 3FN",
"source": "aula-sql",
"level": "intermediario"
}
)
]
)
# Buscar com filtro de payload
results = client.search(
collection_name="documents",
query_vector=query_vec,
query_filter={"must": [
{"key": "level", "match": {"value": "intermediario"}}
]},
limit=5
)
# Redis Vetorial com RediSearch
# Criar indice com campo vetorial HNSW
FT.CREATE idx_docs ON HASH PREFIX 1 doc:
SCHEMA
content TEXT
embedding VECTOR HNSW 6
TYPE FLOAT32
DIM 1536
DISTANCE_METRIC COSINE
# Inserir documento
HSET doc:1
content "Normalizacao ate 3FN reduz redundancia"
embedding "\x3f\x80\x00\x00..."
# Buscar KNN (5 vizinhos mais proximos)
FT.SEARCH idx_docs
"*=>[KNN 5 @embedding $vec AS score]"
PARAMS 2 vec "\x3f\x80\x00\x00..."
SORTBY score
RETURN 2 content score
DIALECT 2
Qdrant - Ideal para
- • Busca semantica + filtros complexos por payload
- • Multi-tenancy nativo com isolamento
- • Escrito em Rust, baixa latencia
- • API REST e gRPC nativas
Redis Vetorial - Ideal para
- • Ja usa Redis? Adicione vetores sem nova infra
- • Cache + busca vetorial na mesma instancia
- • Latencia ultra-baixa (in-memory)
- • TTL nativo para vetores temporarios
🧪 Chroma e Azure AI Search
Chroma e o banco vetorial mais leve para desenvolvimento local e prototipagem rapida. Azure AI Search e a solucao enterprise gerenciada da Microsoft com SLA, integracao com Azure OpenAI e busca hibrida. Dev vs Enterprise.
# Chroma - banco vetorial mais simples
import chromadb
client = chromadb.Client() # In-memory, zero config
# Criar collection
collection = client.get_or_create_collection("my_docs")
# Adicionar documentos (embedding automatico)
collection.add(
documents=[
"Normalizacao ate 3FN reduz redundancia",
"Indices B-tree aceleram buscas por range",
"Transacoes ACID garantem consistencia"
],
ids=["doc1", "doc2", "doc3"],
metadatas=[
{"source": "sql-101"},
{"source": "indices"},
{"source": "transacoes"}
]
)
# Buscar por similaridade
results = collection.query(
query_texts=["como reduzir redundancia?"],
n_results=3
)
print(results["documents"])
// Azure AI Search - Indice com busca vetorial (JSON)
{
"name": "rag-index",
"fields": [
{"name": "id", "type": "Edm.String", "key": true},
{"name": "content", "type": "Edm.String",
"searchable": true},
{"name": "contentVector",
"type": "Collection(Edm.Single)",
"searchable": true,
"dimensions": 1536,
"vectorSearchProfile": "my-vector-profile"}
],
"vectorSearch": {
"algorithms": [
{"name": "my-hnsw", "kind": "hnsw",
"hnswParameters": {
"metric": "cosine", "m": 4,
"efConstruction": 400, "efSearch": 500
}}
],
"profiles": [
{"name": "my-vector-profile",
"algorithm": "my-hnsw"}
]
}
}
🎯 Quando Usar Cada Um
Chroma
Prototipagem, hackathons, dev local, projetos pequenos. Zero config, roda in-memory ou persiste em SQLite. Nao recomendado para producao com alta carga.
Azure AI Search
Producao enterprise, SLA 99.95%, integracao Azure OpenAI, skillsets para enriquecimento automatico, reranking semantico nativo.