train command group covers LLM fine-tuning and iterative agent training.
Previously invisible commands. On PraisonAI releases before PR #4367,
praisonai train exposed only 6 of the 15 subcommands, and the entire remote group was unreachable — you had to install praisonai-train on its own to use them. The integrated CLI imported only the train command module, so the siblings that register as an import side effect never loaded. From #4367 onwards, every subcommand documented on this page (and the new remote group in Remote Training) is reachable through the integrated CLI.Usage
Every
praisonai train <sub> also runs as praisonai-train <sub> when praisonai-train is installed on its own.Requirements
Pick the install that matches what you want to train.pip install "praisonai[train]" previously installed nothing (empty extra). It now pulls praisonai-train[llm], so it installs the Unsloth stack.As of PR #4367, the
[llm] extra pulls in the praisonai wrapper transitively — the llm subcommand imports it during parse_args. You no longer need to pip install praisonai separately for praisonai-train[llm] to work; before this, pip install "praisonai-train[llm]" produced an llm command that died at parse_args.The
[llm] extra now needs the modern base stack: torch>=2.6.0, unsloth>=2025.9.1, trl>=0.18.2, transformers>=4.51.3. Pinning torch<2.6 is why install can fail — upgrade torch first. Tested on Python 3.11 with pytorch-cuda 12.4.praisonai train generate
Synthesize an instruction dataset from a teacher LLM.
Options
YAML-only keys
These have no CLI flag — set them in--config.
Examples
output and num_examples are validated up-front. generate writes to a sibling temp file and os.replaces the destination only when at least one row is produced — a run that fails on credentials or every teacher request leaves any existing file untouched (the swap also preserves the destination’s mode and follows a symlink target). Zero unique rows exits 1. Fixed in PraisonAI PR #4239.generate_dataset() Python API.
praisonai train validate
Quality-check and filter an instruction dataset (dedup, boilerplate/refusal, script purity, diversity).
Options
YAML-only keys
Examples
in / kept / drops / flags / metrics report to stdout. Malformed JSONL lines are skipped with a warning — the run still succeeds on the remaining rows.
validate writes --out atomically (temp file + os.replace), preserves the destination’s file mode when overwriting, and follows symlink targets — mirroring generate/dedup. Zero-kept exits 1 with error: no rows kept — all rows were dropped by QC ({drops}); the destination is never truncated, so an --out that aliases the input keeps its existing bytes. Fixed in PraisonAI PR #4316.score() / filter_rows() Python API.
Export trials with QC (from-trials --qc)
from-trials --qc reuses this QC filter but auto-disables the Tamil script check for English agent trajectories — pass qc_cfg={"script_range": [...]} to opt back in for another language.praisonai train benchmark
Measure and rank generation speed across LLM deployments.
Options
YAML-only keys
Examples
rows/min. n < 1 or concurrency < 1 raises ValueError; if every request fails the CLI exits 1.
See Speed Benchmark for the benchmark_deployments() Python API and cross-endpoint benchmarking.
praisonai train dedup
Merge many JSONL files into one deduped file with a single shared exact + MinHash/LSH index — catching the cross-file near-duplicates that per-file validate always misses.
Options
Examples
in / kept / removed stats block on completion and exits non-zero only on IO errors. The write is atomic — an --out that aliases an input is never truncated before its rows are read.
Cross-file dedup (Python API)
The
global_dedup(), near_dedup(), and MinHashLSH Python API behind this command.praisonai train data from-trials
Export the passing attempts from a scored trials report into a trainer-ready SFT dataset (plus a provenance sidecar) — the “keep what verified, then fine-tune on it” step of the trials loop.
Options
Examples
{out}.jsonl.meta.json — a provenance sidecar mapping each emitted row to its source case, attempt, and score.
Exit code
1 when zero rows are exported. The stderr message hints toward --all / --include-saturated, or to check that the report has passing tool-free attempts. Every skip is counted, never silent — the summary block names skipped_failed, skipped_tool_runs, skipped_unscored, skipped_saturated, and skipped_no_text.from-trials (feature guide + Python API)
The selection discipline,
export_trials() Python API, provenance sidecar, and the rejection-sampling caveat.praisonai train llm
Fine-tune an LLM using Unsloth.
--config a file that names one — one of the two is required.
Options
The four
--remote-* flags send this one run to a remote GPU box instead of training locally — the same as a remote: block in config.yaml or the desktop “Run on” dropdown. Omit --remote-host (and set no remote.host) to train here as before. See Remote in one step.--config sets the baseline, the tuning flags override it. Run with --dry-run first to see the resolved config the trainer would use — file first, flags on top. Everything not covered by a flag still lives in the config file, reachable via --config. Key config options include method (choose sft, dpo, orpo, or kto), chat_template (pick the model’s chat-template family; omit to use the built-in), and assistant_only_loss (mask prompts out of the loss; auto-picks a masking route for any known template family).Precedence
The resolved config is built in three layers — each layer overrides the one above.
An untouched config key survives when a different key is overridden by a flag.
Preview a run with --dry-run
--dry-run prints the resolved config as YAML you can paste back into a file, then a comment listing which keys came from flags — and exits without training.
--remote-host (or --remote-python, --remote-workdir, --remote-gpus) is on the command line, the settled remote: block appears in the printed YAML with credentials redacted — the host, interpreter, workdir, and GPU count the run would actually use:
remote: block is caught here too: a malformed block exits 1 with Bad remote settings at --dry-run, not after dispatch.
--dry-run does not load the training runner, so it works even without the [llm] extra installed.
Supported models
The trainer uses each model’s own chat template, sochat_template is optional — set it only to override.
Full chat_template reference
Types, defaults, and the fail-fast
ValueError when no template is available.The five families above are curated starting points, not the whole list. Run
praisonai train models to see every model the trainer can load (~246 unsloth/… repos), or praisonai train models gemma to filter by family.Examples
method: cpt with modules_to_save: [embed_tokens, lm_head] enables continued pretraining on a raw-text corpus (a dataset with a text column). See Continued Pretraining.The
DATASET positional and --model option are materialised into ./config.yaml in the invocation directory, and that file is the sole input to the trainer — the CLI passes no overrides on top. What --dry-run previews is exactly what trains. See Where config.yaml comes from. Fixed in PR #4367.praisonai-train llm <dataset> (and the wrapper route praisonai train llm <dataset>) now actually launches the trainer. On PraisonAI releases before PR #4317 the legacy dispatcher had no train case, so the command silently forwarded the literal word "train" to an LLM as a chat prompt, exited 0, and never generated a config.yaml or launched the trainer subprocess. If a previous run appeared to succeed instantly without producing lora_model/ or a praisonai-train show session, upgrade and re-run.Vision configs no longer publish by default (PraisonAI #4879). The CLI writes only the keys you supplied to
config.yaml, so a vision run (any model whose name contains vision, -vl-, or visionmodel) typically omits huggingface_save. The vision trainer used to default that flag to the string "true" and push to the Hub anyway — or crash on a missing hf_model_name after training. From #4879 an omitted flag skips publishing, matching the LLM path. See Vision Fine-Tuning.Where config.yaml comes from
The CLI writes./config.yaml from your flags plus resolved defaults in the invocation directory, then hands that single file to the trainer.
1
Materialise the config
praisonai train llm resolves the config (file first, flags on top) and writes it to ./config.yaml in the directory you ran from — the only path the legacy dispatcher and its trainer subprocess read.2
Back up any existing config.yaml
If a
config.yaml was already there and its contents differ from what’s about to be written, the previous contents are saved to ./config.yaml.bak and the run continues:3
No-op writes leave no .bak
Re-running the same command produces no
.bak file — an identical write is detected and skipped. A first run in an empty directory also writes no .bak.Config keys for LLM fine-tuning
Drive fine-tuning fromconfig.yaml (all keys optional and backward compatible).
Unsloth surface keys
Model access, PEFT selectors, quant, and vLLM rollouts — all optional and additive. See Unsloth Surface for the full walkthrough.A
--config file must be a YAML mapping of key: value. A top-level list (or scalar) is refused up front with A training config is a YAML mapping of key: value. — exit 1.Invalid or unknown YAML keys are reported before training starts. Missing required keys (
model_name, max_seq_length, dataset) raise ValueError with a minimal example; unknown keys are collected into one WARNING block with did you mean suggestions and training continues. See Train → Config validation.A
model_name not in the unsloth catalog now prints one WARNING: … line — with a “did you mean?” when there’s a close match — and training continues (unsloth loads models it doesn’t map, so a warning is safer than a refusal). Run praisonai train models to see the catalog, or praisonai train models <family> to filter it.Publishing
Publishing defaults off — set the flag and its matching target to push a fine-tuned model.
Enabling a flag without its target fails fast on load:
Preflight validation
Before any model or GPU load, the trainer fails fast with a single friendly line for the five most common misconfigurations: stale/missing training deps (checked first, before any heavy import), no CUDA GPU, missing Hugging Face credentials, low disk (< 10 GB free), and an invalid quantization_method. The GPU check is skipped when train: false, so publish-only / export-only runs succeed on CPU.
See Train → Preflight validation for the full check table, fix guidance, and the 35 valid quantization values.
Exit codes
Thellm (and the praisonai_train.train.llm.trainer module) entrypoint prints a clean one-line error instead of a traceback for expected failures.
Missing-deps behaviour
On a barepip install praisonai-train, llm prints one of two messages: LLM fine-tuning dependencies not installed with pip install "praisonai-train[llm]" when praisonai-code is absent, or Failed to load LLM fine-tuning runner: <ImportError> when praisonai-code is present but a downstream import (torch/unsloth) failed. See Train for the full flow.
Errors you may see
The most common error afterpip install --no-deps or on a hand-built conda env is a stale training stack. The trainer version-checks six packages (torch, transformers, unsloth, trl, peft, bitsandbytes) before any heavy import and prints one actionable block:
pip install -U ... command — it upgrades every listed package at once. A dev / rc suffix on a matching release satisfies the floor (2.6.0rc1 counts as 2.6.0). See Train → Runtime version-floor enforcement.
Multi-GPU launch
Fine-tune across every GPU on the machine withtorchrun — --nproc_per_node is the number of GPUs.
Remote in one step
Send this one run to a remote GPU box with--remote-host — the same as a remote: block in config.yaml or the desktop “Run on” dropdown. Precedence is flag > YAML > default; with no host settled, the command trains locally as before.
remote: block so the far side does not dispatch again), streams the log, and forwards Ctrl-C to the remote run. Credentials in the block (password, token, identity_file, …) are refused up front. See Remote in one step.
Resume
Setresume_from_checkpoint: true in config.yaml, then re-run the same command — the trainer picks the latest checkpoint in output_dir.
save_total_limit, best-checkpoint, and early-stopping keys.
Environment variables
torchrun sets the distributed variables; you set only your Hugging Face token.
praisonai train models
List every model praisonai train llm knows how to load — the same catalog model_name is validated against.
Options
Examples
* if it’s part of the small curated starting set, or a space otherwise:
* = a good starting point.) and, when the output was truncated, prints {shown} of {total}; -n 0 for all.
How the catalog is built
The command readsunsloth.models.mapper at runtime — both the 4-bit repo keys and their 16-bit mirror values — rather than shipping a vendored copy that would go stale between releases.
When unsloth isn’t installed (the CLI is importable without the training extra), the command falls back to a 7-entry curated list of one current base per family, sized for a single 24 GB GPU in 4-bit. See Supported models.
Exit codes
praisonai train export
Publish an already-trained model to Hugging Face, GGUF, or Ollama without re-running training.
lora_model/ you trained earlier — no dataset, no re-training. The hf target pushes a merged model to the Hub; gguf writes a local .gguf (and additionally pushes to the Hub when --hf is set); ollama creates and pushes an Ollama model.
Options
Examples
Export skips the training-only validation —
TrainModel.for_export() needs no dataset and no dataset: in a config. It still validates --quant. For ollama, when --hf is omitted the Modelfile FROM line points at the local model on disk, so ollama create works without a Hub round-trip.Ollama export ≤ PR #4239 shipped an indented
TEMPLATE. The Modelfile embedded four leading spaces on every continuation line, so the served prompt format tokenised differently from training and degraded fine-tune quality. Re-export any Ollama model built before this fix — the export takes seconds and does not re-train. Fixed in PraisonAI PR #4239.Exit codes
Export an already-trained model
The
TrainModel.for_export() Python API and behaviour notes behind this command.praisonai train llm for the full training path that produces the model you export here.
praisonai train agents
Train agents through iterative feedback loops.
Options
Early Stop (LLM mode)
--iterations N is a maximum, not an exact count. In LLM-as-Judge mode, training stops early as soon as any iteration scores ≥ 9.5 — easy factual prompts often finish in one iteration.
When training stops early, an INFO line is logged even in --quiet mode:
Stopped Early stays absent from the summary.
Human-in-the-loop mode (--human) does not use the 9.5 threshold — the user decides when to stop.
Examples
Summary Rows
When training completes, the summary table always showsTotal Iterations, Average / Min / Max Score, Improvement, and Status. Two extra rows appear only when the run was truncated:
The session JSON persists both signals as
metadata.target_iterations (int) and metadata.early_stopped (bool), so tools reading persisted sessions can distinguish “user asked for 3, got 1 due to 9.5” from “user asked for 1, got 1”.
Storage Backend Options
Store training data in different backends.Exit Codes
As of PraisonAI 4.6.148+ (upstream commits
ce17828, 1a6eed3, fixes PraisonAI#3040) a display-only encoding error on Windows cp1252 no longer masquerades as a training failure — the session is still saved and the exit code is 0.praisonai train serve
Serve a fine-tuned GGUF over an OpenAI-compatible endpoint — auto-fetching the MTP drafter for lossless fast inference on Gemma-4.
Options
How MTP is auto-detected
The base model name (from--base-model, --config, or the model directory’s config.json) drives drafter selection. A Gemma-4 target fetches its matching stock drafter from the Hub; any other family falls back to plain serving with a clear message.
Examples
The server binds to
127.0.0.1 — there is no --host flag. Override the llama-server binary with the LLAMA_CPP_BIN env var (points at the binary or its directory). See Serve & MTP Fast-Inference for the concept-level walkthrough and the honest runtime caveats.praisonai train checkpoints
List the checkpoints a training run saved — answers “what did it save?” without an ls.
Options
Examples
checkpoint-<n> exactly (a checkpoint-final directory is skipped), sorts numerically newest-first, and reports each checkpoint’s size on disk. An empty or missing directory exits 1 with a remediation. JSON entries are {"step": int, "path": str, "bytes": int}.
See List Checkpoints for the full workflow and jq patterns.
praisonai train infer
Run a single generation against a model you just trained — answers “did it work?”.
This subcommand is
infer, not generate — generate is dataset generation.Options
Examples
TextStreamer(skip_prompt=True), so the prompt is not echoed and the first token arrives early. Without the Unsloth / Transformers stack it exits 1 with pip install "praisonai-train[llm]".
See Infer (one-shot inference) for the full walkthrough and the infer vs serve vs benchmark decision guide.
praisonai train list
List all training sessions.
Options
Examples
Without
--storage-backend, list scans the default ~/.praison/train JSON directory. Sessions written by praisonai train agents --storage-backend sqlite ... (or Redis, or a custom file dir) are only visible when the same backend/path pair is passed to list.praisonai train show
Show details of a training session, including its iterations and best score.
Options
Examples
praisonai train apply
Apply learned suggestions from a session to an agent via hooks. Uses the best-scoring iteration by default.
Options
Examples
Standalone script
Installpraisonai-train on its own to get a praisonai-train console script that exposes the same subcommands directly.
praisonai train <sub> example above runs as-is with the praisonai-train <sub> prefix.
See Also
- Train - Training overview and fine-tuning setup
- Export a trained model - Publish a trained model without re-training
- Unsloth Surface - Gated models, PEFT selectors, offline merge, and vLLM rollouts
- Train → Preflight validation - Fast, friendly config checks before any GPU load
- Serve & MTP Fast-Inference - Serve a GGUF over OpenAI HTTP with MTP speculative decoding
- Dataset Tooling - Generate and quality-check instruction datasets
- praisonai-train Package - Standalone package guide
- Multi-GPU Training - Fine-tune across multiple GPUs with torchrun
- Remote Training - Ship a run to a GPU box over SSH with the
remotegroup - Remote in one step - Send a run to a remote GPU box with
--remote-host,remote:YAML, or the desktop dropdown - Checkpointing - Save, resume, and keep the best checkpoint
- Eval - Evaluation and testing
- Storage Backends - Pluggable storage backends

