Ollama: Fundamentos da API REST

A API REST é a interface universal do Ollama — qualquer linguagem, qualquer framework, basta enviar uma requisição HTTP e você está conectado.

⚠️ Nota: A API REST do Ollama não possui autenticação embutida — qualquer pessoa que possa acessar a porta do serviço pode chamar Modelos livremente e ver listas de Modelos instalados. Em produção, você deve adicionar autenticação por API Key via um proxy reverso (como Nginx/Caddy), caso contrário seu serviço de IA corre riscos de abuso, vazamento de dados e esgotamento de recursos.

📋 Pré-requisitos: Você precisa dominar o seguinte primeiro

1. O Que Você Vai Aprender


2. Uma História Real de Uma Fundadora de SaaS

(1) O Problema: Respostas Manuais São Ineficientes

Alice fundou a plataforma de e-commerce GlobalShop. Sua equipe de 50 agentes de atendimento lida com mais de 2.000 tickets diariamente. Cada ticket leva em média 8 minutos, e o tempo de espera dos clientes excede 30 minutos. Ela precisa integrar um LLM no sistema de atendimento via API para rascunhos de respostas automáticas.

(2) A Solução: API REST Gera Respostas Instantaneamente

Usando curl para chamar a API do Ollama, rascunhos de respostas ao cliente são gerados em 3 segundos — agentes apenas precisam revisar e confirmar:

BASH
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5",
  "messages": [{"role": "user", "content": "Refund for order #12345"}]
}'

⚠️ Aviso: A API do Ollama não possui autenticação embutida — qualquer pessoa que possa acessar a porta pode chamá-la. Em produção, você deve adicionar autenticação por API Key via proxy reverso (Nginx/Caddy). Veja a Aula 20 para endurecimento de segurança.

💡 Dica: API streaming (stream: true) é adequada para interfaces de chat com efeito de digitação em tempo real; não-streaming (stream: false) é melhor para processamento em lote e integração de back-end de API. Não-streaming é recomendado para integração de API por ser mais simples.

ℹ️ Info: O Ollama usa por padrão http://127.0.0.1:11434, acessível apenas a partir da máquina local. Para acesso LAN, defina a variável de ambiente OLLAMA_HOST, mas esteja ciente dos riscos de segurança.

3. Guia Completo dos Endpoints da API

(1) Comparação dos Dois Endpoints Centrais

Dimensão /api/generate /api/chat
Finalidade Geração de texto single-shot Diálogo de múltiplas rodadas
Entrada model + prompt Array messages
Contexto Requisição única Suporta histórico de conversa
Mapeamento de API CLI ollama run CLI ollama chat
Caso de uso Geração, complemento, tradução Atendimento ao cliente, assistentes, raciocínio de múltiplas rodadas
100%
sequenceDiagram
    participant C as Cliente
    participant O as Servidor Ollama
    C->>O: POST /api/chat {messages, model, stream}
    O-->>C: NDJSON {message, done: false}
    O-->>C: NDJSON {message, done: false}
    O-->>C: NDJSON {message, done: true, stats}

(2) Parâmetros Comuns de Requisição

Parâmetro Tipo Padrão Descrição
model string Obrigatório Nome do Modelo
stream bool true Se a saída é streaming
options object Parâmetros de Inferência (veja próxima seção)
format string Formato de saída: json
keep_alive string 5m Tempo de retenção do Modelo na memória

▶ Exemplo 1: Requisição de Geração Single-shot

BASH
# Non-streaming generate request
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "Write a haiku about coding",
  "stream": false
}'

# Response (abbreviated)
# {
#   "model": "llama3.2",
#   "response": "Lines of logic flow,\nBug hides in the deep syntax—\nSemicolon found.",
#   "done": true,
#   "total_duration": 2500000000,
#   "eval_count": 18
# }

Saída:

TEXT
{"status":"ok","data":{}}

▶ Exemplo 2: Requisição de Diálogo de Múltiplas Rodadas

BASH
# Chat with message history
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5",
  "messages": [
    {"role": "system", "content": "You are a helpful customer service agent."},
    {"role": "user", "content": "I want to return my order #12345"},
    {"role": "assistant", "content": "I can help with that. May I ask the reason for the return?"},
    {"role": "user", "content": "The product arrived damaged"}
  ],
  "stream": false
}'

Saída:

TEXT
{"status":"ok","data":{}}

4. Parsing de Resposta Streaming

💡 Dica: Streaming (stream: true) e não-streaming (stream: false) cada um tem seus casos de uso: streaming é para efeitos de digitação em tempo real em interfaces de chat para que os usuários vejam conteúdo sem esperar a resposta completa; não-streaming é para processamento em lote e integração de back-end de API onde obter a resposta JSON completa é mais fácil para parsing programático. Recomendamos começar com não-streaming para validar a lógica, depois mudar para streaming para otimizar a UX.

(1) Formato NDJSON Explicado

Respostas streaming usam NDJSON (Newline Delimited JSON), com um objeto JSON por linha:

TEXT
{"model":"llama3.2","message":{"role":"assistant","content":"I"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":" can"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":" help"},"done":false}
{"model":"llama3.2","message":{"role":"assistant","content":""},"done":true,"total_duration":1500000000}
Campo Descrição
message.content Fragmento de texto deste chunk
done Se este é o último chunk
total_duration Tempo total de Inferência (nanosegundos)
eval_count Contagem de tokens gerados
prompt_eval_count Contagem de tokens de entrada

(2) Comparação Streaming vs Não-streaming

Dimensão Streaming (stream: true) Não-streaming (stream: false)
Experiência do usuário Saída caractere por caractere em tempo real Espera pela resposta completa
Latência do primeiro token Muito baixa (~200ms) Espera até toda geração completar
Complexidade de implementação Requer parsing NDJSON Lê JSON diretamente
Caso de uso Interfaces de chat, exibição em tempo real Processamento em lote, back-ends de API

▶ Exemplo 3: Parsing de Respostas Streaming

BASH
# Streaming request with real-time output
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [{"role": "user", "content": "Hello!"}],
  "stream": true
}' | while read -r line; do
    # Extract content field from each NDJSON line
    echo "$line" | python3 -c "
import sys, json
data = json.load(sys.stdin)
if data.get('message', {}).get('content'):
    print(data['message']['content'], end='', flush=True)
"
done

Saída:

TEXT
{"status":"ok","data":{}}

5. Ajuste de Parâmetros de Inferência

(1) Tabela de Parâmetros Centrais

Parâmetro Tipo Faixa Padrão Efeito
temperature float 0-2 0.8 Controla aleatoriedade; valores mais baixos são mais determinísticos
top_p float 0-1 0.9 Amostragem por núcleo, limita faixa de tokens candidatos
top_k int 1-100 40 Amostra apenas dos top-K candidatos
num_ctx int 128-131072 2048 Tamanho da janela de contexto
repeat_penalty float 1-2 1.1 Coeficiente de penalização por repetição
seed int Qualquer -1 Semente aleatória (-1 = aleatório)

(2) Ajuste de Parâmetros por Cenário

Cenário temperature top_p Observações
Geração de código 0.1-0.3 0.9 Requer determinismo e precisão
Respostas de atendimento 0.3-0.5 0.9 Estável mas permite variação moderada
Escrita criativa 0.7-1.0 0.95 Requer diversidade e criatividade
Análise de dados 0.1-0.2 0.9 Deve ser preciso, Alucinação não permitida
⚠️ Aviso: num_ctx afeta diretamente o uso de memória. Um Modelo 8B com num_ctx=8192 precisa de aproximadamente 6GB VRAM; num_ctx=32768 precisa de aproximadamente 12GB VRAM. Defina conforme necessário — não aumente cegamente.

▶ Exemplo 4: Comparação de Ajuste de Parâmetros

BASH
# Low temperature: deterministic output
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "What is 2+2?",
  "stream": false,
  "options": {"temperature": 0.1}
}'
# Response: "2+2 equals 4."

# High temperature: creative output
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt": "What is 2+2?",
  "stream": false,
  "options": {"temperature": 1.5}
}'
# Response: "In the realm of mathematics, 2+2 opens the door to 4..."

Saída:

TEXT
{"status":"ok","data":{}}

▶ Exemplo 5: Saída em Formato JSON

BASH
# Force JSON output format
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.2",
  "messages": [
    {"role": "system", "content": "You are a product catalog API. Return JSON only."},
    {"role": "user", "content": "List 3 laptops under $500"}
  ],
  "format": "json",
  "stream": false,
  "options": {"temperature": 0.3}
}'

# Response is valid JSON
# {"products":[{"name":"Acer Aspire 5","price":449,"spec":"8GB RAM, 256GB SSD"},...]}

Saída:

TEXT
{"status":"ok","data":{}}

6. Exemplo Abrangente: Protótipo de API do SupportBot de Atendimento ao Cliente

💡 Dica: Ao chamar a API em produção, certifique-se de definir o parâmetro keep_alive (por exemplo, "keep_alive": "5m") para evitar carregamento/descarregamento frequente do Modelo que causa atrasos na resposta.

BASH
#!/bin/bash
# ============================================
# Comprehensive: SupportBot API prototype
# Multi-turn customer service via REST API
# ============================================

API="http://localhost:11434/api/chat"
MODEL="qwen2.5"

# Function: Send a chat message and extract response
chat() {
    local system_prompt="$1"
    local user_msg="$2"
    local temp="${3:-0.4}"

    curl -s "$API" -d "$(cat <<EOF
{
  "model": "$MODEL",
  "messages": [
    {"role": "system", "content": "$system_prompt"},
    {"role": "user", "content": "$user_msg"}
  ],
  "stream": false,
  "options": {"temperature": $temp, "num_ctx": 4096}
}
EOF
)" | python3 -c "import sys,json; print(json.load(sys.stdin)['message']['content'])"
}

# Customer service system prompt
SYSTEM="You are SupportBot, a customer service agent for an e-commerce store. Be polite, concise, and helpful. If you cannot answer, say 'Let me connect you with a human agent.'"

# Simulate customer interactions
echo "=== Query 1: Order Status ==="
chat "$SYSTEM" "Where is my order #88765? It has been 5 days."

echo ""
echo "=== Query 2: Return Request ==="
chat "$SYSTEM" "I received a damaged item. Order #12345. I want a refund."

echo ""
echo "=== Query 3: Product Question ==="
chat "$SYSTEM" "Does the wireless headphone support Bluetooth 5.3?"

echo ""
echo "=== Benchmark ==="
time chat "$SYSTEM" "Hello" > /dev/null
💻 Saída:

TEXT
=== Query 1: Order Status ===
I'd be happy to check on your order #88765. Based on our tracking system, your order is currently in transit and expected to arrive within 2-3 business days. You can track it at track.example.com/88765.

=== Query 2: Return Request ===
I'm sorry to hear about the damaged item. For order #12345, I've initiated a return request. You'll receive a prepaid shipping label via email within 24 hours. Once we receive the item, a full refund will be processed within 3-5 business days.

=== Query 3: Product Question ===
Yes, our wireless headphones support Bluetooth 5.3 with a range of up to 15 meters. They also feature active noise cancellation and 30-hour battery life.

❓ Perguntas Frequentes

P: Por que minha requisição curl retorna connection refused? R: O serviço Ollama não está rodando. Execute ollama serve ou verifique se o serviço systemd está iniciado: sudo systemctl status ollama.

P: Devo escolher stream: true ou stream: false? R: Use stream: true para interfaces de chat front-end para obter efeito de digitação em tempo real. Use stream: false para processamento em lote no back-end para obter respostas completas diretamente. Não-streaming é recomendado para integração de API por ser mais simples.

P: Como limito o comprimento da saída? R: Defina o parâmetro num_predict, por exemplo, "num_predict": 200 para limitar a geração a 200 tokens. Note que isso é contagem de tokens, não caracteres.

P: format: json garante saída JSON válida? R: Funciona na maioria dos casos, mas não é 100% garantido. Recomendamos adicionar validação JSON na camada da aplicação, com retry ou fallback para processamento de texto em caso de falha de parsing.

P: Como o diálogo de múltiplas rodadas mantém o contexto? R: O cliente deve manter o array messages por conta própria, enviando o histórico completo de conversa com cada requisição. O servidor Ollama não armazena estado de sessão.

P: Há limites de concorrência nas chamadas de API? R: Por padrão, apenas uma requisição é processada por vez. Defina a variável de ambiente OLLAMA_NUM_PARALLEL para aumentar a concorrência, mas isso requer mais VRAM. Veja a Aula 19 para ajuste de desempenho.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Use curl para chamar /api/generate para gerar uma descrição de produto, experimente stream: true e stream: false para observar a diferença.
  2. Intermediário (Dificuldade ⭐⭐): Use /api/chat para implementar um diálogo de 3 rodadas, mantendo manualmente o array messages, exibindo a resposta completa a cada rodada.
  3. Avançado (Dificuldade ⭐⭐⭐): Escreva um script Shell que simule um fluxo de atendimento SupportBot — recebe perguntas, chama a API, retorna resultados de classificação (intenção + resposta) em formato JSON, suportando saída streaming em tempo real.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%