OpenAI JSONL フォーマットガイド
OpenAI のモデルファインチューニングと Batch API で使用される JSONL フォーマットについて必要な知識をすべて解説。フォーマット仕様、コード例、よくある落とし穴を含みます。
最終更新: 2026年2月
OpenAI JSONL フォーマットとは?
OpenAI は、ファインチューニングデータセットと Batch API リクエストの標準ファイル形式として JSONL(JSON Lines)を使用しています。ファイル内の各行は完全で独立した JSON オブジェクトであり、配列で囲んだり行間にカンマを入れたりする必要はありません。
この形式が選ばれた理由は、効率的なストリーミングと行単位の処理が可能だからです。各トレーニング例や API リクエストを独立して検証でき、データセット全体をメモリに読み込むことなくファイルを処理できます。
正確なフォーマット要件を理解することは非常に重要です。末尾のカンマやフィールドの欠落など、小さなフォーマットエラーでもファイル全体が拒否されます。
ファインチューニング JSONL フォーマット
チャットモデルのファインチューニング(GPT-4o、GPT-4o-mini、GPT-3.5 Turbo)では、各行に会話ターンを含む「messages」配列が必要です。
{"messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"What is the capital of France?"},{"role":"assistant","content":"The capital of France is Paris."}]}{"messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"What is 2+2?"},{"role":"assistant","content":"2+2 equals 4."}]}
必須フィールド
- messages — メッセージオブジェクトの配列(必須)
- role — "system"、"user"、"assistant" のいずれか(必須)
- content — メッセージのテキスト内容(必須)
system メッセージは任意ですが推奨されます。各会話には少なくとも 1 つの user メッセージと 1 つの assistant メッセージが必要です。assistant メッセージがモデルが学習する生成内容です。
Batch API JSONL フォーマット
Batch API は、各行がカスタム ID を持つ API リクエストである異なる JSONL フォーマットを使用します。
{"custom_id":"request-1","method":"POST","url":"/v1/chat/completions","body":{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Hello, how are you?"}]}'}{"custom_id":"request-2","method":"POST","url":"/v1/chat/completions","body":{"model":"gpt-4o-mini","messages":[{"role":"user","content":"What is the weather today?"}]}'}
必須フィールド
- custom_id — 各リクエストの一意な識別子(必須)
- method — HTTP メソッド、通常は "POST"(必須)
- url — API エンドポイントパス(必須)
- body — リクエストボディ、通常の API 呼び出しと同じ(必須)
フォーマット要件
JSONL ファイルが OpenAI に受け入れられるよう、以下のルールに従ってください:
- 各行は有効な JSON である必要があります — 構文エラーは許可されません
- 各行は JSON オブジェクトである必要があります('{' で始まり '}' で終わる)
- ファインチューニングファイルでは各行に「messages」配列を含める必要があります
- 各メッセージには「role」と「content」フィールドの両方が必要です
- 有効なロールは:"system"、"user"、"assistant" です
- ファイルは BOM(バイトオーダーマーク)なしの UTF-8 エンコーディングである必要があります
- 末尾のカンマ、コメント、行間の余分な空白は不可
- 空行は許可され、無視されます
よくある間違い
OpenAI JSONL ファイル作成時に最も頻繁に発生するエラーです:
JSONL の代わりに JSON 配列を使用
間違い:すべてのオブジェクトを [ ] で囲む。JSONL ファイルは配列で囲まず、1 行に 1 オブジェクトでなければなりません。
['{'"messages":[...]'}', '{'"messages":[...]'}']'{'"messages":[...]'}'
'{'"messages":[...]'}'必須フィールドの欠落
すべてのメッセージには「role」と「content」の両方が必要です。どちらかを省略すると検証が失敗します。
'{'"messages":['{'"role":"user"'}']'}''{'"messages":['{'"role":"user","content":"Hello"'}']'}'JSON 内の末尾のカンマ
JSON では配列やオブジェクトの最後の要素の後にカンマを付けることは許可されていません。
'{'"messages":['{'"role":"user","content":"Hi",'}']'}''{'"messages":['{'"role":"user","content":"Hi"'}']'}'BOM 文字や不正なエンコーディング
ファイルを BOM なしの UTF-8 で保存してください。一部のテキストエディタは JSON の解析を壊す不可視の BOM 文字を追加します。
\uFEFF'{'"messages":[...]'}''{'"messages":[...]'}'コード例
プログラムで OpenAI JSONL ファイルを作成する方法:
import jsontraining_data = [{"messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "What is JSONL?"},{"role": "assistant", "content": "JSONL (JSON Lines) is a text format where each line is a valid JSON object."}]},{"messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "How do I fine-tune a model?"},{"role": "assistant", "content": "Prepare a JSONL file with training examples, then use the OpenAI fine-tuning API."}]},]with open("training.jsonl", "w", encoding="utf-8") as f:for entry in training_data:f.write(json.dumps(entry, ensure_ascii=False) + "\n")print(f"Created training.jsonl with {len(training_data)} examples")
const fs = require('fs');const trainingData = [{ messages: [{ role: 'system', content: 'You are a helpful assistant.' },{ role: 'user', content: 'What is JSONL?' },{ role: 'assistant', content: 'JSONL (JSON Lines) is a text format where each line is a valid JSON object.' },]},{ messages: [{ role: 'system', content: 'You are a helpful assistant.' },{ role: 'user', content: 'How do I fine-tune a model?' },{ role: 'assistant', content: 'Prepare a JSONL file with training examples, then use the OpenAI fine-tuning API.' },]},];const jsonl = trainingData.map(d => JSON.stringify(d)).join('\n');fs.writeFileSync('training.jsonl', jsonl + '\n', 'utf-8');console.log(`Created training.jsonl with ${trainingData.length} examples`);