Chamadas à API do Ollama: do curl à interface compatível com o SDK da OpenAI

Aquele comando curl no terminal retornou um JSON com apenas metade de uma palavra. Depois de duas horas tentando entender o problema, descobri que a causa era a resposta em streaming. Por padrão, o Ollama entrega o conteúdo aos poucos, como um fluxo contínuo, e cada objeto JSON contém apenas alguns caracteres.
Para executar LLMs localmente, o Ollama reduziu bastante a barreira de entrada: baixar, instalar e executar — três etapas. Mas, na hora de chamar a API, é fácil se confundir. Qual é a diferença entre a API REST nativa e a interface compatível com o SDK da OpenAI? Como processar respostas em streaming?
Neste artigo, reuni os problemas que encontrei, desde comandos curl até a migração para o SDK da OpenAI sem alterar a lógica do código, além de alguns detalhes que a documentação não deixa tão explícitos.
O Ollama oferece duas APIs
Confesso que isso me confundiu por um bom tempo. Na prática, o Ollama oferece duas interfaces de API diferentes:
API REST nativa: http://localhost:11434/api/*
- Endpoints:
/api/generatepara gerar texto,/api/chatpara conversas e/api/tagspara listar modelos - Resposta em streaming por padrão — exatamente o problema que encontrei às três da manhã
- Chamada HTTP direta, sem precisar de SDK
Interface compatível com a OpenAI: http://localhost:11434/v1/*
- Endpoints:
/v1/chat/completions,/v1/completionse/v1/models - Compatível com os SDKs da OpenAI para Python e JavaScript
- Funciona com o ecossistema de ferramentas da OpenAI já existente
Você pode se perguntar por que existem duas opções. A resposta é que cada uma tem seu papel. A API nativa é mais leve e direta, ideal para quem escreve o próprio cliente HTTP. Já a interface compatível com a OpenAI permite reutilizar código criado para o SDK da OpenAI: basta trocar o base_url.
Sinceramente, é uma decisão de design bem inteligente. Ela atende tanto quem quer fazer uma chamada simples quanto equipes que já têm código integrado ao ecossistema da OpenAI.
API REST nativa: começando pelo curl
Vamos começar pela API nativa. Ela é bem direta: uma interface REST padrão.
Chamada básica com curl
O exemplo mais simples é uma geração de texto:
curl http://localhost:11434/api/generate -d '{
"model": "llama3.2",
"prompt": "Why is the sky blue?",
"stream": false
}'
Repare no stream: false. Por padrão, o Ollama transmite o conteúdo em streaming. Se você quiser uma resposta JSON completa, precisa desativar o streaming explicitamente. Caso contrário, verá uma sequência parecida com esta:
{"model":"llama3.2","response":"That","done":false}
{"model":"llama3.2","response":"'","done":false}
{"model":"llama3.2","response":"s","done":false}
{"model":"llama3.2","response":" a","done":false}
...
{"model":"llama3.2","response":"!","done":true}
Cada objeto JSON contém apenas alguns caracteres, enviados token por token. Esse é o formato NDJSON, sigla de Newline-Delimited JSON: um objeto JSON por linha. Naquela madrugada, eu não tinha percebido isso e tentei processar a resposta como um JSON comum. O resultado foi receber apenas o "That" do primeiro objeto.
O modo de conversa é mais útil
A geração isolada serve para tarefas simples, mas o modo de conversa é o mais usado no dia a dia:
curl http://localhost:11434/api/chat -d '{
"model": "llama3.2",
"messages": [
{ "role": "user", "content": "Hello!" }
],
"stream": false
}'
Você pode manter um array messages e enviar todo o histórico da conversa. Assim, o modelo preserva o contexto, algo especialmente importante ao criar aplicativos de chat.
Como ver os modelos instalados
Às vezes, você só quer conferir quais modelos estão disponíveis localmente:
curl http://localhost:11434/api/tags
O JSON retornado lista todos os modelos baixados, incluindo tamanho, data de modificação e nível de quantização. É bem prático.
Como processar respostas em streaming
Esse ponto merece uma seção própria. A resposta em streaming do Ollama não chega inteira de uma vez; ela é enviada token por token.
Streaming em Python
Veja como processar o fluxo com a biblioteca requests do Python:
import requests
import json
url = "http://localhost:11434/api/chat"
payload = {
"model": "llama3.2",
"messages": [{"role": "user", "content": "Write a short poem"}],
"stream": True
}
response = requests.post(url, json=payload, stream=True)
for line in response.iter_lines():
if line:
chunk = json.loads(line)
print(chunk.get("message", {}).get("content", ""), end="", flush=True)
O ponto principal é response.iter_lines(), que permite ler o fluxo NDJSON linha por linha. Cada chunk pode conter apenas alguns caracteres, então é preciso acumulá-los para obter a resposta completa.
Streaming em JavaScript
No frontend, o processo com a fetch API é parecido:
const response = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
body: JSON.stringify({
model: 'llama3.2',
messages: [{ role: 'user', content: 'Hello!' }],
stream: true
})
});
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
// Processar cada chunk...
}
É verdade que lidar com streaming dá um pouco mais de trabalho do que esperar por uma resposta completa. Em compensação, a experiência melhora bastante: o usuário vê o modelo “pensar” e responder em tempo real, em vez de esperar e receber um bloco enorme de texto de uma vez.
Interface compatível com o SDK da OpenAI: migração sem alterar a lógica
Esta é a parte de que mais gosto. O Ollama oferece uma interface compatível com a API da OpenAI, o que permite migrar código existente quase sem ajustes.
Exemplo com o SDK da OpenAI para Python
Use diretamente o SDK oficial da OpenAI:
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1/',
api_key='ollama' # Não há validação local; qualquer valor serve
)
response = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
Como você pode ver, as únicas mudanças são definir o base_url e fornecer qualquer valor em api_key. Todo o restante do código continua igual.
Alternando entre desenvolvimento e produção
Esse recurso é especialmente útil. Você pode usar o Ollama local no ambiente de desenvolvimento e a OpenAI em produção:
# Ambiente de desenvolvimento .env
OPENAI_API_KEY=anyrandomtext
LLM_ENDPOINT="http://localhost:11434/v1"
MODEL=llama3.2
# Ambiente de produção .env
OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXX
LLM_ENDPOINT="https://api.openai.com/v1"
MODEL=gpt-3.5-turbo
No código, basta ler os valores das variáveis de ambiente:
import os
from openai import OpenAI
client = OpenAI(
base_url=os.getenv('LLM_ENDPOINT'),
api_key=os.getenv('OPENAI_API_KEY')
)
Assim, durante o desenvolvimento, você não precisa gastar com chamadas à API da OpenAI: os testes locais são suficientes. Na hora de publicar, basta mudar as variáveis de ambiente para usar a OpenAI de verdade.
Endpoints compatíveis
A interface do Ollama compatível com a OpenAI aceita estes endpoints:
| Endpoint | Função | Nível de suporte |
|---|---|---|
/v1/chat/completions | Geração de conversas | Suporte completo |
/v1/completions | Autocompletar texto | Suporte completo |
/v1/models | Lista de modelos | Suporte completo |
/v1/embeddings | Embeddings de texto | Suporte completo |
/v1/responses | Nova Responses API | Suporte completo |
Também existe o endpoint experimental /v1/images/generations, mas ele ainda não tem a mesma estabilidade.
Alias de modelos
Um recurso útil é criar um alias para um modelo. Por exemplo, se você quiser que o código pareça chamar o GPT-3.5:
ollama cp llama3.2 gpt-3.5-turbo
Assim, quando o código usar model="gpt-3.5-turbo", quem será executado de fato é o llama3.2 local. Esse truque ajuda bastante na migração de código.
Qual das duas opções escolher?
Depois de tudo isso, talvez você ainda esteja se perguntando qual delas deve usar.
Quando usar a API REST nativa
Ela é indicada quando:
- Você quer a forma mais leve possível de fazer chamadas
- Não precisa do ecossistema do SDK da OpenAI
- Está escrevendo seu próprio cliente HTTP, por exemplo para um dispositivo embarcado ou ambiente especial
- Precisa controlar com precisão os detalhes da resposta em streaming
A API nativa é mais direta e trabalha em um nível mais baixo. Se você já conhece bem o protocolo HTTP, provavelmente vai se sentir à vontade com ela.
Quando usar a interface compatível com o SDK da OpenAI
Ela é indicada quando:
- Você já tem código baseado no SDK da OpenAI
- Precisa migrar rapidamente para uma execução local
- Usa ferramentas do ecossistema da OpenAI, como LangChain ou LlamaIndex
- Precisa alternar entre os ambientes de desenvolvimento e produção
Em resumo, se você quer reaproveitar o que já existe e evitar alterações no código, escolha a interface compatível com a OpenAI.
Minha recomendação
Sinceramente, durante o desenvolvimento eu prefiro usar a interface compatível com o SDK da OpenAI. Ela exige menos alterações, permite aproveitar as ferramentas existentes e facilita a depuração. Ainda assim, há cenários em que a API nativa é mais adequada — por exemplo, ao criar uma ferramenta CLI minimalista ou chamar o modelo em um ambiente sem suporte ao SDK da OpenAI.
Trechos de código para uso prático
Para encerrar, aqui estão alguns trechos que uso com frequência.
Chat em streaming com Python e o SDK da OpenAI
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1/',
api_key='ollama'
)
stream = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Write a poem"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Conversa completa em JavaScript com a API nativa
async function chat(messages) {
const response = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'llama3.2',
messages: messages,
stream: false
})
});
return await response.json();
}
// Manter o histórico da conversa
let conversation = [
{ role: 'user', content: 'Hello!' }
];
const result = await chat(conversation);
conversation.push({
role: 'assistant',
content: result.message.content
});
console.log(result.message.content);
Exemplo com chamada de ferramentas
O Ollama também aceita Function Calling, ou chamadas de ferramentas:
from openai import OpenAI
client = OpenAI(base_url='http://localhost:11434/v1/', api_key='ollama')
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
tools=tools
)
if response.choices[0].message.tool_calls:
print("Model wants to call:", response.choices[0].message.tool_calls[0].function.name)
Para concluir
O design da API do Ollama encontra um bom equilíbrio: oferece a simplicidade e a leveza da API REST nativa, mas também a conveniência e a compatibilidade com o ecossistema do SDK da OpenAI. Cada opção funciona melhor em determinados cenários; a escolha depende das suas necessidades.
Se você está começando com o Ollama, recomendo testar primeiro a interface compatível com o SDK da OpenAI. Ela é fácil de adotar e exige poucas mudanças no código. Depois, quando estiver mais familiarizado, você poderá decidir se a API nativa atende melhor a algum caso específico.
E não se esqueça: respostas em streaming são o padrão e podem confundir. Se você não precisa de streaming, defina explicitamente stream: false. Caso contrário, pode acabar como eu, às três da manhã, encarando metade de uma palavra na tela.
Referências
- Introdução à API do Ollama
- Compatibilidade do Ollama com a OpenAI
- Guia de streaming do Ollama
- Guia da KodeKloud sobre compatibilidade com a OpenAI
Duas formas de chamar a API do Ollama
Fluxo completo de chamadas, desde a API nativa com curl até a interface compatível com o SDK da OpenAI
⏱️ Estimated time: 10 min
- 1
Step 1: Confirme que o Ollama está instalado e em execução
Primeiro, verifique se o Ollama está funcionando:
• Execute no terminal: ollama list (para ver os modelos baixados)
• Ou acesse: http://localhost:11434 (a resposta deve ser Ollama is running)
• Porta padrão: 11434 - 2
Step 2: Escolha a forma de chamada
Escolha de acordo com seu cenário:
• API REST nativa: ideal para chamadas leves e clientes personalizados
• Compatibilidade com o SDK da OpenAI: ideal para código OpenAI existente e migrações rápidas - 3
Step 3: Use a API REST nativa com curl
Chamada mais básica com curl:
• Geração de texto: curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "prompt": "...", "stream": false}'
• Modo de conversa: curl http://localhost:11434/api/chat -d '{"model": "llama3.2", "messages": [...], "stream": false}'
• Atenção: a resposta é transmitida em streaming por padrão; defina stream: false para desativar - 4
Step 4: Use a interface compatível com o SDK da OpenAI
Chamada com o SDK da OpenAI para Python:
• Defina base_url='http://localhost:11434/v1/'
• O api_key pode ter qualquer valor (não há validação local)
• O restante do código é exatamente igual ao usado com a OpenAI
• Para trocar de ambiente, basta alterar o base_url: Ollama local em desenvolvimento e OpenAI em produção - 5
Step 5: Processe respostas em streaming
Pontos principais do processamento em streaming:
• Python: use response.iter_lines() para ler o NDJSON linha por linha
• JavaScript: use response.body.getReader() para ler o fluxo
• Cada chunk contém apenas alguns caracteres; é preciso acumulá-los para obter a resposta completa
• Sem streaming: defina stream: false para receber um JSON completo
FAQ
Qual é a diferença entre a API nativa do Ollama e a interface compatível com o SDK da OpenAI?
Por que a chamada à API do Ollama retornou apenas metade de uma palavra?
• Defina stream: false para desativar o streaming e receber um JSON completo
• Ou processe corretamente o fluxo NDJSON, lendo e acumulando as linhas
Como usar o Ollama local em desenvolvimento e a OpenAI em produção?
Quais endpoints da OpenAI são compatíveis com o Ollama?
É possível criar um alias para um modelo do Ollama?
O Ollama aceita chamadas de ferramentas (Function Calling)?
9 min de leitura · Publicado em: 3 abr 2026 · Atualizado em: 4 set 2026
Guia Ollama LLM local
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Ollama + Open WebUI: como criar uma interface local estilo ChatGPT (guia completo)
Aprenda passo a passo a criar localmente uma interface de conversa com IA no estilo ChatGPT usando Ollama e Open WebUI, com instalação, escolha de modelos, base de conhecimento RAG, integração via API e otimização de desempenho em 30 minutos
Parte 7 de 13
Próximo
Ollama API na prática: guia para clientes em Python e Node.js
Aprenda a usar a API do Ollama com os SDKs nativos para Python e Node.js, respostas em streaming, Agent Loop com ferramentas, modo thinking e integração compatível com a OpenAI
Parte 9 de 13



Comentários
Entre com GitHub para comentar