Fireworks AI 入門 — 初心者のためのハンズオンガイド|2026-09 版
第 10 章

Datasets — 学習データを管理する

ファインチューニングの燃料。JSONL の形式とアップロードの作法

この章で分かること

これは何か

Dataset(データセット)とは、モデルを学習させるために使える、学習サンプルの不変な集合(immutable set of training examples)のことである。学習を始めるには、学習方法(SFT・DPO/ORPO・RFT)にかかわらず、まずこのデータセットという単位でプラットフォームに登録する必要がある。第 9 章までの Serverless・Deployments が「モデルをどう動かすか」の章だったのに対し、この章と第 11 章は「モデルをどう自分の仕事に合わせるか」の章であり、Datasets はその材料を用意する入口にあたる。

ここで出てくる 3 つの学習方法を 1 文ずつ定義しておく。SFT(教師ありファインチューニング、Supervised Fine-Tuning)は正解の応答例を見せてそのとおりに真似させる方式、DPO・ORPO(選好最適化)は良い応答と悪い応答の対を見せて優劣を教える方式、RFT(強化ファインチューニング、Reinforcement Fine-Tuning)は正解の応答例を用意しなくてよく(入れても構わない)、プロンプトと採点役(評価器)だけでモデルに試行錯誤させる方式である。どれを選ぶかの詳しい基準は第 11 章で扱うが、この 3 方式が要求する学習データの形が全く違う、という点がこの章の主題になる。

コンソール(app.fireworks.ai)では、コンソールの dataset タブから Create Dataset ボタンでウィザードを開き、個々のデータセットは app.fireworks.ai/dashboard/datasets/<DATASET_ID> というページを持つ。データセットテーブルからは、ファイル単位のダウンロードと「Download All」による一括ダウンロードもできる。API・CLI から直接触ることも多く、REST では POST https://api.fireworks.ai/v1/accounts/{account_id}/datasets(作成)と POST .../datasets/{dataset_id}:upload(アップロード)の 2 つのエンドポイントが基本になり、CLI では firectl dataset create / list / get / download / delete の一群のサブコマンドで同じ操作ができる。

いつ使うのか

データセットを新しく用意する場面は、大きく分けて次の 3 通りである。

データをどこに置くかという観点では、通常のアップロード・派生生成・BYOB(Bring Your Own Bucket、自前のクラウドバケットを参照させる方式)の 3 択があり、性質がはっきり異なる。

観点通常アップロード(userUploaded)派生生成(sourceDatasetId + filter)BYOB(externalUrl)
データの置き場所Fireworks 管理ストレージ(GCS)にコピーされる同じく Fireworks 管理ストレージ自分の GCS / AWS S3 / Azure Blob。コピーされない
作り方ファイルをそのままアップロード既存データセットを条件式で絞り込む--external-url gs://... で外部 URI を登録
向く場面初めてのデータセット・少量データ大きな元データから用途別に部分集合を作りたいときデータを Fireworks に一切コピーしたくない厳格な要件

BYOB はジョブの実行中だけ元のバケットを in-place で読み、データセットのコピーを持たない。ジョブが終わったらバケットへのアクセス権を剥奪する運用が前提になる。反対に通常アップロードでは、データセット自体はジョブ後も残るので、不要になったら自分で削除する必要がある(この章のハンズオンで実際に削除まで行う)。

仕組み(1)— JSONL は互換性のない 3 つのスキーマに分かれる

Datasets はどの学習方法(SFT / DPO・ORPO / RFT)でも同じ JSONL(1 行 = 1 つの完全な JSON オブジェクト)というファイル形式を使う。しかし行の中身のスキーマは 3 つとも別物で、ルート直下に来るキーからして違う。ここを混同すると、SFT 用に作ったファイルを DPO ジョブにそのまま投げてエラーになる、といった事故が起きる。

SFT(CHAT形式) DPO・ORPO RFT(RL形式) messages[] input.messages[] messages[] のみ role / content preferred_output[] 正解completionは任意 weight(二重の意味) non_preferred_output[] 評価器が0〜1で採点 同じ「messages」という語を使っていても、ルート直下の構造は3方式で異なる
図 10-1 SFT・DPO/ORPO・RFT は同じ JSONL 形式を使うが、1 行の JSON オブジェクトの構造はルート直下から非互換。

SFT(CHAT 形式)は OpenAI 互換の chat completion 形式で、ルート直下に messages 配列を置く。各メッセージは role(system / user / assistant)と content(文字列、または [{"type": "text", "text": "..."}] 形式の配列。両方を同じファイル内・同じ会話内で混在させてよい)を持つ。system は任意だが、使うなら会話の先頭に置く必要がある。

{"messages": [
  {"role": "system", "content": "あなたは親切な旅行アドバイザーです。"},
  {"role": "user", "content": "京都で紅葉が見頃になるのはいつ頃ですか?"},
  {"role": "assistant", "content": "例年11月中旬から12月上旬が見頃です。"}
]}

weight キーには 2 つの独立した意味がある。メッセージ単位の weight はメッセージオブジェクトの中に置き、値は 0 か 1 のみで、0 ならそのメッセージは損失計算から除外される。一方サンプル単位の weight は JSON オブジェクトのルート直下に置き、任意の浮動小数点数(正・負・0 いずれも可)を取り、そのサンプル全体の損失に掛ける乗数になる。ルート直下の weight を使うなら、データセットの全サンプルにこのキーが存在しなければならない(一部のサンプルだけに付けるのは不可)。値域も置く場所も別物なので、この 2 つを取り違えないことが検証の第一歩になる。

ほかに、assistant メッセージには content の代わりに tool_calls を入れる function calling 用のスキーマ(ルート直下に tools 配列を追加)と、推論トレースを載せる reasoning_content キー(assistant メッセージの中、任意)もある。reasoning_content をどう学習コンテキストへ含めるか(unroll するかどうか)はベースモデル依存で、こみ入った話は第 11 章で扱う。

DPO・ORPO は SFT とは全く別のスキーマで、ルート直下に input(messages 配列と tools を含む)・preferred_output(望ましい応答の配列)・non_preferred_output(望ましくない応答の配列)の 3 フィールドを置く。content は文字列と規定されている(SFT のような content parts 配列は仕様に現れない)。1 例につき単一ターン会話のみに対応し、preferred_output / non_preferred_output は会話の最後の assistant メッセージでなければならない。同じデータセットが DPO・ORPO の両方で使え、どちらの損失関数を使うかはジョブ側の設定(--loss-method)で切り替える。

{
  "input": {
    "messages": [{"role": "user", "content": "この提案のメリットを教えて"}],
    "tools": []
  },
  "preferred_output": [
    {"role": "assistant", "content": "コスト削減と納期短縮の両方が見込めます。"}
  ],
  "non_preferred_output": [
    {"role": "assistant", "content": "良いと思います。"}
  ]
}

RFT(RL 形式)は最もシンプルで、messages 配列だけを持つプロンプトの JSONL である。正解の completion を含める必要はない。SFT・DPO が「良い/望ましい出力の例」を渡すのに対し、RFT は「プロンプト」だけを渡し、別途登録した評価器(reward function)がモデルの出力を 0〜1 でスコアリングして学習を進める。プロンプトさえあれば作れるため、SFT・DPO と比べて用意するデータ量は桁違いに小さく、数十〜数千件、時には 100 件未満でも足りることがある。評価器の作り方や RFT ジョブの起動は第 11 章の範囲になる。

仕組み(2)— 混同しやすい 4 つの上限

データセットには複数の「上限」があり、そのうち混同しやすいのが次の 4 つである。これらはそれぞれ別の軸を制限する独立した制約であり、1 つの数字に単純化できない。混同すると「150MB あれば何でもアップロードできる」「300 万件あれば何エポックでも回せる」といった誤解につながる。

制約値(2026-09 時点)出典
API 単発アップロードのファイルサイズ150MB までUpload Dataset Files API
UI での推奨サイズ500MB 未満向き(それ以上は firectl 推奨)SFT / DPO ガイド共通の記述
データセットの例数最小 3 件・最大 300 万件SFT / DPO ガイド共通(Minimum/Maximum examples)
例数 × エポック数300 万以下SFT ガイドの Epochs 節

エポック(学習データを何周なめるか。1 エポック = 全サンプルを 1 回ずつ学習すること)の数え方が絡むため、特に見落としやすいのが最後の「例数 × エポック数 ≤ 300 万」である。300 万件ちょうどのデータセットを用意できても、既定の 1 エポックしか回せない計算になり、2 エポック回したければ 150 万件以下に抑える必要がある。逆に少量データ(例えば数百件)なら、この上限を気にせず 10 エポック・20 エポックと回すことができる。エポック数は既定 1 で、非整数値(例: 1.5 エポック)も指定できる。

仕組み(3)— アップロードは 3 経路、150MB が分岐点

データセットをプラットフォームへ送る主な手段は、コンソール UI・firectl・REST API の 3 つで、どれを使っても最終的に作られるデータセットリソースは同じである(このほか SDK からもデータセットを作成できる。詳しくは第 14 章で扱う)。

経路向くデータ量特徴
コンソール UI500MB 未満dataset タブ → Create Dataset → ウィザードで、作成とアップロードを画面上で完結できる
firectl dataset create大きなファイルにも対応1 コマンドで作成とアップロードの両方を行う(進捗バー付き)。大きなデータセットには firectl が向く、と公式が推奨している
REST API150MB まで(単発)「データセット作成」と「ファイルアップロード」が別リクエストになる。exampleCount はクライアント側が明示的に渡す必要がある

REST API を単発で使う場合の上限は 150MB である。これを超えるファイルを REST 経由で送るときは、単一の :upload エンドポイントではなく、次の 4 段階のフローに切り替える。

アップロードファイル 150MB以下 単発の:uploadで送れる 150MB超 4段階のリクエストが必要 分割アップロード不要 RESTはcreateとuploadの2回 ①create ②Endpoint ③PUT ④validate ≤150MB >150MB 分割なし この4つを順に呼ぶ
図 10-2 150MB を境に、単発の :upload 呼び出しと、署名付き URL を経由する 4 段階のフローに分かれる。
  1. create — POST /v1/accounts/{account_id}/datasets に datasetId(作成するデータセットの ID)と dataset(userUploaded: {} と exampleCount を含む)を渡してエントリだけを先に作る。
  2. getUploadEndpoint — POST .../datasets/{dataset_id}:getUploadEndpoint に、ファイル名とバイト数のマップ(filenameToSize)を渡す。複数ファイルを一度に扱える。
  3. 署名付き URL へ PUT — レスポンスに含まれる filenameToSignedUrls(ファイル名 → 署名付き URL のマップ)を使い、実ファイルをオブジェクトストレージへ直接 PUT する。
  4. validateUpload — POST .../datasets/{dataset_id}:validateUpload を呼び、アップロードの完了を確定させる。リクエスト・レスポンスとも空オブジェクトで、これを呼ぶことでデータセットの状態が UPLOADING から READY へ遷移すると読める設計になっている。

firectl dataset create なら 1 コマンドで作成とアップロードが済む(公式は大きなデータセットでは firectl を推奨している)。

仕組み(4)— データセットからモデルへ、状態遷移で確認する

データセットのリソースには state というフィールドがあり、実際に目にするのは UPLOADING → READY の 2 つだけである(enum にはこのほか未設定を表す値もある)。学習ジョブを作る前には、必ず READY になっていることを確認する。firectl dataset get <id> -o json を実行すると、state に加えて exampleCount(サンプル数)・estimatedTokenCount(推定トークン数)・averageTurnCount(サンプルあたりの平均ターン数)という、アップロード後にしか分からない統計も確認できる。特に estimatedTokenCount は、学習ジョブのコストや所要時間を見積もる最初の材料になる。

UPLOADING READY 学習ジョブが参照 SFTジョブ DPO/ORPOジョブ RFTジョブ 学習済みLoRAモデル アップロード完了 手法は第11章で選ぶ 学習完了
図 10-3 READY になったデータセットは SFT・DPO/ORPO・RFT のいずれのジョブからも参照でき、学習が終わると LoRA モデルにつながる(続きは第 11 章)。

もう 1 点、データセットの中身が想定どおりトークナイズされているかを確認する手段として、学習ジョブ作成後にダッシュボードで見られる「Render Samples」機能がある。これはトークン境界と損失マスク(どのトークンが学習対象になっているか)を可視化するもので、データセット側の weight の付け忘れ・付けすぎに気づく最も確実な方法である。実際の使い方は学習ジョブとセットになるため第 11 章で扱うが、「データセットを作って終わりではなく、ジョブを起動したあとに中身の解釈を検証する」という位置づけはこの章のうちに覚えておきたい。

ハンズオン 10-1 小さな SFT 用 JSONL を作って firectl でアップロード・確認・削除する

  1. ターミナルで API キーを環境変数にセットする(export FIREWORKS_API_KEY=...)。firectl は第 2 章で発行した API キーで既にサインイン済み(firectl signin。インストールと認証は第 14 章)である前提とする。
  2. 最小要件(最小 3 件)を満たす、SFT(CHAT 形式)の JSONL ファイルをローカルに作る。ファイル名は sample-sft.jsonl とする。
{"messages": [{"role": "user", "content": "富士山の標高は?"}, {"role": "assistant", "content": "約3776メートルです。"}]}
{"messages": [{"role": "user", "content": "日本の首都は?"}, {"role": "assistant", "content": "東京です。"}]}
{"messages": [{"role": "user", "content": "1週間は何日?"}, {"role": "assistant", "content": "7日間です。"}]}

データセットの作成・アップロード・削除だけを行うこのハンズオンでは学習ジョブを起動しないため、公式ドキュメントに記載されているトークン課金・GPU 時間課金の対象にはならない。データセットの ID は「1〜63 文字、小文字英数字とハイフンのみ、先頭・末尾にハイフン不可、数字始まり不可」というリソース ID の制約に従う必要があるので、下記のコマンドの ID はそのまま使うか、この制約内で書き換える。

  1. firectl でデータセットを作成・アップロードする(1 コマンドで両方を行う)。
firectl dataset create sample-sft-guide-ch10 ./sample-sft.jsonl \
  --display-name "ch10 ハンズオン用サンプル"
  1. 状態と統計情報を確認する。state が READY になっていれば成功。
firectl dataset get sample-sft-guide-ch10 -o json

exampleCount(3 になっているはず)・estimatedTokenCount・averageTurnCount が出力に含まれていることを確認する。ブラウザでコンソールのデータセット一覧を開き、sample-sft-guide-ch10 を選ぶと、同じデータセットをコンソール上でも確認できる。

  1. ハンズオンで作ったデータセットを削除する(後片付け)。
firectl dataset delete sample-sft-guide-ch10 --wait

--wait を付けると削除が完了するまでコマンドが待機する。以後 firectl dataset get sample-sft-guide-ch10 を実行すると NOT_FOUND になれば削除完了である。

つまずきポイント

SFT 用データセットを DPO ジョブにそのまま使い回そうとする。 どちらも messages という語を含むが、SFT はルート直下が messages 配列そのもの、DPO/ORPO はルート直下が input(messages を含む)・preferred_output・non_preferred_output の 3 フィールドで、構造が非互換である。学習方法を切り替えるときは、データセットも作り直す前提で考える。

REST API 経由での作成時に exampleCount を渡し忘れる。 firectl や UI ではファイルの中身から自動的に扱われるが、REST の 2 リクエスト方式(作成 → アップロード)では exampleCount をクライアント側が明示的に渡す必要がある、と公式ドキュメントに明記されている。渡し忘れに気づきにくいので、REST を直接叩くコードでは特に注意する。

メッセージ単位の weight とサンプル単位の weight を混同する。 前者はメッセージオブジェクトの中にあり値は 0 か 1 のみ、後者は JSON オブジェクトのルート直下にあり任意の浮動小数点数を取る。後者を使うならデータセットの全サンプルに存在しなければならない。値の意味も置き場所も違うキーが同じ名前を共有している点が、このプラットフォーム最大の紛らわしさの 1 つである。

「150MB」と「500MB」を同じ上限だと思い込む。 150MB は REST の単発アップロード API が扱える上限、500MB はコンソール UI が快適に扱える目安であり、別のレイヤーの別の数字である。500MB 未満だから REST 単発でも安全、とは限らない。150MB を超えるファイルは REST では 4 段階のフローが必要になる(公式は大きなデータセットでは firectl を推奨している)。

理解度チェック

Q1. SFT 用の JSONL ファイルを、そのまま DPO ジョブの学習データとして使えますか?

使えない。SFT はルート直下が messages 配列そのものだが、DPO/ORPO はルート直下が input(messages を含む)・preferred_output・non_preferred_output の 3 フィールドという別スキーマで、構造として互換性が無い。

Q2. 280MB の JSONL ファイルを REST API でアップロードしたい。どうすればよいですか?

単発の :upload エンドポイントは 150MB までしか扱えないため使えない。create → getUploadEndpoint(ファイル名とサイズを渡す)→ 返ってきた署名付き URL へファイルを PUT → validateUpload という 4 段階のフローに切り替える必要がある。

Q3. メッセージ単位の weight とサンプル単位の weight の違いは何ですか?

メッセージ単位の weight はメッセージオブジェクトの中に置き、値は 0 か 1 のみ(0 ならそのメッセージは損失計算から除外)。サンプル単位の weight は JSON オブジェクトのルート直下に置き、任意の浮動小数点数(正・負・0 可)を取り、サンプル全体の損失に掛ける乗数になる。後者を使う場合は全サンプルに必須。

Q4. 300 万件のデータセットを 2 エポック回して学習することはできますか?

できない。「例数 × エポック数」の積に 300 万という上限があるため、300 万件のデータセットを回せるのは 1 エポックまで。2 エポック回したいなら、データセットを 150 万件以下に抑える必要がある。

Q5. RFT 用のデータセットには、SFT のような「正解の応答例」が必要ですか?

必要ない。RFT のデータセットは messages 配列(プロンプト)だけを持つ JSONL で、正解の completion は任意。良し悪しの判定は別途登録する評価器(reward function)が 0〜1 のスコアで行う。

まとめ

次章では、この章で用意したデータセットを実際に学習ジョブへ渡し、SFT・DPO/ORPO・RFT のどれを選ぶか、どうジョブを起動し、学習済みモデルをどうデプロイするかを見ていく。

参考リンク