SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor

Como hospedar o LiteLLM como gateway de LLM

Use um endpoint compativel com OpenAI para todos os provedores: LiteLLM em um VPS, com chaves virtuais, limites por chave, fallbacks e imagens fixadas.

O que faz um gateway de LLM autoalojado

LiteLLM é um gateway de LLM de código aberto que aloja no seu próprio servidor: um endpoint HTTP para o qual todas as aplicações enviam pedidos. Depois, o gateway encaminha cada pedido para o fornecedor que deve responder. LLM significa modelo de linguagem de grande dimensão. O gateway utiliza a API de conclusões de chat da OpenAI (interface de programação de aplicações). Por isso, qualquer biblioteca cliente que já comunique com a OpenAI funciona com ele depois de alterar duas coisas: o URL base e a chave.

Essa camada de indireção é o objetivo. As aplicações deixam de armazenar as credenciais dos fornecedores. A troca de um modelo passa a exigir uma linha num ficheiro de configuração no servidor, em vez de uma alteração de código em cinco serviços. Como todas as chamadas passam pelo mesmo processo, existe um local para definir um orçamento e registar o que foi gasto.

Quando estiver em execução, terá:

  • Um endpoint. As aplicações utilizam https://gateway.example.com/v1 e pedem um nome de modelo que definiu, como bulk ou strong.
  • Chaves virtuais. Cada aplicação recebe a sua própria chave, com a sua própria lista de modelos permitidos e o seu próprio limite de gastos. Pode revogar uma chave sem afetar as restantes.
  • Fallbacks. Uma chamada falhada ou um prompt demasiado grande é automaticamente repetido com outro modelo.
  • Um registo em log. Cada pedido escreve uma linha com o respetivo custo. Assim, é possível responder à pergunta "qual aplicação gastou esse valor?".

Por que executar o gateway por conta própria

Um router gerido tem a mesma estrutura, mas com o processo de outra entidade no meio de cada pedido. Executá-lo por conta própria mantém as chaves do seu fornecedor e o texto dos seus prompts num servidor sob o seu controlo. O custo é real: agora é responsável pelo componente de que todas as aplicações dependem. A última secção deste guia trata desse custo, porque é a parte que a maioria dos tutoriais omite.

O que é necessário

  • Uma VPS (servidor privado virtual) com Ubuntu 24.04, Docker e o plugin Compose instalados.
  • Um nome de domínio apontado para esse servidor, se máquinas externas acederem ao gateway por TLS (segurança da camada de transporte).
  • Pelo menos uma chave de API de um fornecedor.

O gateway não executa inferência. Encaminha os pedidos e devolve as respostas em streaming, pelo que o uso de CPU acompanha o volume de pedidos, e não o tamanho do modelo. Uma máquina com 1 vCPU suporta várias aplicações internas sem problemas. O que aumenta é a base de dados, porque o gateway regista uma linha de consumo por pedido.

Escreva primeiro o config.yaml

O ficheiro de configuração define que modelos um cliente pode solicitar. Há quatro secções de nível superior importantes: model_list, litellm_settings, router_settings e general_settings.

model_list:
  - model_name: bulk
    litellm_params:
      model: anthropic/claude-haiku-4-5
      api_key: os.environ/ANTHROPIC_API_KEY
  - model_name: strong
    litellm_params:
      model: anthropic/claude-sonnet-5
      api_key: os.environ/ANTHROPIC_API_KEY
  - model_name: strong
    litellm_params:
      model: openai/gpt-5.5
      api_key: os.environ/OPENAI_API_KEY

litellm_settings:
  num_retries: 2
  request_timeout: 120
  json_logs: true
  set_verbose: false

router_settings:
  allowed_fails: 3
  cooldown_time: 30
  fallbacks: [{"bulk": ["strong"]}]
  context_window_fallbacks: [{"bulk": ["strong"]}]

general_settings:
  background_health_checks: true
  health_check_interval: 300

model_name é o nome que os seus clientes enviam. litellm_params.model é o modelo real, escrito como provider/model. Dê aos modelos nomes baseados na função, e não no fornecedor. Uma aplicação que solicita bulk continua a funcionar quando decidir, no próximo mês, que bulk deve ser outro modelo.

api_key: os.environ/ANTHROPIC_API_KEY indica ao LiteLLM que deve ler essa variável em tempo de execução. A chave literal nunca aparece no ficheiro, o que é importante porque o config.yaml é o ficheiro que coloca no controlo de versões.

Duas entradas partilham o nome strong, intencionalmente. Quando mais de uma deployment contém o mesmo model_name, o router trata-as como equivalentes e distribui entre elas os pedidos para esse nome. É assim que strong continua disponível quando um fornecedor tem problemas durante algum tempo: quando uma deployment entra em cooldown (abaixo), os novos pedidos para strong são enviados para a outra.

num_retries: 2 tenta novamente um erro que permita retry, até duas vezes. Esses retries podem selecionar outra deployment disponível no mesmo grupo de modelos: a documentação de arquitetura do LiteLLM, consultada em 2026-10-29, descreve os retries dentro do grupo e os fallbacks entre grupos como etapas separadas. Um retry para strong pode, portanto, ser enviado para o outro fornecedor sem ativar o failover ponderado. Um fallback só é acionado depois de esgotar esses retries.

allowed_fails e cooldown_time são opções do router, por isso ficam sob router_settings. O proxy constrói o seu router a partir dessa secção e, na v1.95.0, um cooldown_time escrito sob litellm_settings nunca chega ao router. Por isso, os cooldowns permanecem silenciosamente no valor predefinido de 5 segundos. cooldown_time: 30 define durante quanto tempo uma deployment permanece fora da rotação depois de entrar em cooldown. A referência de configuração descreve allowed_fails como o número de falhas que uma deployment tem de exceder dentro de cooldown_time antes de entrar em cooldown. No código-fonte da v1.95.0, allowed_fails: 3 é o valor predefinido. Com esse valor, o router usa os acionadores integrados; a contagem de falhas só passa a ser usada quando define um número diferente. Esses acionadores incluem um cooldown imediato quando uma resposta 429 ocorre num grupo com mais de uma deployment, mais de 50% de falhas no minuto atual depois de pelo menos 5 pedidos nesse grupo e erros que o router não tenta novamente, como um 401 causado por uma key inválida. Há também um acionador separado que coloca uma deployment única em cooldown quando todos os pedidos do minuto atual falham e o tráfego atinge SINGLE_DEPLOYMENT_TRAFFIC_FAILURE_THRESHOLD, cujo valor predefinido é 1000 pedidos. Um fornecedor que devolve respostas 500 em rajadas deixa de ser contactado em cada pedido, enquanto uma resposta 500 isolada a cada poucos minutos nunca aciona o cooldown.

fallbacks e context_window_fallbacks têm acionadores diferentes, e o segundo é o útil que as pessoas costumam ignorar.

  • fallbacks é acionado quando a chamada principal falha.
  • context_window_fallbacks é acionado quando o fornecedor rejeita o pedido por ser maior do que a janela de contexto desse modelo. Assim, um prompt demasiado grande é enviado para um modelo com espaço suficiente, em vez de devolver um erro ao chamador.

Existe também content_policy_fallbacks, para quando um fornecedor recusa o pedido por motivos relacionados com a política de conteúdo. Defina-o apenas se tiver um destino adequado para esses pedidos.

Implementar o LiteLLM numa VPS com Docker Compose

Crie um diretório com três ficheiros: config.yaml, docker-compose.yml e .env. O guia de início rápido oficial usa a etiqueta latest. Em vez disso, fixe uma etiqueta de versão para que docker compose up -d no próximo mês lhe forneça o mesmo gateway que fornece hoje e para que possa reverter a alteração numa única linha.

services:
  litellm:
    image: ghcr.io/berriai/litellm:v1.95.0
    restart: unless-stopped
    command: ["--config", "/app/config.yaml", "--num_workers", "1"]
    ports:
      - "127.0.0.1:4000:4000"
    volumes:
      - ./config.yaml:/app/config.yaml:ro
    env_file: .env
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_USER: litellm
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
      POSTGRES_DB: litellm
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U litellm"]
      interval: 5s
      timeout: 5s
      retries: 10
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

O Compose lê .env duas vezes neste caso. Primeiro, para substituir ${POSTGRES_PASSWORD} dentro do próprio ficheiro Compose e, depois, através de env_file, para passar todas as variáveis para o contentor.

v1.95.0 era a versão atual em agosto de 2026. Consulte a página de versões do projeto e fixe a versão que estiver atual quando fizer a implementação. Cada versão publica uma assinatura, por isso pode verificar a imagem antes de confiar nela:

cosign verify --key https://raw.githubusercontent.com/BerriAI/litellm/v1.95.0/cosign.pub ghcr.io/berriai/litellm:v1.95.0

A linha da porta é 127.0.0.1:4000:4000, que publica a porta apenas na interface de loopback. Se escrever 4000:4000, o seu gateway ficará acessível a partir de toda a Internet, porque o Docker adiciona as suas próprias regras à cadeia FORWARD do iptables e essas regras são avaliadas antes das regras do ufw. Por isso, ufw deny 4000 não o impede. Esta é a forma mais comum de um gateway autoalojado ficar exposto: consulte como o Docker publica diretamente uma porta do contentor, ignorando o ufw. O tráfego externo chega através do reverse proxy.

Mantenha as chaves dos provedores fora da imagem

O ficheiro .env contém todos os segredos. Ele é fornecido como ambiente durante a execução, por isso nunca é incorporado na imagem nem submetido ao controlo de versões.

LITELLM_MASTER_KEY=sk-REPLACE_ME
LITELLM_SALT_KEY=sk-REPLACE_ME_TOO
POSTGRES_PASSWORD=REPLACE_ME_AS_WELL
DATABASE_URL=postgresql://litellm:REPLACE_ME_AS_WELL@db:5432/litellm
STORE_MODEL_IN_DB=True
LITELLM_MODE=PRODUCTION
LITELLM_LOG=ERROR
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-proj-...

Gere as duas chaves do LiteLLM com aleatoriedade real e, em seguida, restrinja as permissões do ficheiro:

printf 'sk-%s\n' "$(openssl rand -hex 32)"
chmod 600 .env

LITELLM_MASTER_KEY é a credencial de administrador. Ela autentica a API de gestão e é a palavra-passe da Admin UI em /ui. Nenhuma aplicação deve ter acesso a ela.

LITELLM_SALT_KEY cifra as credenciais dos provedores armazenadas na base de dados. Defina-o uma vez e não o altere. Se o alterar mais tarde, as credenciais já armazenadas não poderão ser decifradas. Nesse caso, o gateway inicia normalmente, mas todas as chamadas para esses provedores falham na autenticação.

STORE_MODEL_IN_DB=True permite adicionar e editar modelos a partir da Admin UI sem alterar o config.yaml. Isso é conveniente, mas divide a fonte de verdade em duas. Decida qual é a fonte autoritativa e registe essa decisão junto da configuração.

A mesma razão para manter as chaves fora do ficheiro de configuração aplica-se a mantê-las fora das ferramentas que entrega a um agente. Manter os segredos dos provedores fora dos agentes de IA descreve esse padrão, e ficheiros env e segredos no Docker Compose explica os detalhes da implementação.

Inicie o serviço e monitorize o primeiro arranque:

docker compose up -d
docker compose logs -f litellm

Verifique se está efetivamente a funcionar

Existem duas sondagens sem autenticação e uma com autenticação. Cada uma falha por motivos diferentes.

curl -s http://127.0.0.1:4000/health/liveliness
curl -s http://127.0.0.1:4000/health/readiness

/health/liveliness não requer autenticação e responde com "I'm alive!" enquanto o processo está em execução. /health/readiness também não requer autenticação. Devolve um objeto JSON com "status": "healthy" e um campo db, ou 503 quando a base de dados está inacessível. Direcione a monitorização para a prontidão, porque a vivacidade permanece verde num gateway que não consegue consultar uma única chave virtual.

A verificação autenticada é a que comunica com os fornecedores:

curl -s http://127.0.0.1:4000/health \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY"

Responde com os arrays healthy_endpoints e unhealthy_endpoints. Um modelo em unhealthy_endpoints com um erro de autenticação indica que a chave do fornecedor em .env está incorreta ou ausente. Esta é a falha que pretende encontrar agora. Como background_health_checks: true está definido, o proxy executa estas sondagens automaticamente a cada health_check_interval segundos e /health devolve o último resultado. Assim, consultar esse endpoint não envia um pedido de teste aos fornecedores a cada consulta.

Chaves virtuais e limites por chave

Cada aplicação recebe a sua própria chave, criada com base na chave principal.

curl -s http://127.0.0.1:4000/key/generate \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "key_alias": "nightly-summariser",
    "models": ["bulk"],
    "max_budget": 5,
    "budget_duration": "30d",
    "rpm_limit": 60,
    "tpm_limit": 200000
  }'

A resposta contém um campo key que começa por sk-. Essa string é o que a aplicação recebe e é a única informação que a aplicação recebe.

  • models é uma allowlist do que esta chave pode solicitar. A chave acima pode solicitar bulk e nada mais.
  • max_budget: 5 com budget_duration: "30d" corresponde a cinco dólares americanos por mês civil. O LiteLLM repõe um orçamento 30d no dia 1 de cada mês à meia-noite, em UTC, exceto se definir timezone em litellm_settings. O limite não é calculado numa janela móvel de 30 dias. Assim, depois de a chave gastar cinco dólares, deixa de funcionar até ao dia 1 seguinte.
  • rpm_limit e tpm_limit limitam, respetivamente, os pedidos por minuto e os tokens por minuto apenas para esta chave.
  • key_alias é o identificador que reconhecerá no log de custos seis semanas mais tarde. Defina-o sempre.

Quando o orçamento termina, a chamada falha com um erro do tipo budget_exceeded e uma mensagem deste formato:

Budget has been exceeded! Key=<key> Current cost: <spend>, Max budget: <max_budget>

O código de estado depende da versão. Na v1.95.0 fixada, é HTTP 429. A partir da v1.104.0, o padrão é HTTP 422. Definir budget_exceeded_status_code: 429 em litellm_settings repõe o código anterior. Os casos reais de rpm_limit e tpm_limit continuam a devolver 429 em ambas as versões. Confirme qual recebe depois de cada atualização.

O código de estado é o que torna este problema confuso, porque nenhum dos dois códigos indica "orçamento". Uma biblioteca cliente interpreta 429 como um limite de taxa e pode repetir o pedido com backoff, embora o orçamento só volte a estar disponível após a reposição. Também interpreta 422 como um pedido que não pôde ser processado. Registe o corpo da resposta juntamente com o código de estado. Caso contrário, o esgotamento do orçamento parecerá sempre outra coisa.

Inspecione e ajuste as chaves através da mesma API de gestão:

curl -s "http://127.0.0.1:4000/key/info?key=sk-..." \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY"

curl -s -X POST http://127.0.0.1:4000/key/update \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"key": "sk-...", "max_budget": 25}'

Um orçamento aplicado no gateway continua válido mesmo quando o problema está no próprio agente. Por isso, é a base do controlo de custos para agentes de IA num VPS.

Enviar tarefas em massa para um modelo barato

Aponte um cliente para o gateway. URL base, chave e nome do modelo:

curl -s http://127.0.0.1:4000/v1/chat/completions \
  -H "Authorization: Bearer sk-<the virtual key>" \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "bulk",
    "messages": [{"role": "user", "content": "Say hello in five words."}]
  }'

Qualquer biblioteca cliente da OpenAI funciona da mesma forma: defina base_url como https://gateway.example.com/v1 e api_key como a chave virtual.

A política de encaminhamento de config.yaml passa a aplicar-se sem que o chamador tenha conhecimento disso. Um pedido para bulk é encaminhado para o modelo barato. Se essa chamada falhar depois das tentativas configuradas, o pedido é repetido com strong. Se o prompt for demasiado longo para bulk, context_window_fallbacks encaminha-o para strong em vez de devolver um erro. Tarefas em massa, como uma classificação ou a criação de resumos de um backlog, usam o modelo barato por predefinição. Apenas os pedidos mais exigentes têm um custo superior.

É também neste cenário que um gateway se justifica para agentes que utilizam ferramentas. Um servidor MCP (model context protocol) no mesmo VPS e o agente que o controla podem apontar para um único endpoint. Assim, é possível mudar o modelo usado sem reimplementar nenhum dos dois.

Como saber se ocorreu um fallback?

Este é o modo de falha que custa dinheiro, porque nada parece estar avariado. Um fallback bem-sucedido devolve HTTP 200 com um corpo de resposta normal. O seu modelo barato pode ficar indisponível durante um dia, com todas as chamadas a serem silenciosamente atendidas pelo modelo caro. A primeira evidência pode ser a fatura.

A evidência existe nos cabeçalhos da resposta. Peça-os:

curl -s -D - -o /dev/null http://127.0.0.1:4000/v1/chat/completions \
  -H "Authorization: Bearer sk-<the virtual key>" \
  -H 'Content-Type: application/json' \
  -d '{"model":"bulk","messages":[{"role":"user","content":"ping"}]}' \
  | grep -i '^x-litellm'
  • x-litellm-model-group é o nome do modelo sob o qual o pedido foi encaminhado, como bulk. x-litellm-model-id é o ID do deployment que respondeu. Pode consultá-lo com /v1/model/info?litellm_model_id=.... Quando esse ID não corresponde a um dos seus deployments bulk, ocorreu um fallback.
  • x-litellm-attempted-fallbacks e x-litellm-attempted-retries contabilizam os fallbacks. Numa chamada normal, nenhum deles apresenta um valor superior a 0.
  • x-litellm-response-cost é o custo dessa chamada em dólares americanos.
  • x-litellm-call-id é o identificador usado para localizar a mesma chamada nos logs.

Registe x-litellm-attempted-fallbacks em todos os pedidos e crie um alerta sempre que o valor for superior a 0. Esse único número distingue uma política de encaminhamento funcional de uma política que se transformou silenciosamente em "usar sempre o modelo caro".

A versão completa deste mecanismo usa tracing e merece uma configuração própria: Langfuse self-hosted para tracing de chamadas de agentes. O LiteLLM inclui o callback, por isso a integração requer duas linhas e as credenciais.

litellm_settings:
  success_callback: ["langfuse"]
  failure_callback: ["langfuse"]
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=https://langfuse.example.com

Para o Langfuse v3 e posteriores, a página do LiteLLM sobre o Langfuse recomenda agora o preset langfuse_otel. O callback langfuse acima continua documentado. Defina failure_callback e success_callback. Se ignorar este passo, os únicos traces guardados serão os das chamadas em que nada correu mal. Separadamente, o LiteLLM escreve uma linha de custos por pedido no Postgres, e a Admin UI em /ui lê essa tabela. A tabela cresce com o tráfego, por isso monitorize-a se o disco for pequeno.

Coloque o gateway atrás de um proxy reverso

Nada fora do servidor deve conseguir aceder à porta 4000. Termine o TLS no nginx ou no Caddy e encaminhe para o endereço de loopback.

location / {
    proxy_pass http://127.0.0.1:4000;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_buffering off;
    proxy_read_timeout 600s;
}

Essas duas linhas são as que as pessoas costumam omitir. proxy_buffering off é importante porque uma conclusão em streaming é uma sequência de eventos enviados pelo servidor, e, com o buffering ativado, o nginx acumula os blocos em buffers antes de os encaminhar, atrasando a entrega ao cliente. proxy_read_timeout 600s é importante porque o valor predefinido de 60 segundos do nginx é o tempo máximo que ele aguarda entre duas leituras do gateway, e não um limite para a resposta completa. Uma conclusão sem streaming não envia nada até a geração terminar. Por isso, uma geração demorada ultrapassa 60 segundos sem que chegue um byte, e o cliente recebe um 504 enquanto o log de erros regista upstream timed out (110: Connection timed out) while reading response header from upstream. Uma conclusão em streaming que continua a enviar blocos pode durar muito mais de 60 segundos. O timeout só ocorre se o modelo ficar em silêncio durante esse período.

Para o certificado, Certbot com Let's Encrypt no nginx é o caminho mais curto. Se o servidor já disponibiliza vários contentores, Traefik à frente de várias aplicações Compose trata do encaminhamento e dos certificados num único local.

O gateway agora é um ponto único de falha

Seja honesto sobre o que você criou. Agora cada aplicação sob sua responsabilidade depende de um container em um único VPS. Enquanto ele estiver indisponível, nada poderá chamar nenhum modelo, inclusive os provedores que estiverem funcionando normalmente. Isso tem quatro consequências.

  • Uma configuração incorreta derruba tudo de uma vez. restart: unless-stopped reinicia um processo que falhou e reinicia repetidamente um container que não consegue analisar config.yaml. Leia docker compose logs litellm após cada alteração de configuração e faça alterações quando tiver tempo para monitorá-las.
  • O Postgres fica no caminho das requisições quando há perda de cache. A consulta de uma chave virtual usa o banco quando a chave não está em cache; o registro do consumo é feito de forma assíncrona após a resposta. /health/readiness retornar 503 é o aviso de que o gateway está em execução, mas não consegue fazer nenhuma das duas operações.
  • Use os cores primeiro e depois adicione instâncias. A orientação de produção do projeto, de um worker por instância (--num_workers 1), é destinada ao Kubernetes ou a outro autoscaler de pods que adiciona instâncias automaticamente. Em uma VM única ou em um container isolado como este, ela indica o contrário: defina a quantidade de workers como igual à quantidade de vCPUs da máquina. Na máquina com 1 vCPU mostrada acima, isso ainda é --num_workers 1; em uma máquina maior, aumente o valor e lembre-se de que cada worker consome sua própria memória. Um segundo gateway atrás de um balanceador de carga remove o container único da arquitetura. Isso não remove o banco de dados.
  • Faça backup do que não pode ser regenerado. Isso inclui config.yaml e .env, junto com um pg_dump do banco de dados. Perder LITELLM_SALT_KEY torna inúteis as credenciais criptografadas dos provedores dentro desse dump. Por isso, o arquivo de ambiente e o dump devem fazer parte do mesmo job de backup: backups do restic em armazenamento externo.

Para fazer upgrade, edite a tag da imagem e execute docker compose up -d. Por padrão, o LiteLLM executa prisma migrate deploy na inicialização. Assim, o novo container migra o schema do banco de dados no primeiro boot. Faça o dump antes de alterar a tag, porque restaurar a imagem antiga não desfaz uma migração que já foi executada.

Leia as notas de release de todas as versões que você ignorar, não apenas da versão final. Passar de v1.95.0 para v1.104.0 ou posterior atravessa várias alterações incompatíveis: o código de status de orçamento mencionado acima, um proxy que se recusa a iniciar quando a master key está indefinida, vazia ou é publicamente conhecida, e um proxy que encerra quando a configuração do banco de dados falha na inicialização. Com restart: unless-stopped, isso aparece como um loop de reinicialização. Se você vier de v1.102.x ou anterior, as notas da v1.104.0 também pedirão que você crie dois índices LiteLLM_SpendLogs manualmente.

FAQ

O LiteLLM adiciona latência perceptível a cada chamada?

O projeto publica 8 ms no percentil 95 a 1000 requests por segundo, conforme indicado no README em outubro de 2026. Considere esse valor uma estimativa do fornecedor. O fator que realmente altera sua latência é a distância de rede entre suas aplicações e o gateway, porque você adicionou uma viagem de ida e volta a cada chamada. Execute o gateway na mesma região das aplicações que o chamam e meça sua própria sobrecarga com o cabeçalho x-litellm-overhead-duration-ms em uma resposta real.

Por que o streaming parou de funcionar depois que coloquei o nginx na frente?

Porque o nginx armazena em buffer as respostas upstream por padrão, e uma conclusão em streaming é uma série de eventos enviados pelo servidor. Com proxy_buffering ativado, o nginx reúne os chunks nos buffers antes de encaminhá-los, atrasando a entrega ao cliente. Defina proxy_buffering off; no bloco location. Aumente também proxy_read_timeout no mesmo bloco. Por padrão, o nginx desiste após 60 segundos sem receber dados do gateway, um intervalo que uma geração longa sem streaming atinge facilmente, e o cliente recebe um 504.

O que acontece quando uma chave virtual fica sem orçamento?

A chamada falha com um erro do tipo budget_exceeded e uma mensagem no formato Budget has been exceeded! Key=<key> Current cost: <spend>, Max budget: <max_budget>. Na v1.95.0 fixada, o status é HTTP 429; a partir da v1.104.0, o padrão passa a ser HTTP 422. Nenhum dos dois códigos informa que o problema é o orçamento. Essa é a armadilha: uma biblioteca cliente informa 429 como limite de taxa e pode tentar novamente, fazendo as pessoas investigarem limitação de taxa em vez de lerem a mensagem. Registre o corpo da resposta junto com o código de status. Confirme a posição real da chave com /key/info?key=sk-... usando a master key e aumente o limite com /key/update se o orçamento tiver sido definido muito baixo.

O gateway também pode encaminhar para um modelo local, além dos modelos hospedados?

Sim. Essa é mais uma entrada em model_list. Use o prefixo ollama_chat/ com um api_base, por exemplo model: ollama_chat/llama3.1 junto com api_base: http://ollama:11434. Na rede padrão do Compose, localhost dentro de um container significa esse próprio container. Portanto, use o nome do serviço do Compose ou o endereço do host na rede Docker, nunca 127.0.0.1. A rede do host, na qual o container compartilha a pilha de rede do host, é a exceção. Colocar o modelo local em execução é uma tarefa separada: consulte hospedando um LLM localmente com Ollama em um VPS.

Este artigo foi útil?