Alpaga

Documentation

Alpaga parle le dialecte de l'API d'OpenAI : tout client qui accepte une autre adresse de base fonctionne, en lui donnant celle d'Alpaga et votre clé.

Adresse et clé

L'adresse de base est https://alpaga.subalpine.it/v1. Chaque requête porte votre clé dans l'en-tête Authorization: Bearer alp_…. La clé se crée dans votre espace, une fois votre demande d'accès acceptée ; elle ne s'affiche qu'une fois. Les exemples la lisent dans la variable d'environnement ALPAGA_CLE :

export ALPAGA_CLE="alp_…"

Deux routes : POST /v1/chat/completions pour générer, GET /v1/models pour la liste des modèles ouverts à votre compte. Sans model, la requête va au modèle par défaut, qwen3:30b-a3b.

curl

curl https://alpaga.subalpine.it/v1/chat/completions \
  -H "Authorization: Bearer $ALPAGA_CLE" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3:30b-a3b",
    "messages": [
      {"role": "system", "content": "Tu réponds en français, brièvement."},
      {"role": "user", "content": "Résume la règle du hors-jeu au football."}
    ]
  }'
curl https://alpaga.subalpine.it/v1/models -H "Authorization: Bearer $ALPAGA_CLE"

Python

Avec la bibliothèque officielle d'OpenAI (pip install openai) :

import os
from openai import OpenAI

client = OpenAI(base_url="https://alpaga.subalpine.it/v1", api_key=os.environ["ALPAGA_CLE"], timeout=900)

reponse = client.chat.completions.create(
    model="qwen3:30b-a3b",
    messages=[{"role": "user", "content": "Trois idées de titre pour un article sur le compost."}],
    max_tokens=300,
)
print(reponse.choices[0].message.content)
print(reponse.usage)  # jetons lus et écrits

Une génération sur processeur prend du temps : laissez au client un délai large (timeout=900), ou préférez le flux.

JavaScript

Avec la bibliothèque openai pour Node.js (npm install openai) :

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://alpaga.subalpine.it/v1",
  apiKey: process.env.ALPAGA_CLE,
  timeout: 900_000,
});

const reponse = await client.chat.completions.create({
  model: "qwen3:30b-a3b",
  messages: [{ role: "user", content: "Explique la photosynthèse à un enfant de dix ans." }],
});
console.log(reponse.choices[0].message.content);

Gardez la clé côté serveur : dans une page web, elle serait lisible par tous les visiteurs.

Réponses en flux

Avec "stream": true, la réponse arrive mot à mot, au format des événements d'OpenAI (data: {…}, puis data: [DONE]). C'est le plus confortable ici : le premier mot paraît dès que la génération commence.

flux = client.chat.completions.create(
    model="qwen3:30b-a3b",
    messages=[{"role": "user", "content": "Écris un haïku sur la neige."}],
    stream=True,
)
for morceau in flux:
    print(morceau.choices[0].delta.content or "", end="", flush=True)

Paramètres

messages
Obligatoire. Rôles system, user, assistant, contenu en texte.
model
Facultatif : le modèle par défaut sinon. GET /v1/models dit lesquels vous sont ouverts.
max_tokens
Longueur de la réponse, plafonnée à 2 048 jetons par le serveur.
temperature, top_p, seed, stop
Comme chez OpenAI. frequency_penalty et presence_penalty aussi.
response_format
{"type": "json_object"} pour du JSON, ou json_schema avec un schéma pour une forme imposée.
think
Propre à Alpaga : true laisse le modèle raisonner avant de répondre (plus long). Le raisonnement revient dans reasoning_content.

Le contexte (invite et réponse ensemble) est fixé à 8 192 jetons. Les appels d'outils (tools) et plusieurs réponses par requête (n > 1) ne sont pas pris en charge : la requête est refusée (400) plutôt qu'à moitié servie.

Limites et erreurs

Votre compte a un nombre de requêtes par jour (remis à zéro à minuit UTC), parfois par semaine ou un quota de jetons par mois, et un débit par minute : votre espace les donne, avec votre consommation. Les requêtes en cours comptent déjà.

Le serveur n'a pas de carte graphique : les générations passent une à une, à tour de rôle entre comptes. 8 requêtes au plus attendent, dont 2 par compte ; au-delà de 5 minutes d'attente, la requête est abandonnée.

StatutCodeCe qu'il faut faire
401missing_api_key, invalid_api_keyVérifier l'en-tête ; une clé remplacée ou un compte suspendu sont refusés.
403model_not_allowedChoisir un modèle de GET /v1/models.
429rate_limit_exceeded, daily_limit_exceeded, weekly_limit_exceeded, insufficient_quotaAttendre : l'en-tête Retry-After donne le délai en secondes.
429queue_full, account_queue_fullLa file est pleine : réessayer dans 30 secondes.
503queue_timeoutLe serveur est très occupé : réessayer plus tard.
502, 504upstream_*Le moteur ne répond pas : réessayer, puis écrire à contact@subalpine.it.

Les invites et les réponses ne sont pas enregistrées : seuls des compteurs (jetons, durée, issue) le sont, et ce sont eux que montre votre espace.

Autres outils

Tout outil qui accepte un « fournisseur compatible OpenAI » se branche de la même façon : adresse de base https://alpaga.subalpine.it/v1, clé alp_…, modèle qwen3:30b-a3b. C'est le cas de LangChain (ChatOpenAI(base_url=…, api_key=…)), de LlamaIndex, de LiteLLM, de LibreChat et des outils ci-dessous.

Open WebUI

Dans Réglages → Connexions, ajoutez une connexion OpenAI avec l'adresse https://alpaga.subalpine.it/v1 et votre clé : les modèles ouverts à votre compte apparaissent dans la liste.

Aider

Aider lit l'adresse et la clé dans l'environnement ; le préfixe openai/ lui indique de passer par l'API compatible.

export OPENAI_API_BASE="https://alpaga.subalpine.it/v1"
export OPENAI_API_KEY="$ALPAGA_CLE"
aider --model "openai/qwen3:30b-a3b"

Continue

Dans le fichier config.yaml de Continue, un modèle de fournisseur openai pointé sur Alpaga sert à la conversation et aux réécritures.

models:
  - name: Alpaga
    provider: openai
    model: qwen3:30b-a3b
    apiBase: https://alpaga.subalpine.it/v1
    apiKey: alp_…
    roles: [chat, edit]

Claude Code et les agents

Claude Code, le mode agent de Cursor ou celui de Continue ne fonctionnent pas encore avec Alpaga. Ces agents pilotent des outils (lire un fichier, lancer une commande), ce que la passerelle refuse pour l'instant, et leurs seules consignes dépassent le contexte de 8 192 jetons que le serveur ouvre. Claude Code parle en outre le format d'Anthropic, et non celui d'OpenAI.