PT ▾
Obter chave de API

API Ollama em Python e uma alternativa hospedada

A API Ollama em Python leva cerca de dez linhas, e o mesmo formato de código também funciona contra um endpoint hospedado. Este artigo mostra ambos e explica quando escolher qual.

Atualizado

Pontos principais

  • O Ollama escuta na porta 11434 e oferece uma API nativa além de um endpoint /v1 no estilo OpenAI.
  • O pacote ollama, requests puro e o SDK OpenAI funcionam; o SDK OpenAI é o mais portátil.
  • Mover para uma API hospedada significa alterar a URL base, a chave e o nome do modelo.
  • Local é melhor para trabalho offline e hardware fixo; hospedado é mais simples quando você não tem GPU.
Um computador local conectado por um cabo brilhante a um servidor em nuvem, representando APIs LLM locais e hospedadas

A versão curta

Se você pesquisar por ollama api python, geralmente quer uma de três coisas: chamar um modelo rodando na sua própria máquina, fazer streaming de tokens dele ou fazer o mesmo script funcionar em outro lugar. Ollama oferece tudo isso. Ele executa um servidor local, por padrão em http://localhost:11434, e você fala com ele usando o pacote Python ollama, com HTTP puro, ou com qualquer cliente OpenAI apontado para o seu caminho /v1.

O problema é que o modelo precisa rodar no seu hardware. Um laptop sem uma GPU decente será lento com modelos maiores, e um servidor sem uma é uma má escolha. Para esse caso, uma API hospedada compatível com OpenAI é a rota mais fácil, e como o formato de requisição é o mesmo, mudar custa três linhas de configuração. Ambos os caminhos são cobertos abaixo, com código que você pode colar.

Chamando um modelo local com o pacote ollama

Instale Ollama, puxe um modelo e certifique-se de que o servidor está rodando. Então instale o cliente Python:

pip install ollama
ollama pull llama3.2

Uma chamada básica de chat se parece com isso. O nome do modelo é o que você puxou; llama3.2 é apenas um exemplo.

import ollama

response = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "Explain DNS in two sentences."}],
)
print(response["message"]["content"])

Streaming

Passe stream=True e você recebe um iterador de chunks em vez de uma única resposta. Cada chunk carrega uma parte da resposta em message.content.

import ollama

stream = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "Write a haiku about servers."}],
    stream=True,
)
for chunk in stream:
    print(chunk["message"]["content"], end="", flush=True)
print()

Apontando o cliente para outra máquina

Se o Ollama estiver em um host diferente, crie um cliente com um endereço explícito, por exemplo ollama.Client(host="http://192.168.1.20:11434"). Por padrão, o servidor só escuta na máquina local, então o acesso remoto precisa de uma configuração deliberada no lado do servidor. Não o exponha à internet pública sem um proxy e autenticação na frente, porque a API nativa não tem verificação de chave própria.

HTTP puro com requests

Você não precisa do pacote. O endpoint de chat nativo é POST /api/chat. O streaming é o padrão lá, e o stream é JSON delimitado por nova linha, não SSE. Defina "stream": false se quiser um único objeto de volta.

import requests

r = requests.post(
    "http://localhost:11434/api/chat",
    json={
        "model": "llama3.2",
        "messages": [{"role": "user", "content": "Name three HTTP status codes."}],
        "stream": False,
    },
    timeout=120,
)
r.raise_for_status()
print(r.json()["message"]["content"])

Defina um timeout generoso. A primeira requisição após um pull precisa carregar o modelo na memória, e isso pode levar muito mais tempo do que requisições posteriores.

Ler o stream à mão são apenas algumas linhas a mais. Chame requests.post(..., stream=True), itere sobre r.iter_lines(), pule linhas vazias e execute json.loads em cada uma. Cada objeto contém uma pequena parte da resposta, e o último tem "done": true. Isso é útil em um container mínimo onde você prefere não instalar outro pacote, e deixa claro o que a biblioteca faz por você. A API hospedada faz streaming de forma diferente, como linhas SSE que começam com data:, que é mais uma razão para deixar o SDK OpenAI analisar o stream para você em código portátil.

Usando o SDK OpenAI com Ollama

O Ollama também expõe um endpoint estilo OpenAI sob /v1. Isso significa que o pacote oficial openai funciona, e a maioria dos softwares que permitem definir uma URL base personalizada também funciona. A chave é exigida pelo SDK mas ignorada por um Ollama local, então qualquer string serve.

from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Give me a one-line summary of TCP."}],
)
print(resp.choices[0].message.content)

Esta é a forma mais útil, porque desacopla o seu código do servidor. A mesma função pode falar com um modelo local hoje e com outra coisa amanhã, que é a próxima seção.

O mesmo código contra uma API hospedada

A opção hospedada aqui é uma API compatível com OpenAI com um único modelo, uncensored, executada por um provedor independente e ajustada para responder sem recusas de conteúdo para uso adulto legal. É apenas texto. A URL base é https://api.ollamaapi.cc/v1, e você autentica com uma chave Bearer da página de chave de API.

Aqui está uma versão que lê seu destino de variáveis de ambiente, com os valores hospedados como padrão. Para voltar ao seu servidor local, exporte duas variáveis e não mude nada.

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.getenv("LLM_BASE_URL", "https://api.ollamaapi.cc/v1"),
    api_key=os.getenv("LLM_API_KEY", "YOUR_API_KEY"),
)
MODEL = os.getenv("LLM_MODEL", "uncensored")

resp = client.chat.completions.create(
    model=MODEL,
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "List four uses of a message queue."},
    ],
    temperature=0.7,
)
print(resp.choices[0].message.content)

Para execuções locais, defina LLM_BASE_URL=http://localhost:11434/v1, LLM_API_KEY=ollama e LLM_MODEL=llama3.2. O quickstart tem a mesma configuração em curl e Node.

Streaming, modo JSON e ferramentas no lado hospedado

O endpoint hospedado suporta streaming sobre SSE, modo JSON, chamada de funções, e os parâmetros de amostragem usuais (temperature, top_p, stop, seed e as penalidades). Streaming com o SDK é o mesmo loop que você escreveria para qualquer servidor estilo OpenAI:

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Tell a two-paragraph story about a lighthouse."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Para saída estruturada, defina response_format={"type": "json_object"} e diga no prompt que você quer JSON. Sempre analise dentro de um bloco try de qualquer forma; um modelo ainda pode retornar algo que você não esperava.

Uma diferença do uso local importa no código: limites. Uma chave completa permite 8 requisições simultâneas e 300 requisições por minuto, e uma requisição de streaming mantém seu slot até o fim do stream. Se você distribuir com threads, limite o pool para 8 e tente novamente em HTTP 429 usando o cabeçalho Retry-After quando presente.

Mantendo uma conversa

Nem o endpoint de chat local nem o hospedado lembram de nada entre chamadas. O servidor vê apenas as mensagens que você envia, então um chatbot é uma lista que você adiciona e reenvia. O padrão é idêntico para ambos os destinos, que é mais uma razão para manter o cliente estilo OpenAI como seu padrão.

history = [{"role": "system", "content": "You are a helpful assistant."}]

def ask(text):
    history.append({"role": "user", "content": text})
    resp = client.chat.completions.create(model=MODEL, messages=history)
    answer = resp.choices[0].message.content
    history.append({"role": "assistant", "content": answer})
    return answer

print(ask("Pick a name for a hiking app."))
print(ask("Give me a tagline for it."))

Duas notas práticas. Primeiro, modelos locais têm um comprimento de contexto que você define e que a memória precisa conter; se o histórico crescer além disso, as voltas mais antigas são cortadas ou a chamada falha, dependendo das configurações. O modelo hospedado aceita uma janela de 100.000 tokens incluindo a conclusão, que é muito mais do que a maioria dos chats precisa, mas históricos longos ainda custam tokens de entrada em cada volta. Segundo, assim que um histórico fica longo, resuma as voltas mais antigas em uma mensagem curta ao invés de reenviá-las todas. Isso mantém latência e custo estáveis em qualquer backend.

Tentando novamente educadamente

Na API hospedada, uma sobrecarga temporária retorna HTTP 429 com um cabeçalho Retry-After: 5. Um pequeno wrapper lida com isso:

import time
from openai import RateLimitError

def chat_with_retry(messages, tries=4):
    for attempt in range(tries):
        try:
            return client.chat.completions.create(model=MODEL, messages=messages)
        except RateLimitError:
            time.sleep(5 * (attempt + 1))
    raise RuntimeError("still rate limited")

Ollama local não limita você, mas ele enfileira requisições quando o modelo está ocupado, então o mesmo wrapper não faz mal lá.

Local ou hospedado: como decidir

Nenhuma escolha é melhor em geral. Use os pontos abaixo como uma lista de verificação.

  • Escolha o Ollama local se você precisa trabalhar offline, se os dados nunca devem sair da máquina, se você já possui uma GPU capaz, ou se quiser tentar muitos modelos abertos rapidamente.
  • Escolha uma API hospedada se você não tiver GPU, se executar em um VPS pequeno ou em CI, se várias pessoas ou serviços compartilharem um backend, ou se quiser uma janela de contexto longa sem dimensionar a memória manualmente. O modelo hospedado aceita até 100.000 tokens de prompt mais conclusão.
  • Combine os dois durante o desenvolvimento: itere localmente e, em seguida, aponte a produção para a URL hospedada por meio de variáveis de ambiente.

O uso hospedado é cobrado por token, a $0,15 por 1M de tokens de entrada e $0,50 por 1M de tokens de saída, a partir do crédito pré-pago. A página de preços lista os valores de recarga, e novas contas podem obter um crédito de teste de $0,50 com um clique, sem necessidade de cartão. Os prompts não são usados para treinamento.

Erros que você encontrará

SintomaCausa provávelCorreção
Conexão recusada na porta 11434O servidor Ollama não está rodandoInicie o aplicativo ou execute ollama serve
Modelo não encontradoO modelo nunca foi puxado, ou o nome tem um erro de digitaçãoExecute ollama list, então ollama pull o nome que você usa
Tempo esgotado na primeira chamadaO modelo ainda está carregandoAumente o tempo limite ou envie uma solicitação de aquecimento
Erro de autenticação na API hospedadaChave Bearer ausente ou incorretaVerifique LLM_API_KEY e a URL base
HTTP 429 com código concurrencyMais de 8 requisições em andamento (2 em uma chave de teste)Reduza a contagem de workers
HTTP 429 com código rate_limitedAcima do limite de requisições por minutoReduza a taxa e tente novamente

Solicitações falhas ou recusadas no lado hospedado não são cobradas, portanto, a lógica de nova tentativa não custa por tentativas falhas.

Perguntas e respostas

Qual é o endereço padrão da API Ollama?

Um servidor Ollama local escuta em http://localhost:11434. Os endpoints nativos ficam em /api, como /api/chat, e o endpoint estilo OpenAI fica em /v1.

Posso usar o SDK Python da OpenAI com o Ollama?

Sim. Defina base_url para http://localhost:11434/v1 e passe qualquer string como chave de API. O SDK então envia solicitações padrão de conclusão de chat para o seu modelo local.

Como faço para mudar do Ollama para uma API hospedada?

Altere a URL base, a chave e o nome do modelo. Se o seu código os lê de variáveis de ambiente, nenhuma alteração de código será necessária.

A API hospedada funciona sem uma GPU do meu lado?

Sim. O modelo é executado pelo provedor, então o seu script só precisa de uma conexão com a internet e uma chave Bearer. Você paga por token a partir de crédito pré-pago.

Sua chave está a um formulário de distância

Crie uma conta, copie a chave e altere a URL base. Essa é toda a configuração.

Obter chave de API