Skip to main content

ライフサイクルコールバック

コールバックは createTrainer({ callbacks: { ... } }) の下に渡します。バックエンドの SSE イベントストリームから trainer.wait() 内でディスパッチされて動きます。

シグネチャー

interface 自体は 5 プロパティすべて必須ですが、createTrainercallbacks フィールドは Partial<TrainerCallbacks> 型なので、必要なイベントだけ指定すれば OK です。コールバックの戻り値は破棄されます(unknown | Promise<unknown> という戻り値型は、コールバックから値を return しても TypeScript が文句を言わない、というだけの意味です)。

それぞれのコールバックがいつ発火するか

start() を呼んで wait() を呼ばないと、コールバックは決して動きません。arkor start は両方呼んでくれます。プログラムから呼び出す側も同じことをしてください。

パラメータ

onStarted({ job })

SSE ストリームが training.started を報告したときに発火します。ログ行や「学習開始しました」通知に使ってください。

onLog({ step, loss, evalLoss, learningRate, epoch, samplesPerSecond, job })

学習が進むにつれて繰り返し発火します。各数値フィールドは number | null: バックエンドはあるステップで持っているフィールドだけ埋めます(なので evalLoss は eval 以外のステップで null、learningRate は LR スケジューラ更新の合間に null、など)。
よくある用途は次のとおりです。自前のパイプライン(PostHog、Datadog)へのメトリックス転送、早期発散の検知、カスタム Early Stopping(指標が悪化したら学習を自動で打ち切るパターン。詳しくは Early Stopping レシピ を参照)の実装。Early Stopping については、abortSignal の Abort はあなたのローカル wait() を止めるだけだと忘れずに。バックエンドの GPU を実際に止めるには、その後 trainer.cancel() を呼んでください。

onCheckpoint({ step, adapter, job, infer, artifacts })

学習中にバックエンドでアダプタチェックポイントが保存されたときに発火します。adapter{ kind: "checkpoint", jobId, step }infer の詳細は infer ページにあります。要するにチャット形式のリクエストを取り、生の Response を返す関数です。
TypeScript でファインチューニングする価値の多くがここに集まります: 学習途中のモデルを取り置いたプロンプトで、全体の学習完了前に走らせられます。

onCompleted({ job, artifacts })

成功時に 1 回発火。artifactsunknown[]: バックエンドが送った生の artifact リスト。スキーマは進化するため SDK で絞り込みません。

onFailed({ job, error })

バックエンド報告の失敗で 1 回発火。errorstring(バックエンドが送ったメッセージ)であり、Error インスタンスではありません。
onFailedバックエンド側の 失敗専用です。あなたの他のコールバック内で投げられた例外は onFailed には届きません。何が起きるかは下記の 例外ハンドリング を参照してください。

振る舞い

順序

各コールバックは次のイベントがディスパッチされる前に await されます。Promise を返してよく(DB への書き込み、Slack への投稿、infer の呼び出しなど)、SDK は次のフレーム処理前にそれを待ちます。同一トレーナーに対する並行ディスパッチはありません。

例外ハンドリング

コールバック内で throw しても通常の Promise reject のようには 振る舞いません。SDK のイベントループは dispatch を try/catch で包み、throw を SSE 再接続ハンドラ(packages/arkor/src/core/trainer.ts:335-364、続いて :307-320handleFailure)にルートします:
  1. abortSignal.aborted が立っていれば、エラーは再 throw され wait() は reject。
  2. それ以外で maxReconnectAttempts が設定されカウンター超過なら、wait() はラップされたエラーで reject。
  3. それ以外なら、SDK は遅延を入れて SSE ストリームを再オープン。
maxReconnectAttempts のデフォルトは undefined(無制限)です。TrainerInput から設定はできず、createTrainer の第 2 引数 context@internal 注釈付きで予告なく変わり得る)でしか設定できません。実用上、デフォルト設定では throw されたコールバックは catch されてリトライ され、無期限に続く可能性があります。Last-Event-ID がリトライ間で進めば、元の失敗イベント自体もスキップされます。 決定的なエラーハンドリングが必要ならコールバック内で catch してください(下の 2 つ目の例を参照)。

最小例: すべてのイベントをログに出す。
コールバック内で catch して失敗をローカルに閉じ込め、SSE 再接続を起こさないようにする:

型定義

TrainingLogContextCheckpointContextarkor から名前付きでエクスポートされていません。自分のコードで型付きコールバックパラメータが欲しいならインラインで形をミラーしてください。

関連項目