A resposta curta
Crie o cliente com dois argumentos, base_url e api_key, e continue usando os mesmos métodos que você já conhece. A URL base para esta API é https://api.apicompatible.com/v1, o id do modelo é uncensored, e a autenticação é um token bearer padrão que o SDK constrói a partir da sua chave.
from openai import OpenAI
client = OpenAI(
base_url="https://api.apicompatible.com/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a concise assistant."},
{"role": "user", "content": "Name three uses for a hash map."},
],
)
print(resp.choices[0].message.content)
print(resp.usage)
Essa é a alteração completa. O SDK anexa /chat/completions à URL base, então a requisição vai para POST /v1/chat/completions. Se você ainda não tem uma chave, a página da chave de API explica o cadastro e o crédito de teste.
Definindo a URL base com variáveis de ambiente
O SDK Python oficial lê OPENAI_API_KEY e OPENAI_BASE_URL do ambiente quando você não os passa no código. Isso é útil quando o mesmo aplicativo é executado contra diferentes endpoints em desenvolvimento e produção, ou quando uma ferramenta de terceiros constrói o cliente para você e não oferece lugar para editar argumentos do construtor.
export OPENAI_BASE_URL="https://api.apicompatible.com/v1"
export OPENAI_API_KEY="YOUR_API_KEY"
python - <<'EOF'
from openai import OpenAI
client = OpenAI()
r = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Say hello in five words."}],
)
print(r.choices[0].message.content)
EOF
Argumentos explícitos têm prioridade sobre variáveis de ambiente. Se uma chamada for para o host errado, verifique se outra parte do seu código cria um cliente com seu próprio base_url, e se um carregador de .env é executado antes do seu script ler as variáveis.
Mantenha a chave fora do controle de versão. Uma chave em uma variável de ambiente ou gerenciador de segredos é fácil de rotacionar; uma chave em um arquivo comitado não é.
A mesma alteração em Node
O pacote Node usa camel case para a mesma opção. Tudo o resto, incluindo os nomes dos métodos e a forma da resposta, corresponde ao que você escreveria contra qualquer endpoint no formato OpenAI.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.apicompatible.com/v1",
apiKey: process.env.API_KEY,
});
const completion = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "Give me a one-line commit message for a typo fix." }],
});
console.log(completion.choices[0].message.content);
Para uma verificação HTTP bruta sem nenhum SDK, esta chamada curl envia a mesma requisição e é útil para separar problemas do SDK de problemas de chave:
curl https://api.apicompatible.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"uncensored","messages":[{"role":"user","content":"ping"}]}'
Streaming, assíncrono e retentativas
O streaming usa eventos enviados pelo servidor, e o SDK os transforma em um iterador. Passe stream=True e leia os deltas conforme chegam. Os números de uso chegam no final do streaming, então proteja-se contra chunks que não carregam texto.
from openai import OpenAI
client = OpenAI(
base_url="https://api.apicompatible.com/v1",
api_key="YOUR_API_KEY",
)
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Explain idempotency in two sentences."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
O cliente assíncrono aceita os mesmos dois argumentos. Troque OpenAI por AsyncOpenAI, adicione await, e use async for em streams de streaming.
Dois limites importam quando você executa mais de uma requisição ao mesmo tempo. Uma chave completa permite 8 requisições concorrentes e 300 requisições por minuto, e uma chave de teste permite 2 e 60. Uma requisição transmitida mantém seu slot de concorrência até que o stream termine, então um consumidor travado que nunca drena o stream desperdiça um slot. Acima do limite você recebe HTTP 429 com o código de erro rate_limited ou concurrency. O SDK tenta novamente requisições falhas algumas vezes por padrão, e você pode mudar isso com max_retries no cliente. Um 429 com um cabeçalho Retry-After: 5 significa sobrecarga temporária, então esperar cinco segundos é a resposta correta.
Timeouts, reutilização de cliente e depuração do que foi enviado
Crie o cliente uma vez e reutilize-o. Cada cliente mantém seu próprio conjunto de conexões, então criar um novo para cada requisição desperdiça tempo e torna o código de streaming mais difícil de entender. Ambas as opções abaixo são definidas no construtor e se aplicam a cada chamada feita através desse cliente.
from openai import OpenAI
client = OpenAI(
base_url="https://api.apicompatible.com/v1",
api_key="YOUR_API_KEY",
timeout=60.0,
max_retries=2,
)
Gerações longas podem demorar, então um tempo limite muito curto produz erros que parecem falhas de serviço. Escolha um tempo limite que se adapte à sua resposta mais longa esperada, e aumente-o para grandes saídas.
Quando você não consegue saber qual URL ou chave uma requisição usou, ative o log de depuração do SDK. Versões recentes do pacote Python leem uma variável de ambiente OPENAI_LOG, e defini-la como debug imprime a linha da requisição e o status da resposta. Verifique a documentação atual do SDK para o comportamento exato na sua versão, e remova a variável depois, já que os logs podem conter dados sensíveis. O host impresso deve ser api.apicompatible.com. Se mostrar algo diferente, uma instância de cliente diferente ou uma variável de ambiente está substituindo sua configuração.
Um último hábito que economiza tempo: mantenha a URL base, a chave e o id do modelo em um módulo de configuração. Quando os três vivem em um só lugar, alterar endpoints torna-se uma única edição e uma única revisão.
Erros que quebram a primeira chamada
A maioria das primeiras chamadas falhas vem de uma lista curta de causas. Verifique-a na ordem antes de suspeitar do serviço.
A URL base não contém /v1 ou possui um caminho estranho
O SDK adiciona apenas o nome do endpoint, então a URL base deve terminar em /v1. Usar https://api.apicompatible.com sem a parte da versão, ou colar o caminho completo /v1/chat/completions, geralmente produz um erro not-found porque a URL final acaba errada. Imprima client.base_url se não tiver certeza do que o SDK resolveu.
O id do modelo ainda é um nome de outro provedor
Esta API serve um único modelo e seu id é uncensored. Um nome de modelo restante de uma configuração anterior é uma causa frequente de erros, e é fácil de perder quando o nome está em um arquivo de configuração em vez do código. Pesquise seu projeto pela string antiga.
A chave vem do lugar errado
Uma chave de outro provedor não funcionará aqui, e o inverso também é verdadeiro. Se você definir tanto OPENAI_API_KEY quanto um api_key explícito, o valor explícito é usado. Verifique qual deles chegou ao cliente.
Você chama um endpoint que esta API não oferece
A API é apenas de texto. Ela expõe /v1/chat/completions, /v1/responses e /v1/models. Não há endpoints de imagem, áudio ou embeddings e nem ajuste fino, então caminhos de código que os usam têm que permanecer com o provedor original. A análise de custo e trade-off cobre quando essa divisão faz sentido.
A carga útil é muito grande
O corpo máximo da requisição é 8 MB. Contextos longos são válidos até 100.000 tokens no total para prompt mais geração, mas blobs base64 ou arquivos colados grandes podem atingir o limite do corpo primeiro.
Verificando a conexão e seu saldo
Antes de depurar o código do aplicativo, chame GET /v1/models. Uma lista limpa significa que a chave e a URL estão corretas. Toda resposta também carrega um cabeçalho X-Balance-USD, que permite monitorar o gasto sem uma chamada separada. Com o SDK Python, use with_raw_response para ler cabeçalhos:
from openai import OpenAI
client = OpenAI(
base_url="https://api.apicompatible.com/v1",
api_key="YOUR_API_KEY",
)
raw = client.chat.completions.with_raw_response.create(
model="uncensored",
messages=[{"role": "user", "content": "ping"}],
)
print(raw.headers.get("X-Balance-USD"))
print(raw.headers.get("X-Request-Id"))
completion = raw.parse()
print(completion.choices[0].message.content)
Mantenha o valor X-Request-Id quando entrar em contato com o suporte, porque ele identifica a requisição exata. Requisições falhas ou recusadas não são cobradas, então uma chamada com erro custa nada. O preço é $0,15 por 1M tokens de entrada e $0,50 por 1M tokens de saída a partir de crédito pré-pago; a página de preços tem os detalhes e a documentação lista cada parâmetro.
