O LlamaIndex tornou-se uma das bases mais usadas para construir aplicações de pesquisa aumentada por recuperação (RAG) sobre modelos de linguagem. Em outubro de 2026, o pacote llama-index está na versão 0.14.25, lançada a 21 de setembro, e o repositório no GitHub soma aproximadamente 52,5 mil estrelas. Este tutorial mostra, passo a passo, como instalar o framework, indexar documentos próprios, construir um motor de consulta e de chat, trocar a OpenAI por modelos locais com o Ollama e ligar tudo a uma base de dados vetorial pronta para produção.
Jerry Liu, cofundador e CEO da LlamaIndex, resume bem a ideia central da técnica: “RAG is a programmatic way to place relevant context in an LLM’s prompt, not a replacement for every other adaptation method” (“o RAG é uma forma programática de colocar contexto relevante no prompt de um LLM, não um substituto para todos os outros métodos de adaptação”), afirmou em entrevista disponível em louisbouchard.ai. Esta distinção importa porque muita gente trata o RAG como uma solução universal, quando na prática é apenas uma camada de engenharia de prompt automatizada.
Para quem gere equipas pequenas ou projetos pessoais, a vantagem prática do RAG sobre o fine-tuning é direta: não exige treinar um modelo novo, não exige GPUs dedicadas durante semanas e não exige um conjunto de dados de treino cuidadosamente anotado. Basta teres os documentos já existentes (manuais, políticas internas, documentação técnica) e uma forma de os indexar. É esta simplicidade de entrada que explica porque o LlamaIndex continua a ser uma das primeiras bibliotecas que programadores portugueses testam quando querem construir um assistente interno capaz de responder com base em conteúdo próprio, em vez de depender só do conhecimento genérico do modelo. Este tutorial encaixa-se na mesma área de inteligência artificial e modelos de linguagem que já temos vindo a cobrir noutros frameworks e ferramentas open source.
O que é o LlamaIndex e porque está em alta em 2026
O LlamaIndex é uma biblioteca Python (com uma versão TypeScript paralela) criada para ligar fontes de dados privadas, como PDFs, páginas de documentação ou bases de dados internas, a modelos de linguagem como o GPT, o Claude ou modelos locais via Ollama. Em vez de depender apenas do conhecimento que o modelo aprendeu durante o treino, a aplicação consulta primeiro os documentos relevantes e injeta esse texto no prompt antes de pedir uma resposta.
O projeto nasceu em 2022 sob o nome GPT Index e foi reorientado para LlamaIndex pouco depois, quando a equipa percebeu que a arquitetura de indexação funcionava com qualquer modelo, não apenas com o GPT da OpenAI. Segundo a página do projeto na Wikipedia, a empresa por trás do framework recebeu uma ronda Series A de 19 milhões de dólares em março de 2025, elevando o financiamento total divulgado para cerca de 27,5 milhões de dólares. A ferramenta open source continua gratuita; existe ainda um produto gerido chamado LlamaCloud, com serviços de extração, indexação e observabilidade para quem não quer gerir a infraestrutura RAG sozinho.
Em 2026, a procura por tutoriais de LlamaIndex acompanha o crescimento geral dos agentes de IA que precisam de “memória” sobre dados próprios: suporte ao cliente com base em manuais internos, assistentes jurídicos que leem contratos, ou chatbots de documentação técnica. A AWS inclui o LlamaIndex nas suas orientações oficiais para frameworks de IA agêntica, descrevendo-o como adequado para aplicações RAG e agênticas, segundo a página de AWS Prescriptive Guidance.
Arquitetura interna: readers, node parsers, índices e retrievers
Antes de escreveres a primeira linha de código, ajuda a compreender as peças que compõem um pipeline RAG no LlamaIndex, porque cada passo deste tutorial corresponde a uma dessas peças. O fluxo de dados típico segue sempre a mesma sequência lógica, independentemente do fornecedor de modelo que escolheres no final.
- Readers (leitores): convertem ficheiros em bruto, como PDFs, páginas HTML ou ficheiros de texto, em objetos de documento internos que o resto do framework consegue processar. O
SimpleDirectoryReader, usado no passo 5, é o leitor genérico mais comum, mas existem leitores especializados para fontes como Notion, Google Drive ou bases de dados SQL. - Node parsers (divisores de nós): pegam em cada documento e dividem-no em fragmentos menores, chamados nós. É aqui que o
chunk_sizee ochunk_overlapentram em jogo, como vais ver no passo 12. - Modelo de embeddings: transforma cada nó de texto num vetor numérico que representa o seu significado semântico. É este vetor que permite comparar a pergunta do utilizador com os fragmentos de documento, mesmo quando as palavras usadas são diferentes.
- Índice: a estrutura de dados que guarda todos os vetores e permite pesquisas rápidas por semelhança. O
VectorStoreIndexé o tipo de índice mais usado, mas o framework também suporta índices em árvore e em lista para outros padrões de consulta. - Retriever: o componente que, dada uma pergunta, decide quais os nós do índice mais relevantes para responder.
- Response synthesizer (sintetizador de resposta): junta os nós recuperados, monta o prompt final e envia-o ao modelo de linguagem escolhido, devolvendo depois a resposta formatada ao utilizador.
Quando chamas indice.as_query_engine(), o LlamaIndex está, nos bastidores, a juntar automaticamente um retriever e um sintetizador de resposta configurados com valores sensatos por omissão. Todo este tutorial pode ser lido como uma forma de ires substituindo essas omissões por configurações mais adequadas ao teu caso de uso específico, uma peça a cada vez.
Pré-requisitos: Python, hardware e chaves de API
Antes de avançar, confirma que o teu ambiente cumpre os requisitos mínimos. A página do pacote no PyPI exige explicitamente Python 3.10 ou superior, e inferior a 4.0. Versões mais antigas de Python (3.8 ou 3.9) não conseguem instalar a versão atual do pacote.
| Requisito | Versão/valor mínimo | Observações |
|---|---|---|
| Python | >= 3.10, < 4.0 | Confirmado na página do pacote no PyPI |
| llama-index (pacote principal) | 0.14.25 | Lançado a 21 de setembro de 2026 |
| llama-index-core | 0.14.25 | Publicado como pacote separado para instalações personalizadas |
| RAM recomendada | 8 GB ou mais | Mais RAM é necessária se usares modelos locais via Ollama |
| Chave de API | OpenAI, Anthropic ou local | Podes evitar custos de API usando o Ollama em alternativa |
| Sistema operativo | Linux, macOS ou Windows | Este tutorial usa comandos de terminal compatíveis com Linux e macOS |
Vais também precisar de uma pasta com alguns ficheiros de texto, PDF ou Markdown para testar a indexação, de um editor de código (VS Code, por exemplo) e de acesso à linha de comandos. Se quiseres seguir a parte do tutorial que usa a OpenAI, precisas de uma chave de API válida; se preferires não gastar créditos, o passo 9 explica como fazer tudo localmente com o Ollama, sem qualquer custo por token.
Vale também pensar, antes de começares, em onde os teus dados vão ficar. Se os documentos que vais indexar contêm informação sensível ou dados pessoais de clientes, enviar esse texto para uma API externa de embeddings implica que esse conteúdo sai da tua infraestrutura. Para quem trabalha sob o Regulamento Geral de Proteção de Dados (RGPD) em Portugal, isto costuma pesar na decisão entre usar a OpenAI (passos 1 a 8) ou manter tudo localmente com o Ollama (passo 9). Nenhuma das duas opções é universalmente “mais segura”; a escolha depende da classificação dos dados em causa e da política interna da organização para tratamento de dados pessoais.
Passos 1 a 3: ambiente virtual, instalação e chave de API
Passo 1: Criar o ambiente virtual Python
Cria sempre um ambiente virtual isolado antes de instalar qualquer pacote Python de IA, para evitares conflitos de dependências com outros projetos. Abre o terminal na pasta do teu projeto e executa:
mkdir projeto-rag-llamaindex
cd projeto-rag-llamaindex
python3 -m venv venv
source venv/bin/activate
# No Windows: venv\Scripts\activate
Confirma que o Python ativo é a versão correta antes de continuares:
python3 --version
# Deve mostrar Python 3.10.x, 3.11.x, 3.12.x ou 3.13.x
Passo 2: Instalar o LlamaIndex e os pacotes complementares
O pacote llama-index funciona como um “pacote de arranque” que já inclui o núcleo do framework mais algumas integrações comuns. Para um controlo mais fino sobre o que é instalado, podes optar pela instalação modular, começando pelo núcleo e acrescentando só os conectores que precisas:
# Instalação rápida (inclui integrações padrão)
pip install llama-index
# OU instalação modular, mais controlada
pip install llama-index-core
pip install llama-index-llms-openai
pip install llama-index-llms-ollama
pip install llama-index-embeddings-huggingface
Este tutorial segue o caminho modular, porque é o que a documentação oficial recomenda para quem quer evitar instalar dependências que não vai usar (por exemplo, não precisas do conector da OpenAI se vais trabalhar só com o Ollama). Se preferires simplicidade a controlo, o comando único pip install llama-index também funciona para seguir todos os passos seguintes.
Passo 3: Configurar a chave de API e as variáveis de ambiente
Nunca escrevas a chave de API diretamente no código-fonte. Cria um ficheiro .env na raiz do projeto:
# ficheiro .env
OPENAI_API_KEY=sk-a-tua-chave-aqui
E carrega-a no início do teu script Python com a biblioteca python-dotenv:
pip install python-dotenv
# No topo do teu script Python:
from dotenv import load_dotenv
load_dotenv()
Adiciona o ficheiro .env ao teu .gitignore antes de fazeres o primeiro commit. É um dos erros mais comuns em tutoriais de IA: a chave acaba exposta num repositório público e é apanhada por bots de scraping em minutos.
Passos 4 a 6: carregar documentos e criar o índice vetorial
Passo 4: Preparar a pasta de documentos
Cria uma pasta chamada dados e coloca lá os ficheiros que queres consultar: PDFs, ficheiros .txt, .md ou até páginas HTML exportadas. Para este exemplo, usa dois ou três documentos curtos (manuais, FAQs internas, notas de produto) para veres resultados rapidamente sem esperares por uma indexação longa.
mkdir dados
# copia os teus ficheiros PDF/TXT/MD para dentro de dados/
Passo 5: Carregar os documentos com o SimpleDirectoryReader
O carregador de diretório genérico lê automaticamente os formatos mais comuns e converte cada ficheiro num conjunto de objetos de documento internos:
from dotenv import load_dotenv
load_dotenv()
from llama_index.core import SimpleDirectoryReader
documentos = SimpleDirectoryReader("dados").load_data()
print(f"Foram carregados {len(documentos)} documentos.")
Passo 6: Criar o índice vetorial com o VectorStoreIndex
O índice vetorial transforma cada fragmento de texto num vetor numérico (embedding) e guarda-o numa estrutura pesquisável por semelhança semântica. É este índice que permite ao LlamaIndex encontrar o trecho certo mesmo que a pergunta do utilizador use palavras diferentes das do documento original:
from llama_index.core import VectorStoreIndex
indice = VectorStoreIndex.from_documents(documentos)
print("Índice criado com sucesso.")
Por omissão, o LlamaIndex usa o modelo de embeddings da OpenAI se a variável OPENAI_API_KEY estiver definida. Se preferires um modelo de embeddings gratuito e local, usa o conector HuggingFace que instalaste no passo 2 (mais detalhes no passo 9, dedicado a correr tudo localmente).
Passos 7 e 8: motor de consulta e motor de chat com memória
Passo 7: Construir o motor de consulta (query engine)
Com o índice criado, o próximo passo é transformá-lo num motor de consulta capaz de receber perguntas em linguagem natural e devolver respostas com base nos documentos carregados:
motor_consulta = indice.as_query_engine()
resposta = motor_consulta.query("Qual é a política de garantia descrita no documento?")
print(resposta)
Por trás deste código simples, o LlamaIndex faz várias coisas automaticamente: converte a pergunta num vetor, procura os fragmentos de texto mais parecidos no índice, monta um prompt com esses fragmentos como contexto e envia tudo ao modelo de linguagem configurado. É exatamente o processo que Jerry Liu descreve como uma “way of prompting so that you actually get back some context” (“forma de fazer prompting de modo a obteres de facto algum contexto”), segundo a mesma entrevista em louisbouchard.ai.
Passo 8: Adicionar memória com o motor de chat
O motor de consulta trata cada pergunta de forma isolada. Para construir uma conversa com memória, onde o modelo recorda o que foi dito antes, usa o motor de chat:
motor_chat = indice.as_chat_engine(chat_mode="context")
print(motor_chat.chat("Quais são os produtos mencionados no documento?"))
print(motor_chat.chat("E qual deles tem garantia mais longa?"))
Na segunda pergunta, o modelo já sabe a que “deles” se refere, porque o motor de chat mantém o histórico da conversa e volta a consultar o índice a cada nova mensagem, juntando sempre o contexto mais recente ao histórico anterior.
Passo 9: trocar a OpenAI por modelos locais com o Ollama
Uma das maiores vantagens do LlamaIndex é a independência de fornecedor: o mesmo código de indexação funciona com qualquer modelo, só muda a configuração do LLM e dos embeddings. Para correr tudo localmente, sem custos de API e sem enviar dados para fora da máquina, configura o Ollama como motor de inferência e um modelo de embeddings da HuggingFace para a parte de vetorização:
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings, VectorStoreIndex, SimpleDirectoryReader
Settings.llm = Ollama(model="llama3.1", request_timeout=120.0)
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
documentos = SimpleDirectoryReader("dados").load_data()
indice_local = VectorStoreIndex.from_documents(documentos)
motor_local = indice_local.as_query_engine()
print(motor_local.query("Resume o conteúdo principal destes documentos."))
Para este código funcionar, precisas de ter o Ollama instalado e o modelo escolhido já descarregado (ollama pull llama3.1, por exemplo). Esta abordagem elimina a dependência de uma chave de API externa, o que a torna ideal para protótipos internos, ambientes com dados sensíveis ou simplesmente para aprender sem gastar créditos de API.
Passos 10 e 11: persistência do índice e base de dados vetorial com o Chroma
Passo 10: Persistir o índice em disco
Reconstruir o índice a cada execução do script é lento e, se usares a API da OpenAI para embeddings, também tem custo. Guarda o índice em disco depois de o criares pela primeira vez:
# Guardar o índice
indice.storage_context.persist(persist_dir="./armazenamento")
E, nas execuções seguintes, carrega-o em vez de recriares tudo do zero:
from llama_index.core import StorageContext, load_index_from_storage
contexto_armazenamento = StorageContext.from_defaults(persist_dir="./armazenamento")
indice_carregado = load_index_from_storage(contexto_armazenamento)
Passo 11: Ligar o LlamaIndex a uma base de dados vetorial com o Chroma
A persistência em disco funciona bem para protótipos, mas uma aplicação em produção, com milhares de documentos e vários utilizadores em simultâneo, precisa de uma base de dados vetorial dedicada. O Chroma é uma das opções mais populares para começar por ser simples de correr localmente ou em contentor:
pip install chromadb llama-index-vector-stores-chroma
import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext, VectorStoreIndex
cliente_chroma = chromadb.PersistentClient(path="./chroma_db")
colecao = cliente_chroma.get_or_create_collection("documentos_rag")
vector_store = ChromaVectorStore(chroma_collection=colecao)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
indice_producao = VectorStoreIndex.from_documents(
documentos, storage_context=storage_context
)
Esta abordagem separa o armazenamento vetorial da lógica da aplicação, o que facilita escalar para outras bases de dados vetoriais mais tarde (Pinecone, Qdrant ou Weaviate seguem um padrão de integração semelhante), sem teres de reescrever a lógica de indexação ou de consulta.
Passo 12: afinar o chunking e avaliar a qualidade das respostas
O chunking, ou seja, a forma como os documentos são divididos em fragmentos antes de serem convertidos em embeddings, é provavelmente a variável com maior impacto na qualidade final das respostas. Fragmentos demasiado pequenos perdem contexto; fragmentos demasiado grandes diluem a relevância e aumentam o custo por consulta. O LlamaIndex expõe este controlo através de node parsers configuráveis globalmente:
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core import Settings
Settings.node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=50)
indice_afinado = VectorStoreIndex.from_documents(documentos)
Depois de ajustares o chunking, testa sempre com perguntas reais que os utilizadores finais fariam, não apenas com perguntas óbvias que sabes que o documento responde bem. Compara respostas com diferentes valores de chunk_size (experimenta 256, 512 e 1024) e observa se a resposta fica mais completa ou, pelo contrário, começa a incluir informação irrelevante. Esta fase de avaliação manual, ainda que demorada, costuma revelar mais problemas do que qualquer métrica automática isolada.
Uma forma simples de sistematizar essa avaliação, sem recorrer a ferramentas adicionais, é criar um pequeno conjunto de teste próprio: uma folha de cálculo com 20 a 30 perguntas reais e a resposta esperada para cada uma, escrita por alguém que conhece bem o conteúdo dos documentos. Depois de qualquer alteração ao chunking, ao modelo de embeddings ou ao número de fragmentos recuperados, corre o mesmo conjunto de perguntas e compara manualmente as respostas novas com as esperadas. Este processo é trabalhoso no início, mas paga-se rapidamente, porque transforma uma decisão subjetiva (“esta resposta parece melhor”) numa comparação direta e repetível ao longo do tempo, à medida que o conjunto de documentos cresce.
LlamaIndex vs LangChain: qual framework escolher em 2026
É inevitável comparar o LlamaIndex com o LangChain, o outro grande framework open source para aplicações com LLMs. Em termos de popularidade no GitHub, o LangChain soma aproximadamente 110 mil estrelas, contra cerca de 52,5 mil do LlamaIndex, segundo uma comparação publicada em outubro de 2026 no blog da ValueAdd VC. Essa mesma análise caracteriza o LangChain como tendo uma cobertura mais ampla de agentes e integrações genéricas, enquanto o LlamaIndex se posiciona de forma mais forte especificamente em recuperação, indexação e processamento de documentos.
Importa notar que número de estrelas no GitHub mede interesse e visibilidade, não necessariamente uso em produção, downloads reais ou qualidade de resultados. Na prática, a escolha entre os dois costuma depender menos de popularidade e mais da forma como queres estruturar a aplicação.
| Critério | LlamaIndex | LangChain |
|---|---|---|
| Estrelas no GitHub (out. 2026) | ~52,5 mil | ~110 mil |
| Ponto forte declarado | Indexação, recuperação e processamento de documentos | Orquestração genérica de agentes e integrações |
| Curva de aprendizagem para RAG simples | Mais direta (poucas linhas para um índice funcional) | Mais abstrações para o mesmo resultado |
| Produto gerido comercial | LlamaCloud | LangSmith / LangGraph Platform |
| Licenciamento | Open source (MIT) | Open source (MIT) |
| Melhor cenário de uso | Apps centradas em pesquisa sobre documentos próprios | Fluxos de agentes complexos com múltiplas ferramentas |
Se o teu objetivo principal é construir rapidamente um sistema de perguntas e respostas sobre documentos (manuais, contratos, bases de conhecimento), o LlamaIndex tende a exigir menos código para chegar a um resultado funcional. Se precisas de orquestrar fluxos de agentes mais complexos, com múltiplas ferramentas externas e lógica condicional extensa, o LangChain (ou o seu complemento LangGraph) oferece mais peças já construídas para esse cenário. Nada impede, aliás, de usar os dois em conjunto: muitas equipas usam o LlamaIndex apenas para a camada de indexação e recuperação, e o LangChain para orquestrar o resto do agente.
Para equipas pequenas que estão a decidir por onde começar, um critério prático costuma funcionar melhor do que comparar números de estrelas no GitHub: experimenta construir o mesmo protótipo simples, como o deste tutorial, nos dois frameworks, e avalia qual código é mais fácil de ler e de manter seis meses depois, quando já ninguém se lembra em detalhe de como a aplicação foi escrita. Como ambos os projetos são open source e licenciados sob MIT, migrar mais tarde de um para o outro, ou usar ambos lado a lado, não implica qualquer restrição legal adicional. Também vale a pena olhar para alternativas mais focadas em pipelines de dados, como o Haystack, ou para construir RAG diretamente sobre a API da OpenAI sem qualquer framework intermédio, antes de decidires qual abordagem se adequa melhor ao teu projeto.
Segurança e privacidade dos dados num pipeline RAG
Um sistema RAG, por definição, coloca o conteúdo integral dos teus documentos internos ao alcance de um motor de consulta. Isto traz vantagens evidentes de produtividade, mas também levanta questões de segurança que vale a pena resolver antes de qualquer utilizador real tocar na aplicação.
O primeiro ponto de atenção é o controlo de acesso ao nível do documento. O VectorStoreIndex básico, tal como usado neste tutorial, não sabe nada sobre permissões: se um documento confidencial for indexado, qualquer pergunta que toque nesse tema pode trazer esse conteúdo para a resposta, independentemente de quem está a perguntar. Em aplicações multiutilizador, isto obriga a implementar filtragem por metadados (por exemplo, marcar cada nó com o departamento ou nível de acesso a que pertence) e a aplicar esse filtro no momento da consulta, não apenas na interface.
O segundo ponto é a superfície de ataque criada pela própria técnica de RAG: se um atacante conseguir injetar texto malicioso num documento que mais tarde é indexado (um PDF carregado por um utilizador externo, por exemplo), esse texto passa a fazer parte do contexto que é enviado ao modelo em consultas futuras. Este padrão, conhecido como injeção de prompt indireta, é hoje uma das categorias de ataque mais discutidas em aplicações baseadas em LLMs com acesso a dados externos. A mitigação mais eficaz continua a ser tratar qualquer conteúdo recuperado do índice como dados não fiáveis, nunca como instruções do sistema, e validar o que entra na pasta de documentos antes de ser indexado.
Por fim, lembra-te de que cada chamada ao modelo de embeddings e ao modelo de linguagem, quando usas um fornecedor externo como a OpenAI, envia o texto do documento (ou, pelo menos, o fragmento relevante) para fora da tua rede. Revê sempre a política de retenção de dados do fornecedor escolhido antes de indexares documentos com informação pessoal identificável, e considera a alternativa local com Ollama, descrita no passo 9, quando a sensibilidade dos dados justificar esse compromisso adicional de desempenho.
Armadilhas comuns ao construir RAG com LlamaIndex
Antes de avançares para produção, vale a pena conhecer os erros mais frequentes que programadores cometem ao construir a primeira aplicação RAG:
- Ignorar o custo de reindexação: recriar o índice do zero a cada execução gasta créditos de API de embeddings sem necessidade. Usa sempre a persistência em disco (passo 10) ou uma base de dados vetorial dedicada (passo 11) depois da fase inicial de testes.
- Usar o chunk_size por omissão sem testar alternativas: o valor padrão raramente é o ideal para o teu tipo de documento. Contratos jurídicos, código-fonte e manuais técnicos beneficiam de tamanhos de fragmento muito diferentes.
- Misturar documentos de domínios distintos no mesmo índice: juntar manuais de produto com atas de reuniões internas, por exemplo, tende a baixar a precisão da recuperação porque fragmentos irrelevantes competem pelo mesmo espaço no contexto.
- Esquecer de limitar o número de resultados recuperados: sem ajustar o parâmetro de número de nós a devolver, o motor de consulta pode enviar demasiado texto ao modelo, aumentando custo e latência sem melhorar a resposta.
- Não validar a qualidade dos ficheiros de origem: PDFs digitalizados por OCR de má qualidade ou ficheiros com formatação quebrada geram embeddings de baixa qualidade, mesmo que o código esteja perfeito.
- Expor a chave de API no código-fonte ou em repositórios públicos: como referido no passo 3, este continua a ser um dos erros mais caros e mais fáceis de evitar em todo o ecossistema de IA.
Troubleshooting: erros comuns e soluções
A tabela seguinte reúne os problemas mais frequentes relatados por quem está a começar com o LlamaIndex, e a forma mais direta de os resolver:
| Erro ou sintoma | Causa provável | Solução |
|---|---|---|
| ImportError ao importar um submódulo (ex: llms.ollama) | Pacote de integração específico não instalado | Instala o pacote individual, ex: pip install llama-index-llms-ollama |
| AuthenticationError da OpenAI | Variável OPENAI_API_KEY não definida ou chave inválida | Confirma que o ficheiro .env existe e que chamaste load_dotenv() antes de qualquer chamada ao modelo |
| Respostas genéricas que ignoram os documentos | Índice vazio ou pasta de dados incorreta no SimpleDirectoryReader | Confirma o caminho da pasta e imprime len(documentos) para validar a leitura |
| Erro de limite de tokens excedido | chunk_size demasiado grande ou demasiados nós devolvidos pela consulta | Reduz o chunk_size ou limita o parâmetro similarity_top_k no motor de consulta |
| Ligação lenta ou timeout com o Ollama | Modelo local ainda a carregar ou request_timeout demasiado curto | Aumenta o request_timeout e confirma com “ollama list” que o modelo já foi descarregado |
| Índice perdido depois de reiniciar o script | Ausência de persist() ou de uma base de dados vetorial | Adiciona storage_context.persist() ou liga o índice ao Chroma, conforme os passos 10 e 11 |
| Resultados inconsistentes entre execuções | Modelo de embeddings trocado a meio do projeto sem reindexar | Reindexa sempre do zero depois de mudar o modelo de embeddings; embeddings de modelos diferentes não são comparáveis entre si |
| Consumo elevado de memória com muitos documentos | Todos os documentos carregados em memória de uma só vez antes da indexação | Processa os documentos em lotes menores ou usa uma base de dados vetorial externa em vez de manter tudo em memória |
| ModuleNotFoundError para chromadb | Dependência da base de dados vetorial não instalada | Executa pip install chromadb llama-index-vector-stores-chroma |
Dicas avançadas para produção e o projeto completo
Dicas avançadas
Depois de teres a aplicação básica a funcionar, estas práticas ajudam a torná-la mais robusta antes de a colocar à frente de utilizadores reais:
- Define
similarity_top_kexplicitamente no motor de consulta (por exemplo,indice.as_query_engine(similarity_top_k=3)) em vez de depender do valor por omissão, para controlares diretamente quantos fragmentos entram no prompt final. Um valor demasiado baixo faz o modelo perder contexto importante; um valor demasiado alto encarece cada pergunta e pode confundir a resposta com informação irrelevante. - Regista cada pergunta e resposta num ficheiro de log próprio durante a fase de testes. Rever manualmente 50 a 100 interações reais revela padrões de falha que nenhum benchmark genérico apanha, como perguntas formuladas de forma ambígua ou documentos com informação contraditória entre versões.
- Usa um modelo de embeddings mais barato ou local (via HuggingFace) para a fase de indexação, e reserva o modelo mais caro apenas para a geração da resposta final, já que a indexação costuma ser o passo com maior volume de chamadas, sobretudo quando reindexas frequentemente documentos que mudam todos os dias.
- Se trabalhas com documentos muito longos, considera combinar um node parser hierárquico com um sumário automático por secção, em vez de depender só de um chunking uniforme de tamanho fixo. Isto ajuda especialmente com contratos, manuais técnicos extensos ou relatórios com várias dezenas de páginas.
- Em produção, separa sempre o processo de indexação (que corre periodicamente, em lote) do processo de consulta (que corre a cada pedido do utilizador). Misturar os dois no mesmo serviço torna a aplicação lenta a responder sempre que chegam novos documentos, e pode mesmo bloquear pedidos de utilizadores enquanto uma reindexação pesada está a decorrer.
- Define um limite de tempo e um mecanismo de repetição (retry) nas chamadas ao modelo de linguagem e ao modelo de embeddings. APIs externas falham ocasionalmente por motivos de rede ou de limite de pedidos, e uma aplicação em produção não se deve bloquear por completo por causa de uma falha pontual e temporária.
- Considera cache de respostas para perguntas frequentes e repetidas. Se vários utilizadores fazem perguntas semelhantes sobre o mesmo manual, guardar a resposta já gerada evita chamadas redundantes ao modelo de linguagem e reduz custos sem sacrificar a qualidade percebida pelo utilizador final.
O projeto completo: código final do agente RAG
Junta todos os passos anteriores num único script funcional, que carrega documentos, cria (ou reutiliza) um índice persistente no Chroma e expõe um motor de chat com memória, pronto a adaptar a qualquer caso de uso:
import os
import chromadb
from dotenv import load_dotenv
from llama_index.core import (
SimpleDirectoryReader,
VectorStoreIndex,
StorageContext,
Settings,
)
from llama_index.core.node_parser import SentenceSplitter
from llama_index.vector_stores.chroma import ChromaVectorStore
load_dotenv()
Settings.node_parser = SentenceSplitter(chunk_size=512, chunk_overlap=50)
cliente_chroma = chromadb.PersistentClient(path="./chroma_db")
colecao = cliente_chroma.get_or_create_collection("documentos_rag")
vector_store = ChromaVectorStore(chroma_collection=colecao)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
if colecao.count() == 0:
documentos = SimpleDirectoryReader("dados").load_data()
indice = VectorStoreIndex.from_documents(
documentos, storage_context=storage_context
)
print(f"Índice criado com {len(documentos)} documentos.")
else:
indice = VectorStoreIndex.from_vector_store(vector_store)
print("Índice existente carregado do Chroma.")
motor_chat = indice.as_chat_engine(
chat_mode="context", similarity_top_k=3
)
print("Agente RAG pronto. Escreve 'sair' para terminar.")
while True:
pergunta = input("\nTu: ")
if pergunta.strip().lower() == "sair":
break
resposta = motor_chat.chat(pergunta)
print(f"Agente: {resposta}")
Este script já resolve a armadilha mais comum (reindexar sempre do zero): na primeira execução cria o índice e guarda-o no Chroma; nas execuções seguintes, deteta que a coleção já tem dados e reutiliza-os diretamente. Para passares este protótipo para uma API web, basta embrulhar a lógica do motor de chat numa rota FastAPI ou Flask, mantendo o índice carregado em memória entre pedidos em vez de o recriares a cada chamada.
Perguntas Frequentes
O LlamaIndex é gratuito?
Sim, a biblioteca Python é open source e gratuita. Os custos que vais ter vêm das chamadas às APIs de modelos de linguagem e de embeddings que escolheres usar (OpenAI, Anthropic, etc.), ou zero se optares por modelos locais via Ollama. Existe também o LlamaCloud, um produto comercial gerido, separado da biblioteca open source.
Preciso de uma GPU para usar o LlamaIndex?
Não, se usares modelos de linguagem e de embeddings através de uma API externa como a OpenAI. Só precisas de hardware com GPU se quiseres correr os modelos localmente através do Ollama ou de bibliotecas de inferência local, para obteres velocidades de resposta aceitáveis.
Qual é a diferença entre o motor de consulta e o motor de chat?
O motor de consulta (as_query_engine()) trata cada pergunta de forma isolada, sem memória de perguntas anteriores. O motor de chat (as_chat_engine()) mantém o histórico da conversa, permitindo perguntas de seguimento que dependem do contexto de mensagens anteriores.
Posso usar o LlamaIndex com o Claude da Anthropic em vez da OpenAI?
Sim. O LlamaIndex suporta múltiplos fornecedores de modelos de linguagem através de pacotes de integração próprios; basta instalar o conector correspondente e definir esse modelo em Settings.llm, em vez do conector da OpenAI usado nos exemplos deste tutorial.
Quantos documentos consigo indexar antes de precisar de uma base de dados vetorial dedicada?
Não há um número fixo oficial, mas a persistência simples em disco (passo 10) funciona bem para protótipos e volumes pequenos de teste. Assim que o projeto envolve atualizações frequentes, múltiplos utilizadores em simultâneo ou milhares de documentos, uma base de dados vetorial como o Chroma, Pinecone, Qdrant ou Weaviate torna a aplicação mais fiável e mais rápida a escalar.
O LlamaIndex substitui o fine-tuning de modelos?
Não necessariamente. Como explicou Jerry Liu na entrevista já citada, o RAG é uma forma de dar contexto ao prompt, não um substituto universal para outras técnicas de adaptação como o fine-tuning. Em muitos casos práticos, o RAG resolve a necessidade de forma mais rápida e barata do que treinar um modelo novo, mas há cenários onde as duas técnicas se complementam.
O que faço se o motor de chat começar a responder com informação desatualizada?
Confirma se o índice foi reconstruído depois da última alteração aos documentos de origem. Se usas persistência em disco ou uma base de dados vetorial, uma atualização aos ficheiros na pasta “dados” não é refletida automaticamente; é preciso correr novamente a indexação sobre os documentos atualizados.
Vale a pena usar o LlamaIndex em 2026, com tantos outros frameworks disponíveis?
Sim, principalmente se o teu caso de uso principal é pesquisa e recuperação sobre documentos próprios. Mesmo com o LangChain a liderar em estrelas no GitHub, o LlamaIndex continua a ser referido pela AWS e por outras guias de arquitetura como uma opção sólida especificamente para RAG, graças ao número reduzido de linhas de código necessárias para obter um primeiro resultado funcional.
Que tipos de aplicação é que normalmente se constroem com o LlamaIndex?
Os casos de uso mais comuns incluem assistentes de suporte ao cliente que respondem com base em manuais e políticas internas, ferramentas de pesquisa sobre documentação técnica de produto, assistentes jurídicos que ajudam a localizar cláusulas específicas em contratos extensos, e chatbots internos de recursos humanos que respondem a perguntas sobre regulamentos da empresa sem expor um humano a perguntas repetitivas. Em todos estes casos, o padrão é o mesmo: existe um volume considerável de texto já escrito, e a tarefa é tornar esse texto consultável em linguagem natural.
