Apostila completa de IA Local, On-Device & Small Language Models
Rodar modelos de linguagem no próprio hardware — laptop, servidor, navegador ou celular — deixou de ser curiosidade e virou uma opção de arquitetura. Esta apostila cobre por que e quando fazer isso, o panorama de modelos abertos e suas licenças, o hardware e a matemática de VRAM, quantização, os runtimes (llama.cpp, Ollama, vLLM, MLX), IA no navegador e no dispositivo, como servir e integrar, avaliar e rotear entre local e nuvem, e levar a produção no edge.
Por que rodar IA localmente
Objetivo: entender os motivos reais para inferência local (privacidade, custo, latência, offline, controle), os trade-offs, e o panorama que torna isso viável hoje.
1.1 Os motivos
| Motivo | O que muda |
|---|---|
| Privacidade / soberania de dados | o prompt e a resposta nunca deixam a máquina — dados sensíveis, saúde, jurídico, on-prem, LGPD/GDPR sem contrato de subprocessador |
| Custo | zero por token depois do hardware; previsível; escala com uso alto sem a fatura crescer linearmente |
| Latência | sem ida-e-volta de rede; time-to-first-token muito baixo; bom para autocomplete, classificação em massa, loops apertados |
| Offline | funciona no avião, no campo, na fábrica, no dispositivo do usuário |
| Controle e reprodutibilidade | o modelo não muda sob você; você versiona o peso exato; sem deprecação forçada nem rate limit |
| Especialização | um modelo pequeno afinado para uma tarefa pode bater um modelo de fronteira genérico nela (Módulo 8) |
1.2 Os trade-offs
- Qualidade de topo: os melhores modelos abertos alcançam o "bom o suficiente" para muitas tarefas, mas os modelos de fronteira proprietários ainda lideram em raciocínio difícil, contexto muito longo e tarefas agênticas complexas.
- Hardware: você precisa dele, dimensioná-lo e mantê-lo; GPU boa é cara e escassa.
- Operação: atualizar modelos, monitorar, escalar, lidar com picos — vira sua responsabilidade.
- Multimodalidade e ferramentas: o ecossistema aberto está atrás em alguns recursos (voz nativa, uso de computador, algumas modalidades).
Local não é "tudo ou nada". A arquitetura vencedora costuma ser híbrida: o modelo local resolve o volume (classificação, extração, rascunho, autocomplete, dados sensíveis) e a nuvem entra por roteamento quando a tarefa é difícil ou rara (Módulo 8). Pense em "que fração do tráfego pode ser local", não em "trocar o provedor".
1.3 O que tornou isso viável
- Modelos pequenos e capazes (SLMs de 1–14B) que, com bom prompt, RAG e/ou fine-tune, resolvem tarefas de produção.
- Quantização (Módulo 4): rodar um 8B em ~5 GB em vez de 16.
- Runtimes maduros (Módulo 5):
llama.cpp, Ollama, vLLM, MLX — rápidos, fáceis, com API compatível com OpenAI. - Hardware de consumo forte: Apple Silicon com memória unificada, GPUs de 16–24 GB acessíveis, NPUs em laptops.
Perguntas de abertura: "Quando você usaria um modelo local em vez de uma API?" (privacidade/dados sensíveis, custo em alto volume, latência, offline, especialização — e como híbrido), "Quais os trade-offs?" (qualidade de topo, hardware, operação), "O que mudou para isso ser viável?" (SLMs capazes + quantização + runtimes + hardware de consumo).
✏️ Exercício 1 — Local, nuvem ou híbrido
Para cada caso, recomende local, nuvem ou híbrido, justificando: (a) um app de anotações que resume e categoriza notas do usuário, com política de "seus dados não saem do dispositivo"; (b) um assistente jurídico interno que analisa contratos confidenciais e ocasionalmente redige peças complexas; (c) um pipeline que classifica 5 milhões de tickets/dia em 8 categorias; (d) um chatbot de atendimento com perguntas variadas e abertas.
Gabarito (uma boa resposta): (a) on-device — a promessa de privacidade exige; resumo e categorização são tarefas que um SLM faz bem; cuidar de tamanho de download e bateria (Módulo 6). (b) híbrido — extração e classificação de cláusulas rodam local (confidencialidade); a redação de peças complexas roteia para um modelo de fronteira, com o cliente ciente, ou para um modelo aberto grande on-prem. (c) local — 5M/dia numa API é caro e lento; um SLM quantizado num servidor com GPU, em batch (vLLM), classifica isso barato; medir qualidade com eval próprio. (d) nuvem (ou híbrido com roteamento) — perguntas abertas e variadas favorecem um modelo de fronteira; se o volume for alto, um roteador manda as fáceis para um modelo aberto e as difíceis para a nuvem.
O panorama de modelos abertos
Objetivo: conhecer as famílias de modelos de pesos abertos, os tamanhos, as variantes (base/instruct/reasoning), e como ler uma licença e um model card.
2.1 As famílias (nomes que você vai ouvir)
- Llama (Meta) — a família que popularizou pesos abertos; licença própria com algumas restrições de uso.
- Qwen (Alibaba) — forte em multilíngue, código e matemática; várias faixas de tamanho; Apache-2.0 na maioria.
- Gemma (Google) — pequenos e médios, fortes para o tamanho; licença própria.
- Mistral / Mixtral (Mistral AI) — densos e "mixture of experts" (MoE); Apache-2.0 nos abertos.
- Phi (Microsoft) — SLMs treinados com dados sintéticos de alta qualidade; MIT.
- DeepSeek — modelos grandes e de raciocínio, com destilações menores.
- SmolLM / TinyLlama / OLMo / Nemotron — muito pequenos, ou totalmente abertos (dados + código), ou otimizados para NVIDIA.
- O ranking muda a cada mês — o que importa é saber onde procurar e como avaliar no seu caso (Módulo 8), não decorar o "melhor de hoje".
2.2 Tamanhos e o que esperar
| Faixa | Uso realista |
|---|---|
| 0.5–2B | classificação, extração, roteamento, autocomplete, no navegador/celular; precisa de tarefa estreita e bom prompt/fine-tune |
| 3–9B | o "ponto doce" local: chat decente, RAG, resumo, redação, código simples; roda em laptop |
| 12–32B | qualidade notavelmente melhor; pede GPU de 24 GB+ ou Apple Silicon com bastante RAM |
| 70B+ / MoE grandes | perto de modelos de fronteira em muitas tarefas; workstation multi-GPU ou servidor |
2.3 Variantes
- Base (pré-treinado, "completa texto") vs Instruct/Chat (afinado para seguir instruções e conversar — quase sempre o que você quer) vs Reasoning (gera uma cadeia de pensamento antes da resposta; melhor em problemas difíceis, mais lento e verboso).
- Context window: 8k a 128k+ tokens — mas contexto longo custa memória (KV cache) e a qualidade cai muito antes do limite anunciado ("lost in the middle").
- Multilíngue: confira o desempenho em português especificamente — varia bastante entre famílias.
- Multimodal: variantes "VL" (vision-language) que aceitam imagem — ver a apostila Multimodal & Document AI.
2.4 Licenças: "open weights" ≠ "open source"
- Pesos abertos permissivos (Apache-2.0, MIT): uso comercial livre, sem restrição de uso, pode redistribuir e afinar.
- Licenças próprias (Llama Community License, Gemma Terms): geralmente permitem uso comercial, mas com cláusulas — limite de usuários (no caso da Llama, acima de um patamar exige acordo), políticas de uso aceitável, exigência de atribuição, restrições sobre treinar outros modelos com as saídas.
- Totalmente aberto (OLMo, alguns): pesos + dados + código de treino.
- Sempre leia a licença para uso comercial; e o model card: dados de treino (na medida do divulgado), avaliações, limitações, vieses conhecidos, formato de prompt/chat template, data de corte de conhecimento.
Perguntas: "Diferença entre modelo base e instruct?", "O que 'open weights' significa e qual o cuidado de licença?" (não é open source; ler cláusulas de uso comercial), "Que tamanho de modelo roda num laptop e o que esperar dele?" (3–9B, o ponto doce), "Como você escolhe um modelo aberto?" (não pelo ranking do mês — pela avaliação no seu caso, licença, português, tamanho que cabe).
✏️ Exercício 2 — Leia o model card
Você precisa de um modelo para rodar num servidor da empresa (produto comercial B2B), extrair campos de documentos em português, sem enviar dados a terceiros. Liste 6 coisas que você verificaria no model card e na licença antes de escolher, e por quê.
Gabarito (uma boa resposta): (1) licença — permite uso comercial B2B sem limite de usuários e sem exigir acordo? há restrições de uso aceitável que colidam com o produto? (2) tamanho e requisitos — cabe no hardware que temos, na quantização pretendida? (3) desempenho em português — as avaliações incluem PT ou línguas latinas? (4) chat template / formato de prompt — documentado? o runtime suporta? (5) capacidade de saída estruturada — o modelo segue JSON schema bem? há relatos? (6) context window efetivo — os documentos cabem, e a qualidade se mantém nesse comprimento? Extras: data de corte de conhecimento (irrelevante para extração, relevante se houver raciocínio); vieses e limitações documentados; se as saídas podem ser usadas para treinar outros modelos (algumas licenças proíbem).
Hardware: o que cabe onde
Objetivo: entender que VRAM (ou RAM unificada) é o gargalo, estimar a memória de um modelo, e conhecer as opções (GPU, Apple Silicon, CPU, NPU).
3.1 A conta que importa
Para caber, o modelo precisa de:
memória ≈ (nº de parâmetros × bytes por parâmetro) + KV cache + overhead bytes por parâmetro: FP16 / BF16 ......... 2.0 INT8 (Q8) .......... ~1.0 ~4-bit (Q4_K_M) .... ~0.5–0.6 ~2-bit (IQ2) ....... ~0.3 (qualidade cai bastante) KV cache (por token de contexto) cresce com camadas × dim × 2; contexto longo pode custar GIGABYTES além do peso.
| Modelo | FP16 | Q8 | Q4_K_M |
|---|---|---|---|
| ~3B | ~6 GB | ~3 GB | ~2 GB |
| ~8B | ~16 GB | ~8 GB | ~5 GB |
| ~14B | ~28 GB | ~14 GB | ~9 GB |
| ~32B | ~64 GB | ~34 GB | ~20 GB |
| ~70B | ~140 GB | ~70 GB | ~40 GB |
Some o KV cache do contexto que você vai usar, deixe folga para o SO e outros processos, e para GPU: se não couber na VRAM, parte vai para a RAM/CPU (offload) e a velocidade despenca.
3.2 As plataformas
| Plataforma | Notas |
|---|---|
| NVIDIA (CUDA) | o caminho mais suportado; VRAM é tudo (RTX 3090/4090 = 24 GB; profissionais/datacenter = 48–80 GB+). Todos os runtimes rodam bem |
| Apple Silicon (Metal / MLX) | memória unificada: a RAM é a "VRAM". Um Mac com 64–128 GB roda modelos grandes com boa eficiência energética; ótimo para dev local |
| AMD (ROCm) | melhorando; suporte de llama.cpp/vLLM existe mas com mais fricção que CUDA |
| CPU-only | funciona (llama.cpp), viável para modelos pequenos e baixa vazão; lento para chat interativo em modelos médios |
| NPU (laptops "AI PC", celulares) | aceleradores de baixo consumo para on-device; ecossistema (ONNX Runtime, ExecuTorch, Core ML) ainda amadurecendo |
3.3 Velocidade
- Métrica: tokens por segundo (geração) e time-to-first-token (TTFT, dominado pelo processamento do prompt).
- A geração é memory-bandwidth bound: quanto mais rápida a memória e menor o modelo (quantizado), mais tokens/s.
- Prompt longo aumenta o TTFT (é compute bound) — prompt caching ajuda (Módulo 9).
- Alvo de conforto: > ~15–20 tok/s para chat interativo; para batch/pipeline, o que importa é a vazão agregada.
Perguntas: "Quanta memória um modelo de 8B em 4-bit precisa?" (~5 GB de peso + KV cache do contexto), "Por que Apple Silicon é bom para LLM local?" (memória unificada = RAM vira VRAM; eficiência), "O que acontece se o modelo não cabe na VRAM?" (offload para CPU/RAM, velocidade despenca), "O que limita os tokens/s?" (largura de banda de memória; tamanho do modelo).
✏️ Exercício 3 — Dimensione
(a) Você tem uma GPU de 24 GB. Que modelos e quantizações rodam confortavelmente com contexto de 8k? E de 32k? (b) Um Mac de 32 GB de RAM unificada — o que dá para rodar sem sufocar o sistema? (c) Você precisa de 200 tok/s agregados classificando textos curtos — como você chegaria lá?
Gabarito (uma boa resposta): (a) 24 GB: um 14B em Q4/Q5 sobra folga para 8k e ainda cabe 32k com algum aperto; um 32B em Q4 (~20 GB) cabe para 8k mas 32k de KV cache pode estourar — reduzir contexto ou quantizar o KV cache; 8B em qualquer quantização, folgado. (b) 32 GB Mac: deixando ~8–10 GB para o SO, sobra ~22 GB — um 14B em Q4/Q8 ou um 8B com muito contexto; 32B só em Q3/Q4 apertado. (c) 200 tok/s agregados: um SLM pequeno (1–3B) quantizado, servido com vLLM (batching contínuo) numa GPU, processando os textos em lote; medir a qualidade com um eval próprio e subir de tamanho só se precisar. Textos curtos = TTFT baixo, ótimo throughput.
Quantização
Objetivo: entender o que é quantizar, os formatos (GGUF, GPTQ, AWQ, MLX…), os níveis, e o trade-off qualidade × tamanho × velocidade.
4.1 A ideia
Os pesos de um modelo são guardados em ponto flutuante de 16 bits. Quantizar é representá-los com menos bits (8, 5, 4, até 2), com um esquema de escala/zero-point por bloco para limitar a perda. O modelo fica 2–4× menor e mais rápido (menos bytes para mover da memória), ao custo de alguma degradação de qualidade — pequena em 8/5/4 bits, crescente abaixo disso.
4.2 Formatos
| Formato | Ecossistema | Notas |
|---|---|---|
| GGUF | llama.cpp, Ollama, LM Studio, Jan | o padrão de fato para inferência local em CPU/GPU mista; níveis Q4_K_M, Q5_K_M, Q6_K, Q8_0, e os IQ (2–4 bits com "importance matrix") |
| GPTQ | GPU (transformers, vLLM, TGI) | quantização pós-treino com calibração; 4-bit comum |
| AWQ | GPU (vLLM, TGI, SGLang) | "activation-aware"; boa qualidade em 4-bit, rápido em serving |
| EXL2 | ExLlamaV2 (GPU NVIDIA) | bits variáveis por camada; muito rápido em GPU única |
| bitsandbytes (NF4) | transformers | quantização "on the fly" ao carregar; usada em QLoRA (fine-tuning) |
| MLX | Apple Silicon | formato próprio do MLX; 4-bit e 8-bit |
4.3 Escolher o nível
- Q8 / 8-bit: degradação praticamente imperceptível; use quando a memória permite.
- Q5_K_M / Q4_K_M (~4–5 bit): o ponto doce — perda pequena, cabe bem, rápido.
Q4_K_Mé a escolha padrão da maioria. - Q3 e abaixo / IQ2: só quando é a única forma de o modelo caber; a qualidade cai de forma notável — muitas vezes um modelo menor em Q4 é melhor que um maior em Q2.
- KV cache quantization (Q8/Q4 do cache): economiza memória em contexto longo, com perda pequena.
- Medir: perplexity dá um sinal grosseiro; o que vale é rodar o seu eval (Módulo 8) com cada quantização.
Assumir que "4-bit é ruim" — na prática Q4_K_M é excelente para a maioria dos usos. Rodar um 70B em Q2 quando um 32B em Q4 caberia melhor e renderia mais. Comparar modelos sem fixar a quantização. Ignorar o KV cache ao dimensionar contexto longo. Usar um GGUF antigo/genérico quando há um recém-requantizado com "imatrix" (melhor). Quantizar o modelo e não re-testar a saída estruturada (JSON) — às vezes degrada mais que o texto livre.
Perguntas: "O que é quantização e qual o trade-off?" (menos bits por peso → menor e mais rápido, alguma perda de qualidade), "GGUF, GPTQ, AWQ — quando cada um?" (GGUF para local CPU/GPU mista; AWQ/GPTQ para serving em GPU), "Que nível você usaria por padrão?" (Q4_K_M / 4-bit; Q8 se sobra memória), "70B em Q2 ou 32B em Q4?" (quase sempre o menor em Q4 — a degradação de Q2 supera o ganho de tamanho).
✏️ Exercício 4 — Plano de quantização
Você vai servir um assistente de código para o time numa GPU de 24 GB. Candidatos: um 14B e um 32B, ambos "code". Descreva como você decidiria o modelo e a quantização, o que mediria, e o papel do KV cache.
Gabarito (uma boa resposta): montar um eval próprio com ~50–100 tarefas reais do time (completar função, explicar erro, escrever teste) e um juiz (checagem automática onde der + LLM-as-judge). Testar: 14B em Q8 (~14 GB, sobra para contexto grande) e em Q5; 32B em Q4 (~20 GB, KV cache aperta — talvez quantizar o cache em Q8) e em Q3. Comparar acurácia no eval, tokens/s e o contexto máximo viável (código pede contexto). Provável resultado: se o 32B-Q4 ganha claramente no eval e ainda dá > 20 tok/s com o contexto necessário, vale; senão, 14B-Q8 pela folga de contexto e velocidade. KV cache: dimensionar para o contexto-alvo (ex.: 16–32k) — ele pode custar vários GB e é o que decide se o 32B cabe.
Runtimes e ferramentas
Objetivo: conhecer os motores de inferência (llama.cpp, Ollama, LM Studio, vLLM, TGI, SGLang, MLX) e escolher pelo caso — dev local, servidor de produção, edge.
5.1 O mapa
| Ferramenta | É | Para |
|---|---|---|
| llama.cpp | o motor C/C++ (CPU + GPU via Metal/CUDA/Vulkan), formato GGUF | a base de quase tudo local; embutir em apps; edge; controle fino |
| Ollama | um "Docker de modelos" sobre llama.cpp: ollama run qwen2.5, registry, API | dev local rápido, protótipos, workstations; o mais fácil de começar |
| LM Studio / Jan | apps de desktop com UI + servidor local | quem prefere interface; testar modelos; usuários não-devs |
| vLLM | servidor de inferência de alta vazão (GPU): continuous batching, PagedAttention, prefix caching | produção com muitas requisições concorrentes; o padrão para serving sério |
| TGI (Hugging Face) | servidor de produção, similar ao vLLM | produção; integra com o ecossistema HF |
| SGLang | serving com foco em programas estruturados e cache agressivo de prefixo | produção com muitos prompts que compartilham prefixo (RAG, agentes) |
| MLX / MLX-LM | framework da Apple para Apple Silicon | dev e inferência em Mac; fine-tuning leve local |
| llamafile | um único executável (modelo + runtime) multiplataforma | distribuir um modelo "que só roda", sem instalação |
5.2 O padrão que une tudo: API compatível com OpenAI
Praticamente todo runtime expõe um endpoint /v1/chat/completions compatível com a API da OpenAI. Isso torna a inferência local um drop-in: o mesmo SDK, a mesma chamada, só muda a base_url.
from openai import OpenAI client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") # Ollama resp = client.chat.completions.create( model="qwen2.5:7b-instruct-q4_K_M", messages=[{"role": "user", "content": "Resuma em 3 bullets: ..."}], stream=True, ) for chunk in resp: print(chunk.choices[0].delta.content or "", end="")
5.3 Modelfile e chat template
- Cada família tem um chat template (como as mensagens viram tokens: marcadores de system, user, assistant). Usar o errado degrada muito a saída. Os runtimes trazem o template no GGUF; confirme.
- No Ollama, um Modelfile empacota modelo +
SYSTEM+ parâmetros (temperature,num_ctx,stop) num "modelo" nomeado — versionável, como um Dockerfile.
# Modelfile FROM qwen2.5:7b-instruct-q4_K_M PARAMETER num_ctx 8192 PARAMETER temperature 0.2 SYSTEM """Você é um extrator. Responda SEMPRE com JSON válido no schema fornecido."""
5.4 Escolher
- Começar / prototipar / dev local: Ollama (ou LM Studio).
- Embutir num app / edge / controle total: llama.cpp direto (ou via binding).
- Servir em produção com concorrência: vLLM (ou TGI / SGLang).
- Mac: Ollama/MLX para dev; MLX para fine-tune leve.
Perguntas: "Qual a relação entre llama.cpp e Ollama?" (Ollama é uma camada de conveniência sobre o motor llama.cpp), "O que você usa para servir em produção e por quê?" (vLLM/TGI/SGLang — continuous batching, PagedAttention, prefix cache = muito mais throughput que llama.cpp puro sob concorrência), "Como você troca uma API da OpenAI por um modelo local?" (mesma SDK, muda a base_url — endpoint compatível), "O que é o chat template e por que importa?".
✏️ Exercício 5 — Escolha a stack
Para cada cenário, escolha o(s) runtime(s) e justifique: (a) você quer testar 5 modelos hoje à tarde no seu laptop; (b) um serviço interno que atende ~200 requisições concorrentes de RAG (prompts com um prefixo de sistema grande e comum); (c) um app desktop que embute um modelo de 3B e não pode depender de nada instalado; (d) fine-tune leve de um 8B no seu Mac.
Gabarito: (a) Ollama ou LM Studio — ollama pull + run, troca de modelo em segundos. (b) vLLM ou SGLang — continuous batching para os 200 concorrentes e prefix caching para não reprocessar o prompt de sistema comum a cada chamada (grande economia em RAG). (c) llama.cpp embutido (ou llamafile) — compila junto, GGUF ao lado do binário, zero instalação. (d) MLX-LM (LoRA no MLX) — feito para Apple Silicon; ou mlx_lm.lora. Ver a apostila Fine-tuning e Customização de Modelos.
IA no navegador e no dispositivo
Objetivo: rodar modelos dentro do navegador (WebGPU) e em iOS/Android, entender os casos de uso e os limites (download, bateria, térmico).
6.1 No navegador
| Tecnologia | O que faz |
|---|---|
| WebLLM (MLC) | roda LLMs no navegador via WebGPU, com API compatível com OpenAI; modelos de ~1–8B quantizados |
| transformers.js (Hugging Face) | roda modelos (LLMs pequenos, embeddings, visão, áudio) via ONNX Runtime Web (WASM + WebGPU) |
| ONNX Runtime Web / WebNN | a camada de execução; WebNN (emergente) expõe a NPU/GPU do dispositivo ao navegador |
| MediaPipe LLM Inference (Google) | LLMs pequenos on-device na web e em mobile |
| Prompt API do navegador | API experimental que expõe um modelo pequeno embutido no próprio navegador (ex.: Gemini Nano no Chrome) — sem download pela sua página |
| WebGPU | o pré-requisito: acesso à GPU pela web; suporte já amplo, com fallback para WASM (CPU, bem mais lento) |
| Ver também a apostila WebGPU & GPU Compute no Navegador para o mecanismo de baixo nível. | |
6.2 Em iOS e Android
- llama.cpp compila para ARM e roda em celular (via bindings; apps como o do próprio ecossistema demonstram).
- MLC LLM — runtime multiplataforma (iOS, Android, WebGPU) com o mesmo modelo compilado.
- ExecuTorch (PyTorch) e Core ML (Apple) / LiteRT (ex-TFLite, Google) — os caminhos "nativos" para rodar modelos otimizados na NPU/GPU do aparelho.
- Apple Intelligence (Foundation Models framework) e Gemini Nano (AICore, Android) — modelos do sistema operacional que o app chama sem embutir nada.
6.3 Casos de uso realistas on-device
- Autocomplete e reescrita de texto; correção; resumo de página/nota; tradução curta.
- Classificação e roteamento (intenção, sentimento, marcação); extração de campos.
- RAG local sobre os dados do usuário (embeddings + um SLM) — busca semântica privada.
- Assistentes offline em apps de campo, saúde, educação.
- Não para: raciocínio pesado, contexto muito longo, agentes complexos — ainda é território de nuvem.
6.4 Os limites
- Tamanho do download: um SLM quantizado tem centenas de MB a > 1 GB — pesado para carregar numa página; cache no dispositivo (Cache Storage / OPFS) é essencial, e ainda assim a primeira visita dói.
- Bateria e térmico: inferência sustentada esquenta e drena; bom para rajadas curtas, ruim para uso contínuo.
- Memória: navegadores e apps móveis têm orçamentos apertados; modelos maiores travam ou são mortos pelo SO.
- Variabilidade de hardware: o que voa no seu aparelho engasga no do usuário — teste em dispositivos medianos e tenha fallback (servidor ou modelo menor).
- Compatibilidade: WebGPU e as APIs de modelo do SO ainda não estão em 100% dos dispositivos — detecte e degrade.
Perguntas: "Como se roda um LLM no navegador?" (WebGPU + WebLLM/transformers.js; ou a Prompt API do navegador), "Que tarefas fazem sentido on-device?" (autocomplete, classificação, extração, resumo, RAG privado — não raciocínio pesado), "Quais os limites?" (download, bateria, térmico, memória, variabilidade de hardware — sempre com fallback), "O que é a Prompt API / Gemini Nano / Apple Intelligence?" (modelo do SO/navegador que o app usa sem embutir).
✏️ Exercício 6 — App com IA on-device
Um app de anotações web quer: (a) resumir uma nota, (b) sugerir tags, (c) busca semântica nas notas — tudo sem enviar dados ao servidor. Descreva a arquitetura (modelos, runtime, onde roda), como lidar com o primeiro carregamento, e o fallback.
Gabarito (uma boa resposta): um modelo de embeddings pequeno (via transformers.js, ONNX, ~20–100 MB) roda no navegador para indexar as notas num vetor local (IndexedDB/OPFS) — resolve (c) busca semântica. Um SLM de 1–3B quantizado via WebLLM (WebGPU) — ou a Prompt API do navegador, se disponível, evitando o download — faz (a) resumo e (b) sugestão de tags. Primeiro carregamento: baixar o modelo em segundo plano com barra de progresso, cachear em Cache Storage/OPFS, e deixar o app utilizável (sem IA) enquanto baixa; oferecer um botão "ativar IA local". Fallback: se não há WebGPU ou o aparelho é fraco, ou (i) usar só a busca por embeddings (que é leve) e desativar o resumo, ou (ii) oferecer processamento no servidor com consentimento explícito. Testar em um Android mediano.
Servir e integrar
Objetivo: expor o modelo local via API, com streaming, tool calling, saída estruturada, embeddings, concorrência e observabilidade.
7.1 A API
- Endpoint compatível com OpenAI (
/v1/chat/completions,/v1/embeddings,/v1/completions) — reuse SDKs, frameworks (LangChain, LlamaIndex, o AI SDK) e ferramentas existentes. - Streaming (SSE) para UX responsiva — o TTFT local costuma ser baixo, aproveite.
- Parâmetros que importam:
temperature,top_p,max_tokens,stop,seed(reprodutibilidade),num_ctx.
7.2 Saída estruturada
- JSON schema / structured outputs: vLLM, llama.cpp e Ollama suportam forçar a saída a um schema — o decodificador só amostra tokens que mantêm o JSON válido (via GBNF grammar no llama.cpp, outlines/xgrammar no vLLM).
- Isso é mais confiável que "peça JSON no prompt e reze"; essencial para extração, classificação e chamadas de ferramenta.
- Gramáticas também impõem enums, regex, listas — útil para roteadores e parsers.
# exemplo conceitual: forçar um schema resp = client.chat.completions.create( model="...", messages=[...], extra_body={"guided_json": {"type":"object", "properties":{"sentimento":{"enum":["pos","neg","neutro"]}, "score":{"type":"number"}}, "required":["sentimento","score"]}} # nome do campo varia por runtime )
7.3 Tool / function calling local
- Modelos instruct recentes suportam tool calling (emitir uma chamada de função estruturada); o runtime expõe no formato OpenAI (
tools,tool_calls). - Qualidade varia por modelo e tamanho — teste; um schema forçado + few-shot ajuda modelos menores.
- Base para agentes locais (ver a apostila Criação de Agentes de IA e MCP).
7.4 Embeddings locais e RAG
- Modelos de embedding abertos (multilíngues, pequenos) rodam local via mesmo runtime ou dedicado.
- RAG 100% local: embeddings locais + um vector store local (SQLite/DuckDB + índice, LanceDB, Chroma) + o SLM local para gerar. Nada sai da máquina. Ver a apostila IA Generativa & RAG.
7.5 Concorrência e observabilidade
- llama.cpp/Ollama servem bem 1–poucos usuários; para concorrência real, vLLM/TGI com continuous batching (várias requisições no mesmo passo de GPU).
- Uma fila com limite e timeout evita derrubar o servidor em pico.
- Métricas a expor: tokens/s, TTFT, tamanho da fila, ocupação de VRAM, requisições/s, taxa de erro. Ver a apostila Observabilidade & SRE.
- Um gateway na frente (LiteLLM, um proxy próprio) unifica local + nuvem sob a mesma API e centraliza logging, rate limit e roteamento (Módulo 8).
Perguntas: "Como você garante JSON válido de um modelo local?" (structured outputs / GBNF grammar no decodificador — não só pedir no prompt), "Dá para fazer RAG sem nada sair da máquina?" (sim — embeddings locais + vector store local + SLM local), "Como servir para muitos usuários concorrentes?" (vLLM com continuous batching + fila + gateway), "Que métricas você monitora num serviço de inferência?" (tokens/s, TTFT, fila, VRAM, erro).
✏️ Exercício 7 — Serviço de extração
Projete um serviço interno que recebe um documento e devolve um JSON com 10 campos, 100% on-prem, ~50 req/min. Descreva: runtime, como garantir o schema, embeddings (se usar), concorrência, e 4 métricas.
Gabarito (uma boa resposta): Runtime: vLLM numa GPU, servindo um SLM instruct de 7–14B em AWQ/Q4, com guided JSON (xgrammar/outlines) forçando o schema dos 10 campos — garante saída parseável. Prompt de sistema com o schema e 2–3 exemplos few-shot; temperature baixa (0–0.2); seed fixa para reprodutibilidade. Embeddings: só se o documento for grande e precisar de retrieval de trechos relevantes antes da extração — aí um embedding local + recorte. Concorrência: 50 req/min é tranquilo para vLLM com continuous batching; uma fila com timeout de 30s e limite de profundidade; um gateway (LiteLLM) na frente para logging e para rotear ao modelo maior/nuvem os casos que falham a validação. Métricas: TTFT e tokens/s p50/p95; taxa de JSON inválido (deve ser ~0 com grammar); taxa de campos "não encontrado" (sinal de qualidade); ocupação de VRAM e tamanho da fila; custo por documento (energia/amortização) vs a API equivalente.
Qualidade, avaliação e roteamento
Objetivo: avaliar se um SLM local basta para a sua tarefa, e desenhar arquiteturas de roteamento e cascata entre local e nuvem.
8.1 Avaliar no seu caso
- Rankings públicos (leaderboards, benchmarks) dão um sinal, mas não predizem o seu resultado — contaminação, tarefas diferentes, prompt diferente.
- Monte um eval set próprio: 50–300 exemplos representativos da sua tarefa, com a resposta esperada (ou um verificador).
- Métricas: exatidão/checagem automática onde possível (o JSON tem os campos certos? o código roda? a classificação bate?); LLM-as-judge para respostas abertas (com rubrica); custo e latência.
- Compare: SLM local (várias quantizações e tamanhos) vs o modelo de fronteira que você usaria, no mesmo eval. Ver a apostila LLMOps & Avaliação de Sistemas de IA.
8.2 "Small model + contexto" > "big model sozinho"
Um SLM raramente perde por falta de "inteligência" nas tarefas de produto — perde por falta de informação ou estrutura. Antes de subir de tamanho, tente:
- RAG — dar ao modelo os documentos certos (a maioria das "alucinações" some).
- Few-shot — 2–5 exemplos bons no prompt.
- Saída estruturada — forçar o schema tira metade dos erros de formato.
- Decompor — várias chamadas pequenas e verificáveis em vez de uma grande.
- Ferramentas — deixar o modelo calcular/consultar em vez de "lembrar".
- Fine-tune — para uma tarefa estreita e repetitiva, um SLM afinado pode superar um modelo de fronteira genérico (ver a apostila Fine-tuning e Customização de Modelos).
8.3 Padrões de roteamento
| Padrão | Como |
|---|---|
| Cascata (fallback) | tenta o modelo local; se a confiança é baixa (verificador falha, o modelo diz "não sei", o schema não valida), escala para o modelo maior/nuvem |
| Roteador por dificuldade | um classificador leve (ou heurística) decide, antes, se a requisição vai para o local ou a nuvem |
| Roteador por dado | dados sensíveis → sempre local; o resto → política de custo/qualidade |
| Especialista por tarefa | SLMs afinados diferentes por tipo de tarefa; um dispatcher escolhe |
| Draft + verify | o local gera um rascunho; o modelo grande só revisa/corrige (menos tokens caros) |
8.4 O cálculo
- Se 80% do tráfego é resolvido local com qualidade aceitável, o custo de inferência cai drasticamente e a latência média melhora — mesmo mantendo a nuvem para os 20%.
- Meça taxa de escalonamento, custo por requisição (local + nuvem), qualidade agregada e latência p50/p95 — e ajuste o limiar do roteador.
Perguntas: "Como você decide se um modelo local é bom o bastante?" (eval set próprio, no seu caso, comparado ao modelo de fronteira; leaderboards não bastam), "O que tentar antes de aumentar o modelo?" (RAG, few-shot, saída estruturada, decompor, ferramentas, fine-tune), "Como funciona um roteamento local↔nuvem?" (cascata com fallback por confiança; roteador por dificuldade/dado; medir taxa de escalonamento e custo/qualidade agregados), "O que é draft + verify?".
✏️ Exercício 8 — Desenhe o roteamento
Um produto de suporte responde perguntas de clientes. Hoje tudo vai para uma API cara. Você quer reduzir custo mantendo a qualidade. Descreva a arquitetura de roteamento, o que roda local, como decidir o fallback, e como você provaria que não piorou.
Gabarito (uma boa resposta): RAG local: embeddings locais sobre a base de conhecimento + um SLM de 7–14B quantizado, servido com vLLM. Fluxo: recuperar trechos → o SLM local gera a resposta com saída estruturada (resposta + campo confiança + usei_as_fontes booleano). Fallback para o modelo de fronteira quando: o retrieval não trouxe nada relevante (score baixo), o modelo marcou baixa confiança, a resposta não citou fonte, ou um verificador de segurança/política acusa. Roteador prévio opcional: um classificador leve manda direto para a nuvem as perguntas classificadas como "complexas/ambíguas". Prova: um eval set de ~200 perguntas reais com respostas de referência + LLM-as-judge com rubrica; rodar (i) 100% nuvem (baseline) e (ii) o roteamento, comparando qualidade agregada, e medir custo por resposta e latência p50/p95. Objetivo: qualidade dentro de uma margem pequena do baseline, custo bem menor. Monitorar em produção a taxa de escalonamento e um sample de avaliações humanas.
Produção e edge
Objetivo: dimensionar um serviço de inferência, aplicar caching, cuidar de segurança e atualização de modelos, gerir uma frota edge, e fazer o cálculo de custo on-prem vs cloud vs API.
9.1 Dimensionar o serviço
- Vazão depende de: modelo × quantização, batch size, comprimento de prompt/saída, e a GPU. Meça com carga realista (não um prompt de teste).
- Batching contínuo (vLLM) mantém a GPU ocupada intercalando requisições — a diferença entre 5 e 50 req/s.
- Paralelismo para modelos que não cabem numa GPU: tensor parallel (dividir cada camada entre GPUs) e pipeline parallel (dividir camadas) — noção; adiciona latência e complexidade.
- Autoscaling por profundidade de fila / utilização; GPUs demoram a subir — tenha capacidade base + burst.
9.2 Caching
- Prefix / prompt cache: reusar o processamento de um prefixo comum (system prompt, exemplos, documentos de RAG repetidos) entre requisições — corta o TTFT drasticamente. vLLM/SGLang fazem automático.
- Cache de resposta exato (hash do prompt) para requisições idênticas.
- Semantic cache: se um prompt novo é semanticamente igual a um já respondido (similaridade de embedding acima de um limiar), devolver a resposta cacheada — cuidado com falsos positivos.
9.3 Segurança
- O dado não vaza para um terceiro — essa é a grande vantagem. Mas:
- Prompt injection continua valendo: se o modelo local lê conteúdo não confiável (documentos, web, e-mail) e tem ferramentas, ele pode ser manipulado. Aplique o OWASP LLM Top 10 (ver a apostila Segurança de Aplicações de IA): isolar ferramentas, validar saídas, princípio do menor privilégio, human-in-the-loop para ações sensíveis.
- Proveniência do peso: baixe modelos de fontes confiáveis (o publisher oficial no Hugging Face); um GGUF é dado, não código, mas o pipeline ao redor não é — cuidado com "carregadores" e scripts de terceiros.
- Acesso ao endpoint: o servidor de inferência interno precisa de auth, rate limit e rede fechada como qualquer serviço.
9.4 Ciclo de vida do modelo
- Versione o peso exato (hash, quantização, template) — reprodutibilidade que a API não dá.
- Atualizar: novo modelo entra como candidato, roda o eval, canário/A-B com % do tráfego, rollback fácil (é só trocar o arquivo/tag).
- Registro de modelos (um bucket + metadados, ou um MLflow/registry) — ver a apostila MLOps.
9.5 Frota edge
- Muitos dispositivos rodando o modelo (celulares, PDVs, máquinas de fábrica): distribuir o peso (CDN, atualização diferencial), lidar com heterogeneidade de hardware (vários tamanhos/quantizações), telemetria mínima e com consentimento, e um fallback para servidor quando o local não dá conta.
- Considere WebNN/Prompt API/modelo do SO para não distribuir peso você mesmo, quando disponível.
9.6 Custo: on-prem × cloud GPU × API
| Opção | Quando ganha |
|---|---|
| API (nuvem) | volume baixo/variável, sem apetite operacional, precisa do modelo de topo, time-to-market |
| GPU na cloud (aluguel) | volume alto e constante, quer controle do modelo sem comprar hardware; pague pela GPU, não pelo token |
| GPU on-prem | volume muito alto e previsível por anos, requisitos de dados/latência, e há quem opere; amortiza o capital |
| On-device | o custo de inferência é do usuário; escala "de graça"; privacidade máxima; qualidade limitada pelo aparelho |
Faça a conta com tokens/mês reais: custo de API ao volume × vs (aluguel de GPU + engenharia) vs (capex + energia + engenharia). Some o valor da privacidade e do controle. Ver FinOps: Gestão Financeira de Nuvem e Otimização de Custos de Cloud e IA.
Duas alavancas mudam a economia de um serviço local: prefix caching (em RAG e agentes, 60–90% dos tokens de entrada são prefixo repetido — cacheá-lo pode dobrar a vazão) e speculative decoding (um modelo minúsculo "rascunha" vários tokens que o modelo grande verifica de uma vez — 1.5–3× mais tokens/s sem perda de qualidade). Ative os dois antes de comprar mais GPU.
Perguntas: "Como você escala um serviço de inferência local?" (continuous batching, prefix cache, speculative decoding, paralelismo se não couber, autoscaling por fila), "O modelo local elimina os riscos de segurança de IA?" (não — o dado não vaza, mas prompt injection e mau uso de ferramentas continuam; aplique o OWASP LLM Top 10), "Como você atualiza um modelo em produção?" (versionar o peso, eval, canário/A-B, rollback trocando o arquivo), "Quando on-prem vence a API?" (volume muito alto e previsível + requisitos de dados/latência + quem opere).
✏️ Exercício 9 — Faça a conta e o plano
Uma empresa gasta US$ 40 mil/mês numa API de LLM, tráfego estável, ~70% em tarefas simples e repetitivas (classificação, extração, resumo). Descreva um plano para reduzir esse custo com IA local, incluindo a análise de viabilidade e os riscos.
Gabarito (uma boa resposta): Fase 1 (análise): instrumentar o tráfego atual — quais tarefas, quantos tokens de entrada/saída, qual a distribuição. Confirmar que ~70% são tarefas estreitas. Montar eval sets por tarefa. Fase 2 (piloto): escolher 2–3 SLMs (7–14B) e testar quantizações no eval de cada tarefa; onde não bater, tentar RAG/few-shot/saída estruturada/fine-tune antes de desistir. Fase 3 (infra): um servidor com 1–2 GPUs (aluguel na cloud primeiro, para não comprar às cegas), vLLM com continuous batching + prefix cache + speculative decoding; um gateway (LiteLLM) roteando: tarefas simples → local, o resto → a API atual (cascata com fallback por confiança). Fase 4 (rollout): mover uma tarefa por vez, monitorando qualidade (eval + amostragem humana), custo por requisição e latência. Economia esperada: se 70% do tráfego sai da API, o gasto com API cai para ~US$ 12–15 mil; some ~US$ 2–5 mil/mês de GPU alugada + engenharia — economia líquida relevante, com melhor latência média e dados sensíveis contidos. Riscos: algumas tarefas "simples" podem ter caudas difíceis (o fallback cobre); manutenção e on-call novos; a qualidade precisa de monitoramento contínuo, não só o teste inicial; se o volume cair muito, o on-prem deixa de compensar (por isso começar com aluguel).
Mercado de trabalho: roadmap, entrevistas e portfólio
Objetivo: converter o conteúdo dos módulos em contratação — onde a habilidade é usada, um plano de estudo, um banco de perguntas e projetos que geram entrevista.
10.1 Onde IA local pesa
- Applied AI / AI engineer: escolher modelo, montar RAG, avaliar, rotear local↔nuvem, cortar custo.
- ML platform / inference infra: servir modelos (vLLM/TGI), GPU, caching, autoscaling, custo.
- Edge / on-device ML: modelos em mobile/navegador/IoT, quantização, otimização.
- Product engineer em produtos com requisitos de privacidade (saúde, jurídico, governo, fintech).
- Solutions / forward-deployed: implantar IA on-prem em clientes com restrição de dados.
10.2 Roadmap de estudo (5–7 semanas)
| Semanas | Foco | Prática |
|---|---|---|
| 1 | Panorama, modelos, hardware (Módulos 1–3) | Instalar Ollama; rodar 3 modelos de tamanhos diferentes; medir tokens/s e memória; ler 3 model cards |
| 2 | Quantização e runtimes (Módulos 4–5) | Comparar Q4/Q5/Q8 do mesmo modelo num eval próprio pequeno; subir um vLLM |
| 3 | On-device (Módulo 6) | Um app web com WebLLM ou transformers.js: resumo + embeddings locais |
| 4 | Servir e integrar (Módulo 7) | Um serviço de extração com saída estruturada (grammar/guided JSON) e métricas |
| 5 | Avaliação e roteamento (Módulo 8) | Construir um roteador local↔nuvem com cascata por confiança; medir custo/qualidade |
| 6 | Produção e custo (Módulo 9) | Ativar prefix cache e speculative decoding; fazer a planilha on-prem × cloud × API |
| 7 | Portfólio | Publicar os benchmarks e os estudos de caso com números |
10.3 Banco de perguntas (com a resposta que aprova)
Júnior/pleno — "Quando rodar um modelo localmente?"
Privacidade/dados sensíveis, custo em alto volume, latência baixa, offline, controle/reprodutibilidade, e especialização (um SLM afinado numa tarefa). Quase sempre como híbrido: local resolve o volume, a nuvem entra por roteamento nas tarefas difíceis ou raras.
Pleno — "Quanta memória um modelo de 8B precisa?"
Em FP16, ~16 GB; em 8-bit, ~8 GB; em 4-bit (Q4_K_M), ~5 GB — mais o KV cache do contexto, que em janelas longas pode custar vários GB, mais folga para o SO. Se não couber na VRAM, parte vai para a RAM (offload) e a velocidade cai muito.
Pleno — "O que é quantização e que nível você usa?"
Representar os pesos com menos bits (16 → 8/5/4/2), tornando o modelo 2–4× menor e mais rápido, com alguma perda. Q4_K_M (4-bit) é o padrão — perda pequena; Q8 quando sobra memória. Abaixo de 3-bit a qualidade cai muito; um modelo menor em Q4 costuma bater um maior em Q2.
Pleno/infra — "llama.cpp, Ollama ou vLLM?"
llama.cpp é o motor (CPU+GPU, GGUF), ótimo para embutir e edge. Ollama é uma camada de conveniência sobre ele, ótima para dev local. vLLM é para produção com concorrência: continuous batching, PagedAttention e prefix caching dão muito mais throughput sob carga. Todos expõem API compatível com OpenAI.
Pleno — "Como garantir JSON válido de um modelo local?"
Structured outputs no decodificador: uma gramática (GBNF no llama.cpp; outlines/xgrammar no vLLM) que só permite tokens que mantêm o JSON/schema válido. Muito mais confiável que pedir JSON no prompt. Também impõe enums, regex e listas.
Sénior — "Como você decide se um SLM local é bom o suficiente?"
Não por leaderboard — por um eval set próprio (50–300 exemplos da tarefa real) com verificação automática onde dá e LLM-as-judge para o resto, comparando o SLM (várias quantizações) com o modelo de fronteira no mesmo eval. E, antes de subir de tamanho, tento RAG, few-shot, saída estruturada, decomposição, ferramentas e fine-tune.
Sénior — "Desenhe um roteamento local↔nuvem."
Cascata: tenta o local; escala para a nuvem quando um verificador falha, a confiança é baixa, o schema não valida, ou o retrieval veio vazio. Opcionalmente um roteador prévio (classificador leve) por dificuldade, e regra por dado (sensível → sempre local). Um gateway unifica os dois sob a mesma API. Medir taxa de escalonamento, custo por requisição e qualidade/latência agregadas; ajustar o limiar.
Armadilha — "É local, então não tem risco de segurança"
O dado não vai para um terceiro — essa parte melhora. Mas prompt injection, exfiltração via ferramentas e mau uso continuam iguais se o modelo lê conteúdo não confiável e tem capacidade de agir. Aplica-se o OWASP LLM Top 10: isolar ferramentas, validar saídas, menor privilégio, human-in-the-loop para ações sensíveis, e proteger/autenticar o endpoint de inferência.
10.4 Projetos de portfólio que geram entrevista
- Benchmark comparativo (âncora): 3–4 modelos × 3 quantizações num eval próprio de uma tarefa real, com tabela de acurácia, tokens/s, memória e "custo por 1k requisições" — e a recomendação.
- Serviço de inferência: um vLLM com API compatível, saída estruturada, prefix cache, métricas (Grafana) e um teste de carga documentado.
- App com IA on-device: uma página com WebLLM/transformers.js que faz resumo + busca semântica local, com estratégia de download/cache e fallback.
- Roteador local↔nuvem: um gateway com cascata por confiança, medindo custo e qualidade antes/depois num caso real.
- RAG 100% local: embeddings locais + vector store local + SLM local, com um eval de fidelidade — "nada sai da máquina".
10.5 Fontes para continuar
- Docs: llama.cpp, Ollama, vLLM, SGLang, TGI, MLX / MLX-LM, transformers.js, WebLLM / MLC LLM, ExecuTorch, Core ML.
- Modelos e comunidade: Hugging Face (model cards, o Hub, os leaderboards), r/LocalLLaMA, os blogs das foundries (Meta, Qwen, Mistral, Google/Gemma, Microsoft/Phi).
- Conceito: os papers e posts sobre quantização (GPTQ, AWQ, k-quants, imatrix), PagedAttention (vLLM), speculative decoding; o blog do Simon Willison sobre LLMs locais; os guias de "LLM inference" da própria HF.
- Nesta trilha: Engenharia de LLMs, IA Generativa & RAG, LLMOps & Avaliação de Sistemas de IA, Fine-tuning e Customização de Modelos, Segurança de Aplicações de IA (OWASP LLM Top 10), Criação de Agentes de IA, MCP, MLOps, FinOps, Otimização de Custos de Cloud e IA, Observabilidade & SRE.
Cinco ideias sustentam IA local: (1) o motivo é privacidade, custo, latência, offline e controle — e a arquitetura vencedora é híbrida, com roteamento; (2) VRAM é o gargalo e quantização (Q4_K_M como padrão) é o que faz caber; (3) Ollama para dev, vLLM para produção, todos com API compatível com OpenAI — trocar de provedor é mudar a base_url; (4) um SLM + RAG + saída estruturada + fine-tune resolve a maior parte das tarefas de produto — avalie no seu caso, não no leaderboard; (5) em produção, prefix cache e speculative decoding antes de comprar GPU, e o OWASP LLM Top 10 continua valendo.