FR ▾

Base_url personnalisée du SDK Python OpenAI : configuration et corrections

Un câble déplacé d'un socket de serveur à un autre, montrant un changement d'URL de base pour un SDK

Les SDK OpenAI vous permettent de remplacer l'endpoint avec un seul argument. Cette page montre la configuration exacte de la base_url personnalisée du SDK Python OpenAI pour cette API, ainsi que l'équivalent Node, le streaming et les erreurs qui causent la plupart des premiers appels échoués.

Dernière mise à jour

Résumé

  • Définissez base_url sur https://api.apicompatible.com/v1 et passez votre clé en tant que api_key ; rien d'autre dans votre code ne doit changer.
  • L'identifiant du modèle est uncensored. Laisser un ancien nom de modèle en place est la raison la plus courante d'échec d'un premier appel.
  • Le streaming fonctionne avec stream=True, et chaque requête en streaming occupe un de vos slots de concurrence jusqu'à sa fin.
  • Les variables d'environnement vous permettent de changer d'endpoint sans toucher au code.

La réponse courte

Créez le client avec deux arguments, base_url et api_key, et continuez à utiliser les mêmes méthodes que vous connaissez déjà. L'URL de base pour cette API est https://api.apicompatible.com/v1, l'identifiant du modèle est uncensored, et l'authentification est un jeton bearer standard que le SDK construit à partir de votre clé.

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)

C'est la seule modification. Le SDK ajoute /chat/completions à l'URL de base, de sorte que la requête aboutit à POST /v1/chat/completions. Si vous n'avez pas encore de clé, la page clé API explique l'inscription et le crédit d'essai gratuit.

Définition de l'URL de base avec des variables d'environnement

Le SDK Python officiel lit OPENAI_API_KEY et OPENAI_BASE_URL depuis l'environnement lorsque vous ne les passez pas dans le code. C'est utile lorsque la même application s'exécute sur différents endpoints en développement et en production, ou lorsqu'un outil tiers construit le client pour vous et ne vous donne aucun endroit pour modifier les arguments du constructeur.

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

Les arguments explicites l'emportent sur les variables d'environnement. Si un appel va vers le mauvais hôte, vérifiez si une autre partie de votre code construit un client avec sa propre base_url, et si un chargeur .env s'exécute avant que votre script ne lise les variables.

Gardez la clé hors du contrôle de version. Une clé dans une variable d'environnement ou un gestionnaire de secrets est facile à faire tourner ; une clé dans un fichier validé ne l'est pas.

Le même changement dans Node

Le package Node utilise le camelCase pour la même option. Tout le reste, y compris les noms de méthodes et la forme de la réponse, correspond à ce que vous écririez contre n'importe quel endpoint au format 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);

Pour une vérification HTTP brute sans aucun SDK, cet appel curl envoie la même requête et est pratique pour séparer les problèmes de SDK des problèmes de clé :

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, asynchrone et réessais

Le streaming utilise les événements serveur, et le SDK les transforme en itérateur. Passez stream=True et lisez les deltas à mesure qu'ils arrivent. Les chiffres d'utilisation arrivent à la fin du flux, alors protégez-vous contre les blocs qui ne contiennent pas de texte.

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()

Le client asynchrone prend les mêmes deux arguments. Remplacez OpenAI par AsyncOpenAI, ajoutez await, et utilisez async for sur les flux.

Deux limites sont importantes lorsque vous exécutez plus d'une requête à la fois. Une clé complète permet 8 requêtes simultanées et 300 requêtes par minute, et une clé d'essai permet 2 et 60. Une requête de streaming conserve son emplacement de concurrence jusqu'à la fin du flux, donc un consommateur bloquant qui ne vide jamais le flux gaspille un emplacement. Au-delà d'une limite, vous obtenez un HTTP 429 avec le code d'erreur rate_limited ou concurrency. Le SDK réessaie les requêtes échouées quelques fois par défaut, et vous pouvez modifier cela avec max_retries sur le client. Un 429 avec un en-tête Retry-After: 5 signifie une surcharge temporaire, donc attendre cinq secondes est la bonne réponse.

Timeouts, réutilisation du client et débogage de ce qui a été envoyé

Créez le client une fois et réutilisez-le. Chaque client conserve son propre pool de connexions, donc créer un nouveau client pour chaque requête perd du temps et rend le code de streaming plus difficile à raisonner. Les deux options ci-dessous sont définies sur le constructeur et s'appliquent à chaque appel effectué via ce client.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.apicompatible.com/v1",
    api_key="YOUR_API_KEY",
    timeout=60.0,
    max_retries=2,
)

Les générations longues peuvent prendre du temps, donc un timeout très court produit des erreurs qui ressemblent à des défauts de service. Choisissez un timeout qui correspond à votre réponse la plus longue attendue, et augmentez-le pour les grandes sorties.

Lorsque vous ne pouvez pas dire quelle URL ou quelle clé une requête a utilisée, activez la journalisation de débogage du SDK. Les versions récentes du package Python lisent une variable d'environnement OPENAI_LOG, et sa définition sur debug imprime la ligne de requête et le statut de réponse. Consultez la documentation actuelle du SDK pour le comportement exact dans votre version, et supprimez la variable ensuite, car les journaux peuvent contenir des données sensibles. L'hôte imprimé devrait être api.apicompatible.com. S'il affiche autre chose, une autre instance de client ou une variable d'environnement annule votre paramètre.

Une dernière habitude qui fait gagner du temps : gardez l'URL de base, la clé et l'identifiant du modèle dans un seul module de configuration. Lorsque les trois vivent à un seul endroit, changer d'endpoint devient une seule modification et une seule revue.

Erreurs qui cassent le premier appel

La plupart des premiers appels échoués proviennent d'une courte liste de causes. Parcourez-la dans l'ordre avant de soupçonner le service.

L'URL de base manque de /v1 ou a un chemin parasite

Le SDK ajoute uniquement le nom de l'endpoint, donc l'URL de base doit se terminer par /v1. Utiliser https://api.apicompatible.com sans le segment de version, ou coller le chemin complet /v1/chat/completions, génère généralement une erreur 404 car l'URL finale est incorrecte. Affichez client.base_url si vous n'êtes pas sûr de ce que le SDK a résolu.

L'identifiant du modèle est toujours un nom d'un autre fournisseur

Cette API sert un seul modèle et son identifiant est uncensored. Un nom de modèle laissé d'une configuration précédente est une cause fréquente d'erreurs, et il est facile à manquer lorsque le nom se trouve dans un fichier de configuration au lieu du code. Recherchez l'ancienne chaîne dans votre projet.

La clé provient du mauvais endroit

Une clé d'un autre fournisseur ne fonctionnera pas ici, et l'inverse est également vrai. Si vous définissez à la fois OPENAI_API_KEY et une api_key explicite, la valeur explicite est utilisée. Vérifiez laquelle a atteint le client.

Vous appelez un endpoint que cette API n'offre pas

L'API est textuelle uniquement. Elle expose /v1/chat/completions, /v1/responses et /v1/models. Il n'y a pas d'endpoints pour les images, l'audio ou les embeddings, ni de fine-tuning, donc les chemins de code qui les utilisent doivent rester sur leur fournisseur d'origine. L'analyse des coûts et des compromis couvre quand cette séparation a du sens.

La charge utile est trop volumineuse

Le corps de requête maximum est de 8 Mo. Les contextes longs sont bons jusqu'à 100 000 tokens au total pour le prompt plus la complétion, mais les blobs base64 ou les fichiers collés énormes peuvent atteindre la limite du corps en premier.

Vérification de la connexion et de votre solde

Avant de déboguer le code applicatif, appelez GET /v1/models. Une liste propre signifie que la clé et l'URL sont correctes. Chaque réponse porte également un en-tête X-Balance-USD, ce qui vous permet de surveiller les dépenses sans un appel séparé. Avec le SDK Python, utilisez with_raw_response pour lire les en-têtes :

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)

Gardez la valeur X-Request-Id lorsque vous contactez le support, car elle identifie la requête exacte. Les requêtes échouées ou refusées ne sont pas facturées, donc une mauvaise requête ne coûte rien. La tarification est de $0,15 par 1M de tokens d'entrée et de $0,50 par 1M de tokens de sortie depuis le crédit prépayé ; la page de tarification a les détails et la documentation liste chaque paramètre.

Questions fréquentes

Ai-je besoin d'un SDK spécial pour utiliser une base_url personnalisée ?

Non. Les packages Python et Node OpenAI standard acceptent une option d'URL de base. Vous modifiez cette option et la clé, et conservez vos appels existants.

Est-ce base_url ou baseURL ?

Python utilise base_url et Node utilise baseURL. Les deux prennent la même valeur, https://api.apicompatible.com/v1.

Quel nom de modèle dois-je envoyer ?

Envoyez uncensored comme modèle. Cette API exécute un seul modèle, il n'y a donc rien d'autre à choisir.

Pourquoi obtiens-je une erreur HTTP 429 lorsque j'exécute seulement quelques requêtes ?

Une clé d'essai permet 2 requêtes simultanées, et les flux ouverts comptent pour ce nombre jusqu'à leur fin. Fermez ou terminez les flux, ou passez à une clé complète pour 8 requêtes simultanées.

Obtenez votre clé en quelques secondes

Inscrivez-vous, copiez le token, mettez à jour l'URL de l'endpoint. C'est toute la configuration.

Ouvrir un compte