RAG com Qdrant e Ollama: LLM Local com Embeddings

10 min de leitura Inteligência Artificial
RAG com Qdrant e Ollama: LLM Local com Embeddings

A era da Inteligência Artificial Generativa está se deslocando rapidamente do modelo "tudo na nuvem" para arquiteturas locais e privadas. Para empresas e desenvolvedores que priorizam a soberania dos dados, a latência reduzida e o controle total sobre o ciclo de vida dos modelos, rodar LLMs (Large Language Models) localmente em uma VPS ou servidor dedicado tornou-se uma realidade acessível. No entanto, treinar um modelo do zero ou fazer fine-tuning complexo para cada domínio específico é custoso e demorado.

A solução elegante que uniu a comunidade de IA open-source é o padrão RAG (Retrieval-Augmented Generation). Neste tutorial, vamos explorar como implementar um sistema robusto de RAG utilizando Ollama para gerenciar os modelos e Qdrant como seu vetor store. Esta combinação permite que sua LLM local — seja ela Qwen, Llama ou Mistral — responda com base em documentos atualizados, sem necessidade de retreinamento constante.

O que é RAG e por que usar Qdrant?

O RAG funciona como um sistema de memória externa para sua LLM. Em vez de confiar apenas no treinamento prévio do modelo (que pode estar desatualizado ou ser genérico), o RAG busca informações relevantes em uma base de dados vetorial antes de gerar uma resposta. O processo divide-se em três etapas: ingestão, recuperação e geração.

O Qdrant surge como a escolha ideal para este pipeline. Diferente de bancos de dados relacionais tradicionais, o Qdrant é um banco de dados vetorial escrito em Rust, projetado para alta performance e escalabilidade. Ele armazena embeddings (representações numéricas do significado semântico dos textos) e permite buscas por similaridade extremamente rápidas. Ao integrar o Qdrant com o Ollama, criamos uma infraestrutura que pode ser exposta via API REST, facilitando a integração com interfaces como AnythingLLM ou aplicações customizadas em Python.

Pré-requisitos e Infraestrutura

Para seguir este guia, você precisará de um ambiente Linux (Ubuntu/Debian recomendado) rodando em uma VPS. Certifique-se de ter acesso SSH com privilégios de root ou sudo. Para a execução eficiente dos modelos de linguagem e cálculos vetoriais, recomenda-se pelo menos 8GB de RAM e, idealmente, uma GPU dedicada (NVIDIA) ou um CPU forte com suporte a AVX2 para inferência via CPU.

Vamos instalar dois componentes principais: o Qdrant Server e o Ollama. Utilizaremos contêineres Docker para garantir isolamento e facilidade de manutenção.

Etapa 1: Instalando e Configurando o Qdrant

O primeiro passo é provisionar o banco de dados vetorial. O Qdrant oferece uma imagem oficial no Docker Hub que já vem pré-configurada com a API REST necessária para ingestão e consulta.

  1. Crie um diretório para persistir os dados do Qdrant. Isso garante que seus embeddings não sejam perdidos ao reiniciar o contêiner.
mkdir -p ~/qdrant/storage

Olha só, manter a persistência é crucial para sistemas de produção. Sem isso, cada reinicialização apagaria seu conhecimento vetorial.

  1. Inicie o contêiner do Qdrant mapeando a porta padrão 6333 e montando o volume de dados:
docker run -d \
  --name qdrant \
  -p 6333:6333 \
  -v ~/qdrant/storage:/qdrant/storage \
  qdrant/qdrant

Após a execução, verifique se o serviço está respondendo. Você pode acessar http://seu-ip:6333/dashboard ou verificar via terminal:

curl http://localhost:6333/healthcheck

Se retornar um JSON com status "ok", seu vetor store está pronto. Agora, vamos criar uma coleção específica para armazenar os embeddings relacionados ao seu domínio.

Etapa 2: Configurando o Ollama e Baixando Modelos

O Ollama simplifica drasticamente a gestão de LLMs locais. Ele lida com o download, versionamento e execução dos modelos em CUDA (GPU) ou CPU.

  1. Instale o Ollama seguindo a documentação oficial para Linux:
curl -fsSL https://ollama.com/install.sh | sh

Depois da instalação, precisamos de dois modelos distintos para nossa arquitetura RAG:

  • Um modelo de Embedding: Responsável por converter texto em vetores. O nomic-embed-text é leve e performático.
  • Um modelo LLM (Geração): Pode ser o Llama 3, Qwen 2.5 ou Mistral, dependendo da complexidade das perguntas que você espera processar.
  1. Baixe o modelo de embedding:
ollama pull nomic-embed-text
  1. Baixe o modelo LLM principal. Vamos usar o Qwen como exemplo, pois tem excelente suporte a português e raciocínio lógico:
ollama pull qwen2.5:7b

O Ollama expõe uma API local na porta 11434. Teste se o modelo está respondendo corretamente enviando um prompt simples:

curl http://localhost:11434/api/generate -d '{
  "model": "qwen2.5:7b",
  "prompt": "Qual a capital da França?",
  "stream": false
}'

Etapa 3: Ingestão de Dados e Criação de Embeddings

Agora que a infraestrutura está pronta, precisamos popular o Qdrant com dados. Vamos pegar um arquivo de texto simples (por exemplo, um manual técnico ou documentação da sua empresa) e transformá-lo em vetores.

Crie um arquivo chamado documentos.txt e adicione algum conteúdo de teste:

Sou um assistente virtual especializado em suporte técnico.
Posso ajudar com configuração de servidores, Docker e Linux.

Para processar isso, precisamos de um script Python que use a biblioteca qdrant-client e chame o Ollama para gerar os embeddings. Instale as dependências:

pip install qdrant-client ollama

Crie um script chamado ingest.py:

import uuid
import qdrant_client
import ollama
import math

# Configuração dos clientes
qdrant = qdrant_client.QdrantClient(host="localhost", port=6333)
ollama_client = ollama.Client(host="localhost", port=11434)

COLLECTION_NAME = "meus_dados"
EMBEDDING_MODEL = "nomic-embed-text"

# 1. Criar a coleção se não existir
if not qdrant.collection_exists(COLLECTION_NAME):
    qdrant.create_collection(
        collection_name=COLLECTION_NAME,
        vectors_config=qdrant_client.models.VectorParams(
            size=768, # Tamanho do embedding do nomic-embed-text
            distance=qdrant_client.models.Distance.COSINE
        )
    )

# 2. Ler e chunkear o texto (dividir em partes menores)
with open("documentos.txt", "r") as f:
    content = f.read()
    
# Chunking simples por linhas para demonstração
chunks = [line.strip() for line in content.split('\n') if line.strip()]

print(f"Processando {len(chunks)} chunks...")

# 3. Gerar embeddings e upsert no Qdrant
for i, chunk in enumerate(chunks):
    # Chama o Ollama para gerar o embedding
    response = ollama_client.embeddings(model=EMBEDDING_MODEL, input=chunk)
    embedding = response["embedding"]
    
    # Cria o ponto de dados no Qdrant
    qdrant.upsert(
        collection_name=COLLECTION_NAME,
        points=[
            qdrant_client.models.PointStruct(
                id=str(uuid.uuid4()),
                vector=embedding,
                payload={"text": chunk} # Payload para recuperar o texto original depois
            )
        ]
    )
    print(f"Chunk {i+1}/{len(chunks)} inserido.")

print("Ingestão concluída com sucesso!")

Rode o script:

python ingest.py

Se tudo correr bem, seu Qdrant agora contém vetores representando semanticamente o texto do seu arquivo. Note que usamos Distance.COSINE, que é padrão para a maioria dos modelos de embedding modernos.

Etapa 4: Consultando e Gerando Respostas (RAG Loop)

A magia do RAG acontece aqui. Precisamos recuperar o trecho mais relevante ao prompt do usuário e injetar esse contexto no prompt da LLM.

Crie o arquivo rag_query.py:

import qdrant_client
import ollama

COLLECTION_NAME = "meus_dados"
EMBEDDING_MODEL = "nomic-embed-text"
LLM_MODEL = "qwen2.5:7b"

qdrant = qdrant_client.QdrantClient(host="localhost", port=6333)
ollama_client = ollama.Client(host="localhost", port=11434)

user_question = "O que eu posso fazer com este assistente?"

# 1. Gerar embedding da pergunta do usuário
print("Gerando embedding da consulta...")
query_embedding = ollama_client.embeddings(model=EMBEDDING_MODEL, input=user_question)["embedding"]

# 2. Buscar os k pontos mais similares no Qdrant
k = 1 # Retornar apenas o top 1 resultado para este exemplo
results = qdrant.search(
    collection_name=COLLECTION_NAME,
    query_vector=query_embedding,
    limit=k
)

if not results:
    print("Nenhum dado encontrado.")
else:
    # Extrair o texto relevante
    context_text = results[0].payload['text']
    print(f"Dado recuperado: {context_text}")
    
    # 3. Construir o prompt com contexto (RAG)
    system_prompt = f"""Você é um assistente útil. Responda a pergunta do usuário baseada apenas no contexto abaixo. Se não souber a resposta, diga que não encontrou informações.

Contexto: {context_text}

Pergunta: {user_question}"""

    # 4. Gerar resposta com a LLM
    print("\nGerando resposta...")
    response = ollama_client.chat(
        model=LLM_MODEL,
        messages=[{'role': 'user', 'content': system_prompt}]
    )
    
    print(f"Resposta Final: {response['message']['content']}")

Execute a consulta:

python rag_query.py

Você verá que o sistema recuperou a linha específica do texto e pediu ao Qwen para formular uma resposta natural baseada nela. Isso é o RAG em ação: dados específicos + inteligência generalista.

Etapa 5: Integração com AnythingLLM (Opcional)

Se você não deseja escrever código Python para cada interação, pode integrar seu stack Ollama-Qdrant ao AnythingLLM, uma interface web poderosa que gerencia workspaces de RAG.

  1. Instale o AnythingLLM conforme a documentação do site oficial.
  2. No painel de configurações, selecione "Ollama" como provedor de LLM e insira http://localhost:11434.
  3. Para o Vector Store, escolha "Qdrant" e insira http://localhost:6333.
  4. Crie um novo Workspace, faça upload de seus PDFs ou TXTs e clique em "Build Workspace".

O AnythingLLM fará o chunking, embedding e armazenamento no Qdrant automaticamente, permitindo que você interaja via chat web sem escrever uma linha de código.

Considerações Finais sobre Escalabilidade e Fine-Tuning

Embora o RAG resolva 80% dos problemas de atualização de conhecimento, há cenários onde ele não basta. Se você precisa que a LLM adote um tom de voz específico ou siga regras de negócio complexas que não cabem em prompts, considere fazer fine-tuning. No entanto, o fine-tuning é caro e difícil de manter.

A tendência moderna é usar RAG para dados dinâmicos (documentos, manuais) e fine-tuning apenas para comportamentos estáticos. O stack Qdrant + Ollama oferece a flexibilidade perfeita: você pode adicionar novos documentos ao Qdrant em tempo real sem tocar no modelo base.

Para produção, lembre-se de:

  • Segurança: Coloque o Qdrant e o Ollama atrás de um Nginx ou Traefik com autenticação básica se expuser a porta 6333 ou 11433 à internet.
  • Chunking Inteligente: Para documentos longos, use bibliotecas como LangChain ou LlamaIndex para fazer chunking semântico (por parágrafos ou tópicos) em vez de apenas por linhas.
  • Hidração de Metadados: Armazene metadados (autor, data, tipo de documento) no payload do Qdrant para filtrar buscas antes mesmo de calcular a similaridade vetorial.

Com essa configuração, você tem um sistema de IA local, privado e altamente personalizado rodando em sua VPS. A combinação de RAG com Qdrant e modelos como Llama ou Qwen via Ollama é, hoje, o padrão ouro para implementações empresariais de IA generativa self-hosted.

Compartilhar: Link copiado!
Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000