Aller au contenu principal
Leçon 7 sur 12 · Batch API : traitement en masse

Pipeline complet de bout en bout

Leçon 7 sur 12 Mis à jour le 2 novembre 2026 Développeur
Sur cette page
  1. Assembler les pièces
  2. Pipeline Python complet
  3. Pipeline cURL pas à pas
  4. Gestion des erreurs en production
  5. Optimisation des coûts
  6. Points clés à retenir

Cours révisé le 2 novembre 2026 d’après la documentation de xAI : la remise batch est de 20 % sur les modèles texte éligibles (et non 50 %), les exemples suivent l’API REST et le SDK officiel xai-sdk (client.batch.* ; l’API Batch de xAI n’a pas le format de celle d’OpenAI, le SDK OpenAI ne s’y applique pas), et l’API Responses passe avant Chat Completions, endpoint hérité chez xAI. Sources : Batch API · Référence REST · Tarifs batch.

Assembler les pièces

Les leçons précédentes ont couvert chaque étape isolément. Cette leçon les assemble dans un pipeline complet, de la préparation des données à l’exploitation des résultats. Vous repartirez avec un script que vous pourrez adapter à votre cas d’usage.

Pipeline Python complet

import json
import time

from xai_sdk import Client

client = Client()  # clé lue dans XAI_API_KEY

# --- Étape 1 : préparer les données ---
documents = [
    {"id": f"doc-{i}", "text": f"Contenu du document {i}..."}
    for i in range(100)
]

# --- Étape 2 : écrire le fichier JSONL ---
with open("batch_requests.jsonl", "w", encoding="utf-8") as f:
    for doc in documents:
        ligne = {
            "custom_id": doc["id"],
            "method": "POST",
            "url": "/v1/responses",
            "body": {
                "model": "grok-4.3",
                "input": [
                    {"role": "system", "content": "Résume en deux phrases."},
                    {"role": "user", "content": doc["text"]},
                ],
                "max_output_tokens": 200,
            },
        }
        f.write(json.dumps(ligne, ensure_ascii=False) + "\n")

# --- Étape 3 : téléverser le fichier ---
with open("batch_requests.jsonl", "rb") as f:
    fichier = client.files.upload(f, filename="batch_requests.jsonl")

# --- Étape 4 : créer le batch à partir du fichier (il est alors scellé) ---
batch = client.batch.create(batch_name="resumes_documents", input_file_id=fichier.id)
print(f"Batch créé : {batch.batch_id}")

# --- Étape 5 : attendre la fin du traitement ---
while True:
    batch = client.batch.get(batch_id=batch.batch_id)
    etat = batch.state
    if batch.cancel_by_xai_message:
        raise RuntimeError(f"Batch annulé par xAI : {batch.cancel_by_xai_message}")
    if etat.num_requests > 0 and etat.num_pending == 0:
        break
    print(f"{etat.num_success + etat.num_error}/{etat.num_requests} requêtes traitées")
    time.sleep(300)  # toutes les 5 minutes

# --- Étape 6 : récupérer les résultats, page par page ---
resultats, echecs = {}, []
jeton = None
while True:
    page = client.batch.list_batch_results(
        batch_id=batch.batch_id, limit=100, pagination_token=jeton
    )
    for r in page.succeeded:
        resultats[r.batch_request_id] = r.response.content
    echecs.extend(page.failed)
    if page.pagination_token is None:
        break
    jeton = page.pagination_token

with open("batch_results.json", "w", encoding="utf-8") as f:
    json.dump(resultats, f, ensure_ascii=False, indent=2)

print(f"{len(resultats)} résultats, {len(echecs)} échecs")
print("Coût total : %.4f $" % (batch.cost_breakdown.total_cost_usd_ticks / 1e10))

Trois détails comptent. La condition d’arrêt exige num_requests > 0, car un batch créé depuis un fichier est lu en arrière-plan : juste après sa création, ses compteurs peuvent encore être tous à zéro. Le champ cancel_by_xai_message signale une annulation par xAI, par exemple sur une ligne invalide. Et le coût s’exprime en ticks, des dix-milliardièmes de dollar.

Pipeline cURL pas à pas

Si vous préférez la ligne de commande, voici l’équivalent en cURL (avec jq pour lire les réponses) :

# 1. Téléverser le fichier JSONL
FILE_ID=$(curl -s -X POST https://api.x.ai/v1/files \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -F file="@batch_requests.jsonl" | jq -r '.id')
echo "Fichier : $FILE_ID"

# 2. Créer le batch à partir du fichier
BATCH_ID=$(curl -s -X POST https://api.x.ai/v1/batches \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"name\": \"resumes_documents\", \"input_file_id\": \"$FILE_ID\"}" | jq -r '.batch_id')
echo "Batch : $BATCH_ID"

# 3. Lire les compteurs
curl -s "https://api.x.ai/v1/batches/$BATCH_ID" \
  -H "Authorization: Bearer $XAI_API_KEY" | jq '.state'

# 4. Récupérer la première page de résultats
curl -s "https://api.x.ai/v1/batches/$BATCH_ID/results?limit=100" \
  -H "Authorization: Bearer $XAI_API_KEY" > resultats-page-1.json

Les pages suivantes s’obtiennent en ajoutant &pagination_token=… avec la valeur renvoyée par la page précédente.

Gestion des erreurs en production

Un pipeline robuste distingue trois familles d’erreurs :

Erreurs de soumission : le téléversement ou la création du batch échoue. Réessayez les erreurs transitoires (délai dépassé, limite de débit, erreur serveur) avec un délai croissant : 1 s, 2 s, 4 s, 8 s.

Erreurs de traitement : certaines requêtes échouent dans le batch. Elles figurent dans page.failed avec leur message ; relancez-les, et elles seules, dans un nouveau batch.

Délai et expiration : le délai de 24 heures est indicatif, pas garanti. Ce qui ne pardonne pas, c’est l’expiration (expire_time) : passé ce moment, les résultats ne sont plus accessibles. Récupérez-les au fil de l’eau plutôt qu’en une fois à la fin.

# Requêtes en échec : les identifier pour les relancer dans un nouveau batch
for r in echecs:
    print(f"Échec : {r.batch_request_id} — {r.error_message}")
a_relancer = {r.batch_request_id for r in echecs}

Optimisation des coûts

Les économies se cumulent sur quatre leviers. Le choix du modèle d’abord, de loin le plus puissant : au tarif standard du 2 novembre 2026, grok-4.3 coûte 1,25 $ par million de tokens d’entrée et 2,50 $ en sortie, contre 2 $ et 6 $ pour grok-4.7 (prompts de moins de 200 000 tokens). Pour de la classification ou de l’extraction courte, le modèle le plus léger suffit souvent, et la remise batch de 20 % s’applique aux deux. La longueur des réponses ensuite : max_output_tokens évite de payer des sorties inutilement longues — pour une classification, quelques tokens suffisent. Les prompts : dix tokens retirés d’un prompt répété 50 000 fois, ce sont 500 000 tokens d’entrée en moins. Le cache enfin : xAI met automatiquement en cache les débuts de requête identiques, et la remise batch s’applique aussi aux tokens servis depuis le cache ; placez donc les consignes communes en tête de chaque requête, avant la partie qui varie.

Points clés à retenir

  • Un pipeline complet couvre six étapes : préparation, JSONL, téléversement, création, surveillance, récupération
  • Un batch issu d’un fichier est lu en arrière-plan : attendez num_requests > 0 avant de conclure qu’il est terminé
  • Gérez les trois familles d’erreurs : soumission, traitement, délai et expiration
  • Récupérez et sauvegardez les résultats au fil de l’eau, avant expire_time
  • Choix du modèle, longueur des sorties, prompts courts et préfixes communs maximisent les économies