JSONL pour les données d'entraînement IA

Un guide complet pour préparer des données d'entraînement JSONL pour l'IA et le machine learning. Couvre le fine-tuning OpenAI, Anthropic Claude, les datasets HuggingFace, la validation des données et les pipelines de données à grande échelle.

Dernière mise à jour : février 2026

Pourquoi JSONL est le standard pour les données d'entraînement IA

JSONL (JSON Lines) est devenu le standard de facto pour les données d'entraînement IA et machine learning. Chaque grand fournisseur d'IA, d'OpenAI à Anthropic en passant par HuggingFace, utilise JSONL comme format principal pour les datasets de fine-tuning. La raison est simple : JSONL stocke un exemple par ligne, ce qui rend trivial le streaming des données pendant l'entraînement, le mélange des exemples, le comptage des enregistrements, la division en ensembles d'entraînement et de test, et l'ajout de nouveaux échantillons sans réécrire le fichier entier.

Contrairement à un tableau JSON unique qui doit être entièrement analysé avant utilisation, les fichiers JSONL peuvent être traités ligne par ligne. Cela compte lorsque vos datasets d'entraînement atteignent des millions d'exemples représentant des gigaoctets. Dans ce guide, vous apprendrez les formats JSONL exacts attendus par OpenAI, Anthropic Claude et HuggingFace, comment valider et nettoyer vos données, et comment préparer des datasets à grande échelle pour des sessions d'entraînement en production.

Format JSONL pour le fine-tuning OpenAI

OpenAI utilise JSONL à la fois pour le fine-tuning et l'API Batch. Pour le fine-tuning de modèles de chat comme GPT-4o-mini, chaque ligne doit contenir un tableau messages avec la structure standard de complétion de chat. Les trois rôles, system, user et assistant, définissent la conversation que le modèle doit apprendre à reproduire.

Chaque ligne est un exemple d'entraînement. Le message system définit le comportement, le message user est l'entrée, et le message assistant est la sortie cible que le modèle doit apprendre.

Format d'entraînement Chat Completion
{"messages": [{"role": "system", "content": "You are a helpful customer support agent for an e-commerce platform."}, {"role": "user", "content": "Where is my order #12345?"}, {"role": "assistant", "content": "I can see that order #12345 was shipped on February 10th via FedEx. The tracking number is FX987654321. Based on the latest update, it should arrive by February 14th."}]}
{"messages": [{"role": "system", "content": "You are a helpful customer support agent for an e-commerce platform."}, {"role": "user", "content": "I want to return my purchase."}, {"role": "assistant", "content": "I would be happy to help with your return. Could you please provide the order number and the reason for the return? Our return policy allows returns within 30 days of delivery for most items."}]}

Pour les conversations multi-tours, incluez l'historique complet de la conversation. Le modèle apprend de chaque tour assistant dans le tableau messages. C'est ainsi que vous enseignez au modèle à gérer les questions de suivi.

Entraînement sur des conversations multi-tours
{"messages": [{"role": "system", "content": "You are a Python programming tutor."}, {"role": "user", "content": "What is a list comprehension?"}, {"role": "assistant", "content": "A list comprehension is a concise way to create lists in Python. Instead of writing a for loop to build a list, you can write it in one line: [expression for item in iterable if condition]."}, {"role": "user", "content": "Can you show me an example?"}, {"role": "assistant", "content": "Sure! Here is an example that creates a list of squares for even numbers:\n\nsquares = [x**2 for x in range(10) if x % 2 == 0]\n# Result: [0, 4, 16, 36, 64]\n\nThis is equivalent to:\nsquares = []\nfor x in range(10):\n if x % 2 == 0:\n squares.append(x**2)"}]}

OpenAI exige au minimum 10 exemples d'entraînement, mais recommande 50-100 pour des améliorations notables. Tous les messages doivent avoir les champs role et content. Le message system est optionnel mais recommandé pour un comportement cohérent. Utilisez le CLI OpenAI pour valider votre fichier avant le téléversement : openai tools fine_tunes.prepare_data -f training.jsonl

Format d'entraînement Anthropic Claude

Anthropic utilise JSONL pour le fine-tuning des modèles Claude. Le format utilise des tours human et assistant dans une conversation structurée. Bien que le format exact dépende de la méthode de fine-tuning et de la version de l'API, le modèle de base suit la structure de l'API Messages.

Chaque ligne contient une conversation avec un prompt système et des messages alternés user/assistant. Le modèle apprend à produire les réponses assistant en fonction du contexte de la conversation.

Format Messages de Claude
{"system": "You are a medical information assistant. Provide accurate, general health information while always recommending consulting a healthcare professional.", "messages": [{"role": "user", "content": "What are the symptoms of vitamin D deficiency?"}, {"role": "assistant", "content": "Common symptoms of vitamin D deficiency include fatigue and tiredness, bone pain and muscle weakness, mood changes including depression, slow wound healing, and frequent infections. However, many people with mild deficiency may not notice symptoms. A blood test is the only way to confirm your vitamin D levels. I recommend speaking with your doctor who can order the appropriate test and recommend supplementation if needed."}]}
{"system": "You are a medical information assistant. Provide accurate, general health information while always recommending consulting a healthcare professional.", "messages": [{"role": "user", "content": "Is it safe to take ibuprofen daily?"}, {"role": "assistant", "content": "Taking ibuprofen daily for extended periods can carry risks including stomach ulcers and gastrointestinal bleeding, increased risk of heart attack and stroke, kidney problems with long-term use, and potential interactions with other medications. For occasional pain relief, short-term use at recommended doses is generally considered safe for most adults. However, if you find yourself needing daily pain relief, please consult your doctor. They can evaluate the underlying cause and recommend a safer long-term treatment plan."}]}

Pour les données d'entraînement multi-tours, incluez la conversation complète avec des messages alternés user et assistant. Le modèle apprend le flux de conversation et comment maintenir le contexte à travers les tours.

Conversations multi-tours avec Claude
{"system": "You are a cooking assistant specializing in Italian cuisine.", "messages": [{"role": "user", "content": "How do I make carbonara?"}, {"role": "assistant", "content": "Authentic carbonara uses just five ingredients: spaghetti, guanciale (cured pork cheek), eggs, Pecorino Romano cheese, and black pepper. The key technique is tempering the egg mixture with the hot pasta water so it creates a creamy sauce without scrambling."}, {"role": "user", "content": "Can I use bacon instead of guanciale?"}, {"role": "assistant", "content": "While guanciale gives the most authentic flavor, pancetta is a closer substitute. Bacon works in a pinch but its smoky flavor changes the dish significantly. If using bacon, choose an unsmoked variety. Whichever you use, cut it into small pieces and render the fat slowly over medium-low heat until crispy."}]}

Datasets HuggingFace avec JSONL

La bibliothèque datasets de HuggingFace prend en charge nativement JSONL comme format d'entrée. Vous pouvez charger des fichiers JSONL locaux, streamer des datasets distants et convertir facilement entre les formats. JSONL est le format recommandé pour partager des datasets sur le HuggingFace Hub.

Utilisez la bibliothèque datasets pour charger des fichiers JSONL dans un objet Dataset. Cela fournit un accès mémoire-mappé efficace, un découpage train/test intégré et une intégration transparente avec l'API Trainer.

Chargement de datasets JSONL
from datasets import load_dataset
# Load a local JSONL file
dataset = load_dataset('json', data_files='training.jsonl')
print(dataset)
# DatasetDict({
# train: Dataset({
# features: ['messages', 'system'],
# num_rows: 5000
# })
# })
# Load with train/test split
dataset = load_dataset('json', data_files={
'train': 'train.jsonl',
'test': 'test.jsonl'
})
# Stream a large remote dataset
dataset = load_dataset(
'json',
data_files='https://example.com/large_dataset.jsonl',
streaming=True
)
for example in dataset['train']:
print(example)
break

Convertissez n'importe quel dataset HuggingFace au format JSONL pour l'utiliser avec d'autres pipelines d'entraînement. La méthode to_json écrit chaque exemple comme une ligne JSON séparée.

Exportation vers JSONL
from datasets import load_dataset
# Load a dataset from the Hub
dataset = load_dataset('squad', split='train')
# Export to JSONL
dataset.to_json('squad_train.jsonl')
print(f'Exported {len(dataset)} examples')
# Export with specific columns
dataset.select_columns(['question', 'context', 'answers']).to_json(
'squad_filtered.jsonl'
)
# Process and export
def format_for_finetuning(example):
return {
'messages': [
{'role': 'user', 'content': example['question']},
{'role': 'assistant', 'content': example['answers']['text'][0]}
]
}
formatted = dataset.map(format_for_finetuning, remove_columns=dataset.column_names)
formatted.to_json('squad_chat_format.jsonl')

Validation et nettoyage des données

La qualité des données d'entraînement impacte directement les performances du modèle. Du JSON invalide, des champs manquants, des exemples excessivement longs et des entrées en double peuvent tous dégrader les résultats du fine-tuning. Validez et nettoyez toujours vos fichiers JSONL avant de lancer une session d'entraînement.

Ce script valide chaque ligne de votre fichier JSONL contre les problèmes courants : JSON invalide, champs requis manquants, contenu vide et longueur de tokens. Exécutez-le avant le téléversement pour détecter les problèmes en amont.

Validateur de données d'entraînement JSONL
import json
import sys
from collections import Counter
def validate_training_data(path: str) -> dict:
"""Validate a JSONL file for AI fine-tuning."""
stats = Counter()
errors = []
with open(path, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
if not line:
continue
stats['total'] += 1
# Check valid JSON
try:
data = json.loads(line)
except json.JSONDecodeError as e:
errors.append(f'Line {line_num}: Invalid JSON - {e}')
stats['invalid_json'] += 1
continue
# Check messages field exists
if 'messages' not in data:
errors.append(f'Line {line_num}: Missing "messages" field')
stats['missing_messages'] += 1
continue
messages = data['messages']
# Check message structure
for i, msg in enumerate(messages):
if 'role' not in msg:
errors.append(f'Line {line_num}, msg {i}: Missing "role"')
stats['missing_role'] += 1
if 'content' not in msg:
errors.append(f'Line {line_num}, msg {i}: Missing "content"')
stats['missing_content'] += 1
elif not msg['content'].strip():
errors.append(f'Line {line_num}, msg {i}: Empty content')
stats['empty_content'] += 1
# Check has at least one assistant message
roles = [m.get('role') for m in messages]
if 'assistant' not in roles:
errors.append(f'Line {line_num}: No assistant message')
stats['no_assistant'] += 1
stats['valid'] += 1
return {'stats': dict(stats), 'errors': errors[:50]}
result = validate_training_data('training.jsonl')
print(f"Total: {result['stats'].get('total', 0)}")
print(f"Valid: {result['stats'].get('valid', 0)}")
if result['errors']:
print(f"\nFirst {len(result['errors'])} errors:")
for err in result['errors']:
print(f' {err}')

Les exemples d'entraînement en double gaspillent des ressources de calcul et peuvent biaiser le modèle vers des patterns surreprésentés. Ce script supprime les doublons exacts basés sur le hash du contenu de chaque ligne.

Script de dédoublonnage
import json
import hashlib
def deduplicate_jsonl(input_path: str, output_path: str) -> dict:
"""Remove duplicate training examples from a JSONL file."""
seen_hashes = set()
total = 0
unique = 0
with open(input_path, 'r') as fin, open(output_path, 'w') as fout:
for line in fin:
line = line.strip()
if not line:
continue
total += 1
# Hash the normalized JSON to catch formatting differences
data = json.loads(line)
canonical = json.dumps(data, sort_keys=True)
content_hash = hashlib.sha256(canonical.encode()).hexdigest()
if content_hash not in seen_hashes:
seen_hashes.add(content_hash)
fout.write(json.dumps(data) + '\n')
unique += 1
duplicates = total - unique
print(f'Total: {total}, Unique: {unique}, Removed: {duplicates}')
return {'total': total, 'unique': unique, 'duplicates': duplicates}
deduplicate_jsonl('training.jsonl', 'training_deduped.jsonl')

Préparation de données à grande échelle

Les datasets d'entraînement en production contiennent souvent des centaines de milliers ou des millions d'exemples. À cette échelle, vous avez besoin de pipelines automatisés pour le mélange, le découpage et le partitionnement de vos données JSONL. Une préparation appropriée prévient les problèmes d'entraînement comme l'oubli catastrophique et garantit des expériences reproductibles.

Ce script mélange vos données aléatoirement et les divise en ensembles d'entraînement et de test. Le mélange est essentiel car les fichiers JSONL sont souvent générés dans l'ordre, et l'entraînement sur des données ordonnées peut conduire à une mauvaise généralisation.

Pipeline de découpage train/test et mélange
import json
import random
from pathlib import Path
def prepare_training_data(
input_path: str,
output_dir: str,
test_ratio: float = 0.1,
seed: int = 42
) -> dict:
"""Shuffle and split JSONL into train/test sets."""
random.seed(seed)
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
# Load all examples
examples = []
with open(input_path, 'r') as f:
for line in f:
line = line.strip()
if line:
examples.append(json.loads(line))
# Shuffle
random.shuffle(examples)
# Split
split_idx = int(len(examples) * (1 - test_ratio))
train_data = examples[:split_idx]
test_data = examples[split_idx:]
# Write output files
train_path = output / 'train.jsonl'
test_path = output / 'test.jsonl'
for data, path in [(train_data, train_path), (test_data, test_path)]:
with open(path, 'w') as f:
for example in data:
f.write(json.dumps(example) + '\n')
print(f'Train: {len(train_data)} examples -> {train_path}')
print(f'Test: {len(test_data)} examples -> {test_path}')
return {'train': len(train_data), 'test': len(test_data)}
prepare_training_data(
'all_examples.jsonl',
'./prepared_data/',
test_ratio=0.1,
seed=42
)

Lorsque les datasets sont trop volumineux pour un seul fichier ou que vous devez distribuer l'entraînement sur plusieurs GPU, partitionnez le fichier JSONL en morceaux plus petits. Chaque partition peut être traitée indépendamment.

Partitionnement de fichiers pour l'entraînement distribué
import json
from pathlib import Path
def shard_jsonl(
input_path: str,
output_dir: str,
shard_size: int = 50000
) -> int:
"""Split a large JSONL file into smaller shards."""
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
shard_num = 0
line_count = 0
current_file = None
with open(input_path, 'r') as fin:
for line in fin:
line = line.strip()
if not line:
continue
if line_count % shard_size == 0:
if current_file:
current_file.close()
shard_path = output / f'shard_{shard_num:04d}.jsonl'
current_file = open(shard_path, 'w')
shard_num += 1
current_file.write(line + '\n')
line_count += 1
if current_file:
current_file.close()
print(f'Created {shard_num} shards from {line_count} examples')
return shard_num
shard_jsonl('large_dataset.jsonl', './shards/', shard_size=50000)

Validez vos données d'entraînement en ligne

Utilisez nos outils gratuits dans le navigateur pour valider, formater et convertir vos données d'entraînement JSONL avant de les téléverser sur OpenAI, Anthropic ou HuggingFace.

Prêt à préparer vos données d'entraînement ?

Validez, formatez et inspectez vos fichiers d'entraînement JSONL directement dans votre navigateur. Aucun téléversement, aucune inscription, 100% privé.

Questions fréquemment posées

Données d'entraînement JSONL — Formats OpenAI, Claude et ...