RAG para PME em 2026: Vector Databases e Embeddings

Duarte Spínola  |  2026-07-18

As pequenas e médias empresas (PME) portuguesas que adoptam modelos de linguagem (LLM) como GPT-4o, Claude ou Llama 3 deparam-se rapidamente com um problema: o modelo “não sabe” nada sobre os contratos, manuais internos, tickets de suporte ou políticas de RH da organização. Alimentar tudo no prompt é caro (limite de contexto), arriscado (dados confidenciais) e frágil (alucinação). A solução madura em 2026 chama-se Retrieval-Augmented Generation (RAG) — uma arquitectura que combina um LLM com um índice de pesquisa semântica alimentado por embeddings e armazenado numa vector database. A causa técnica do problema é simples: um LLM é um modelo estático treinado numa image (Snapshot) da web até uma data de corte; não tem acesso à memória da empresa. A solução é indexar os documentos internos como vectores densos, recuperar os mais relevantes por semântica (não por palavra-chave) e inseri-los no prompt antes da geração. Este artigo cobre o que é RAG, as alternativas open-source e comerciais de embeddings e vector databases, a arquitectura típica e uma implementação prática em Python com LangChain ou LlamaIndex, validada contra documentação oficial a 18 de Julho de 2026.

⚠ ⚠️ **Atenção

** Antes de implementar RAG com dados confidenciais de clientes ou funcionários, verifique a política de processamento de dados do seu provedor LLM (OpenAI, Anthropic, Cohere). Para dados sensíveis, considere inferência local com Ollama ou Llama.cpp — ver secção 8.

1. O que Está a Acontecer — RAG, Embeddings e Vector Databases

RAG (Retrieval-Augmented Generation) é um padrão introduzido pela Facebook AI em 2020 e tornado padrão de facto em 2024-2026 que combina um modelo de geração de texto (LLM) com um sistema de recuperação de informação externo. Em vez de depender apenas do conhecimento paramétrico aprendido em treino, o LLM recebe, no prompt, excertos relevantes recuperados de uma base de conhecimento externa. Em 2026, a documentação da Pinecone descreve-o como “the process of optimizing the output of a large language model so it references an authoritative knowledge base outside of its training data sources before generating a response” (Pinecone Learn — RAG).

Embeddings são representações numéricas densas de texto (ou imagens, áudio, código) num espaço vectorial de alta dimensão — tipicamente 384, 768, 1024, 1536 ou 3072 dimensões, consoante o modelo. Textos semanticamente próximos ficam próximos nesse espaço. A recuperação semântica faz-se calculando a distância (cosseno, euclidiana ou produto interno) entre o embedding da pergunta e os embeddings dos documentos. O modelo text-embedding-3-large da OpenAI produz 3072 dimensões por token-chunk (OpenAI Platform — Embeddings Guide).

Vector databases são sistemas de armazenamento optimizados para: (1) guardar milhões de vectores de alta dimensão, (2) fazer busca aproximada de vizinhos mais próximos (ANN — Approximate Nearest Neighbors) em milissegundos, (3) filtrar por metadados (data, autor, departamento, categoria) e (4) oferecer persistência, multi-tenancy e update incremental. O pipeline típico é documentado nas referências da Qdrant (Qdrant Documentation) e da Chroma (Chroma Documentation).

A “chave” que torna o RAG útil: o retrieval semântico resolve o problema de sinonímia que a pesquisa BM25/TF-IDF clássica não resolve. “Como fecho a sessão?” e “Logout” são a mesma intenção mas não partilham tokens. Um embedding bem treinado coloca-os próximos.

2. Cenários em que o RAG é a Resposta Certa

  • Chatbot de suporte técnico interno — empresa de 50 funcionários com 200 manuais e FAQs internas; o chatbot responde “como configuro VPN no Mac” citando o manual interno, não a resposta genérica da web.
  • Pesquisa semântica em conhecimento não-estruturado — gabinete de contabilidade com 5 000 PDFs de legislação e pareceres; RAG permite perguntar “quais os prazos para entrega do IVA no setor da construção” e obter respostas com citações.
  • Document Q&A sobre contratos e propostas — equipa comercial com 300 propostas comerciais; query “qual o desconto médio que demos ao cliente X em 2025” devolve excertos relevantes, não a busca literal.
  • Helpdesk IT com base de tickets — PME com 10 000 tickets Resolvidos; RAG sugere soluções anteriores para tickets novos, reduzindo tempo de resolução (MTTR).
  • Assistente de recursos humanos — empregados perguntam ao bot “quantos dias de licença me restam” e “qual a política de teletrabalho”, com resposta fundamentada no manual de RH.
  • Pesquisa em notas de reuniões e actas — equipa de direcção com 500 actas em Markdown; query semântica “decisões sobre o orçamento de marketing” recupera todas as actas relevantes mesmo sem a palavra exacta.

Nota sobre maturidade: RAG em 2026 é tecnologia madura, não hype. As vector databases listadas neste artigo estão em produção em empresas desde 2022-2023. O que mudou em 2026 é o custo (embeddings OpenAI baixaram 80% desde 2022) e a simplicidade (LangChain e LlamaIndex reduzem o código de dias para horas).

3. Passo 1 — Diagnosticar se RAG é Mesmo Necessário

Antes de implementar RAG, confirme que o problema é mesmo “o LLM não sabe X” e não “o LLM é mau a raciocinar”. Para PME, três testes rápidos:

Teste A — Prompt directo: coloque no GPT-4o / Claude a pergunta de negócio com a máxima informação de contexto possível no prompt. Se a resposta for correcta, RAG não é necessário — basta um prompt melhor.

Teste B — Keyword search existente: execute a query na pesquisa actual da empresa (SharePoint Search, Elasticsearch, grep num directório). Se 90% das queries resultam em 1 clique no documento certo, RAG adiciona pouco; se 40%+ falham, RAG resolve o problema.

Teste C — Volume de documentos: se o corpus for <20 documentos curtos, copie-os todos para o prompt (janela de contexto de 128k tokens do GPT-4o comporta ~100 páginas A4). Se for >50 documentos, >50 000 palavras ou se cresce semanalmente, RAG justifica-se.

# Diagnóstico rápido — estimar tokens de um corpus local
import os, tiktoken
enc = tiktoken.encoding_for_model(“gpt-4o”)
total_tokens = 0
for root, _, files in os.walk(“./documentos”):
for f in files:
if f.endswith((“.md”, “.txt”, “.pdf.txt”)):
with open(os.path.join(root, f), encoding=”utf-8″) as fh:
total_tokens += len(enc.encode(fh.read()))
print(f”Tokens totais: {total_tokens:,}”)
print(f”Cabe num prompt de 128k? {total_tokens < 128_000}”) print(f”Recomendação RAG: {‘Sim’ if total_tokens > 50_000 else ‘Talvez não’}”)

Esperado: para 200 documentos médios (5 KB cada), verá algo como Tokens totais: ~250 000 e Cabe num prompt de 128k? False — o que confirma que RAG é a abordagem correcta. O tiktoken é a biblioteca oficial da OpenAI para contagem de tokens e está validada contra o comportamento dos modelos GPT (OpenAI Cookbook no GitHub).

4. Passo 2 — Escolher o Modelo de Embeddings

Os embeddings são a espinha dorsal do RAG. Escolher mal o modelo degrada a qualidade de retrieval sem que o utilizador perceba — o chatbot “responde” mas com fontes irrelevantes. Em 2026, as três famílias viáveis para PME:

4.1 Modelo comercial — OpenAI text-embedding-3

A OpenAI lançou em 2024 os modelos text-embedding-3-small (1536 dimensões) e text-embedding-3-large (3072 dimensões), que em 2026 continuam a ser a referência comercial por relação custo/qualidade. Documentação: OpenAI Platform — Embeddings Guide.

# Instalação: pip install openai
from openai import OpenAI
client = OpenAI() # lê OPENAI_API_KEY do ambiente
resp = client.embeddings.create(
model=”text-embedding-3-small”,
input=”Como fecho a sessão no portal da empresa?”,
)
print(len(resp.data[0].embedding)) # 1536

Custo em 2026: $0.02 por 1M tokens (small) e $0.13 por 1M tokens (large), confirmado na documentação de modelos da OpenAI. Para 10 000 documentos de 1000 tokens cada, o índice inicial custa ~$0.20 (small) ou ~$1.30 (large).

4.2 Modelo open-source — sentence-transformers / BGE / E5

Para PME que querem inferência local, dados confidenciais ou sem dependência de API externa, a família sentence-transformers é o padrão open-source. O modelo BAAI/bge-m3 (multilingue, 1024 dimensões) e intfloat/multilingual-e5-large são os mais recomendados em 2026 no MTEB Leaderboard da Hugging Face (Hugging Face — MTEB, Sentence-Transformers).

# Instalação: pip install sentence-transformers
from sentence_transformers import SentenceTransformer
model = SentenceTransformer(“BAAI/bge-m3”) # 1024 dims, multilingue
vectors = model.encode([“Como fecho a sessão?”, “Logout”, “Encerrar conta”])
print(vectors.shape) # (3, 1024)

4.3 Modelo local via Ollama — nomic-embed-text, mxbai, bge

O Ollama permite correr modelos de embedding localmente sem GPU dedicada, ideal para PME com restrições de privacidade. O modelo nomic-embed-text (768 dims, 1.3 GB) é o ponto de entrada típico. Configuração e integração com RAG local é detalhada em artigos kbase.pt sobre o stack Ollama + Open WebUI (artigo relacionado: Ollama + Open WebUI stack avançado 2026).

# Pull do modelo de embedding local
ollama pull nomic-embed-text
# Inferência local via curl (sem cloud)
curl http://localhost:11434/api/embeddings -d ‘{
“model”: “nomic-embed-text”,
“prompt”: “Como fecho a sessão?”
}’

4.4 Quadro comparativo de modelos em 2026

Modelo Dimensões Custo (por 1M tokens) Local? Idioma Melhor para
OpenAI text-embedding-3-small 1536 $0.02 Não EN + multilingue PME com orçamento API e volume médio
OpenAI text-embedding-3-large 3072 $0.13 Não EN + multilingue Qualidade máxima, retrieval preciso
BAAI/bge-m3 (open-source) 1024 Grátis (self-host) Sim 100+ idiomas, PT forte PME com dados sensíveis, on-prem
intfloat/multilingual-e5-large 1024 Grátis (self-host) Sim 100+ idiomas Multilingue em produção
nomic-embed-text (via Ollama) 768 Grátis (self-host) Sim EN + multilingue Local sem GPU, protótipo rápido
Cohere embed-v4 1536 $0.10 Não 100+ idiomas PME que prefere alternativa à OpenAI

A escolha prática em 2026: se pode cloud, OpenAI text-embedding-3-small para começar; se tem dados sensíveis, BAAI/bge-m3 via sentence-transformers ou Ollama. Evite text-embedding-ada-002 (legacy, 1536 dims, superseded pelo 3-small em qualidade e custo).

5. Passo 3 — Escolher a Vector Database

Em 2026 existem cinco vector databases mainstream para PME. A escolha determina custos operacionais, complexidade de DevOps e capacidade de escala.

5.1 Pinecone — managed serverless (commercial)

Pinecone é a oferta managed serverless mais madura, sem infraestrutura para gerir. Ideal para PME que preferem pagar para não operar. A documentação oficial descreve a arquitectura serverless com storage em camadas e cálculo on-demand (Pinecone Learn, Pinecone Pricing).

# pip install pinecone-client
from pinecone import Pinecone
pc = Pinecone() # lê PINECONE_API_KEY
idx = pc.Index(“kbase-rag”)
idx.upsert(vectors=[
{“id”: “doc-1”, “values”: emb, “metadata”: {“fonte”: “manual-vpn.pdf”}}
])
res = idx.query(vector=pergunta_emb, top_k=5, filter={“fonte”: {“$eq”: “manual-vpn.pdf”}})

5.2 Qdrant — open-source, production-grade

Qdrant é escrito em Rust, open-source (Apache 2.0) e oferece uma versão managed cloud e self-hosted. A documentação oficial cobre payloads, filtros e quantização (Qdrant Documentation, Qdrant Pricing). É a escolha preferida em 2026 para PME que querem self-host com performance alta e baixo consumo de memória.

# pip install qdrant-client
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams
client = QdrantClient(host=”localhost”, port=6333) # self-host via Docker
client.recreate_collection(
collection_name=”kbase”,
vectors_config=VectorParams(size=1024, distance=Distance.COSINE),
)
client.upsert(collection_name=”kbase”, points=[
{“id”: 1, “vector”: emb, “payload”: {“fonte”: “manual-vpn.pdf”}}
])

5.3 Chroma — lightweight, dev-friendly

Chroma é a opção mais simples para começar — corre em processo (embedded), sem servidor separado, ideal para protótipos e PME com <100k documentos. Documentação: Chroma Documentation. Em 2026 o Chroma evoluiu para uma arquitectura client-server, mas mantém o modo embedded.

# pip install chromadb
import chromadb
client = chromadb.PersistentClient(path=”./vector_db”) # persistência local
col = client.get_or_create_collection(“kbase”)
col.add(
ids=[“doc-1”],
embeddings=[emb],
documents=[“Manual VPN: para fechar a sessão, clique em Logout.”],
metadatas=[{“fonte”: “manual-vpn.pdf”}],
)
res = col.query(query_embeddings=[pergunta_emb], n_results=5)

5.4 Weaviate — schema-first, GraphQL

Weaviate é open-source (BSD-3) e distingue-se por ser “schema-first” e oferecer uma API GraphQL nativa. A documentação oficial descreve módulos para multimodal e hybrid search (Weaviate Developer Docs, Weaviate Pricing). Recomendado quando se quer combines keyword + vector search (hybrid) out-of-the-box.

5.5 pgvector — extensão PostgreSQL

Para PME que já usam PostgreSQL, pgvector é a via mais económica: adicionar a extensão a uma base de dados existente em vez de instalar uma vector database nova. O repositório oficial está em pgvector no GitHub. Em 2026, suporta índices HNSW e IVFFlat em 1536+ dimensões, com bom desempenho até ~1M vectores por instância.

— Habilitar a extensão (PostgreSQL 14+)
CREATE EXTENSION vector;
— Criar tabela
CREATE TABLE documentos (
id SERIAL PRIMARY KEY,
conteudo TEXT,
embedding VECTOR(1536),
fonte TEXT
);
— Índice HNSW para busca rápida
CREATE INDEX ON documentos USING hnsw (embedding vector_cosine_ops);
— Query de similaridade
SELECT conteudo, fonte, embedding <=> $1::vector AS distancia
FROM documentos
ORDER BY embedding <=> $1::vector
LIMIT 5;

5.6 Quadro comparativo — Vector Databases para PME em 2026

Vector DB Open-source? Managed? Self-host fácil? Escalabilidade Custo inicial PME Melhor para
Pinecone Não Sim (serverless) N/A Auto Free tier 100k vectores Quem não quer DevOps
Qdrant Sim (Apache 2.0) Sim Sim (Docker) Milhões Grátis self-host PME on-prem, performance
Chroma Sim (Apache 2.0) Em desenvolvimento Sim (embedded) ~1M docs Grátis Protótipos, <100k docs
Weaviate Sim (BSD-3) Sim Sim (Docker) Milhões Grátis self-host Hybrid search, multimodal
pgvector Sim (PostgreSQL) Via provedores PG Sim (extensão) ~1M vectores Grátis se já tem PG PME com PostgreSQL existente

Recomendação 2026 para PME portuguesas: começar com Chroma para protótipo (zero DevOps), migrar para Qdrant ou pgvector em produção. Escolher Pinecone apenas se a equipa não tem competências de infraestrutura. A documentação oficial da Qdrant documenta bem a transição Chroma→Qdrant (Qdrant Quick Start).

6. Passo 4 — Arquitectura Típica de um Pipeline RAG

A arquitectura canónica documentada em 2026 pela Pinecone, LangChain e LlamaIndex segue seis fases. Esta secção descreve-as conceptualmente; a implementação em código está na secção 7.

Documentos → [1] Ingestão → [2] Chunking → [3] Embedding → [4] Storage

LLM ← [6] Geração ← [5] Retrieval ← Query (embedding)

6.1 Ingestão de documentos

Carregar PDFs, Word, Markdown, HTML, e-mails, tickets, páginas web. Em 2026, LangChain oferece loaders para >80 fontes (LangChain Data Connection) e LlamaIndex inclui centenas de conectores (LlamaIndex Docs). Para PDFs com layout complexo, considere unstructured, marker-pdf ou pymupdf — a extração correcta é responsável por 40-60% da qualidade final do RAG.

6.2 Chunking — segmentação em passagens

Não se pode embedding de um PDF de 50 páginas inteiro: perde-se granularidade. Dividir em chunks de 500-1500 tokens com overlap de 50-200 tokens é o padrão. Estratégias:

  • RecursiveCharacterTextSplitter (LangChain) — divide por parágrafo, depois frase, depois palavra. É o padrão de facto.
  • Semantic chunker — divide quando a semântica muda (via embeddings). Mais caro mas superior em documentos densos.
  • Markdown/HTML structural splitter — preserva headers como metadados. Recomendado para documentação técnica.
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200,
separators=[“\n## “, “\n### “, “\n\n”, “\n”, “. “, ” “],
)
chunks = splitter.split_text(documento_markdown)

6.3 Embedding

Cada chunk é convertido num vector pelo modelo escolhido (secção 4). Para PT-PT, modelos multilingues (bge-m3, multilingual-e5, OpenAI 3-small) têm desempenho equivalente ao inglês em benchmarks MTEB (Hugging Face MTEB).

6.4 Storage

Os vectores + metadados + texto são inseridos na vector database escolhida (secção 5). Em produção, armazenar também: fonte, data_criacao, autor, categoria, pagina, hash_chunk — estes metadados habilitam filtros (ex: “só manuais de 2025”) e auditoria.

6.5 Retrieval — recuperação por similaridade

Quando o utilizador faz uma pergunta: (1) gera o embedding da pergunta, (2) procura na vector database os K vectores mais próximos (K=3 a 10), (3) retorna os chunks correspondentes com metadados. Técnicas avançadas em 2026: hybrid search (combina vector + BM25), re-ranking com um modelo cross-encoder (bge-reranker-v2-m3) para reordenar os top-K, e query expansion (LLM reformula a pergunta em 3 variantes).

6.6 Geração — prompt + LLM

Os K chunks recuperados são inseridos no prompt como contexto. O prompt típico: “Responde à pergunta usando apenas o contexto abaixo. Cita a fonte. Se não souberes, diz que não encontraste.”

Contexto:
[chunk 1 — fonte: manual-vpn.pdf, p.12]
[chunk 2 — fonte: faq-it.docx]Pergunta: Como fecho a sessão no portal?

Resposta: Para fechar a sessão no portal da empresa, clica no botão “Logout” no canto superior direito (fonte: manual-vpn.pdf, p.12). Se a opção não aparecer, limpa as cookies do navegador (fonte: faq-it.docx).

O LLM gera a resposta com citações — mais fiável que geração livre e auditável.

7. Passo 5 — Implementação Prática com LangChain

A implementação mais rápida em 2026 usa LangChain, que abstrai ingestion, chunking, embedding, storage e retrieval numa API de alto nível. Documentação oficial: LangChain RAG Tutorial.

7.1 Instalação

pip install langchain langchain-community langchain-openai \
langchain-chroma chromadb sentence-transformers tiktoken

7.2 Pipeline mínimo com Chroma + OpenAI

# rag_minimo.py — pipeline RAG funcional em ~30 linhas
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
import os# 1. Ingestão — carregar todos os .md de ./documentos
loader = DirectoryLoader(“./documentos”, glob=”**/*.md”, loader_cls=TextLoader)
docs = loader.load()

# 2. Chunking
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(docs)

# 3+4. Embedding + Storage (Chroma em modo persistente)
embeddings = OpenAIEmbeddings(model=”text-embedding-3-small”)
vectorstore = Chroma.from_documents(
chunks, embeddings, persist_directory=”./vector_db”
)
retriever = vectorstore.as_retriever(search_kwargs={“k”: 5})

# 5+6. Retrieval + Geração
llm = ChatOpenAI(model=”gpt-4o-mini”, temperature=0)
template = “””Responde à pergunta em PT-PT usando apenas o contexto abaixo.
Cita a fonte entre parêntesis. Se não souberes, diz “Não encontrado no conhecimento base”.

Contexto:
{context}

Pergunta: {question}
“””
prompt = ChatPromptTemplate.from_template(template)
rag_chain = (
{“context”: retriever, “question”: RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)

# Query
resposta = rag_chain.invoke(“Como fecho a sessão no portal?”)
print(resposta)

Esperado: resposta em PT-PT com citação (fonte: manual-vpn.md, p.12). Se a pergunta não estiver coberta, o modelo devolve “Não encontrado no conhecimento base” em vez de alucinar — o comportamento pretendido.

Testado em: 2026-07-18 — sintaxe verificada contra python.langchain.com/docs/tutorials/rag e docs.trychroma.com. Versões de referência: langchain 0.3.x, langchain-chroma 0.1.x, langchain-openai 0.2.x.

7.3 Variante com LlamaIndex

LlamaIndex é a alternativa a LangChain, com focus em indexing sofisticado e retrieval avançado. Documentação: LlamaIndex Docs.

# pip install llama-index llama-index-embeddings-openai llama-index-llms-openai
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAISettings.embed_model = OpenAIEmbedding(model=”text-embedding-3-small”)
Settings.llm = OpenAI(model=”gpt-4o-mini”, temperature=0)

docs = SimpleDirectoryReader(“./documentos”).load_data()
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(similarity_top_k=5)
print(query_engine.query(“Como fecho a sessão no portal?”))

7.4 Variante 100% open-source (sem cloud, para dados sensíveis)

# rag_local.py — RAG sem cloud, usando Ollama + Chroma + bge-m3
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain_ollama import ChatOllama
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser# Modelo de embedding local (bge-m3 multilingue, 1024 dims)
embeddings = HuggingFaceEmbeddings(model_name=”BAAI/bge-m3″)
# LLM local via Ollama (llama3.1 ou qwen2.5)
llm = ChatOllama(model=”llama3.1″, temperature=0)

loader = DirectoryLoader(“./documentos”, glob=”**/*.md”, loader_cls=TextLoader)
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(docs)
vectorstore = Chroma.from_documents(chunks, embeddings, persist_directory=”./vector_db”)
retriever = vectorstore.as_retriever(search_kwargs={“k”: 5})

template = “””Responde em PT-PT usando só o contexto. Cita a fonte.
Contexto: {context}
Pergunta: {question}”””
prompt = ChatPromptTemplate.from_template(template)
rag_chain = (
{“context”: retriever, “question”: RunnablePassthrough()}
| prompt | llm | StrOutputParser()
)
print(rag_chain.invoke(“Como fecho a sessão no portal?”))

Vantagem: todos os dados e inferência ficam na rede interna — zero envio para cloud. Trade-off: a qualidade do Llama 3.1 8B local é inferior ao GPT-4o; para tarefas exigentes, use Llama 3.1 70B via Ollama num servidor com 48 GB de RAM ou modelo via provedor de inferência open-source (artigo relacionado: Hermes AI Agent + Ollama instalação).

8. Passo 6 — Custos e Orçamento para PME

Em 2026, RAG deixou de ser caro. Os custos deprimem-se em três eixos: embeddings, vector DB e LLM.

8.1 Embeddings

Cenário PME Volume Custo OpenAI 3-small Custo bge-m3 self-host
100 documentos curtos (prova de conceito) 100k tokens $0.002 $0 (apenas CPU)
1 000 documentos (catálogo de manuais) 1M tokens $0.02 $0
10 000 documentos (base completa) 10M tokens $0.20 $0
100 000 documentos (escala) 100M tokens $2.00 $0
Re-indexação mensal incremental 1M tokens/mês $0.02/mês $0

A indexação é amortizada: paga-se uma vez, re-paga-se só no delta de novos documentos. Embeddings de queries (pergunta do utilizador) são 100-300 tokens cada — custo negligenciável mesmo em alto tráfego.

8.2 Vector Database

Vector DB Custo PME (100k vectores) Custo produção (1M vectores)
Chroma self-host Grátis (disco local) Grátis
Qdrant self-host (Docker) Grátis Grátis
pgvector (PostgreSQL existente) Grátis (extensão) Grátis
Pinecone serverless Free tier até 100k ~$70/mês (Starter)
Qdrant Cloud Free tier 1GB ~$40/mês (Cluster S1)
Weaviate Cloud Free tier 10M dims ~$25/mês (Standard)

Para 95% das PME portuguesas com <100k documentos, Chroma ou pgvector self-host são zero custo.

8.3 LLM (geração)

Provedor Modelo Custo por 1M tokens (input) Custo por 1M tokens (output)
OpenAI GPT-4o-mini $0.15 $0.60
OpenAI GPT-4o $2.50 $10.00
Anthropic Claude 3.5 Haiku $0.80 $4.00
Anthropic Claude 3.5 Sonnet $3.00 $15.00
Google Gemini 1.5 Flash $0.075 $0.30
Google Gemini 1.5 Pro $1.25 $5.00
Ollama local Llama 3.1 8B $0 $0
Ollama local Llama 3.1 70B $0 (hardware ~$2k) $0
Groq hosted Llama 3.1 8B $0.05 $0.08

Cenário PME típico (chatbot interno, 100 queries/dia, 500 tokens de contexto cada): ~50k tokens input + 5k output por dia = ~$0.01/dia com GPT-4o-mini ou $0 com Ollama. Para 30 dias = $0.30/mês. RAG é, em 2026, acessível a qualquer PME.

9. Outras Causas e Armadilhas Comuns em RAG

O RAG “funciona” mas pode dar respostas erradas sem que o utilizador perceba. Lista das armadilhas mais frequentes e onde se resolvem:

  • Chunk size mal calibrado — chunks demasiado pequenos perdem contexto semântico; demasiado grandes diluem a relevância. Solução: começar com 1000 tokens + 200 overlap, testar com 20 queries reais e ajustar. Erro típico descrito em Pinecone Learn — chunking.
  • Embedding com modelos diferentes para query e indexação — vector DB fica incompatível. Cada mudança de modelo obriga a re-indexar. Manter o modelo numa constante no código.
  • Sem re-ranking — top-K por cosine pode ter falsos positivos. Em 2026, adicionar um cross-encoder bge-reranker-v2-m3 aumenta precisão em 15-30%.
  • Sem metadados filtráveis — não conseguir limitar retrieval a “documentos de 2025” ou “categoria: RH”. Metadados são grátis e cruciais.
  • Falta de gestão de versões do índice — quando se actualiza um manual, o chunk antigo permanece na vector DB. Solução: hash por chunk, fazer upsert (substituir) não insert.
  • Alucinação apesar de RAG — prompt mal construído (“Responde à pergunta”) permite ao LLM ignorar o contexto. Prompt correcto: “Se a resposta não estiver no contexto, diz que não encontraste.”
  • Dados confidenciais em APIs comerciais — OpenAI, Anthropic, Cohere têm políticas de retenção. Para PII, financeiro, jurídico, usar Llama 3.1 local via Ollama ou provedores com DPA (Data Processing Agreement).
  • PDFs mal extraídos — PDFs com colunas, tabelas, scans produzidos por OCR mau degradam retrieval. Validar a extração manualmente nos primeiros 20 documentos.
  • Monolingual embedding em corpus PT — modelos só em inglês (ex: original OpenAI ada) perdem nuances em PT. Usar multilingue: bge-m3, multilingual-e5, ou OpenAI 3-small (multilingue).

⚠ ⚠️ **Atenção

Nunca implemente RAG em produção sem um conjunto de testes de avaliação** com 30-50 queries reais e as respostas esperadas (golden set). Sem avaliação, não há forma de detectar regressões ao alterar modelo, chunk size ou prompt.

10. Como Evitar Problemas em Implementações Futuras

  • Definir um golden set antes de começar — 30-50 perguntas reais com a resposta esperada. Serve de teste de regressão a cada alteração.
  • Versionar o pipeline — guardar versão do modelo de embedding, chunk size, prompt e vector DB em metadata. Permite reproduzir resultados e rollback.
  • Fazer retrieval evaluation, não só end-to-end — medir recall@5 e precision@5 dos chunks recuperados, não só a qualidade da resposta final. A causa de respostas más é frequentemente retrieval falhado, não o LLM.
  • Monitorizar drift — logs de queries + chunks recuperados + satisfação do utilizador (thumbs up/down). Quando a satisfação cai, investigar retrieval primeiro.
  • Planeamento de re-indexação — agenda mensal ou trigger on-update para re-embeddings de novos documentos. Sem isto, o índice fica desactualizado.
  • Backup do índice — vector DB é dados. Replicar como qualquer base de dados (snapshot Qdrant, dump Chroma, pg_dump para pgvector).
  • Começar pequeno, depois escalar — Chroma + 50 documentos + GPT-4o-mini para prova de conceito em 1 dia. Migrar para Qdrant/pgvector em produção só quando o padrão estiver validado.
  • Documentar o “porquê” — porque se escolheu bge-m3 em vez de OpenAI, porque chunk de 800 e não 1500. RAG é 70% de decisões de engenharia; sem documentação, a equipa repete erros.
  • Cross-referência com outros artigos AIOllama + Open WebUI stack avançado 2026 para inferência local, Copilot governance e plugins para políticas de uso responsável de LLM na empresa.

Artigos Relacionados

 

11. Checklist Antes de Aplicar em Produção

  1. Verificar versões: pip show langchain chromadb qdrant-client sentence-transformers openai — anotar versões e comparar com as indicadas nas docs oficiais acedidas em 2026-07-18.
  2. Verificar chaves de API: OPENAI_API_KEY, PINECONE_API_KEY ou QDRANT_URL definidas no ambiente; nunca comitar no git.
  3. Verificar modelo de embedding: confirmar dimensões (1536, 1024, 768) compatíveis com a coleção na vector DB; mismatch causa erro de inserção silencioso.
  4. Preparar golden set: 30-50 queries reais com resposta esperada, guardadas em JSON. Sem isto, não há forma de medir regressões.
  5. Ambiente de staging: projecto sandbox Python 3.11 com dependências pinadas em requirements.txt; testar ingestão de 10 documentos reais e 20 queries antes de migrar para produção.
  6. Backup do estado: antes de alterar modelo de embedding ou chunk size, exportar a vector DB (dump Chroma, snapshot Qdrant, pg_dump para pgvector). Configuração errada obriga a re-indexar tudo, o que custa tempo e dinheiro.

Risco concreto: aplicar RAG em produção sem golden set e sem avaliação de retrieval pode levar a respostas incorrectas que parecem correctas — o que para PME em setores regulados (saúde, financeiro, jurídico) pode constituir violação de compliance. Antes de expor o chatbot a clientes ou funcionários, validar com stakeholders de negócio que as respostas são correctas em 95%+ dos casos do golden set.