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.
{"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.
{"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.
{"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.
{"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.
from datasets import load_dataset# Load a local JSONL filedataset = load_dataset('json', data_files='training.jsonl')print(dataset)# DatasetDict({# train: Dataset({# features: ['messages', 'system'],# num_rows: 5000# })# })# Load with train/test splitdataset = load_dataset('json', data_files={'train': 'train.jsonl','test': 'test.jsonl'})# Stream a large remote datasetdataset = 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.
from datasets import load_dataset# Load a dataset from the Hubdataset = load_dataset('squad', split='train')# Export to JSONLdataset.to_json('squad_train.jsonl')print(f'Exported {len(dataset)} examples')# Export with specific columnsdataset.select_columns(['question', 'context', 'answers']).to_json('squad_filtered.jsonl')# Process and exportdef 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.
import jsonimport sysfrom collections import Counterdef 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:continuestats['total'] += 1# Check valid JSONtry:data = json.loads(line)except json.JSONDecodeError as e:errors.append(f'Line {line_num}: Invalid JSON - {e}')stats['invalid_json'] += 1continue# Check messages field existsif 'messages' not in data:errors.append(f'Line {line_num}: Missing "messages" field')stats['missing_messages'] += 1continuemessages = data['messages']# Check message structurefor i, msg in enumerate(messages):if 'role' not in msg:errors.append(f'Line {line_num}, msg {i}: Missing "role"')stats['missing_role'] += 1if 'content' not in msg:errors.append(f'Line {line_num}, msg {i}: Missing "content"')stats['missing_content'] += 1elif not msg['content'].strip():errors.append(f'Line {line_num}, msg {i}: Empty content')stats['empty_content'] += 1# Check has at least one assistant messageroles = [m.get('role') for m in messages]if 'assistant' not in roles:errors.append(f'Line {line_num}: No assistant message')stats['no_assistant'] += 1stats['valid'] += 1return {'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.
import jsonimport hashlibdef deduplicate_jsonl(input_path: str, output_path: str) -> dict:"""Remove duplicate training examples from a JSONL file."""seen_hashes = set()total = 0unique = 0with open(input_path, 'r') as fin, open(output_path, 'w') as fout:for line in fin:line = line.strip()if not line:continuetotal += 1# Hash the normalized JSON to catch formatting differencesdata = 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 += 1duplicates = total - uniqueprint(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.
import jsonimport randomfrom pathlib import Pathdef 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 examplesexamples = []with open(input_path, 'r') as f:for line in f:line = line.strip()if line:examples.append(json.loads(line))# Shufflerandom.shuffle(examples)# Splitsplit_idx = int(len(examples) * (1 - test_ratio))train_data = examples[:split_idx]test_data = examples[split_idx:]# Write output filestrain_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.
import jsonfrom pathlib import Pathdef 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 = 0line_count = 0current_file = Nonewith open(input_path, 'r') as fin:for line in fin:line = line.strip()if not line:continueif 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 += 1current_file.write(line + '\n')line_count += 1if current_file:current_file.close()print(f'Created {shard_num} shards from {line_count} examples')return shard_numshard_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.