implantação 100% local rodando em Linux Ubuntu 24.04, persistente, com GPU, Agent (ReAct) e RAG. Ideal para laboratório, PoC e estudo de MLOps/Engenharia de Prompt.
- Visão Geral
- Arquitetura
- Requisitos
- 1) Infraestrutura & Setup (DevOps)
- 2) Projeto Python (Engineering & Agents)
- 3) Agente ReAct com Busca no Google
- 4) RAG Local com ChromaDB
- 5) Docker Compose (opcional)
- 6) Troubleshooting (Boss Fights)
- 7) Segurança & Boas Práticas
- 8) Cheatsheet
- Licença
Este guia documenta a configuração do LLM open-source Mistral 7B rodando 100% local via Ollama dentro de Docker, acelerado por GPU NVIDIA GTX 1060 (6GB). A pilha inclui:
- Ollama para servir o modelo (com quantização que cabe em 6 GB VRAM);
- Agent (ReAct) para usar Google Search como Tool e contornar knowledge cutoff;
- RAG local com ChromaDB + Sentence-Transformers para buscar conhecimento nos seus PDFs/textos.
- Implementação do LLM com a interface gráfica Open-WebUI para que fique com uma aparência semelhante aos famosos chats de genIA que conhecemos.
- Processador: Ryzen 5 1600 6/12
- Memória: 16GB memória ram DDR4 2666mhz XPG
- GPU: GTX 1060 6GB Gitabyte G1 Gaming
- PSU: Fonte 600w
+------------------+
+------------------------------------> | Open-WebUI |
| +------------------+
| ^
| |
| |
| +-------------------+ +------------------+ +--------------------------+
| | Cliente (CLI/py) | <-----> | Ollama (API) | <------> | GPU NVIDIA (GTX 1060) |
| +-------------------+ +------------------+ +--------------------------+
| | ^
| v |
| +-------------------+ |
+-------| Agent (ReAct) | ----(Google)------+ +-----------------------+
| + RAG (Chroma) | -----------------------| Base de Conhecimento |
+-------------------+ | (PDFs / .txt / etc) |
+-----------------------+
- Linux com Docker Engine ativo;
- Driver NVIDIA + NVIDIA Container Toolkit instalados;
- GPU: GTX 1060 6GB VRAM (funciona com quantização
q4_xdo Mistral); - Acesso à internet apenas para baixar imagens/modelos e, se desejar, usar a Tool de busca;
- Python 3.10+ (sugerido).
Dica: teste a GPU com
nvidia-smie o suporte no Docker comdocker run --rm --gpus all nvidia/cuda:12.2.0-base nvidia-smi.
Pré-requisitos: NVIDIA Driver + Container Toolkit e Docker OK.
Permissão e Limpeza do Ollama nativo (evitar conflito):
# Adicionar o usuário ao grupo docker (requer logout/login)
sudo usermod -aG docker $USER
# Parar serviços em conflito
sudo systemctl stop ollama || true
docker stop ollama || true
docker rm ollama || true
# Limpeza de cache local do ollama (nativo)
rm -rf ~/.ollamaSubir o servidor Ollama com GPU (persistente):
docker run -d --restart always --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamaObservação: O contêiner baixa os modelos sob demanda. Você pode executar
docker exec -it ollama ollama pull mistralpara antecipar o download. Em placas com 6GB, priorize quantizações comomistral:instruct-q4_K_Mpara estabilidade.
docker ps
# Deve mostrar o contêiner 'ollama' com STATUS: Up X seconds/minutes
docker exec -it ollama ollama run mistral:7b
# Iniciar o Docker com o mistral:7b
watch -n 1 nvidia-smi
# Para monitorar em tempo real o uso da GPU NvidiaTeste rápido via CLI (baixa o modelo se necessário):
docker exec -it ollama ollama run mistral "Escreva um haicai sobre DevOps."No comando abaixo irei colocar o conteiner docker com o Open-WebUI na porta 3000 e abrir o link http://localhost:3000/
docker run -d \
-p 3000:8080 \
--add-host=host.docker.internal:host-gateway \
-v open-webui:/app/backend/data \
--name open-webui \
--restart always \
ghcr.io/open-webui/open-webui:main# Criar e Ativar Ambiente Virtual
python3 -m venv .venv
source .venv/bin/activate
# Bibliotecas essenciais (Agents + RAG)
pip install --upgrade pip
pip install langchain-community google-search-results
pip install chromadb sentence-transformers pypdfModelos de embedding: por padrão, usaremos
sentence-transformers/all-MiniLM-L6-v2(leve e eficiente).
Métrica: Throughput (Tokens/s) e Latência. O exemplo abaixo estima T/s por contagem de “palavras” de saída (aproximação simples).
import time
from langchain_community.llms import Ollama
MODELO = "mistral" # ou "mistral:instruct-q4_K_M" se preferir instruções/quantização
llm = Ollama(model=MODELO, temperature=0.3)
def executa_e_mede(prompt: str):
start_time = time.time()
response = llm.invoke(prompt)
elapsed = time.time() - start_time
tokens_aprox = len(response.split()) # aproximação simples
print(f"Latência Total: {elapsed:.2f} s")
print(f"Throughput (T/s) ~ {tokens_aprox / elapsed:.2f}")
print("Resposta:
", response[:500], "...")
executa_e_mede("Explique o que é DevOps em 3 parágrafos.")
# Em testes reais com GTX 1060 6GB, ~9–10 T/s é um valor típico com quantização adequada.Para medições mais precisas, considere streaming e contagem de tokens no servidor, ou comparar tempos em prompts/repostas fixas.
Objetivo: contornar knowledge cutoff usando uma Tool de busca. O Agent decide quando consultar a internet.
export GOOGLE_API_KEY="SUA_CHAVE_AQUI"
export GOOGLE_CSE_ID="SEU_CX_ID_AQUI"import os
from langchain_community.llms import Ollama
from langchain_community.utilities import GoogleSearchAPIWrapper
from langchain_community.tools import GoogleSearchRun
from langchain.agents import AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
# LLM (Ollama)
llm = Ollama(model="mistral", temperature=0.3)
# Tools: Google Search
search = GoogleSearchAPIWrapper()
google_tool = GoogleSearchRun(api_wrapper=search, name="GoogleSearch")
tools = [google_tool]
# Prompt ReAct: formato rígido para reduzir parsing errors
prompt_template = PromptTemplate.from_template(
"""
Você é um assistente de IA inteligente. Use as ferramentas fornecidas quando necessário.
Ferramentas disponíveis: {tools}
Siga rigorosamente o formato abaixo (português):
Question: a pergunta do usuário
Thought: seu raciocínio breve sobre o próximo passo
Action: a ação a executar, escolha UMA dentro de [{tool_names}]
Action Input: o input para a ação (texto)
Observation: o resultado da ação
... (este ciclo Thought/Action/Action Input/Observation pode repetir N vezes) ...
Thought: concluiu? Se sim, responda.
Final Answer: sua resposta final e objetiva ao usuário
Comece!
Question: {input}
{agent_scratchpad}
"""
)
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt_template)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True # autocorreção de formatação
)
pergunta = "Qual é o próximo jogo do São Paulo Futebol Clube e quando será?"
resultado = agent_executor.invoke({"input": pergunta})
print(resultado["output"])Nota: O Agent pode fazer chamadas externas. Se desejar somente local, remova a Tool e use RAG (seção abaixo).
Exemplo mínimo para perguntar sobre seus PDFs localmente (sem internet):
from langchain_community.llms import Ollama
from langchain_community.document_loaders import PyPDFLoader
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import SentenceTransformerEmbeddings
from langchain.chains import RetrievalQA
# 1) Carregar documentos
loader = PyPDFLoader("meu_arquivo.pdf")
docs = loader.load()
# 2) Embeddings + VectorStore
emb = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
vectordb = Chroma.from_documents(docs, embedding=emb, persist_directory=".ragdb")
retriever = vectordb.as_retriever(search_kwargs={"k": 4})
# 3) LLM + Cadeia de QA
llm = Ollama(model="mistral:instruct-q4_K_M", temperature=0.2)
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever)
# 4) Perguntar
resposta = qa.invoke({"query": "Resuma os pontos principais do documento."})
print(resposta["result"])Persistência: o Chroma em
persist_directoryguarda o índice entre execuções.
Se preferir compor serviços (ex.: Ollama + sua API/Frontend), um exemplo simples:
# docker-compose.yml
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
ports:
- "11434:11434"
volumes:
- ollama:/root/.ollama
deploy:
resources:
reservations:
devices:
- capabilities: ["gpu"] # requer docker compose plugin com suporte a GPU
volumes:
ollama:Subir:
docker compose up -d
-
permission deniedao usar Docker
Adicione o usuário ao grupodockere faça logout/login:sudo usermod -aG docker $USER -
GPU não detectada (
no CUDA-capable device)
Verifiquenvidia-smino host e suporte no container (nvidia-container-toolkit). -
Porta 11434 em uso
Ajuste-p 11434:11434para outra porta livre (ex.:-p 11435:11434). -
VRAM insuficiente / OOM
Use quantizações q4_K_M ou similares:mistral:instruct-q4_K_M.
Evite prompts/respostas gigantes; reduzatemperature/comprimento. -
Modelos sumindo após reboot
Garanta--restart alwayse volume nomeado-v ollama:/root/.ollama. -
Agent quebrando com parsing
Mantenha o prompt ReAct rígido ehandle_parsing_errors=True.
- API Keys em variáveis de ambiente ou
.env(não commitar); - Rede: exponha a API do Ollama apenas na LAN/localhost quando possível;
- Controle de versão: versionar somente código, não índices (
.ragdb) nem caches; - Observabilidade: logar tempos/respostas para avaliar latência e T/s ao longo do tempo.
# Parar/remover serviço antigo
sudo systemctl stop ollama || true
docker stop ollama || true && docker rm ollama || true
# Subir Ollama com GPU
docker run -d --restart always --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
# Baixar modelo (quantizado) e testar
docker exec -it ollama ollama pull mistral:instruct-q4_K_M
docker exec -it ollama ollama run mistral:instruct-q4_K_M "Diga 'GG DevOps!'"Uso educacional/laboratorial. Verifique licenças dos modelos e bibliotecas antes de uso comercial.