Aller au contenu principal

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 :

  1. Rendez-vous sur console.mistral.ai/build/files
  2. Cliquez sur “Upload”
  3. Sélectionnez votre fichier JSONL
  4. 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_id unique et un body conforme à 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=False pour le français et les caractères accentués