Format JSONL, custom_id et Upload de Fichiers
Mis à jour le 29 juillet 2026
Le format JSONL : colonne vertébrale du Batch Inference
Le format JSONL (JSON Lines) est le standard utilisé par Mistral pour structurer vos requêtes batch. Chaque ligne du fichier est un objet JSON autonome représentant une requête individuelle. Ce choix n’a rien d’arbitraire : un fichier d’un million de lignes se génère en streaming sans jamais tenir en mémoire, se relit ligne par ligne, et s’inspecte à la main quand une requête pose problème. Là où un gros tableau JSON unique vous obligerait à tout charger pour vérifier une seule entrée, le JSONL vous laisse travailler au niveau de la ligne.
Structure d’une requête JSONL
Chaque ligne de votre fichier JSONL contient deux champs obligatoires :
{
"custom_id": "req-001",
"body": {
"max_tokens": 100,
"messages": [
{"role": "user", "content": "Résumez ce document en 3 points."}
]
}
}
Le custom_id est un identifiant unique que vous définissez pour chaque requête, et c’est lui qui rend le résultat exploitable. Mistral ne garantit pas l’ordre de traitement : le fichier de sortie peut très bien commencer par la requête 8 472. Sans custom_id, vous vous retrouvez avec un tas de réponses dont vous ignorez à quel document chacune se rapporte. Prenez donc l’habitude de le dériver de votre propre référentiel — doc-001, email-2024-03-15-042, product-sku-ABC123 — plutôt que d’un compteur anonyme : quand une réponse pose problème, vous retrouvez la source d’origine sans requête SQL. Deux règles pratiques accompagnent ce choix : l’unicité au sein du fichier, faute de quoi le traitement remonte une erreur, et une longueur raisonnable, parce qu’un identifiant de deux cents caractères rend les logs illisibles.
Le champ body, lui, ne demande aucun apprentissage supplémentaire : il contient exactement la structure que vous utiliseriez pour un appel API synchrone à l’endpoint cible. Si vous ciblez /v1/chat/completions, le body est identique à ce que vous passeriez dans un appel client.chat.complete(). Un prompt validé en interactif se transpose donc tel quel dans un batch.
Préparer un fichier JSONL en Python
Voici comment générer programmatiquement un fichier JSONL à partir d’une liste de documents :
import json
documents = [
{"id": "doc-001", "text": "L'intelligence artificielle transforme..."},
{"id": "doc-002", "text": "Les réseaux de neurones profonds..."},
{"id": "doc-003", "text": "Le traitement du langage naturel..."},
]
with open("batch_requests.jsonl", "w", encoding="utf-8") as f:
for doc in documents:
request = {
"custom_id": doc["id"],
"body": {
"model": "mistral-small-latest",
"max_tokens": 200,
"messages": [
{
"role": "system",
"content": "Vous êtes un assistant qui résume des textes."
},
{
"role": "user",
"content": f"Résumez ce texte : {doc['text']}"
}
]
}
}
f.write(json.dumps(request, ensure_ascii=False) + "\n")
Notez le ensure_ascii=False : sans lui, json.dumps échappe les accents en séquences \uXXXX. Le fichier reste valide, mais devient impossible à relire humainement, et le moindre débogage sur un corpus français tourne au déchiffrage. Prenez le réflexe dès la première ligne de code.
Uploader le fichier sur Mistral
En production, l’upload se fait par l’API Python :
from mistralai import Mistral
client = Mistral(api_key="votre-clé-api")
# Upload du fichier JSONL
with open("batch_requests.jsonl", "rb") as f:
batch_file = client.files.upload(
file=("batch_requests.jsonl", f),
purpose="batch"
)
print(f"Fichier uploadé : {batch_file.id}")
print(f"Taille : {batch_file.bytes} octets")
print(f"Statut : {batch_file.purpose}")
Le paramètre purpose="batch" indique à Mistral que ce fichier est destiné au traitement batch et non à d’autres fonctionnalités comme le fine-tuning ou le RAG. C’est une déclaration d’intention qui conditionne la suite : un fichier uploadé avec le mauvais purpose ne sera pas accepté par le job.
Pour un test rapide ou une équipe non technique, AI Studio offre le même service par l’interface graphique :
- Rendez-vous sur
console.mistral.ai/build/files - Cliquez sur “Upload”
- Sélectionnez votre fichier JSONL
- Choisissez le purpose “Batch Processing”
L’interface vous retourne un file_id, exactement comme l’API, et c’est cet identifiant que vous utiliserez pour créer le job batch.
Validation du fichier
Un batch d’un million de lignes qui échoue à la trois centième pour un custom_id dupliqué vous coûte un cycle complet d’attente. Quelques secondes de validation locale évitent cette perte. Le script suivant vérifie d’un seul passage la validité JSON, la présence des deux champs obligatoires et l’unicité des identifiants :
import json
errors = []
seen_ids = set()
with open("batch_requests.jsonl", "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
try:
data = json.loads(line)
except json.JSONDecodeError as e:
errors.append(f"Ligne {line_num}: JSON invalide - {e}")
continue
# Vérifier les champs obligatoires
if "custom_id" not in data:
errors.append(f"Ligne {line_num}: custom_id manquant")
if "body" not in data:
errors.append(f"Ligne {line_num}: body manquant")
# Vérifier l'unicité des custom_id
cid = data.get("custom_id")
if cid in seen_ids:
errors.append(f"Ligne {line_num}: custom_id dupliqué '{cid}'")
seen_ids.add(cid)
if errors:
print(f"{len(errors)} erreur(s) trouvée(s) :")
for e in errors:
print(f" - {e}")
else:
print(f"Fichier valide : {len(seen_ids)} requêtes prêtes.")
Faites-en une étape systématique de votre pipeline de préparation, exécutée juste avant l’upload.
Limites et contraintes
Le file batching plafonne à un million de lignes par fichier, ce qui suppose de découper les corpus plus gros en plusieurs soumissions. L’encodage doit être de l’UTF-8, et le format impose strictement une requête JSON par ligne : un objet JSON réparti sur plusieurs lignes, tel que le produirait un json.dumps(..., indent=2) mal placé, casse le parsing côté serveur. Restent les deux règles déjà vues, dont le non-respect fait échouer le job : le custom_id doit être unique dans le fichier, et le body doit correspondre au schéma de l’endpoint ciblé.
Points clés à retenir
- Le format JSONL structure vos requêtes batch avec un objet JSON par ligne
- Chaque requête a un
custom_idunique et unbodyconforme à l’endpoint cible - L’upload se fait via l’API Python (
client.files.upload) ou via AI Studio - Validez toujours votre fichier avant soumission pour éviter les erreurs de traitement
- Utilisez
ensure_ascii=Falsepour le français et les caractères accentués