AIトレーニングデータ用JSONL

AIと機械学習向けのJSONLトレーニングデータ準備の包括的ガイド。OpenAIファインチューニング、Anthropic Claude、HuggingFaceデータセット、データ検証、大規模データパイプラインを網羅。

最終更新:2026年2月

なぜJSONLがAIトレーニングデータの標準なのか

JSONL(JSON Lines)はAIおよび機械学習のトレーニングデータにおけるデファクトスタンダードとなっています。OpenAIからAnthropicからHuggingFaceまで、すべての主要AIプロバイダーがファインチューニングデータセットの主要フォーマットとしてJSONLを使用しています。理由はシンプルです:JSONLは1行に1つのサンプルを格納するため、トレーニング中のデータストリーミング、サンプルのシャッフル、レコード数のカウント、訓練・テストセットへの分割、ファイル全体を書き換えることなく新しいサンプルの追加が容易に行えます。

使用前にすべてを解析する必要がある単一のJSON配列とは異なり、JSONLファイルは1行ずつ処理できます。これはトレーニングデータセットが数百万のサンプルに成長し、ギガバイト単位になる場合に重要です。このガイドでは、OpenAI、Anthropic Claude、HuggingFaceが期待する正確なJSONLフォーマット、データの検証とクリーニング方法、そして本番トレーニング実行のための大規模データセット準備方法を学びます。

OpenAI ファインチューニング JSONL フォーマット

OpenAIはファインチューニングとBatch APIの両方でJSONLを使用します。GPT-4o-miniなどのチャットモデルのファインチューニングでは、各行に標準的なチャット補完構造のmessages配列を含める必要があります。system、user、assistantの3つのロールが、モデルが再現すべき会話を定義します。

各行は1つのトレーニングサンプルです。systemメッセージは動作を設定し、userメッセージは入力、assistantメッセージはモデルが学習すべきターゲット出力です。

チャット補完トレーニングフォーマット
{"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."}]}

マルチターン会話の場合、完全な会話履歴を含めます。モデルはmessages配列内のすべてのassistantターンから学習します。これはモデルにフォローアップ質問の処理を教える方法です。

マルチターン会話トレーニング
{"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は最低10個のトレーニングサンプルを要求しますが、目に見える改善には50〜100個を推奨しています。すべてのメッセージにはroleとcontentフィールドが必要です。systemメッセージはオプションですが、一貫した動作のために推奨されます。アップロード前にOpenAI CLIでファイルを検証できます:openai tools fine_tunes.prepare_data -f training.jsonl

Anthropic Claude トレーニングフォーマット

AnthropicはClaudeモデルのファインチューニングにJSONLを使用します。フォーマットはhumanとassistantのターンを構造化された会話で使用します。正確なフォーマットはファインチューニング方法とAPIバージョンに依存しますが、コアパターンはMessages APIの構造に従います。

各行にはシステムプロンプトと交互のuser/assistantメッセージを含む会話が含まれます。モデルは会話コンテキストが与えられた場合のassistantレスポンスを生成することを学習します。

Claude Messages フォーマット
{"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."}]}

マルチターンのトレーニングデータでは、userとassistantメッセージが交互に並ぶ完全な会話を含めます。モデルは会話の流れとターン間でのコンテキスト維持方法を学習します。

マルチターン 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."}]}

HuggingFace データセットと JSONL

HuggingFaceのdatasetsライブラリはJSONLを入力フォーマットとしてネイティブにサポートしています。ローカルJSONLファイルの読み込み、リモートデータセットのストリーミング、フォーマット間の変換が容易に行えます。HuggingFace Hubでデータセットを共有するための推奨フォーマットはJSONLです。

datasetsライブラリを使用してJSONLファイルをDatasetオブジェクトに読み込みます。効率的なメモリマップドアクセス、組み込みのtrain/test分割、Trainer APIとのシームレスな統合が提供されます。

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

任意のHuggingFaceデータセットをJSONLフォーマットに変換し、他のトレーニングパイプラインで使用します。to_jsonメソッドは各サンプルを個別のJSON行として書き出します。

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')

データ検証とクリーニング

トレーニングデータの品質はモデルのパフォーマンスに直接影響します。無効なJSON、欠落フィールド、過度に長いサンプル、重複エントリはすべてファインチューニング結果を劣化させる可能性があります。トレーニング実行を開始する前に、必ずJSONLファイルを検証してクリーニングしてください。

このスクリプトはJSONLファイルの各行を一般的な問題(無効なJSON、必須フィールドの欠落、空のコンテンツ、トークン長)について検証します。問題を早期に発見するために、アップロード前に実行してください。

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}')

重複するトレーニングサンプルは計算リソースを無駄にし、過剰に代表されるパターンにモデルをバイアスさせる可能性があります。このスクリプトは各行のコンテンツハッシュに基づいて完全な重複を削除します。

重複排除スクリプト
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')

大規模データ準備

本番トレーニングデータセットは数十万から数百万のサンプルを含むことがよくあります。この規模では、JSONLデータのシャッフル、分割、シャーディングのための自動化パイプラインが必要です。適切な準備により、壊滅的忘却などのトレーニング問題を防ぎ、再現可能な実験を確保します。

このスクリプトはデータをランダムにシャッフルし、trainセットとtestセットに分割します。JSONLファイルは順序通りに生成されることが多く、順序付きデータでのトレーニングは一般化が不十分になる可能性があるため、シャッフルは不可欠です。

Train/Test 分割とシャッフルパイプライン
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
)

データセットが単一ファイルには大きすぎる場合や、複数GPUに分散してトレーニングする必要がある場合、JSONLファイルを小さなチャンクにシャーディングします。各シャードは独立して処理できます。

分散トレーニング用ファイルシャーディング
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)

トレーニングデータをオンラインで検証

無料のブラウザベースツールを使用して、OpenAI、Anthropic、HuggingFaceにアップロードする前にJSONLトレーニングデータを検証、フォーマット、変換できます。

トレーニングデータの準備を始めましょう

ブラウザ上でJSONLトレーニングファイルを検証、フォーマット、検査できます。アップロード不要、登録不要、100%プライベート。

よくある質問

JSONL トレーニングデータ — OpenAI、Claude&Hugging Face フォーマット | jso...