トレーナー
createTrainer: 必須フィールド、データセットソース、LoRA 設定、start / wait / cancel のライフサイクル。
createTrainer は Arkor プロジェクトの中核です。Arkor がファインチューニングについて把握する情報(ベースモデルから LoRA ランクまで)はすべて、ここに渡したオブジェクトに集約されます。
最小例
import { createTrainer } from "arkor";
export const trainer = createTrainer({
name: "support-bot-v1",
model: "unsloth/gemma-4-E4B-it",
dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
});これだけで有効なトレーナーです。それ以外はすべてデフォルト値で埋められます。
必須フィールド
| フィールド | 型 | 補足 |
|---|---|---|
name | string | Studio とマネージドバックエンドに表示されるジョブ名。 |
model | string | バックエンドが認識するモデル ID。サポートしているモデル を参照。 |
dataset | DatasetSource | データセットソース を参照。 |
データセットソース
DatasetSource は type で判別される union です:
type DatasetSource =
| { type: "huggingface"; name: string; split?: string; subset?: string }
| { type: "blob"; url: string; token?: string };- HuggingFace。最もよく使う形。Arkor が名前でデータセットを取得します。デフォルトの split を上書きするには
split、複数の subset を公開しているデータセットにはsubsetを使います。 - Blob URL。バックエンドが取得できる任意の HTTPS URL。URL の取得に認証が必要なら
tokenを渡してください。値はクラウド API に転送されてデータセット取得時に使われます(具体的なワイヤーフォーマットはバックエンド側で定義され、SDK の契約には含まれません)。
LoRA 設定
LoRA の設定は lora で渡します。4 つのフィールドすべてが型付きです:
lora?: {
r: number; // LoRA ランク
alpha: number; // LoRA alpha
maxLength?: number; // 最大シーケンス長
loadIn4bit?: boolean; // QLoRA 量子化
}lora を省略するとバックエンドが妥当なデフォルトを適用します。同梱テンプレートでの出発点としては r: 16, alpha: 16 が無難な選択です。
よく使うハイパーパラメーター
| フィールド | 型 | 役割 |
|---|---|---|
maxSteps | number | 学習ステップの上限。最も単純に回せるツマミ。 |
numTrainEpochs | number | maxSteps の代替: データセットを何周するか。 |
learningRate | number | オプティマイザーのステップサイズ。 |
batchSize | number | デバイスごとの学習バッチサイズ。 |
optim | string | オプティマイザー名(バックエンドのリストが有効値を決める)。 |
lrSchedulerType | string | LR スケジュール(linear、cosine など)。 |
weightDecay | number | 正則化の重み。 |
maxSteps だけ設定すれば、それ以外はバックエンドのデフォルトのままです。最初の数回の学習ではそれが普通望ましい挙動です。
dryRun でのスモークテスト
createTrainer({
name: "smoke",
model: "unsloth/gemma-4-E4B-it",
dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
dryRun: true,
});dryRun: true はトレーナーのエンドツーエンドのスモークテストをバックエンドに依頼します。フルパイプライン(学習ループ含む)が、切り詰めたデータセットと制限付きステップで実行されるので素早く終わります。GPU 時間は使いますが、はるかに少ない量です。CI や、初めてコールバックを組んでいるときに便利です。
createTrainer の返り値
interface Trainer {
readonly name: string;
start(): Promise<{ jobId: string }>;
wait(): Promise<TrainingResult>;
cancel(): Promise<void>;
}start()はマネージドバックエンドにジョブを投入し、割り当てられたjobIdを返します。完了は待たず、コールバックも単独では発火しません。wait()は学習の SSE イベントストリームを開き、学習が終わる(or 失敗する)と返ります。登録したコールバックはすべてwait()内から発火します。start()を呼んだ後wait()を呼ばないと、コールバックは決して動きません。cancel()はバックエンドに学習の停止を依頼します。これはベストエフォートのリクエストです。学習がすでに終端状態(completed、failed、cancelled)にある場合バックエンドはエラーを返すことがあるので、catch する準備をしてください。
arkor start が代わりに start() と wait() を呼びます(Studio の "Run training" ボタンが内部で起動するのもこの CLI です)。start() と wait() を直接呼ぶのは、CLI の外側で学習を自分のコードに組み込む場合だけです。arkor dev 自体はトレーナーを実行しません。Studio UI を起動するだけです。
AbortSignal で wait() を止める
const controller = new AbortController();
const trainer = createTrainer({
name: "cancellable",
model: "unsloth/gemma-4-E4B-it",
dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
abortSignal: controller.signal,
});
// あとで、どこからでも:
controller.abort();abortSignal はあくまで ローカルの wait() に関するものです。Abort すると wait() 内の SSE イベントストリームの fetch と、リトライ/バックオフの遅延が停止されます。現在の実装では Abort 時に例外が発生します(バックオフの delay が signal.reason で reject し、failure handler はシグナルが Abort されていれば再 throw する)。なので wait() はクリーンに resolve せず reject します。Abort するなら try / catch で囲んでください:
try {
await trainer.wait();
} catch (err) {
if (controller.signal.aborted) {
// 想定通り: wait() を止めるよう頼んだ
} else {
throw err;
}
}abortSignal は cancel() を呼びませんし、バックエンドに学習の停止を依頼もしません。マネージド側ではジョブが GPU 時間を使い続けます。学習を実際に止めたい(コストも止めたい)場合は別途 trainer.cancel() を呼んでください:
controller.abort(); // ローカルの wait() が reject
await trainer.cancel(); // バックエンドにジョブ停止を依頼「この学習を待つのはもういい」(リクエストタイムアウト、親プロセス終了)なら abortSignal。「バックエンド側で学習を止めたい」なら cancel() を使ってください。
イベントへのリアクション
学習には ライフサイクルコールバック(onStarted、onLog、onCheckpoint、onCompleted、onFailed)を組み込めます。次に読むべきコンセプトです。