Documentation Index
Fetch the complete documentation index at: https://arkor-92aeef0e-eng-736.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
スターターテンプレートのカスタマイズ
プロジェクト生成ツールは動くトレーナーを src/arkor/trainer.ts に書き出します。テンプレートは出発点で、どのフィールドも変更してよく、多くのプロジェクトは最初の数回の学習でデフォルトを卒業します。このレシピは最初に出てくる 4 つのカスタマイズを順に見ます。
出発点のトレーナー(--template triage 直後)はこんな形:
// src/arkor/trainer.ts (scaffolded)
import { createTrainer } from "arkor";
export const trainer = createTrainer({
name: "triage-run",
model: "unsloth/gemma-4-E4B-it",
dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
datasetFormat: { type: "chatml" },
maxSteps: 100,
evalSteps: 25,
lora: { r: 16, alpha: 16, loadIn4bit: false },
callbacks: {
onLog: ({ step, loss, evalLoss }) => {
const lossPart =
typeof loss === "number" && Number.isFinite(loss)
? ` loss=${loss.toFixed(4)}`
: "";
const evalPart =
typeof evalLoss === "number" && Number.isFinite(evalLoss)
? ` evalLoss=${evalLoss.toFixed(4)}`
: "";
console.log(`step=${step}${lossPart}${evalPart}`);
},
},
});
evalSteps: 25 がデフォルトで導入されているので、学習 loss と並んで eval loss の系列も出力されます — Studio の loss チャートは evalLoss を自動で拾い、上の onLog コールバックも eval が走ったステップだけターミナル行末に evalLoss=… を追記します(maxSteps: 100 で 25 ごと、つまり 1 run あたり 4 回)。各 field=… セグメントは Number.isFinite でガードされているので、eval-only ステップで loss=null が出たり、training-only ステップで evalLoss=null が出ることはありません(SDK は欠損値を null に正規化し、evalLoss の型は number | null です)。 eval が不要なら evalSteps を外し、onLog の evalLoss 関連も合わせて削ってください。
1. データセットを差し替える
データセットはモデルが実際に学ぶものです。一番よくある変更は、デモデータセットから自分のデータセットへの切り替えです。
別の HuggingFace データセットを使う。 name を渡し、必要なら split と subset を固定:
dataset: {
type: "huggingface",
name: "your-org/your-private-dataset",
split: "train", // 任意。データセットのデフォルト split
subset: "v3", // 任意。複数 subset を持つデータセット用
},
Blob URL を使う(バックエンドが取得できる任意の HTTPS URL)。Hub に置けないデータに便利:
dataset: {
type: "blob",
url: "https://internal.example.com/data/2026-04.jsonl",
token: process.env.DATASET_TOKEN, // バックエンドの blob 取得時に転送(ワイヤーフォーマットはバックエンド側で定義)
},
今のところ { type: "file" } オプションはありません。ローカルファイルはバックエンドが到達できる場所にホストしてください。SDK § DatasetSource を参照。
2. ハイパーパラメーターを調整する
TrainerInput 上の型付きオプションは安全に調整できるツマミです。省略すれば、それぞれクラウド API のデフォルト値が使われます:
createTrainer({
// ...
lora: {
r: 32, // ランクが高いほどよく学べるがコストも上がる
alpha: 64, // しばしば 2 × r
maxLength: 2048, // 長いサンプルをこのトークン数で切り詰める
loadIn4bit: true, // QLoRA、約 4 倍のメモリ節約、わずかな品質コスト
},
maxSteps: 500,
learningRate: 2e-4,
batchSize: 8,
weightDecay: 0.01,
lrSchedulerType: "cosine",
});
トレーナーファイル自体を高速に反復して試したいときは dryRun を立てます:
createTrainer({
// ...
dryRun: true,
});
dryRun: true はデータセットを切り詰め、ステップ数を制限してフルパイプラインを走らせます。GPU 時間は使います(スモークテストであり、何もしないわけではありません)が、学習は数分で終わるので、長い学習にコミットする前に設定とコールバックの挙動を確認できます。SDK § createTrainer を参照。
上級者向けフィールド(warmupSteps、loggingSteps、saveSteps、evalSteps、trainOnResponsesOnly、datasetFormat、datasetSplit)は unknown として型付けされ、クラウド API にそのまま転送されます。バックエンドの想定形を既に知っている場合のみ使ってください。SDK は渡す値を型チェックしません。
3. ライフサイクルコールバックを追加する
このセクションの他のレシピは、いずれもコールバックで噛み合います。生成済みのトレーナーでも、コールバックを 1 つずつ足していけます:
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" },
lora: { r: 16, alpha: 16 },
maxSteps: 100,
callbacks: {
onLog: ({ step, loss, evalLoss }) => {
const lossPart =
typeof loss === "number" && Number.isFinite(loss)
? ` loss=${loss.toFixed(4)}`
: "";
const evalPart =
typeof evalLoss === "number" && Number.isFinite(evalLoss)
? ` evalLoss=${evalLoss.toFixed(4)}`
: "";
console.log(`step=${step}${lossPart}${evalPart}`);
},
onCheckpoint: async ({ step, infer }) => {
// /ja/cookbook/mid-run-eval を参照
// 型付きフィールドの抽出は /ja/cookbook/structured-outputs を参照
},
onCompleted: async ({ job, artifacts }) => {
// /ja/cookbook/notifications を参照
},
onFailed: async ({ job, error }) => {
// /ja/cookbook/notifications を参照
},
},
});
このセクションのレシピは、最もよくある組み合わせです:
学習に合うものを選んでください。トレーナーファイルはただの TypeScript なので、自由に組み合わせられます。
4. ベースモデルを変える
model フィールドはクラウド API に文字列としてそのまま転送されます。現在対応しているのは gemma-4-E4B-it(すべてのスターターテンプレートに同梱)です。クラウド API がそれ以外のどの ID を受け付けるかを決めます。サポートされない値を送ると上流から 4xx が返り、training.failed イベントにバックエンドのエラーメッセージが乗ります。
model: "unsloth/gemma-4-E4B-it", // 現在サポートされている値
別のベースを試すことはロードマップ に明示的に挙がっています。それが実現するまでは、model フィールドを選択肢のあるメニューではなく、サポートされる単一の値として扱ってください。
全部まとめる
上記すべてのカスタマイズを使ったトレーナーはこんな形:
// src/arkor/trainer.ts
import { createTrainer } from "arkor";
const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK_URL;
async function postSlack(text: string): Promise<void> {
if (!SLACK_WEBHOOK) return;
try {
await fetch(SLACK_WEBHOOK, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ text }),
});
} catch (err) {
console.warn("slack post failed:", err);
}
}
export const trainer = createTrainer({
name: "support-bot-v2",
model: "unsloth/gemma-4-E4B-it",
dataset: { type: "huggingface", name: "arkorlab/triage-demo" },
lora: { r: 32, alpha: 64, maxLength: 2048, loadIn4bit: true },
maxSteps: 500,
learningRate: 2e-4,
callbacks: {
onLog: ({ step, loss, evalLoss }) => {
const lossPart =
typeof loss === "number" && Number.isFinite(loss)
? ` loss=${loss.toFixed(4)}`
: "";
const evalPart =
typeof evalLoss === "number" && Number.isFinite(evalLoss)
? ` evalLoss=${evalLoss.toFixed(4)}`
: "";
console.log(`step=${step}${lossPart}${evalPart}`);
},
onCompleted: async ({ job, artifacts }) => {
await postSlack(`✓ ${job.name} done (${artifacts.length} artifact(s))`);
},
onFailed: async ({ job, error }) => {
await postSlack(`✗ ${job.name} failed: ${error}`);
},
},
});
これでもまだ 30 行のファイルで、上から下まで一読できます。テンプレートの要点は、生成される具体的なコードそのものではなく、すでに学習が配線済みの状態を出発点として与えてくれることにあります。上のカスタマイズは、エディターを開いた 1 セッションのうちに到達できます。
Early Stopping を上に重ねるなら、Early Stopping を参照してください。Abort された学習がバックエンドの GPU を回し続けないようにする AbortController + trainer.cancel() のペアを示しています。