API publiqueChat completions

Chat completions

Génère une réponse conversationnelle à partir d'une liste de messages. Endpoint principal de la plateforme, compatible avec le format openai.chat.completions.create. Supporte le streaming SSE.

stablev1compatible OpenAISSE

Endpoint#endpoint

POSThttps://ai.3gks.cloud/v1/chat/completionsauth : Bearer sk-3gk-…
Compatibilité OpenAI. Le SDK officiel openai Python et Node.js fonctionne immédiatement en pointant base_url sur notre domaine. Aucune réécriture nécessaire.

Paramètres requête#params

ChampDescription
model
string
requis
Identifiant du modèle : <code>3gk-llm</code> (alias stable, découplé du modèle sous-jacent). La liste complète est exposée par GET /v1/models.
ex. "3gk-llm"
messages
array<Message>
requis
Historique de la conversation. Rôles supportés : "system", "user", "assistant", "tool". content accepte une chaîne, null, ou un tableau de parts typées — voir "Contenus multimodaux" ci-dessous.
effort
"off" | "low" | "medium" | "high"
défaut "off"
Extension 3GK. Règle l'effort de raisonnement (chain-of-thought) de <code>3gk-llm</code>. Raisonnement opt-in : off par défaut (configurable côté admin). Voir le tableau dédié ci-dessous. Inconnu ⇒ 400 invalid_request.
reasoning_effort
"minimal" | "low" | "medium" | "high"
Alias standard OpenAI de effort (minimal ⇒ low). Ignoré si effort est présent (effort prime). Inconnu ⇒ 400 invalid_request.
stream
boolean
défaut false
Si true, la réponse est envoyée en Server-Sent Events. Booléen STRICT : la chaîne "true" est refusée (400 invalid_request), jamais convertie. Voir Streaming SSE.
background
boolean
défaut false
Extension 3GK. Si true, la requête est acceptée immédiatement (202 + identifiant job_…) et exécutée en arrière-plan ; le résultat se récupère via GET /v1/jobs/{id}. Booléen STRICT, comme stream. Incompatible avec stream (400 invalid_request). Voir Jobs asynchrones.
temperature
number · 0.0 → 2.0
défaut 0.7
Contrôle la créativité. Valeurs basses pour des sorties déterministes, hautes pour de la variété.
max_tokens
integer
défaut plafond
Budget de réponse (hors raisonnement), borné par le plafond de sortie de la plateforme. Cf. encarts "Plafond de sortie" et "Réconciliation max_tokens" ci-dessous. max_completion_tokens accepté en alias OpenAI.
top_p
number · 0.0 → 1.0
défaut 1.0
Nucleus sampling. Alternative à temperature.
n
integer · 1 → 4
défaut 1
Nombre de complétions générées. Plafonné à 4 : au-delà (ou en dessous de 1) ⇒ 400 invalid_request. Attention, le plafond de tokens de sortie de la plateforme s'applique PAR choix — une requête peut donc générer, et facturer, jusqu'à plafond × n tokens.
stream_options
{ include_usage?: boolean }
Options de streaming. Objet STRICT : seule la clé include_usage est acceptée, toute autre clé ⇒ 400 invalid_request.
stop
string | string[]
Séquences qui interrompent la génération.
seed
integer
Améliore la reproductibilité (best-effort, non garanti).
user
string
Identifiant opaque de l'utilisateur final. Utile pour le débogage côté admin.
top_k
integer · -1 → 1000
Extension du moteur d'inférence, relayée <strong>sur la route nominale vLLM uniquement</strong> (jamais vers le backend de repli). <code>-1</code> = désactivé. Hors bornes ⇒ 400 invalid_request. Sans effet sur le coût.
min_p
number · 0.0 → 1.0
Extension du moteur d'inférence, relayée <strong>sur la route nominale vLLM uniquement</strong>. Probabilité minimale relative d'un token. Hors bornes ⇒ 400 invalid_request. Sans effet sur le coût.
repetition_penalty
number · &gt; 0 et ≤ 2
Extension du moteur d'inférence, relayée <strong>sur la route nominale vLLM uniquement</strong>. Hors bornes (dont 0) ⇒ 400 invalid_request. Sans effet sur le coût.
parallel_tool_calls
boolean
Standard OpenAI, relayé <strong>sur la route nominale vLLM uniquement</strong>. <code>false</code> interdit les appels d'outils en parallèle. Une valeur non booléenne ⇒ 400 invalid_request ; <code>null</code> est accepté et traité comme une absence.
Paramètres relayés : liste blanche. En plus des champs ci-dessus, seuls ces paramètres OpenAI standard sont relayés au backend d'inférence : max_completion_tokens, stop, presence_penalty, frequency_penalty, logit_bias, logprobs, top_logprobs, response_format, tools, tool_choice. Leur comportement dépend du modèle cible. S'y ajoutent quatre réglages d'échantillonnage sans effet sur le coût — top_k, min_p, repetition_penalty et parallel_tool_calls — décrits dans le tableau ci-dessus et relayés sur la route nominale vLLM uniquement : ils sont validés (une valeur hors bornes est refusée en 400 invalid_request, elle n'est pas ignorée). Tout autre paramètre est accepté sans erreur mais silencieusement retiré avant l'envoi — y compris les extensions propres au moteur d'inférence (best_of, min_tokens, ignore_eos, guided_json, chat_template_kwargs, vllm_xargs…), dont le coût de génération n'est pas bornable. Ne comptez donc jamais sur un passthrough intégral : vérifiez que le paramètre figure bien dans cette liste.

Contenus multimodaux

Le champ content d'un message peut être un tableau de parts. Trois types sont acceptés, tous en ligne : text, image_url et input_audio. Tout autre type (input_image, image_embeds, prompt_embeds…) est refusé en 400 invalid_request.

  • text — champ text (chaîne) obligatoire.
  • image_url — image_url.url doit être une data URL base64 (data:image/png|jpeg|webp|gif;base64,…). Les URL http(s) distantes sont refusées : le backend d'inférence les téléchargerait depuis son propre réseau. Encodez l'image côté client. detail optionnel : auto, low ou high.
  • input_audio — input_audio.data en base64 (jamais une URL) et input_audio.format à wav ou mp3.

Le poids total du corps reste soumis à la limite de taille de la plateforme (413 payload_too_large) : une image base64 pèse ~33 % de plus que le binaire.

Générations longues (> 100 s). En mode synchrone non streamé, une génération qui dépasse ~100 s est coupée par l'infrastructure (erreur 524). Deux parades : le streaming SSE (tant que le premier token arrive vite), ou le mode asynchrone background: true — soumission immédiate puis récupération par polling. Voir Jobs asynchrones.

Paliers d'effort

Le paramètre effort contrôle l'effort de raisonnement chain-of-thought de 3gk-llm (modèle à raisonnement). Le client choisit un palier — le budget de tokens raisonnement est figé côté gateway et ne peut pas être réglé directement. Le raisonnement est opt-in : sans effort ni reasoning_effort, le palier appliqué est off (défaut configurable côté admin).

effortThinkingBudget raisonnement
off (défaut)désactivé—
lowactivé1 024 tokens
mediumactivé4 096 tokens
highactivé16 384 tokens

Vous pouvez aussi utiliser le paramètre standard OpenAI reasoning_effort (minimal | low | medium | high) pour réactiver le raisonnement sans le champ propriétaire effort : minimal est mappé sur low. Si les deux sont fournis, effort prime.

Plafond de sortie

La plateforme borne le budget de réponse de chaque requête. Ce plafond vaut aujourd'hui 4 096 tokens ; il est administrable et peut évoluer, ne le codez pas en dur.

  • Un max_tokens (ou max_completion_tokens) supérieur au plafond est ramené au plafond, sans erreur : la requête est servie, mais la réponse s'arrêtera sur finish_reason: "length" bien avant la valeur demandée.
  • Une valeur inférieure ou égale au plafond est appliquée telle quelle.
  • Si vous n'envoyez ni l'un ni l'autre, le plafond est imposé comme budget de réponse.
  • Le plafond s'applique par choix de complétion : avec n > 1, la sortie totale peut atteindre plafond × n.
Monter l'effort n'allonge pas la réponse. Le plafond borne le budget de réponse, pas le max_tokens relayé au backend : avec effort: high, celui-ci vaut 16 384 (raisonnement) + 4 096 (réponse) = 20 480. Ces 16 384 tokens supplémentaires sont consommés par le raisonnement, qui n'est pas la réponse. Pour produire un texte plus long que le plafond, il faut découper la demande en plusieurs requêtes — augmenter l'effort ne sert à rien, et peut même raccourcir la réponse si le modèle épuise son budget en réflexion.
Savoir que votre valeur a été abaissée. Quand votre max_tokens est ramené au plafond, la réponse porte l'en-tête X-3GK-Output-Tokens-Capped, dont la valeur est le plafond appliqué. Son absence signifie que votre budget a été respecté. Un finish_reason: "length" sans cet en-tête est donc une réponse tronquée sur la limite que vous avez vous-même fixée.

Réconciliation max_tokens

Côté backend, max_tokens plafonne le total raisonnement + réponse. Pour vous éviter de soustraire vous-même le budget de raisonnement, la gateway traite votre max_tokens comme le budget de réponse uniquement et ajoute le budget de raisonnement avant de relayer :

max_tokens_relayé = thinking_token_budget + max_tokens_user
  • Si max_tokens absent : le plafond de sortie est imposé (cf. ci-dessous).
  • Pour effort: off : pas d'ajout, on relaie votre valeur une fois plafonnée, et le raisonnement est désactivé en amont (enable_thinking=false).
  • max_completion_tokens (alias OpenAI récent) prime sur max_tokens si les deux sont fournis.
  • Cette réconciliation s'applique uniquement aux modèles qui supportent le thinking (c'est le cas de 3gk-llm). Pour les autres, votre max_tokens passe inchangé.
Comportement en fallback Scaleway. Si la requête bascule vers Scaleway (mode auto/forceFallback ou vLLM indisponible), effort est honoré de la même façon : activation/désactivation du raisonnement (enable_thinking) et réconciliation de max_tokens identiques. Seule réserve : le plafonnement strict du raisonnement (thinking_token_budget) n'est pas garanti côté Scaleway — la longueur du raisonnement peut donc varier, mais votre budget de réponse reste préservé.
Savoir quel backend a répondu. Chaque réponse expose un header X-3GK-Backend (primary = infrastructure nominale, fallback = secours) et X-3GK-Resolved-Model indiquant l'identifiant public du modèle servi. Utile pour vérifier qu'une requête est bien servie en nominal plutôt qu'en secours.

Exemples#exemples

python
from openai import OpenAI

client = OpenAI(
    base_url="https://ai.3gks.cloud/v1",
    api_key="sk-3gk-7XQp4kL8…",
)

response = client.chat.completions.create(
    model="3gk-llm",
    messages=[
        {"role": "system", "content": "Tu es un assistant pour courtier en assurance."},
        {"role": "user", "content": "Résume ce contrat : …"},
    ],
    temperature=0.3,
    max_tokens=512,
)

print(response.choices[0].message.content)

Format de réponse#response

Réponse JSON conforme à l'API OpenAI. L'identifiant id est préfixé 3gk-cmpl- suivi de 24 caractères aléatoires — utilisez-le pour corréler avec les logs admin en cas de support.

application/json
{
  "id": "3gk-cmpl-7XQp4kL8mNfRtQzVa2bC3dE4",
  "object": "chat.completion",
  "created": 1715761712,
  "model": "3gk-llm",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Le contrat couvre la responsabilité civile…"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 412,
    "completion_tokens": 248,
    "total_tokens": 660
  }
}

Sur les paliers low / medium / high, le champ choices[].message.reasoning et usage.completion_tokens_details.reasoning_tokens sont également retournés. En effort: off, ces champs sont strippés.

Codes de réponse#status

200 OK
Succès · La réponse JSON contient le champ choices.
202
queued · Mode background: true : job accepté, réponse {id: "job_…", status: "queued"}. Résultat via GET /v1/jobs/{id}.
400
invalid_request · Paramètre manquant ou format invalide : model/messages absent, stream ou background non booléen, n hors de 1..4, part de contenu non supportée ou image en URL distante, stream + background combinés.
400
model_not_supported · L'identifiant demandé n'est pas dans la liste autorisée. Utilisez 3gk-llm ou consultez GET /v1/models.
400
context_length_exceeded · Prompt au-delà du nombre de tokens maximal accepté (définitions tools comprises). Raccourcissez le contexte.
401
auth_error · Clé absente, mal formée, révoquée ou compte suspendu.
402
insufficient_quota · Accès facturation bloqué avant toute exécution (essai terminé, crédit épuisé, plafond du forfait, facture de dépassement impayée, litige de paiement).
413
payload_too_large · Corps de requête au-delà de la taille maximale acceptée — fréquent avec des images base64.
429
rate_limit_exceeded · Cadence trop élevée pour votre adresse IP, ou trop d'appels simultanés pour votre compte. Backoff exponentiel.
502
upstream_error · L'instance vLLM ou Scaleway a renvoyé une erreur 5xx, un JSON invalide ou est injoignable.
503
upstream_error · Aucun backend disponible pour servir le modèle demandé (configuration en cours côté plateforme).
503
internal · Tarification du service non configurée pour un compte facturé : l'appel est refusé plutôt que servi hors tarif. Réessayez plus tard.
504
upstream_timeout · Le backend a dépassé le timeout configuré (par défaut 600 s, surchargeable par instance).
500
internal · Erreur native non gérée côté gateway. À remonter au support.

Pour le détail du format d'erreur et des stratégies de retry, voir Codes d'erreur.

Routage & fallback#routing

Les requêtes chat.completions sont routées par défaut vers nos instances vLLM locales (GPU hébergés en France). Si l'administrateur a configuré un mode fallback ou auto et que les instances vLLM sont indisponibles, le trafic bascule vers Scaleway Generative APIs (Paris, FR). Aucune donnée ne sort du territoire français.

Comportement actuel des erreurs upstream. En V1, une erreur réseau ou un 5xx sur le backend choisi est remonté directement au client (502 / 504) sans retry automatique. Pour basculer en Scaleway, l'administrateur doit activer le mode auto ou forceFallback.