Pipeline complet de bout en bout
Sur cette page
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 > 0avant 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