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

Evaluations — 鍛えたモデルの出来を測る

勘ではなく評価ジョブで。Evaluator の作り方と読み方

この章で分かること

これは何か

第 4 章の Playground で 1 つのプロンプトに 1 つの応答を目で確認するやり方は、モデルの「感触」を掴むには十分だが、「ファインチューン前後でどちらが良いか」「本番に出してよい品質か」を判断する材料にはならない。1 回きりの目視では再現できず、数十〜数千件の入力に対する合否を人手で数えるのも現実的ではないからだ。この章で扱う Evaluations(評価)は、この判断を勘ではなく評価ジョブ(Evaluation Job)という繰り返し実行できる仕組みに置き換える機能である。

評価の中核にあるのは Evaluator(評価器)という Fireworks 上のリソースで、コンソールでは「Evaluations dashboard」という画面から扱う(個別ページの URL は app.fireworks.ai/dashboard/evaluators/<EVALUATOR_ID> の形式)。この画面は「evaluators」と「evaluation jobs」という 2 つのリソースを一覧・フィルタでき、Evaluator の状態列には後述する Active・Building・Failed の 3 状態が表示される。Evaluator の実体は Python プロジェクト一式(requirements.txt と @evaluation_test を含む test_*.py)で、Eval Protocol(EP)という、Fireworks 以外のトレーナー(TRL・rLLM・OpenAI RFT など)からも使えるオープンな枠組みがその書き方を定義している。コンソールにはこの Python ソースを直接編集できるコードエディタもある。

いつ使うのか

Evaluations が向くのは次のような場面である。

紛らわしいのは、第 11 章で扱った「学習済みモデルの評価(Evaluating Trained Models)」ページとの関係である。両者は「評価」という同じ言葉を使うが、役割が違う。あちらは学習直後に preemptible デプロイ(アイドルの予約 GPU を間借りする、評価・バッチ専用の安価なデプロイ)を立てて 1 リクエストだけ手動で疎通確認する、評価対象モデルを動かす実行環境の用意である。この章の Evaluator・Evaluation Job は、その実行環境に対して何をもって合格とするかを自動で採点する仕組みである。実務では preemptible デプロイ(または本番デプロイ)でモデルを動かし、そのエンドポイントを Evaluator の completion_params に指定して Evaluation Job で採点する、という組み合わせで使うこともある。

観点学習済みモデルの評価(第 11 章)Evaluation Job(この章)
役割評価対象モデルをどこで動かすか(実行環境の用意)何をもって合格とするか(採点の自動化)
実行環境firectl で作る preemptible デプロイ(借用 GPU)Fireworks 管理のジョブ基盤(Evaluator は e2b サンドボックス上でビルド)
対象1 つのデプロイ済みモデルへ手動で curlデータセット全行 × Evaluator の自動バッチ
出力レスポンス本文を目で見るmetrics(スコア集計)と出力データセット
繰り返しやすさ都度手動でデプロイを作り直す同じ Evaluator を Evaluation Job にも RFT にも使い回せる

仕組み(1)— 評価はどこに挟まるか

Evaluations は単独の機能ではなく、学習からデプロイまでの意思決定ループの中に挟まる。第 11 章の学習ジョブが終わったら、第 9 章の本番デプロイを作る前に、まずこの章の評価で「合格」かどうかを確かめる。合格しなければ、学習の設定(データセット・エポック数・手法の選び直しなど)に戻ってやり直すことになる。ここで言う「評価」は Evaluator からモデルを直接呼び出せることが前提だが、ファインチューン済みモデルは Serverless では呼べないため(第 11 章)、先に第 11 章の preemptible デプロイ(評価専用の安価なデプロイ)でエンドポイントを立て、そのモデル名を Evaluator の completion_params に渡す必要がある。本番運用中のモデルを測り直すときは、既存の on-demand デプロイをそのまま指してもよい。

学習ジョブ SFT・DPO・RFT 評価 Evaluation Job 本番デプロイ on-demand 学習完了 合格 不合格 → 再学習
図 12-1 評価は学習と本番デプロイの間に挟まる意思決定ポイントで、合格しなければ学習に戻るループになっている。

仕組み(2)— Evaluator の中身と作り方

Evaluator は Eval Protocol の @evaluation_test というデコレータで書く。1 行が 1 件の入力(messages と、正解があれば ground_truth)を表す JSONL データセットを読み込み、行ごとに ロールアウト(モデルを実際に呼び出して応答を得ること)を実行し、その応答(トラジェクトリ)を採点関数に渡して 0〜1 のスコアを返す、という一連の流れをひとまとめにしたものである。ロールアウトをどう起こすかは rollout_processor で切り替えられ、たとえば SingleTurnRolloutProcessor は completion_params に指定したモデルを 1 回呼び出す。Fireworks のモデルを呼ぶときは、LiteLLM(複数の LLM プロバイダを同じ書き方で呼び分けられるライブラリ)互換のプロバイダルート表記で fireworks_ai/accounts/fireworks/models/<モデル名> のように書く。

テストケース 会話 + 正解 ロールアウト モデル推論 トラジェクトリ 応答メッセージ 採点結果 0.0 〜 1.0 入力を渡す 推論して生成 採点
図 12-2 1 件のテストケースは、ロールアウト(推論)を経てトラジェクトリになり、@evaluation_test 内の採点ロジックが 0〜1 のスコアに変換する。

採点の粒度は mode パラメータで 3 通り選べる。既定の pointwise は行を 1 件ずつ独立に採点し、groupwise は同じ入力に対する複数モデル・複数パラメータの結果をまとめて比較する(completion_params を 2 つ以上渡す必要がある)、all はデータセット全体を関数に渡して横断的な分析を行う。合否判定は passed_threshold に成功率(例: 0.8)を渡すだけでもよいし、{"success": 0.8, "standard_error": 0.05} のように標準誤差(スコアのばらつきの目安)の条件を足すこともできる。

書いた Evaluator を Fireworks に登録する主な経路は 2 つある。推奨は ep upload CLI で、テストファイルをスキャンして選択し、アップロードまでを自動でやってくれる。API を直接叩く場合は次の 6 ステップが要る(Create Evaluator API のドキュメントに明記されている手順)。このほかに、後述の ep local-test でローカルテストを実行すると、その時点で Evaluator とデータセットが自動的に Fireworks へ登録される経路もある。

  1. Evaluator リソースを作成する(POST .../evaluatorsV2。後で状態を取得する Get Evaluator は V2 サフィックスなしの .../evaluators/{id} で、この非対称は取り違えやすい)
  2. ソースディレクトリを .gitignore を尊重しつつ .tar.gz に固める
  3. 署名付きアップロード URL を取得する
  4. その URL へ .tar.gz を PUT する
  5. アップロード検証(バリデーション)をトリガーする
  6. Evaluator の状態が ACTIVE になるまでポーリングする

登録後の Evaluator は ACTIVE・BUILDING・BUILD_FAILED のいずれかの状態を持つ。BUILDING は「e2b(Evaluator のコードをサードパーティのサンドボックス基盤で隔離実行する仕組み)のテンプレートをビルド中」という意味で、Evaluation Job にも RFT にもまだ使えない。BUILD_FAILED になったら、専用のビルドログ取得エンドポイントでログを確認できる。

仕組み(3)— Evaluation Job を走らせる

Evaluator が ACTIVE になったら、Evaluation Job(POST .../evaluationJobs)でデータセット全体に対する採点を 1 回のジョブとして走らせられる。必須フィールドは evaluator・inputDataset・outputDataset の 3 つで、いずれも accounts/<アカウント ID>/評価器またはデータセットの種類/<ID> という完全修飾名で指定する。少しつまずきやすいのは outputDataset で、これは「ジョブが作成する出力データセット」の名前でありながら必須フィールドになっている。つまり、まだ存在しないリソースの名前を、作成前に自分で決めて渡す設計になっている。

エバリュエータ 状態: ACTIVE 入力データセット (inputDataset) 評価ジョブ この3つを指定 出力データセット 名前は作成時に指定 参照 参照 実行 → この名前で作成
図 12-3 評価ジョブは Evaluator と入力データセットを指定して作成し、実行が終わると出力データセットとスコア集計が得られる。

ジョブの状態(gatewayJobState)は非同期ジョブ全般で使い回される共通の enum で、API はより細かい 20 の状態を返す。ポーリングで判定すべきは終端状態で、JOB_STATE_COMPLETED(成功)・JOB_STATE_FAILED(失敗)・JOB_STATE_CANCELLED(途中停止)のいずれかに達したら処理を止める。そこに至るまでに JOB_STATE_VALIDATING・JOB_STATE_RUNNING・JOB_STATE_WRITING_RESULTS などの中間状態を通るが、遷移の順序は docs で定義されていない。完了すると、レスポンスの metrics(メトリック名 → スコアの map)と outputStats(出力データセットの集計統計)にジョブ全体の結果が入る。

仕組み(4)— 評価と RFT 報酬の二役

Evaluator は Evaluation Job だけでなく、第 11 章で扱った RFT(Reinforcement Fine-Tuning)の報酬関数としても使われる。RFT の仕組みは「SFT が正解ラベル付きの例を渡すのに対し、RFT はプロンプトと Evaluator(0〜1 でスコアを返す報酬関数)を渡す」という 1 点に集約される。ここで使う Evaluator は Evaluation Job で使うものと同じ @evaluation_test の仕組みで、「ロールアウトを 1 つの報酬に変換する」という役割は変わらない。両者の違いは呼ばれる頻度にある。Evaluation Job は固定のデータセットに対して 1 回だけバッチで走るのに対し、RFT では学習が進むたびに繰り返し呼び出され、そのつど新しいロールアウトを採点する。ロールアウトの起こし方(rollout_processor)自体は Evaluator 側の設定で、たとえば自分の本番環境(エージェントサーバーなど)でロールアウトを実行したい場合は RemoteRolloutProcessor を Evaluator に設定して接続する構成も用意されている。

エバリュエータ score 0〜1 評価ジョブ 固定データセットを一括採点 RFT トレーニング ロールアウトの報酬として反復利用 バッチで1回 学習ステップ毎
図 12-4 同じ Evaluator が、評価ジョブでは固定データセットの一括採点に、RFT では学習中に繰り返し呼ばれる報酬関数として使われる。

ハンズオン

ハンズオン 12-1 最小の Evaluator を作ってローカルでテストし、登録する

  1. Eval Protocol の Python SDK をインストールする(この SDK が ep CLI も提供する)。
pip install pytest requests git+https://github.com/eval-protocol/python-sdk.git
  1. 作業用ディレクトリを作り、テストケースの JSONL を用意する(capitals.jsonl)。1 行が 1 件の EvaluationRow に対応する。
{"messages": [{"role": "user", "content": "What is the capital of France?"}], "ground_truth": "Paris"}
{"messages": [{"role": "user", "content": "What is the capital of Japan?"}], "ground_truth": "Tokyo"}
  1. Evaluator 本体(test_capital.py)を書く。正解の都市名が応答に含まれているかで 1.0 か 0.0 を返す、最小の採点ロジックにする。
from eval_protocol.pytest import evaluation_test, SingleTurnRolloutProcessor
from eval_protocol.models import EvaluationRow

@evaluation_test(
    input_dataset=["capitals.jsonl"],
    completion_params=[{
        "model": "fireworks_ai/accounts/fireworks/models/gpt-oss-120b",
        "temperature": 0.0,
    }],
    rollout_processor=SingleTurnRolloutProcessor(),
    passed_threshold=0.8,
    mode="pointwise",
)
def test_capital_cities(row: EvaluationRow) -> EvaluationRow:
    expected = row.ground_truth
    answer = row.messages[-1].content or ""
    row.evaluation_result.score = 1.0 if expected.lower() in answer.lower() else 0.0
    return row
  1. 登録に使う requirements.txt を同じディレクトリに置く。
git+https://github.com/eval-protocol/python-sdk.git
  1. API キーとアカウント ID を環境変数にセットする(export FIREWORKS_API_KEY=... と export ACCOUNT_ID=...)。アカウント ID は ~/.fireworks/auth.ini の account_id で確認できる。
  1. 別のターミナルでログサーバーを起動する。既定ポートは 8000 で、このターミナルは動かしたままにする。
ep logs

次のステップは実際に Fireworks の Serverless モデル(gpt-oss-120b)へ 2 件分の推論リクエストを送る。少額のトークン課金が発生する(2026-09 時点で入力 $0.15 / キャッシュ入力 $0.015 / 出力 $0.60、いずれも 1M トークンあたり USD。正確な単価は料金ページで確認する)。evalprotocol.io の公式例は Llama 3.1 8B を使っているが、Llama 3.1 8B は Fireworks の Serverless 提供モデル表に無いため、Serverless で提供中の gpt-oss-120b に置き換えている。

  1. 元のターミナルでローカルテストを実行する。
ep local-test --entry test_capital.py::test_capital_cities

2 件とも score が 1.0 になれば成功。詳細ログは手順 6 で起動した ep logs(http://localhost:8000)で確認できる。pytest の実行と同時に、この Evaluator とデータセットは Fireworks へ自動的に登録される。

  1. Evaluator を明示的な ID(capital-cities-eval)で登録する(同じ ID で登録し直すときは --force を付ける)。ep upload は Create Evaluator API の 6 ステップ(作成・パッケージング・アップロード URL 取得・アップロード・検証・ビルド待ち)をまとめて実行する。
ep upload --path . --entry test_capital.py::test_capital_cities --evaluator-id capital-cities-eval --yes
  1. 状態が ACTIVE になったかを確認する。BUILDING のままなら少し待って再実行する。
curl "https://api.fireworks.ai/v1/accounts/$ACCOUNT_ID/evaluators/capital-cities-eval" \
  -H "Authorization: Bearer $FIREWORKS_API_KEY"

レスポンスの state が ACTIVE になっていれば、この Evaluator は Evaluation Job からも RFT からも参照できる状態になっている。コンソールでも app.fireworks.ai/dashboard/evaluators/capital-cities-eval で同じ状態を確認できる。

ハンズオン 12-2 Evaluation Job を 1 回作成してスコアを見る

  1. ハンズオン 12-1 で使った capitals.jsonl を、入力データセットとして Fireworks に登録する。
firectl dataset create capitals-eval-ds capitals.jsonl

Evaluation Job を作成すると、入力データセットの全行に対して Evaluator のロールアウト(この例では Serverless 推論)が実行される。行数が増えるほど課金も比例して増えるため、まずは数行の小さいデータセットで試すこと。

  1. Evaluation Job を作成する。outputDataset にはまだ存在しないデータセット名を指定する(ジョブが完了時にこの名前で作成する)。
curl -X POST "https://api.fireworks.ai/v1/accounts/$ACCOUNT_ID/evaluationJobs" \
  -H "Authorization: Bearer $FIREWORKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "evaluationJob": {
      "evaluator": "accounts/'"$ACCOUNT_ID"'/evaluators/capital-cities-eval",
      "inputDataset": "accounts/'"$ACCOUNT_ID"'/datasets/capitals-eval-ds",
      "outputDataset": "accounts/'"$ACCOUNT_ID"'/datasets/capitals-eval-out"
    },
    "evaluationJobId": "capitals-eval-job-1"
  }'
  1. ジョブの状態が JOB_STATE_COMPLETED になるまでポーリングする。
curl "https://api.fireworks.ai/v1/accounts/$ACCOUNT_ID/evaluationJobs/capitals-eval-job-1" \
  -H "Authorization: Bearer $FIREWORKS_API_KEY"

state が JOB_STATE_COMPLETED になったら、同じレスポンスの metrics にスコアの集計が、outputStats に出力データセットの統計が入っている。outputDataset で指定した名前のデータセットには、行ごとの詳細な採点結果が保存されている。

  1. 後片付け。入力・出力の両データセットを削除する。
firectl dataset delete capitals-eval-ds
firectl dataset delete capitals-eval-out

Evaluator(capital-cities-eval)は firectl の削除コマンドが無いため、コンソールの Evaluations dashboard から削除する。消さずに残すなら、このハンズオンをもう一度試すときは outputDataset・evaluationJobId・Evaluator ID を別名にする(同じ名前は衝突する)。

つまずきポイント

Evaluator が BUILDING のうちは使えない。 登録直後は e2b サンドボックスのビルドが終わっておらず、Evaluation Job にも RFT のセレクタにも選べない(コンソールのセレクタでは、ビルド中の Evaluator はツールチップとステータスバッジ付きで選択不可になる)。ACTIVE になるまで待つか、Get Evaluator でポーリングする。

「学習済みモデルの評価」ページと Evaluation Job を混同しない。 第 11 章の preemptible デプロイを使った評価は、学習直後に 1 モデルへ手動で疎通確認する、評価対象モデルを動かす実行環境の用意であり、Eval Protocol の Evaluator を使う仕組みではない。どちらも「評価」と呼ばれるが役割が違い、preemptible デプロイで動かしたモデルを Evaluator から呼んで Evaluation Job で採点する、という組み合わせで使うこともある。

outputDataset は作成前のリソース名を自分で決めて渡す。 Create Evaluation Job の必須フィールドでありながら、その名前のデータセットはジョブが実行されて初めて作られる。既存のデータセット名と衝突しない名前を先に決めておく必要がある。

ローカルテストのリトライは既定で 0 回。 EP_MAX_RETRY の既定値は 0 で、一時的な API エラーでもそのままテスト失敗として表示される。Evaluator のロジック自体は正しいのに失敗と誤解しないよう、まずエラー内容を確認し、必要なら EP_MAX_RETRY を上げて再実行する。

理解度チェック

Q1. Evaluator の状態が BUILDING であるとは、具体的に何が起きていますか?

Evaluator の実行環境である e2b サンドボックスのテンプレートをビルドしている最中である。この状態では Evaluation Job にも RFT にも使えず、ビルドが終わって ACTIVE になって初めて参照できるようになる。

Q2. Evaluation Job を作成するときに必須の 3 フィールドは何ですか?また、そのうち作成時点でまだ存在しないリソースを指すのはどれですか?

evaluator・inputDataset・outputDataset の 3 つ。このうち outputDataset は「このジョブが作成する出力データセット」の名前であり、ジョブ作成時点ではまだ存在しないリソースの名前を自分で決めて渡す。

Q3. RFT における Evaluator の役割と、Evaluation Job における役割はどう違いますか?

どちらも同じ Evaluator(ロールアウトを 0〜1 のスコアに変換する採点ロジック)を使うが、呼ばれる頻度が違う。Evaluation Job は固定データセットに対して 1 回だけバッチで走るのに対し、RFT では学習が進むたびに繰り返し呼び出され、そのつど新しいロールアウトを採点して報酬にする。

Q4. 「学習済みモデルの評価」ページの preemptible デプロイと、この章の Evaluation Job は同じものですか?

違う。preemptible デプロイは学習直後に借用 GPU で 1 モデルへ手動で疎通確認する、評価の器(実行環境)を用意する仕組みで、Eval Protocol の Evaluator は使わない。Evaluation Job は Evaluator を使ってデータセット全体を自動採点する仕組みで、両者は役割が異なる。preemptible デプロイでモデルを動かし、そのエンドポイントを Evaluator から呼ぶ形で Evaluation Job と組み合わせて使うこともある。

Q5. Evaluator を Fireworks に登録する方法として公式に推奨されているのはどれで、API を直接叩く場合は何ステップ必要ですか?

推奨は ep upload CLI で、これが全ステップを自動化する。API を直接叩く場合は、①リソース作成 → ②ソースを tar.gz 化 → ③署名付きアップロード URL 取得 → ④アップロード → ⑤検証トリガー → ⑥ ACTIVE になるまでポーリング、の 6 ステップが必要になる。

まとめ

次章では、API キーの発行・利用量の把握・請求管理・チーム運用といった、アカウントまわりの実務を扱う。

参考リンク