IA Local com Docker + RTX 3070 Ti
Guia Completo: Ollama + Open WebUI
Stack recomendada para rodar modelos de linguagem localmente com GPU NVIDIA, interface de gerenciamento e suporte a Docker.
Índice
- Visão Geral da Stack
- Pré-requisitos
- Instalação do NVIDIA Container Toolkit
- Configuração do Docker Compose
- Subindo a Stack
- Gerenciando Modelos
- Catálogo de Modelos Recomendados
- Setup Completo Sugerido
- Usando o Open WebUI
- Busca na Web com SearXNG
- Benchmark Comparativo de Modelos
- Transcrição de Áudio com Whisper
- Alternativas à Stack Principal
- Solução de Problemas
- Referências
1. Visão Geral da Stack
A combinação Ollama + Open WebUI é a solução mais madura e recomendada pela comunidade para rodar LLMs localmente com suporte a GPU NVIDIA via Docker.
| Componente | Função |
|---|---|
| Ollama | Backend responsável por baixar, gerenciar e servir os modelos via API REST |
| Open WebUI | Interface web estilo ChatGPT para interagir com os modelos e gerenciar tudo |
Por que essa stack?
- Suporte nativo a NVIDIA CUDA — ideal para a RTX 3070 Ti (8 GB de VRAM)
- Catálogo enorme de modelos: Llama 3, Mistral, Gemma, Phi, DeepSeek, Qwen e muito mais
- Interface completa com histórico de conversas, gerenciamento de modelos, RAG, múltiplos usuários e suporte a plugins
- Docker Compose simples e bem documentado
- API compatível com OpenAI — funciona com ferramentas que usam o padrão OpenAI
Capacidade da RTX 3070 Ti
A RTX 3070 Ti possui 8 GB de VRAM, o que permite rodar modelos de até ~8B parâmetros com quantização Q4/Q5 confortavelmente. Modelos maiores (14B+) são possíveis com quantizações mais agressivas (Q2/Q3), mas com impacto na qualidade das respostas.
2. Pré-requisitos
Antes de começar, verifique se você tem o seguinte instalado:
- Sistema Operacional: Linux (recomendado Ubuntu 22.04+) ou Windows com WSL2
- Docker: versão 24.0 ou superior
- Docker Compose: versão 2.x (já incluído no Docker Desktop)
- Driver NVIDIA: versão 525 ou superior
- NVIDIA Container Toolkit: necessário para expor a GPU ao Docker (instalação na seção seguinte)
Verificando os pré-requisitos
# Verificar versão do Docker
docker --version
# Verificar versão do Docker Compose
docker compose version
# Verificar driver NVIDIA
nvidia-smi
# Verificar versão do driver (deve ser >= 525)
nvidia-smi --query-gpu=driver_version --format=csv,noheader
3. Instalação do NVIDIA Container Toolkit
O NVIDIA Container Toolkit é essencial para que os containers Docker possam acessar a GPU.
No Ubuntu/Debian
# 1. Adicionar o repositório NVIDIA
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 2. Instalar o toolkit
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# 3. Configurar o Docker para usar o runtime NVIDIA
sudo nvidia-ctk runtime configure --runtime=docker
# 4. Reiniciar o Docker
sudo systemctl restart docker
Verificando a instalação
# Deve exibir informações da sua GPU de dentro de um container
docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi
Se a saída exibir os dados da sua RTX 3070 Ti, a configuração está correta.
4. Configuração do Docker Compose
Crie um diretório para o projeto e o arquivo docker-compose.yml:
mkdir ~/ia-local && cd ~/ia-local
Crie o arquivo docker-compose.yml com o seguinte conteúdo:
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
- OLLAMA_KEEP_ALIVE=5m
volumes:
- ollama_data:/root/.ollama
ports:
- "11434:11434"
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
depends_on:
- ollama
environment:
- OLLAMA_BASE_URL=http://ollama:11434
volumes:
- open_webui_data:/app/backend/data
ports:
- "3000:8080"
restart: unless-stopped
searxng:
image: searxng/searxng:latest
container_name: searxng
environment:
- SEARXNG_BASE_URL=http://localhost:8889
volumes:
- ./searxng:/etc/searxng
ports:
- "8889:8080"
restart: unless-stopped
whisper:
image: onerahmet/openai-whisper-asr-webservice:latest
container_name: whisper
environment:
- ASR_MODEL=medium
- ASR_ENGINE=faster_whisper
- ASR_COMPUTE_TYPE=int8
volumes:
- ./whisper/uploads:/tmp/uploads
- ./whisper/cache:/root/.cache
ports:
- "9000:9000"
restart: unless-stopped
volumes:
ollama_data:
open_webui_data:
Nota sobre
OLLAMA_KEEP_ALIVE=5m: mantém o modelo carregado na VRAM por 5 minutos após a última resposta. Se uma nova mensagem for enviada antes do tempo expirar, o contador reinicia. Isso evita o tempo de recarregamento em conversas ativas. Use0se quiser liberar a VRAM imediatamente após cada resposta (útil quando outros serviços disputam memória).
Estrutura do projeto
~/ia-local/
├── docker-compose.yml
├── searxng/
│ └── settings.yml
├── whisper/
│ ├── cache/
│ └── uploads/
└── transcrever.sh
Os dados dos modelos e do WebUI serão armazenados em volumes Docker. O SearXNG usa um diretório local (./searxng) para facilitar a edição do arquivo de configuração.
5. Subindo a Stack
# Dentro do diretório ~/ia-local
docker compose up -d
Aguarde o download das imagens na primeira execução. Após isso:
| Serviço | URL |
|---|---|
| Open WebUI | http://localhost:3000 |
| Ollama API | http://localhost:11434 |
| SearXNG | http://localhost:8889 |
| Whisper API | http://localhost:9000 |
Verificando o status
# Ver status dos containers
docker compose ps
# Ver logs em tempo real
docker compose logs -f
# Ver logs de um serviço específico
docker compose logs -f ollama
docker compose logs -f open-webui
Parando a stack
# Parar sem remover os dados
docker compose stop
# Parar e remover os containers (dados preservados nos volumes)
docker compose down
# Parar, remover containers E volumes (APAGA TODOS OS MODELOS)
docker compose down -v
6. Gerenciando Modelos
Os modelos podem ser gerenciados tanto pela linha de comando quanto diretamente pela interface do Open WebUI.
Via linha de comando
# Baixar um modelo
docker exec -it ollama ollama pull <nome-do-modelo>
# Listar modelos instalados
docker exec -it ollama ollama list
# Remover um modelo
docker exec -it ollama ollama rm <nome-do-modelo>
# Ver informações detalhadas de um modelo
docker exec -it ollama ollama show <nome-do-modelo>
# Rodar um modelo interativamente no terminal
docker exec -it ollama ollama run <nome-do-modelo>
Via Open WebUI
- Acesse http://localhost:3000
- Vá em Configurações → Modelos
- Use o campo de busca para encontrar e baixar modelos diretamente pelo nome
- Gerencie modelos instalados (deletar, atualizar) pela mesma tela
Monitorando o uso da GPU durante inferência
# Monitorar uso da GPU em tempo real
watch -n 1 nvidia-smi
# Ou com mais detalhes
nvidia-smi dmon -s u
7. Catálogo de Modelos Recomendados
7.1 Modelos Gerais (indicados no setup básico)
| Modelo | Parâmetros | VRAM aprox. | Ideal para |
|---|---|---|---|
llama3.2:3b |
3B | ~2,5 GB | Respostas rápidas, uso leve |
mistral:7b |
7B | ~5 GB | Equilíbrio perfeito entre velocidade e qualidade |
llama3.1:8b |
8B | ~6 GB | Uso geral de alta qualidade |
deepseek-r1:8b |
8B | ~6 GB | Raciocínio e resolução de problemas |
phi4:14b (Q4) |
14B | ~8 GB | Máximo desempenho (no limite da VRAM) |
7.2 Raciocínio e Lógica
| Modelo | VRAM aprox. | Observação |
|---|---|---|
deepseek-r1:7b |
~5 GB | Raciocínio muito superior a modelos comuns do mesmo tamanho |
qwq:32b (Q4) |
~8 GB | Excelente em matemática e lógica; no limite da VRAM |
docker exec -it ollama ollama pull deepseek-r1:7b
docker exec -it ollama ollama pull qwq:32b
7.3 Código
| Modelo | VRAM aprox. | Observação |
|---|---|---|
qwen2.5-coder:7b |
~5 GB | Um dos melhores para código em 8 GB; supera o CodeLlama |
codellama:7b |
~5 GB | Clássico, ótimo para completions estilo Copilot |
starcoder2:7b |
~5 GB | Suporta mais de 600 linguagens |
docker exec -it ollama ollama pull qwen2.5-coder:7b
docker exec -it ollama ollama pull codellama:7b
docker exec -it ollama ollama pull starcoder2:7b
7.4 Multilíngue e Português
| Modelo | VRAM aprox. | Observação |
|---|---|---|
qwen2.5:7b |
~5 GB | Excelente suporte a português; melhor que Llama em tarefas multilíngue |
aya:8b |
~6 GB | Desenvolvido pela Cohere especificamente para multilíngue |
docker exec -it ollama ollama pull qwen2.5:7b
docker exec -it ollama ollama pull aya:8b
7.5 Contexto Longo (Documentos)
| Modelo | VRAM aprox. | Observação |
|---|---|---|
gemma2:9b (Q4) |
~7 GB | Do Google; janela de contexto grande, excelente em seguir instruções |
internlm2_5:7b |
~5 GB | Contexto de até 200k tokens; ideal para analisar documentos extensos |
docker exec -it ollama ollama pull gemma2:9b
docker exec -it ollama ollama pull internlm2_5:7b
7.6 Conversação Geral
| Modelo | VRAM aprox. | Observação |
|---|---|---|
neural-chat:7b |
~5 GB | Otimizado pela Intel para conversação natural |
command-r:35b (Q2/Q3) |
~8 GB | Excelente em RAG e conversação longa; versão muito comprimida |
docker exec -it ollama ollama pull neural-chat:7b
7.7 Embeddings (para RAG e busca semântica)
Modelos leves que rodam preferencialmente na CPU. Essenciais para usar o RAG do Open WebUI.
| Modelo | Observação |
|---|---|
nomic-embed-text |
Leve e eficiente; recomendado como padrão para RAG |
mxbai-embed-large |
Um dos melhores modelos de embedding open source disponíveis |
docker exec -it ollama ollama pull nomic-embed-text
docker exec -it ollama ollama pull mxbai-embed-large
7.8 Gemma 4 (Google DeepMind) — Multimodal com Raciocínio
O Gemma 4 é a geração mais recente do Google DeepMind, com suporte a texto e imagem, raciocínio configurável (thinking mode) e variantes MoE (Mixture of Experts) que ativam apenas uma fração dos parâmetros por token — tornando modelos maiores viáveis em hardware limitado.
Requer Ollama atualizado. Se o pull retornar
requires a newer version of Ollama, atualize primeiro (ver seção 14).
| Tag | Tamanho | VRAM | Parâmetros ativos | Ideal para |
|---|---|---|---|---|
gemma4:e2b |
~7,2 GB | ✅ Cabe com folga | ~2B | Uso rápido e leve |
gemma4:e4b |
~9,6 GB | ⚠️ Offload parcial | ~4B | Equilíbrio qualidade/velocidade |
gemma4:26b |
~18 GB | ⚠️ Offload VRAM→RAM | ~4B ativos | Máxima qualidade viável |
gemma4:31b |
~20 GB | ❌ Inviável com 8 GB | — | Requer hardware maior |
Recomendação para o setup com RTX 3070 Ti (8 GB VRAM) + 48 GB RAM: use
gemma4:26b. Apesar de pesar 18 GB, o Ollama distribui automaticamente as camadas entre VRAM e RAM. A geração é mais lenta do que oe4b, mas a qualidade de raciocínio científico, código e análise de dados é significativamente superior. Ideal para tarefas como doutorado, vibe coding e análise de dados geoespaciais.
# Variante leve (cabe totalmente na VRAM)
docker exec -it ollama ollama pull gemma4:e2b
# Variante intermediária (melhor custo-benefício)
docker exec -it ollama ollama pull gemma4:e4b
# Variante completa (máxima qualidade — recomendada com 48 GB RAM)
docker exec -it ollama ollama pull gemma4:26b
Sobre o tempo de carregamento
O primeiro token de cada conversa demora alguns segundos enquanto o modelo é carregado na VRAM. Com OLLAMA_KEEP_ALIVE=5m, o modelo permanece carregado por 5 minutos de inatividade — o que elimina esse custo em conversas ativas.
8. Setup Completo Sugerido
Para cobrir a maioria dos casos de uso do dia a dia sem sobrecarregar o armazenamento:
# 1. Modelo geral + português (uso cotidiano)
docker exec -it ollama ollama pull qwen2.5:7b
# 2. Código (desenvolvimento)
docker exec -it ollama ollama pull qwen2.5-coder:7b
# 3. Raciocínio (lógica, matemática, análise)
docker exec -it ollama ollama pull deepseek-r1:7b
# 4. Embedding (necessário para o RAG do Open WebUI)
docker exec -it ollama ollama pull nomic-embed-text
Com esses 4 modelos você cobre: conversação geral em português, geração e revisão de código, raciocínio avançado e busca semântica sobre documentos.
Espaço em disco estimado
| Modelo | Tamanho em disco |
|---|---|
qwen2.5:7b |
~4,7 GB |
qwen2.5-coder:7b |
~4,7 GB |
deepseek-r1:7b |
~4,7 GB |
nomic-embed-text |
~274 MB |
| Total | ~14,5 GB |
9. Usando o Open WebUI
Primeiro acesso
- Acesse http://localhost:3000
- Crie uma conta de administrador no primeiro acesso
- Faça login e explore a interface
Funcionalidades principais
| Funcionalidade | Como acessar |
|---|---|
| Conversar com modelos | Tela inicial → selecione o modelo no topo |
| Baixar/gerenciar modelos | Configurações → Modelos |
| RAG (chat com documentos) | Nova conversa → ícone de clipe → envie um PDF/TXT |
| Configurar modelo de embedding | Configurações → Documentos → Modelo de Embedding |
| Criar assistentes personalizados | Espaço de Trabalho → Assistentes |
| Histórico de conversas | Painel lateral esquerdo |
| API Key para integração | Configurações → Conta → Chaves de API |
Configurando o RAG
Para usar o sistema de RAG (Retrieval-Augmented Generation) — que permite fazer perguntas sobre documentos próprios:
- Vá em Configurações → Documentos
- Em Modelo de Embedding, selecione
nomic-embed-text - Salve as configurações
- Em qualquer conversa, clique no ícone de clipe e envie seu documento
- O modelo responderá com base no conteúdo do arquivo
10. Busca na Web com SearXNG
Por padrão, os modelos locais não têm acesso à internet. O SearXNG é um mecanismo de busca self-hosted que pode ser integrado ao Open WebUI para permitir que os modelos consultem informações atuais antes de responder.
Isso é essencial para perguntas como "como está o clima hoje?", "qual é a cotação do dólar?" ou qualquer outra que exija dados em tempo real.
Configuração inicial do settings.yml
Antes de subir o container pela primeira vez, crie o arquivo de configuração:
# Criar o diretório
mkdir -p ~/ia-local/searxng
# Gerar o settings.yml a partir da imagem oficial
docker run --rm --entrypoint cat searxng/searxng:latest \
/usr/local/searxng/searx/settings.yml \
> ~/ia-local/searxng/settings.yml
# Verificar se foi gerado corretamente
wc -l ~/ia-local/searxng/settings.yml
Em seguida, abra o arquivo e localize a seção search: para habilitar o formato JSON (necessário para integração com o Open WebUI):
nano ~/ia-local/searxng/settings.yml
Encontre e deixe a seção exatamente assim:
search:
formats:
- html
- json
Atenção: Não use
sedpara editar essa seção — o arquivo YAML é sensível à indentação e o comando pode inserir entradas duplicadas ou mal formatadas, impedindo o container de iniciar. Edite manualmente comnanoou outro editor de texto.
Como alternativa mais simples, você pode substituir todo o conteúdo do arquivo por uma versão mínima que herda as configurações padrão da imagem:
cat > ~/ia-local/searxng/settings.yml << 'EOF'
use_default_settings: true
search:
formats:
- html
- json
server:
bind_address: "0.0.0.0"
port: 8080
secret_key: "troque-por-uma-chave-aleatoria"
EOF
Subindo e verificando o SearXNG
docker compose up -d searxng
# Aguardar alguns segundos e verificar
docker compose ps
docker logs searxng --tail=10
# Testar a busca via API
curl "http://localhost:8889/search?q=clima+brasilia&format=json" | head -c 300
Se retornar um JSON com resultados, o SearXNG está funcionando corretamente.
Integrando ao Open WebUI
- Acesse http://localhost:3000
- Vá em Avatar → Configurações → Busca na Web
- Ative o toggle Habilitar Busca na Web
- Selecione o provedor SearXNG
- URL:
http://searxng:8080(porta interna do Docker, não a 8889) - Clique em Salvar
A URL interna usa a porta
8080porque os containers se comunicam pela rede interna do Docker. A porta8889é apenas para acesso pelo navegador no host.
Ativando a busca em uma conversa
A busca web não é ativada automaticamente em todas as conversas. Para usá-la:
- Na caixa de mensagem, clique no ícone "+" (canto inferior esquerdo)
- Ative a opção Busca na Web
- O ícone ficará destacado quando ativo
- Envie sua pergunta normalmente
Solução de problemas do SearXNG
| Sintoma | Causa provável | Solução |
|---|---|---|
| Container em loop de restart | settings.yml com YAML inválido |
Recriar o arquivo manualmente |
curl: Failed to connect |
Container não está rodando | docker compose ps e verificar logs |
"number_of_results": 0 |
Nenhum engine retornou resultado | Aguardar e tentar novamente |
| Erro no Open WebUI ao buscar | URL incorreta | Usar http://searxng:8080 (não localhost) |
11. Benchmark Comparativo de Modelos
O Ollama expõe métricas detalhadas de desempenho em cada resposta via API. É possível usar essas métricas para comparar modelos e escolher o mais adequado para cada caso de uso.
Métricas disponíveis
| Métrica | Descrição |
|---|---|
| eval_count | Número de tokens gerados na resposta |
| eval_duration | Tempo de geração em nanosegundos |
| load_duration | Tempo para carregar o modelo na VRAM |
| total_duration | Tempo total da requisição (carregamento + geração) |
| tokens/s | Velocidade de geração (calculada a partir das anteriores) |
O tempo do 1º token tende a ser alto na primeira execução (modelo carregando na VRAM) e próximo de zero nas seguintes, pois o Ollama mantém o modelo em memória por padrão.
Script de benchmark
Salve o script abaixo como benchmark.sh no diretório da stack:
#!/bin/bash
OLLAMA_URL="http://localhost:11434"
PROMPT="Explique o que é inteligência artificial em 3 parágrafos."
RESULTS_FILE="benchmark_results.md"
MODELS=(
"qwen2.5:7b"
"deepseek-r1:7b"
"qwen2.5-coder:7b"
"mistral:7b"
"llama3.1:8b"
)
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
echo -e "${CYAN}=====================================${NC}"
echo -e "${CYAN} Benchmark de Modelos Ollama ${NC}"
echo -e "${CYAN}=====================================${NC}"
echo ""
cat > "$RESULTS_FILE" << EOF
# Benchmark de Modelos Ollama
**Data:** $(date '+%d/%m/%Y %H:%M')
**Prompt:** "${PROMPT}"
| Modelo | Tokens gerados | Tempo total (s) | Tokens/s | Tempo 1º token (ms) |
|--------|---------------|-----------------|----------|----------------------|
EOF
for MODEL in "${MODELS[@]}"; do
echo -e "Testando ${GREEN}${MODEL}${NC}..."
if ! docker exec ollama ollama list 2>/dev/null | grep -q "^${MODEL}"; then
echo -e " ${YELLOW}Modelo não instalado, pulando...${NC}"
echo "| ${MODEL} | - | - | - | - |" >> "$RESULTS_FILE"
continue
fi
RESPONSE=$(curl -s -X POST "${OLLAMA_URL}/api/generate" \
-H "Content-Type: application/json" \
-d "{\"model\": \"${MODEL}\", \"prompt\": \"${PROMPT}\", \"stream\": false}")
TOTAL_DURATION=$(echo "$RESPONSE" | grep -o '"total_duration":[0-9]*' | cut -d: -f2)
EVAL_COUNT=$(echo "$RESPONSE" | grep -o '"eval_count":[0-9]*' | cut -d: -f2)
EVAL_DURATION=$(echo "$RESPONSE" | grep -o '"eval_duration":[0-9]*' | cut -d: -f2)
LOAD_DURATION=$(echo "$RESPONSE" | grep -o '"load_duration":[0-9]*' | cut -d: -f2)
TOTAL_S=$(echo "scale=2; ${TOTAL_DURATION:-0} / 1000000000" | bc)
LOAD_MS=$(echo "scale=0; ${LOAD_DURATION:-0} / 1000000" | bc)
if [ -n "$EVAL_COUNT" ] && [ -n "$EVAL_DURATION" ] && [ "$EVAL_DURATION" -gt 0 ]; then
TPS=$(echo "scale=1; ${EVAL_COUNT} / (${EVAL_DURATION} / 1000000000)" | bc)
else
TPS="N/A"
fi
echo -e " Tokens: ${EVAL_COUNT:-N/A} | Total: ${TOTAL_S}s | Velocidade: ${TPS} tok/s"
echo "| ${MODEL} | ${EVAL_COUNT:-N/A} | ${TOTAL_S} | ${TPS} | ${LOAD_MS} |" >> "$RESULTS_FILE"
done
echo "" >> "$RESULTS_FILE"
echo "_Tempo total = tempo de geração + carregamento do modelo na VRAM_" >> "$RESULTS_FILE"
echo -e "${GREEN}Resultados salvos em: ${YELLOW}${RESULTS_FILE}${NC}"
Como usar
# Tornar executável
chmod +x ~/ia-local/benchmark.sh
# Editar os modelos a testar (variável MODELS no script)
nano ~/ia-local/benchmark.sh
# Executar
cd ~/ia-local
./benchmark.sh
# Ver os resultados
cat benchmark_results.md
Exemplo de saída
| Modelo | Tokens gerados | Tempo total (s) | Tokens/s | Tempo 1º token (ms) |
|--------------------|---------------|-----------------|----------|----------------------|
| qwen2.5:7b | 312 | 18.4 | 42.1 | 823 |
| deepseek-r1:7b | 489 | 31.2 | 38.7 | 910 |
| qwen2.5-coder:7b | 298 | 17.9 | 43.5 | 798 |
| mistral:7b | 341 | 20.1 | 40.2 | 856 |
| llama3.1:8b | 367 | 23.5 | 37.8 | 944 |
Dicas para um benchmark mais preciso
- Execute o benchmark duas vezes e considere apenas a segunda rodada — na primeira, o modelo ainda não está carregado na VRAM
- Use sempre o mesmo prompt para comparações justas
- Feche outros programas que consomem VRAM antes de rodar
- Teste com prompts de diferentes tipos: conversação, código, raciocínio
12. Transcrição de Áudio com Whisper
O faster-whisper é uma implementação otimizada do Whisper da OpenAI, com suporte a aceleração via GPU e modo CPU. É integrado à stack via container Docker e expõe uma API REST para transcrição de arquivos de áudio.
Decisão: GPU ou CPU?
| Modo | Quando usar | Vantagem |
|---|---|---|
GPU (latest-gpu) |
Transcrições rápidas e pontuais | Muito mais rápido |
CPU (latest) |
Arquivos longos ou máquinas com GPU compartilhada | Não disputa VRAM com o display e o Ollama |
Em sistemas onde a GPU também serve o display (como desktops com monitor conectado), transcrever arquivos longos com GPU pode travar o vídeo e o teclado. Nesses casos, use o modo CPU.
Configuração inicial
Crie os diretórios necessários:
mkdir -p ~/ia-local/whisper/cache
mkdir -p ~/ia-local/whisper/uploads
O serviço já está incluído no docker-compose.yml da seção 4. Para subir:
docker compose up -d whisper
docker logs whisper -f
Aguarde a mensagem Application startup complete. — na primeira execução o modelo medium (~1,5 GB) será baixado automaticamente para ./whisper/cache.
Modelos disponíveis
| Modelo | Tamanho | RAM/VRAM | Qualidade | Velocidade |
|---|---|---|---|---|
tiny |
~75 MB | ~1 GB | Baixa | Muito rápida |
base |
~145 MB | ~1 GB | Razoável | Rápida |
small |
~465 MB | ~2 GB | Boa | Moderada |
medium |
~1,5 GB | ~5 GB | Muito boa | Moderada |
large-v3 |
~3 GB | ~10 GB | Excelente | Lenta |
Para uso cotidiano em CPU,
mediumcomint8oferece o melhor equilíbrio entre qualidade e velocidade.
Testando a API
# Gerar um áudio de teste
ffmpeg -f lavfi -i "sine=frequency=440:duration=3" -ar 16000 -ac 1 /tmp/teste.wav
# Transcrever
curl -X POST "http://localhost:9000/asr?language=pt&output=txt&encode=false" \
-H "Content-Type: multipart/form-data" \
-F "audio_file=@/tmp/teste.wav"
Integração com o Open WebUI (microfone ao vivo)
O Open WebUI possui um motor de transcrição embutido (faster-whisper interno) usado para gravação ao vivo via microfone. Para configurá-lo:
- Acesse http://localhost:3000
- Vá em Avatar → Configurações → Áudio
- Em Speech-to-Text Engine, selecione
Whisper (Local) - Em STT Model, troque
basepormediume clique no ícone de download ⬇ - Clique em Salvar
O microfone no chat funciona para gravação ao vivo. Para transcrever arquivos de áudio existentes (ex.: gravações do iPhone), use o script da próxima seção.
Script de transcrição com barra de progresso
O script abaixo aceita qualquer formato de áudio (.m4a, .mp4, .wav, .mp3), divide automaticamente em chunks de 30 minutos e exibe uma barra de progresso. O resultado é salvo em um arquivo .txt com o mesmo nome do áudio.
Salve como ~/ia-local/transcrever.sh:
#!/bin/bash
# Uso: ./transcrever.sh arquivo.m4a [idioma]
ARQUIVO="$1"
IDIOMA="${2:-pt}"
WHISPER_URL="http://localhost:9000/asr"
CHUNK_MIN=30
SAIDA="${ARQUIVO%.*}.txt"
TMP_DIR=$(mktemp -d /tmp/whisper_XXXXXX)
# Funções auxiliares
barra() {
local ATUAL=$1 TOTAL=$2
local PERC=$(( ATUAL * 100 / TOTAL ))
local FEITO=$(( PERC / 5 ))
local VAZIO=$(( 20 - FEITO ))
printf "\r [%-${FEITO}s%${VAZIO}s] %d%% (%d/%d partes)" \
"$(printf '#%.0s' $(seq 1 $FEITO 2>/dev/null))" "" "$PERC" "$ATUAL" "$TOTAL"
}
limpar() {
rm -rf "$TMP_DIR"
}
trap limpar EXIT
# Validações
if [ -z "$ARQUIVO" ]; then
echo "Uso: $0 <arquivo_audio> [idioma]"
echo "Exemplo: $0 gravacao.m4a pt"
exit 1
fi
if [ ! -f "$ARQUIVO" ]; then
echo "Arquivo não encontrado: $ARQUIVO"
exit 1
fi
# Detectar duração total
echo "Analisando arquivo..."
DURACAO=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$ARQUIVO" 2>/dev/null | cut -d. -f1)
if [ -z "$DURACAO" ] || [ "$DURACAO" -eq 0 ]; then
echo "Erro: não foi possível determinar a duração do arquivo."
exit 1
fi
CHUNK_SEG=$(( CHUNK_MIN * 60 ))
TOTAL_CHUNKS=$(( (DURACAO + CHUNK_SEG - 1) / CHUNK_SEG ))
echo "Duração total : $(( DURACAO / 60 ))min $(( DURACAO % 60 ))s"
echo "Partes : $TOTAL_CHUNKS (${CHUNK_MIN}min cada)"
echo "Saída : $SAIDA"
echo ""
# Dividir em chunks e transcrever
> "$SAIDA"
INICIO=0
PARTE=1
while [ "$PARTE" -le "$TOTAL_CHUNKS" ]; do
barra "$PARTE" "$TOTAL_CHUNKS"
CHUNK_WAV="$TMP_DIR/parte_$(printf '%03d' $PARTE).wav"
# Converter chunk para wav 16kHz mono
ffmpeg -ss "$INICIO" -t "$CHUNK_SEG" -i "$ARQUIVO" \
-ar 16000 -ac 1 -f wav "$CHUNK_WAV" \
-y -loglevel quiet 2>/dev/null
# Transcrever
RESULTADO=$(curl -s -X POST \
"${WHISPER_URL}?language=${IDIOMA}&output=txt&encode=false" \
-H "Content-Type: multipart/form-data" \
-F "audio_file=@${CHUNK_WAV}")
echo "$RESULTADO" >> "$SAIDA"
INICIO=$(( INICIO + CHUNK_SEG ))
PARTE=$(( PARTE + 1 ))
done
echo ""
echo ""
echo "✓ Transcrição concluída: $SAIDA"
chmod +x ~/ia-local/transcrever.sh
Como usar o script
# Arquivo em português (padrão)
./transcrever.sh gravacao.m4a
# Especificando o idioma
./transcrever.sh lecture.mp4 en
# O resultado será salvo como gravacao.txt ou lecture.txt
Saída durante a transcrição
Analisando arquivo...
Duração total : 92min 14s
Partes : 4 (30min cada)
Saída : gravacao.txt
[#### ] 25% (1/4 partes)
Formatos de áudio suportados
O script converte o áudio via ffmpeg antes de enviar, aceitando qualquer formato que o ffmpeg reconheça. Os mais comuns são m4a (iPhone), mp4, mp3, wav e ogg.
Arquivos do iPhone salvos localmente geralmente são
.m4a. Quando compartilhados diretamente (AirDrop, mensagem), podem chegar como.mp4— ambos funcionam normalmente.
Limpando os logs do Whisper
sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' whisper)
13. Alternativas à Stack Principal
| Ferramenta | Tipo | Prós | Contras |
|---|---|---|---|
| LM Studio | App desktop | Interface polida, fácil de usar | Não roda em Docker |
| LocalAI | Backend Docker | Compatível com API OpenAI, muito flexível | Configuração mais complexa |
| AnythingLLM | App/Docker | Focado em RAG, excelente para bases de conhecimento | Pode ser integrado ao Ollama |
| Jan.ai | App desktop | Open source, minimalista | Sem suporte a Docker |
| Text Generation WebUI | Docker | Suporta formatos variados (GGUF, GPTQ, AWQ) | Interface mais técnica |
Usando o AnythingLLM junto com o Ollama
O AnythingLLM pode ser adicionado à stack como interface alternativa focada em documentos:
# Adicione ao docker-compose.yml
anythingllm:
image: mintplexlabs/anythingllm:latest
container_name: anythingllm
depends_on:
- ollama
environment:
- OLLAMA_BASE_PATH=http://ollama:11434
volumes:
- anythingllm_data:/app/server/storage
ports:
- "3001:3001"
restart: unless-stopped
14. Solução de Problemas
GPU não está sendo detectada
# Verificar se o runtime NVIDIA está configurado
docker info | grep -i runtime
# Testar acesso à GPU
docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi
# Se falhar, reconfigurar o runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Modelos rodando na CPU em vez da GPU
# Verificar se o Ollama detectou a GPU
docker exec -it ollama ollama run llama3.2:3b "oi"
docker logs ollama | grep -i gpu
Se aparecer no GPU detected, verifique se o runtime: nvidia está no docker-compose.yml e se o NVIDIA Container Toolkit foi instalado corretamente.
Open WebUI não conecta ao Ollama
# Verificar se ambos os containers estão rodando
docker compose ps
# Testar a API do Ollama diretamente
curl http://localhost:11434/api/tags
# Ver logs do Open WebUI
docker compose logs open-webui
Erro de memória (Out of Memory) ao carregar modelo
- Use uma versão com quantização menor: ex., troque
phi4:14bporphi4:14b-q4_K_M - Feche outros programas que consomem VRAM (jogos, outros modelos)
- Escolha um modelo menor (7B em vez de 14B)
Atualizando as imagens
# Baixar versões mais recentes de todos os serviços
docker compose pull
# Reiniciar com as novas imagens
docker compose up -d
Para atualizar apenas um serviço específico:
# Atualizar só o Ollama (necessário para modelos recentes como o Gemma 4)
docker compose pull ollama
docker compose up -d ollama
# Atualizar só o Open WebUI
docker compose pull open-webui
docker compose up -d open-webui
Importante: O Gemma 4 e outros modelos recentes exigem versões atualizadas do Ollama. Se o pull retornar
requires a newer version of Ollama, atualize o container do Ollama antes de tentar novamente.
15. Referências
- Ollama — Documentação Oficial
- Ollama — Biblioteca de Modelos
- Open WebUI — Repositório GitHub
- SearXNG — Repositório GitHub
- Whisper ASR Webservice — Repositório GitHub
- faster-whisper — Repositório GitHub
- NVIDIA Container Toolkit — Guia de Instalação
- Docker Compose — Referência
Documentação gerada em março de 2026. Atualizada em abril de 2026 com Gemma 4, atualização de containers e configuração de KEEP_ALIVE. Versões e disponibilidade de modelos podem variar.