> ## Documentation Index
> Fetch the complete documentation index at: https://arkor-92aeef0e-eng-615.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# トレーナー

> createTrainer: 必須フィールド、データセットソース、LoRA 設定、start / wait / cancel のライフサイクル。

`createTrainer` は Arkor プロジェクトの中核です。Arkor がファインチューニングについて把握する情報（ベースモデルから LoRA ランクまで）はすべて、ここに渡したオブジェクトに集約されます。

## 最小例

```ts theme={null}
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。[サポートしているモデル](/ja/models) を参照。 |
| `dataset` | `DatasetSource` | [データセットソース](#データセットソース) を参照。                     |

## データセットソース

`DatasetSource` は `type` で判別される union です:

```ts theme={null}
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 つのフィールドすべてが型付きです:

```ts theme={null}
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` でのスモークテスト

```ts theme={null}
createTrainer({
  name: "smoke",
  model: "unsloth/gemma-4-E4B-it",
  dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
  dryRun: true,
});
```

`dryRun: true` はトレーナーのエンドツーエンドのスモークテストをバックエンドに依頼します。フルパイプライン（学習ループ含む）が、切り詰めたデータセットと制限付きステップで実行されるので素早く終わります。GPU 時間は使いますが、はるかに少ない量です。CI や、初めてコールバックを組んでいるときに便利です。

## `createTrainer` の返り値

```ts theme={null}
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()` を止める

```ts theme={null}
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` で囲んでください:

```ts theme={null}
try {
  await trainer.wait();
} catch (err) {
  if (controller.signal.aborted) {
    // 想定通り: wait() を止めるよう頼んだ
  } else {
    throw err;
  }
}
```

`abortSignal` は `cancel()` を呼びませんし、バックエンドに学習の停止を依頼もしません。マネージド側ではジョブが GPU 時間を使い続けます。学習を実際に止めたい（コストも止めたい）場合は別途 `trainer.cancel()` を呼んでください:

```ts theme={null}
controller.abort();          // ローカルの wait() が reject
await trainer.cancel();      // バックエンドにジョブ停止を依頼
```

「この学習を待つのはもういい」（リクエストタイムアウト、親プロセス終了）なら `abortSignal`。「バックエンド側で学習を止めたい」なら `cancel()` を使ってください。

## イベントへのリアクション

これを TypeScript で行う目的は、学習に [ライフサイクルコールバック](/ja/concepts/lifecycle)（`onStarted`、`onLog`、`onCheckpoint`、`onCompleted`、`onFailed`）を組み込めることです。次に読むべきコンセプトです。
