DEV Community

Cover image for Como Usar LLMs Locais como APIs: Guia Completo
Lucas
Lucas

Posted on • Originally published at apidog.com

Como Usar LLMs Locais como APIs: Guia Completo

Seu laptop pode servir um modelo de 70 bilhões de parâmetros atrás do mesmo endpoint no formato OpenAI usado em produção. Na prática, você troca apenas a URL base e mantém o mesmo SDK, payload e fluxo de testes. Isso permite desenvolvimento offline, custo zero por token em ambiente local e um caminho mais privado para dados sensíveis. Este guia mostra como escolher um runtime, expor um endpoint compatível com OpenAI, apontar seu cliente para ele e validar tudo com Apidog antes de promover alterações para um modelo hospedado.

Experimente o Apidog hoje

TL;DR

Você pode executar uma API LLM local com Ollama, vLLM ou llama.cpp. Todos conseguem expor um endpoint REST compatível com OpenAI.

O padrão é simples:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)
Enter fullscreen mode Exit fullscreen mode

Com essa troca, o mesmo código que chama https://api.openai.com/v1 pode chamar Llama 3.3, DeepSeek V4 ou Qwen 3.6 localmente. Use ambientes no Apidog para manter os mesmos testes de cenário contra targets locais e hospedados.

Introdução

A pilha de API LLM local deixou de ser apenas experimento. Hoje, os principais runtimes conseguem expor endpoints no formato /v1/chat/completions, compatível com OpenAI. Isso muda a implementação: você não precisa manter dois clientes, dois contratos ou dois fluxos de autenticação.

Para desenvolvedores de API, o ganho está na substituição de configuração, não na reescrita de código.

Exemplo de variável de ambiente:

# local
LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama

# produção
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=$OPENAI_API_KEY
Enter fullscreen mode Exit fullscreen mode

Se seus modelos de requisição no Apidog hoje apontam para https://api.openai.com/v1/chat/completions, substitua o host por {{BASE_URL}}. Depois, execute o mesmo cenário contra Local e Production.

Se você já rastreia gastos com API por recurso, também pode comparar custo, latência e qualidade entre um modelo local e um hospedado.

Este guia cobre:

  • escolha do runtime;
  • configuração do servidor local;
  • conexão via SDK OpenAI;
  • testes de cenário com Apidog;
  • trade-offs de quantização;
  • comparação de custo e latência.

Para uma visão geral de modelos, consulte Melhores LLMs locais 2026.

Por que LLMs locais fazem sentido para desenvolvedores de API

Você provavelmente depura código que chama LLMs em ambientes imperfeitos: avião, conferência com Wi-Fi ruim, rede corporativa bloqueando saída para *.openai.com ou infraestrutura de cliente sem acesso público. Uma API LLM local resolve esse problema porque espelha o contrato de produção sem depender de rede externa.

Os principais motivos são:

  1. Desenvolvimento offline
    Você mantém o ciclo de build, teste e depuração mesmo sem conexão.

  2. Privacidade
    Prompts podem conter dados regulados: notas clínicas, contratos, identificadores, números de conta ou dados internos. Rodar localmente evita enviar esse conteúdo para um endpoint externo durante desenvolvimento.

  3. Custo
    Testes, fixtures, geração de dados e pipelines internos podem consumir milhões de tokens. Localmente, o custo marginal por token tende a zero depois que o hardware está disponível.

  4. Estabilidade
    Um modelo local é um arquivo em disco. Você controla quando atualizar pesos, tags e quantização. Isso ajuda em suítes de regressão que dependem de comportamento estável.

A parte importante: como o endpoint é compatível com OpenAI, o SDK que você já usa continua funcionando.

Três runtimes que entregam endpoints compatíveis com OpenAI

Quatro runtimes dominam o espaço local. Três entregam servidor REST compatível com OpenAI diretamente; o llama.cpp entrega isso via llama-server.

Escolha pela carga de trabalho:

  • Ollama: melhor ponto de entrada para laptop e desenvolvimento individual.
  • vLLM: melhor para throughput e clusters de desenvolvimento.
  • llama.cpp: melhor para controle fino, quantização e hardware variado.
  • LM Studio/Jan: úteis para times que preferem GUI, normalmente usando llama.cpp por baixo.

Ollama

Ollama é o caminho mais rápido para subir uma API LLM local. Ele baixa modelos, gerencia quantização GGUF, aplica templates de prompt e expõe HTTP na porta 11434.

Instalação no macOS:

brew install ollama
ollama serve &
ollama pull llama3.3:70b-instruct-q4_K_M
ollama run llama3.3:70b-instruct-q4_K_M
Enter fullscreen mode Exit fullscreen mode

Endpoint compatível com OpenAI:

http://localhost:11434/v1
Enter fullscreen mode Exit fullscreen mode

Teste rápido com curl:

curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ollama" \
  -d '{
    "model": "llama3.3:70b-instruct-q4_K_M",
    "messages": [
      { "role": "user", "content": "Responda apenas OK." }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

Use Ollama quando você precisa de:

  • setup rápido;
  • desenvolvimento local;
  • demos;
  • runners de CI simples;
  • testes de contrato sem custo por token.

vLLM

vLLM é voltado para throughput. Ele usa PagedAttention e batching contínuo para servir muitas requisições concorrentes com maior eficiência.

Instalação e servidor:

pip install vllm

vllm serve meta-llama/Llama-3.3-70B-Instruct \
  --port 8000 \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192
Enter fullscreen mode Exit fullscreen mode

Endpoint:

http://localhost:8000/v1
Enter fullscreen mode Exit fullscreen mode

Se quiser exigir autenticação:

vllm serve meta-llama/Llama-3.3-70B-Instruct \
  --port 8000 \
  --api-key dev-secret
Enter fullscreen mode Exit fullscreen mode

Cliente:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="dev-secret",
)
Enter fullscreen mode Exit fullscreen mode

Use vLLM quando você precisa de:

  • concorrência;
  • batching;
  • GPU CUDA ou ROCm;
  • ambiente compartilhado para vários devs;
  • testes mais próximos de produção.

Ele não é a melhor opção para Apple Silicon.

llama.cpp

llama.cpp é o runtime C++ que popularizou o ecossistema GGUF. Ele roda em muitos tipos de hardware e oferece controle detalhado de quantização, offload para GPU, contexto e uso de memória.

Build com Metal no macOS:

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j LLAMA_METAL=1
Enter fullscreen mode Exit fullscreen mode

Servidor compatível com OpenAI:

./llama-server \
  -m models/llama-3.3-70b-q4_k_m.gguf \
  --port 8080 \
  --host 0.0.0.0 \
  -c 8192 \
  -ngl 99
Enter fullscreen mode Exit fullscreen mode

Endpoint:

http://localhost:8080/v1/chat/completions
Enter fullscreen mode Exit fullscreen mode

A flag -ngl 99 tenta descarregar o máximo de camadas possível para a GPU.

Use llama.cpp quando você precisa de:

  • rodar em hardware limitado;
  • controlar quantização;
  • ajustar memória e contexto;
  • testar modelos GGUF específicos;
  • evitar dependências pesadas.

LM Studio e Jan encapsulam o llama.cpp em uma interface gráfica e também podem expor endpoints compatíveis com OpenAI em portas configuráveis.

Verifique o endpoint com Python

Depois de subir o runtime, valide o contrato usando o SDK OpenAI.

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)

resp = client.chat.completions.create(
    model="llama3.3:70b-instruct-q4_K_M",
    messages=[
        {
            "role": "user",
            "content": "Reply with the word OK only."
        }
    ],
)

print(resp.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Se a saída for OK, você validou:

  • runtime ativo;
  • porta correta;
  • contrato compatível com OpenAI;
  • SDK funcionando;
  • modelo carregado.

Teste sua LLM local com Apidog

Uma API LLM local só é útil se seus testes conseguirem alternar entre local e produção sem duplicar cenários. No Apidog, faça isso com variáveis de ambiente.

1. Crie o ambiente local

No Apidog, crie um ambiente chamado Local.

Adicione:

BASE_URL=http://localhost:11434/v1
API_KEY=ollama
MODEL=llama3.3:70b-instruct-q4_K_M
Enter fullscreen mode Exit fullscreen mode

2. Crie o ambiente de produção

Clone seu ambiente existente ou crie um novo chamado Production.

Use:

BASE_URL=https://api.openai.com/v1
API_KEY=<sua-chave>
MODEL=<modelo-hospedado>
Enter fullscreen mode Exit fullscreen mode

3. Parametrize a requisição

Configure a URL:

{{BASE_URL}}/chat/completions
Enter fullscreen mode Exit fullscreen mode

Headers:

Authorization: Bearer {{API_KEY}}
Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode

Body:

{
  "model": "{{MODEL}}",
  "messages": [
    {
      "role": "system",
      "content": "Você é um assistente que responde em JSON."
    },
    {
      "role": "user",
      "content": "Retorne {\"status\":\"ok\"}."
    }
  ],
  "temperature": 0.2
}
Enter fullscreen mode Exit fullscreen mode

4. Adicione asserções

Crie um cenário com verificações como:

choices[0].message.role == "assistant"
choices[0].message.content is not empty
usage.total_tokens > 0
Enter fullscreen mode Exit fullscreen mode

Essas asserções validam o contrato mínimo da resposta.

5. Execute contra Local e Production

Rode o cenário com o ambiente Local.

Depois, troque para Production e rode novamente.

O objetivo é manter o mesmo cenário verde nos dois destinos. Se uma atualização de runtime, modelo ou provedor mudar o formato da resposta, você detecta antes de quebrar a aplicação.

O mesmo padrão se aplica a testar agentes de IA que chamam APIs multi-etapas.

Alterne targets no SDK OpenAI

Use variáveis de ambiente para evitar URLs hardcoded.

Python

import os
from openai import OpenAI

def get_client():
    return OpenAI(
        base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1"),
        api_key=os.environ["LLM_API_KEY"],
    )

client = get_client()

response = client.chat.completions.create(
    model=os.environ.get("LLM_MODEL", "llama3.3:70b-instruct-q4_K_M"),
    messages=[
        {
            "role": "system",
            "content": "You are a JSON-only assistant."
        },
        {
            "role": "user",
            "content": "Return {\"status\": \"ok\"}."
        },
    ],
    response_format={"type": "json_object"},
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Execução local:

export LLM_BASE_URL=http://localhost:11434/v1
export LLM_API_KEY=ollama
export LLM_MODEL=llama3.3:70b-instruct-q4_K_M

python app.py
Enter fullscreen mode Exit fullscreen mode

Execução em produção:

export LLM_BASE_URL=https://api.openai.com/v1
export LLM_API_KEY=$OPENAI_API_KEY
export LLM_MODEL=<modelo-hospedado>

python app.py
Enter fullscreen mode Exit fullscreen mode

JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: process.env.LLM_BASE_URL || "https://api.openai.com/v1",
  apiKey: process.env.LLM_API_KEY,
});

const resp = await client.chat.completions.create({
  model: process.env.LLM_MODEL || "llama3.3:70b-instruct-q4_K_M",
  messages: [
    {
      role: "user",
      content: "Say hi."
    }
  ],
});

console.log(resp.choices[0].message.content);
Enter fullscreen mode Exit fullscreen mode

Execução local:

LLM_BASE_URL=http://localhost:11434/v1 \
LLM_API_KEY=ollama \
LLM_MODEL=llama3.3:70b-instruct-q4_K_M \
node app.js
Enter fullscreen mode Exit fullscreen mode

Integre os testes ao CI

Depois que o cenário está funcionando no Apidog, você pode usá-lo como smoke test no CI.

Fluxo recomendado:

  1. Suba o runtime local no job ou use um host interno.
  2. Exporte as variáveis do ambiente.
  3. Execute a coleção com apidog-cli.
  4. Falhe o build se uma asserção quebrar.

Exemplo conceitual no GitHub Actions:

name: llm-contract-tests

on:
  pull_request:

jobs:
  test-local-llm:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Start Ollama
        run: |
          curl -fsSL https://ollama.com/install.sh | sh
          ollama serve &
          sleep 5
          ollama pull llama3.3:70b-instruct-q4_K_M

      - name: Run Apidog scenarios
        run: |
          apidog run ./apidog-collection.json \
            --env Local
Enter fullscreen mode Exit fullscreen mode

Engenheiros de QA podem integrar o mesmo padrão em pipelines de teste de API.

Técnicas avançadas e dicas profissionais

Escolha a quantização certa

Quantização decide se um modelo cabe no seu hardware.

Formatos GGUF comuns:

Quantização Quando usar
Q8 Melhor qualidade, maior uso de RAM/VRAM
Q5_K_M Bom equilíbrio quando há memória suficiente
Q4_K_M Padrão prático para chat local
Q3/Q2 Útil para memória restrita, com perda visível de qualidade

Regra prática:

  • use Q4_K_M para chat e desenvolvimento geral;
  • use Q5_K_M se tiver folga de memória;
  • use Q8 para geração de código ou tarefas mais sensíveis à qualidade;
  • evite Q2 para raciocínio complexo ou contexto longo.

Ajuste offload para GPU

No llama.cpp, use -ngl:

./llama-server -m model.gguf -ngl 99
Enter fullscreen mode Exit fullscreen mode

No Ollama, controle via configuração do modelo quando necessário.

Quanto mais camadas na GPU, maior o throughput. Se a VRAM acabar, reduza o número de camadas ou use uma quantização menor.

Mantenha mmap ativado

O mapeamento de memória (mmap) permite que o sistema operacional carregue pesos sob demanda. Em geral, mantenha ativado.

Só considere desativar se você tem um motivo específico, como isolamento em contêiner com limites rígidos de memória.

Use batching no vLLM

O vLLM ganha eficiência com concorrência.

Exemplo:

vllm serve meta-llama/Llama-3.3-70B-Instruct \
  --max-num-seqs 64
Enter fullscreen mode Exit fullscreen mode

Para hardware maior, como H100, aumente:

vllm serve meta-llama/Llama-3.3-70B-Instruct \
  --max-num-seqs 256
Enter fullscreen mode Exit fullscreen mode

Ative streaming

Streaming reduz a latência percebida.

Python:

stream = client.chat.completions.create(
    model="llama3.3:70b-instruct-q4_K_M",
    messages=[{"role": "user", "content": "Explique streaming em uma frase."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="")
Enter fullscreen mode Exit fullscreen mode

JavaScript:

const stream = await client.chat.completions.create({
  model: process.env.LLM_MODEL,
  messages: [{ role: "user", content: "Explique streaming em uma frase." }],
  stream: true,
});

for await (const chunk of stream) {
  const token = chunk.choices[0]?.delta?.content;
  if (token) process.stdout.write(token);
}
Enter fullscreen mode Exit fullscreen mode

Use Modelfile no Ollama

O Modelfile permite encapsular prompt de sistema, temperatura e sequências de parada.

Exemplo:

FROM llama3.3:70b-instruct-q4_K_M

SYSTEM """
Você é um assistente que responde sempre em JSON válido.
"""

PARAMETER temperature 0.2
PARAMETER stop "</json>"
Enter fullscreen mode Exit fullscreen mode

Crie o modelo:

ollama create my-assistant -f Modelfile
Enter fullscreen mode Exit fullscreen mode

Use no cliente:

response = client.chat.completions.create(
    model="my-assistant",
    messages=[{"role": "user", "content": "Retorne status ok."}],
)
Enter fullscreen mode Exit fullscreen mode

Erros comuns

Evite estes problemas:

  • hardcodar http://localhost:11434 no código de produção;
  • esquecer de configurar max_tokens;
  • não definir sequência de parada em fluxos longos;
  • rodar dois runtimes na mesma porta;
  • ignorar Authorization, já que Ollama pode aceitar, mas vLLM com --api-key rejeita;
  • esperar qualidade de modelo hospedado premium em um modelo local pequeno e quantizado;
  • mudar pesos ou quantização sem rodar os testes de cenário;
  • comparar latência local e hospedada sem medir TTFT e throughput separadamente.

Local vs. hospedado: custo e latência

Os números abaixo assumem um M3 Max com 128 GB de memória unificada para uso local e preços públicos atuais para endpoints hospedados. O Tempo para o Primeiro Token, ou TTFT, é medido a frio, sem batching, em um prompt de 1.024 tokens.

Modelo TTFT Local Throughput Local Equivalente Hospedado Preço Hospedado TTFT Hospedado
Llama 3.3 70B Q4_K_M 1.2 s 12 tok/s GPT-5.5 Instant $5 / $30 per 1M 200 ms
DeepSeek V4 67B Q4_K_M 1.4 s 10 tok/s DeepSeek-Chat hospedado $0.55 / $2.20 per 1M 280 ms
Qwen 3.6 32B Q5_K_M 0.7 s 28 tok/s Qwen-Max hospedado $1.60 / $6.40 per 1M 240 ms
Gemma 4 27B Q4_K_M 0.5 s 35 tok/s Gemini 3 Flash $0.35 / $1.05 per 1M 180 ms

A coluna hospedada tende a vencer em latência. A coluna local vence em custo quando o volume diário de tokens é alto e vence em privacidade desde a primeira requisição.

Um padrão prático:

  • use local durante desenvolvimento interno;
  • use hospedado em staging para validar integração real;
  • mantenha ambos os targets verdes no CI;
  • escolha o target de produção com base em latência, custo e classificação de dados.

Para benchmarks e guias específicos, consulte Como executar o DeepSeek V4 localmente e o guia de uso original do DeepSeek V4.

Casos de uso no mundo real

Fintech com dados sensíveis

Uma equipe de conformidade em Singapura usa Ollama nos laptops dos engenheiros para redigir relatórios de atividades suspeitas. Os prompts contêm números de conta e padrões de transação que não podem sair do país sob regras locais.

Implementação prática:

  • endpoint local recebe o prompt completo;
  • endpoint hospedado recebe apenas uma versão redigida;
  • cenário no Apidog verifica se a etapa de redação roda antes de qualquer chamada externa.

Estúdio de jogos

Um estúdio em Estocolmo usa uma instância local do Qwen 3.6 para treinar designers em engenharia de prompt.

Benefícios:

  • sem custo por token durante treinamento;
  • uso offline;
  • menor risco de vazamento de narrativa ou assets;
  • mesma coleção de testes usada depois contra Gemini 3 Flash em produção.

Eles podem reutilizar o guia da API Gemini 3 Flash para conectar o target hospedado.

Saúde com vLLM em rede privada

Uma startup de saúde executa vLLM em uma A100 dentro da rede hospitalar do cliente. O endpoint não tem DNS público.

Arquitetura:

  • vLLM roda em VLAN interna;
  • Jenkins executa testes de integração na mesma rede;
  • aplicação usa o mesmo SDK OpenAI;
  • ambientes locais, internos e hospedados usam o mesmo contrato.

Checklist de implementação

Use esta sequência para colocar uma API LLM local no seu fluxo:

  1. Escolha o runtime:

    • Ollama para laptop;
    • vLLM para concorrência;
    • llama.cpp para controle de memória.
  2. Suba o servidor:

    • Ollama: http://localhost:11434/v1;
    • vLLM: http://localhost:8000/v1;
    • llama.cpp: http://localhost:8080/v1.
  3. Valide com curl ou SDK OpenAI.

  4. Mova base_url, api_key e model para variáveis de ambiente.

  5. Configure ambientes no Apidog:

    • Local;
    • Production.
  6. Crie asserções mínimas:

    • role do assistant;
    • conteúdo não vazio;
    • tokens usados;
    • status HTTP 200.
  7. Rode os mesmos cenários contra os dois ambientes.

  8. Integre ao CI.

Conclusão

A pilha de API LLM local amadureceu o suficiente para entrar no fluxo normal de desenvolvimento. Você pode mover prompts entre um endpoint hospedado e um endpoint local sem reescrever cliente, testes ou CI.

Resumo operacional:

  • use Ollama para começar rápido;
  • use vLLM quando precisar de throughput;
  • use llama.cpp quando memória e quantização forem críticas;
  • exponha um endpoint compatível com OpenAI;
  • configure base_url e api_key por ambiente;
  • valide tudo com cenários no Apidog.

Para escolher um modelo, comece com Melhores LLMs locais 2026. Para testar fluxos agentic sobre esses endpoints, leia Como testar a API de agentes de IA.

Top comments (0)