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 메시지는 선택 사항이지만 권장됩니다. 각 대화에는 최소 하나의 user 메시지와 하나의 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(Byte Order Mark) 없이 UTF-8로 인코딩되어야 합니다
- 후행 쉼표, 주석 또는 줄 사이의 여분의 공백이 없어야 합니다
- 빈 줄은 허용되며 무시됩니다
일반적인 실수
OpenAI JSONL 파일을 만들 때 가장 빈번한 오류입니다:
JSONL 대신 JSON 배열 사용
잘못됨: 모든 객체를 [ ]로 감싸기. JSONL 파일은 래핑 배열 없이 줄당 하나의 객체가 있어야 합니다.
['{'"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`);