Train

Model training and fine-tuning

The train command group covers LLM fine-tuning and iterative agent training.

Usage

bash
praisonai train {generate|validate|benchmark|dedup|from-trials|llm|models|agents|export|serve|list|show|apply|checkpoints|infer|remote}

Requirements

Pick the install that matches what you want to train.

CommandGets youWhen to use
pip install praisonai-trainAgent training via agents/list/show/apply, no CUDA/Unsloth; litellm included for LLM-as-Judge gradingFastest way to try LLM-as-Judge / human-feedback agent training
pip install "praisonai-train[llm]"Above + Unsloth/torch stack for llm, and the praisonai wrapper (pulled in transitively)Fine-tuning a base model
pip install praisonaiFull stack: praisonai train ... routes through the code tierStandard PraisonAI install
pip install "praisonai[train]"Now equivalent to praisonai + praisonai-train[llm]Full stack plus fine-tuning deps

praisonai train generate

Synthesize an instruction dataset from a teacher LLM.

bash
praisonai train generate [OPTIONS]

Options

OptionShortDescriptionDefault
--config-cYAML config file (all keys below can live here)–
--output-oOutput JSONL file (required)–
--recipe-rRecipe name (e.g. tamil) or an inline dicttamil
--deployment-dTeacher model / Azure deployment name (required)–
--num-nNumber of examples to generate (required)–
--concurrency–Parallel teacher requests32
--start-offset–Prompt-index offset for disjoint parallel workers0
--snapshot-every–Copy the output to snapshots/{stem}_{n}.jsonl every N rows–

YAML-only keys

These have no CLI flag — set them in --config.

KeyTypeDefaultDescription
endpointstrenv AZURE_OPENAI_ENDPOINT / OPENAI_BASE_URLChat completions endpoint
api_keystrenv AZURE_OPENAI_KEY / OPENAI_API_KEYBearer / Azure api-key
azureboolautoForce Azure vs OpenAI routing
api_versionstr2024-10-21Azure only
max_completion_tokensint2048Teacher max_completion_tokens
request_timeoutint120Per-request HTTP timeout (seconds)
dedup_fromlist[]JSONL paths whose instruction values are excluded
stop_filepath~/.praisonai_train_stopTouch this file to halt immediately
snapshot_dirpathsnapshotsDirectory for --snapshot-every snapshots

Examples

bash
# One-command dataset
praisonai train generate -r tamil -d gpt-4o -n 1000 -o data/tamil.jsonl

# Drive everything from YAML
praisonai train generate --config generate.yaml

# Disjoint parallel slice (offset past the first worker)
praisonai train generate -r tamil -d gpt-4o -n 5000 --start-offset 5000 -o data/b.jsonl

See Dataset Tooling for recipes, dedup, snapshots, and the generate_dataset() Python API.


praisonai train validate

Quality-check and filter an instruction dataset (dedup, boilerplate/refusal, script purity, diversity).

bash
praisonai train validate [OPTIONS] DATASET

Options

OptionShortDescriptionDefault
dataset (positional)–JSONL dataset to validate (or input: in config)–
--config-cYAML config for thresholds–
--out-oWrite filtered (kept) rows to this JSONL–
--no-near-dup–Skip the O(n²) near-dup pass on very large datasetsfalse

YAML-only keys

KeyTypeDefaultDescription
near_dupbooltrueEnable near-duplicate detection
near_dup_jaccardfloat0.74-gram Jaccard threshold (≈ Self-Instruct ROUGE-L 0.7)
min_output_charsint20Below this, output is dropped as too_short
script_range[int, int][2944, 3071] (Tamil block)Unicode range that defines the target script
script_dropfloat0.5Drop rows below this script purity
script_flagfloat0.7Flag (but keep) rows between script_drop and this

Examples

bash
# Validate and write the clean rows
praisonai train validate data/tamil.jsonl --out data/clean.jsonl

# Drive thresholds from YAML
praisonai train validate --config validate.yaml

# Skip the O(n^2) near-dup pass on a large dataset
praisonai train validate data/big.jsonl --no-near-dup --out data/clean.jsonl

The command prints an in / kept / drops / flags / metrics report to stdout. Malformed JSONL lines are skipped with a warning — the run still succeeds on the remaining rows.

See Dataset Tooling for the full check list and the 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.

bash
praisonai train benchmark [OPTIONS]

Options

OptionShortDescriptionDefault
--config-cYAML config file–
--deployment-dDeployment/model to benchmark (repeatable; required via flag or config)–
--n-nRequests per deployment24
--concurrency–In-flight requests per deployment8
--api-version–Azure OpenAI api-version"2024-10-21"
--max-tokens–max_completion_tokens per request2048
--recipe-rRecipe supplying the default prompt"tamil"
--json-mode / --no-json-mode–Send the response_format JSON hint; disable for endpoints without JSON modeTrue
--output-oWrite ranked results as JSON–

YAML-only keys

KeyTypeDescription
endpointstrShared endpoint for every target (falls back to AZURE_OPENAI_ / OPENAI_)
api_keystrShared API key
azurebooltrue for Azure OpenAI, false for OpenAI-compatible
promptdictExplicit {system, user} prompt sent on every request
request_timeoutintPer-request timeout in seconds (default 180)

Examples

bash
# Compare two deployments from the environment credentials
praisonai train benchmark -d gpt-4o -d gpt-4o-mini --n 24 --concurrency 8 -o bench.json

# Drive everything from YAML
praisonai train benchmark --config benchmark.yaml

# OpenAI-compatible endpoint without JSON mode
praisonai train benchmark -d llama-3.1-70b --no-json-mode

The command prints each target as it finishes, then a table ranked by 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.

Diagram

Cross-file dedup

📁 batch_*.jsonl

🔐 sha1 exact

🧬 MinHash + LSH

💾 merged.jsonl

bash
praisonai train dedup FILES... --out MERGED.jsonl \
    [--method minhash|sliding] \
    [--threshold 0.7] \
    [--exact-only]

Options

OptionTypeDefaultDescription
FILES... (positional)list[Path]—One or more JSONL files to merge and dedup across. Glob expansion happens in the shell (batch_*.jsonl).
--outPathrequiredPath to write the merged, deduplicated JSONL.
--methodstrminhashNear-dup engine — minhash (scalable MinHash + LSH) or sliding (bounded look-back window).
--thresholdfloat0.7Jaccard threshold above which two rows are treated as near-duplicates.
--exact-onlyflagfalseSkip near-dup detection — only sha1 exact matches are removed. Fastest mode.
--configPath—YAML supplying the same keys (near_dup_method, near_dup_window, minhash_perm, ngram_n, minhash_seed, near_dup_jaccard) for reproducible runs.

Examples

bash
# Merge parallel-generation batches, remove exact + near-duplicates
praisonai train dedup batch_*.jsonl --out data/merged.jsonl

# Exact-only, fastest path (no near-dup pass)
praisonai train dedup a.jsonl b.jsonl c.jsonl --out merged.jsonl --exact-only

Drive it from YAML for a reproducible config:

yaml
# dedup.yaml
inputs: [batch_1.jsonl, batch_2.jsonl, batch_3.jsonl]
out: data/merged.jsonl
near_dup_method: minhash
near_dup_jaccard: 0.75
minhash_perm: 128
ngram_n: 4
minhash_seed: 1
bash
praisonai train dedup --config dedup.yaml

The command prints a 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.

bash
praisonai train data from-trials REPORT [OPTIONS]

Options

FlagShortTypeDefaultDescription
REPORT (positional)—pathrequiredSerialised trials-report JSON
--out-opath{report_stem}.jsonlOutput JSONL
--all—flagfalseInclude failed / unscored attempts (only_passed=False)
--include-saturated—flagfalseInclude all-pass / zero-pass cases (frontier_only=False)
--format—messages \alpacamessagesmessages = ShareGPT {"conversations": [...]}; alpaca = {instruction, input, output}
--qc—flagfalseRun emitted rows through the same QC filter as validate

Examples

bash
# Basic: keep passing, tool-free, frontier attempts as ShareGPT rows
praisonai-train data from-trials trials.json -o data/train.jsonl

# Small report: include failed/unscored attempts and saturated cases
praisonai-train data from-trials trials.json --all --include-saturated -o data/train.jsonl

# Alpaca instead of ShareGPT
praisonai-train data from-trials trials.json --format alpaca -o data/train.jsonl

# Run the exported rows through the same QC filter as validate
praisonai-train data from-trials trials.json --qc -o data/train.jsonl

Every run also writes {out}.jsonl.meta.json — a provenance sidecar mapping each emitted row to its source case, attempt, and score.

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.

bash
praisonai train llm [OPTIONS] [DATASET]

Pass a dataset path, or --config a file that names one — one of the two is required.

Diagram

Config resolution

⚙️ Defaults

📄 config.yaml

🚩 CLI flags

🔍 –dry-run
preview

🚀 train

Options

OptionShortDescriptionDefault
--model-mBase model to fine-tune — Llama, Gemma, Qwen, Mistral, and Phi bases are validated–
--config-cTraining config YAML. The flags below override it. See Config keys for LLM fine-tuning for every key a config file may set.–
--dry-run–Print the resolved config as YAML (including the settled remote: block, with credentials redacted) and exit, without training. Bad remote settings are caught here too. Does not load the runner.false
--method–Training method — `sft \cpt \dpo \orpo \kto \grpo (method`)–
--max-seq-length–Sequence length (max_seq_length)–
--epochs–Epochs (num_train_epochs). Ignored if --max-steps is set.–
--max-steps–Stop after this many steps (max_steps)–
--learning-rate–Learning rate (learning_rate)–
--batch-size–Per-device batch size (per_device_train_batch_size)–
--grad-accum–Gradient accumulation steps (gradient_accumulation_steps)–
--lora-r–LoRA rank (lora_r)–
--lora-alpha–LoRA alpha (lora_alpha)–
--output-dir–Where checkpoints go (output_dir)–
--chat-template–Chat template name (chat_template)–
--remote-host–SSH alias to train on, as in ~/.ssh/config (remote.host). Omit to train locally.–
--remote-python–Interpreter on the remote host (remote.python)python3
--remote-workdir–Directory on the remote host to work in (remote.workdir)~/.praisonai-train
--remote-gpus–How many GPUs the remote run expects to find (remote.gpus)1
--verbose-vVerbose outputfalse

Precedence

The resolved config is built in three layers — each layer overrides the one above.

OrderSourceSets
1Bare defaults (from TrainModel)Baseline values
2--config config.yamlYour saved config
3Tuning flags on the command lineThe keys you override

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.

bash
praisonai-train llm -c config.yaml --lora-r 32 --epochs 2 --dry-run
yaml
lora_r: 32
max_seq_length: 2048
model_name: unsloth/gemma-2-2b-it-bnb-4bit
num_train_epochs: 2.0

# 2 value(s) came from flags: lora_r, num_train_epochs

When --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:

bash
praisonai-train llm -c config.yaml --remote-host gpubox --dry-run
yaml
lora_r: 32
model_name: unsloth/gemma-2-2b-it-bnb-4bit
remote:
  gpus: 1
  host: gpubox
  python: python3
  workdir: ~/.praisonai-train

A bad 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, so chat_template is optional — set it only to override.

Model familyExample --modelOptional chat_template
Llamaunsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bitllama-3.1 / llama-3
Gemmaunsloth/gemma-2-2b-it-bnb-4bitgemma / gemma-2
Qwenunsloth/Qwen2.5-0.5B-Instruct-bnb-4bitqwen-2.5 / qwen-3
Mistralunsloth/mistral-7b-instruct-v0.3-bnb-4bitmistral
Phiunsloth/Phi-3-mini-4k-instruct-bnb-4bitphi-3
Full chat_template reference

Types, defaults, and the fail-fast ValueError when no template is available.

Examples

bash
# Fine-tune with a dataset
praisonai train llm dataset.json

# Fine-tune with a specific base model
praisonai train llm --model llama-3.1 dataset.json

# Fine-tune Gemma or Qwen with their native templates (no config needed)
praisonai train llm dataset.json --model unsloth/gemma-2-2b-it-bnb-4bit
praisonai train llm dataset.json --model unsloth/Qwen2.5-0.5B-Instruct-bnb-4bit

# Override tuning knobs straight from the CLI
praisonai-train llm data.jsonl --lora-r 32 --epochs 2

# Start from a config file, override one key
praisonai-train llm -c config.yaml --max-seq-length 4096

# Preview the resolved config without training
praisonai-train llm -c config.yaml --dry-run

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:

    text
    NOTE: config.yaml already existed; the previous contents were saved to config.yaml.bak.
  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 from config.yaml (all keys optional and backward compatible).

KeyTypeDefaultDescription
methodstr"sft"Training method — sft, dpo, orpo, or kto. Case-insensitive. See Preference Training.
modelstr—Alias for model_name (parity with --model). If both are set, model_name wins.
methodstr"sft"Training method. One of sft, cpt, dpo, orpo, kto, grpo. cpt is continued pretraining on a raw-text corpus — see Continued Pretraining; grpo is scored by reward functions — see Reward Functions & GRPO.
embedding_learning_ratefloatlearning_rate / 10Only used when method: cpt. Rate for embed_tokens / lm_head when they are in modules_to_save.
chat_templatestrNone (model’s own)Force a specific Unsloth chat template — e.g. "llama-3.1", "gemma", "qwen-2.5". Required when the base model’s tokenizer has no built-in template, else the trainer raises ValueError.
assistant_only_loss`”auto” \bool`"auto"Mask prompts out of the loss (SFT). "auto" masks whenever a route is available — TRL’s {% generation %} or Unsloth’s turn markers; true forces on (errors only when neither route is available); false forces off. train_on_responses_only is accepted as an alias.
betafloattrainer defaultPreference-loss temperature for dpo / orpo / kto.
max_prompt_lengthintmax_seq_length // 2Prompt truncation length for dpo / orpo / kto.
desirable_weightfloattrainer defaultkto only — weight on thumbs-up examples.
undesirable_weightfloattrainer defaultkto only — weight on thumbs-down examples.
dataset[].num_samplesint—Train on the first N rows of the split. Positive integer — validated on load.
trainbooltrueSet false to skip training and publishing.
huggingface_saveboolfalsePush merged LoRA to Hugging Face. Requires hf_model_name.
huggingface_save_ggufboolfalsePush GGUF quantizations to Hugging Face. Requires hf_model_name.
ollama_saveboolfalsePush to Ollama. Requires ollama_model.

Unsloth surface keys

Model access, PEFT selectors, quant, and vLLM rollouts — all optional and additive. See Unsloth Surface for the full walkthrough.

KeyTypeDefaultAreaDescription
hf_tokenstr—model accessHF token. Downloads gated bases and authenticates publishing. Overridden by HF_TOKEN.
trust_remote_codebool—model accessRequired for custom-code models.
revisionstr—model accessPin a HF branch, tag, or SHA for reproducibility.
finetune_last_n_layersint—PEFTTune only the last N transformer blocks.
layers_to_transform`int \list[int]`—PEFTExplicit layer indices to adapt.
layers_patternstr—PEFTPattern selecting which layers to adapt.
target_parameterslist[str]—PEFTSelectors — required to LoRA MoE experts.
init_lora_weights`str \bool`—PEFTLoRA init scheme ("gaussian", "pissa", "olora").
merged_save_dirstr—quantMerge the adapter into this local folder — no Hub needed.
imatrix_filestr—quantPrecomputed importance matrix for imatrix quants. Auto-fetched when unset.
fast_inferenceboolfalsevLLMTurn on vLLM rollouts for GRPO.
gpu_memory_utilizationfloat—vLLMvLLM GPU memory fraction. Only sent when fast_inference is on.
max_lora_rankint—vLLMMax LoRA rank vLLM allocates for. Only sent when fast_inference is on.

See Train → Config.yaml example for the full file.

Publishing

Publishing defaults off — set the flag and its matching target to push a fine-tuned model.

To publish toSet flagAnd target
Hugging Face (merged)huggingface_save: truehf_model_name
Hugging Face (GGUF)huggingface_save_gguf: truehf_model_name
Ollamaollama_save: trueollama_model

Enabling a flag without its target fails fast on load:

ValueError: hf_model_name is required when huggingface_save or huggingface_save_gguf is enabled.
ValueError: ollama_model is required when ollama_save is enabled.

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

The llm (and the praisonai_train.train.llm.trainer module) entrypoint prints a clean one-line error instead of a traceback for expected failures.

ExitMeaning
0Training (or export) completed successfully.
1Expected, actionable failure — printed as a single ERROR: <message> line to stderr with no Python traceback. Covers preflight failures, config errors, HF/Ollama publish errors, and ollama create/push failures. As of PR #4317, a non-zero SystemExit from the router (e.g. missing training deps) also propagates through the train_llm Typer command, so $? sees the failure. Clean exits still return 0.
130Interrupted by Ctrl-C — printed as Interrupted. to stderr.
otherAn unexpected exception — the full Python traceback is printed (a real bug; please file it).

Missing-deps behaviour

On a bare pip 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:

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 after pip 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:

text
Training dependencies are missing or too old.
Missing: unsloth
torch 2.5.1 is older than the required 2.6.0
Install with: pip install -U "unsloth>=2025.9.1" "torch>=2.6.0"

Run the printed 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 with torchrun — --nproc_per_node is the number of GPUs.

bash
torchrun --nproc_per_node=2 -m praisonai_train.train.llm.trainer train --config config.yaml

The trainer detects the distributed launch, loads the full model per rank, and lets only rank 0 save and publish. See Multi-GPU for the full walkthrough.

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.

bash
praisonai-train llm dataset.json --model unsloth/gemma-2-2b-it-bnb-4bit --remote-host gpubox

The dispatcher ships the config (stripping the 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

Set resume_from_checkpoint: true in config.yaml, then re-run the same command — the trainer picks the latest checkpoint in output_dir.

yaml
# config.yaml
save_strategy: "steps"
save_steps: 50
resume_from_checkpoint: true
bash
praisonai-train llm config.yaml

See Checkpointing for save_total_limit, best-checkpoint, and early-stopping keys.

Environment variables

torchrun sets the distributed variables; you set only your Hugging Face token.

VariableSet byPurpose
LOCAL_RANKtorchrunThis process’s GPU index on the node.
WORLD_SIZEtorchrunTotal number of processes / GPUs.
RANKtorchrunGlobal process rank (0 = main process).
UNSLOTH_USE_NEW_MODELtrainerSet to 1 under DDP before unsloth imports (DDP-safe checkpointing).
HF_TOKENyouNeeded only when publishing to Hugging Face.

praisonai train models

List every model praisonai train llm knows how to load — the same catalog model_name is validated against.

bash
praisonai train models [SEARCH] [OPTIONS]

Options

OptionShortDescriptionDefault
search (positional)—Case-insensitive substring filter, e.g. gemma, qwen, 7b.—
--json-jEmit the (filtered) list as a JSON array.false
--limit-nMax rows to show. 0 shows the full catalog.40

Examples

bash
# Everything unsloth maps (~246 repos on a recent unsloth release)
praisonai train models

# Just the Gemma family
praisonai train models gemma

# JSON for scripts
praisonai train models --json

# The full list, un-truncated
praisonai train models -n 0

Each row is prefixed with * if it’s part of the small curated starting set, or a space otherwise:

* unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit
  unsloth/Meta-Llama-3.1-8B-Instruct
  ...

The trailing line explains the marker (* = 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 reads unsloth.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

ExitMeaning
0Rows printed, or JSON emitted.
1The filter matched nothing — prints Nothing matches '<search>' with the remediation Try a family name (gemma, qwen, llama) or a size (7b).

praisonai train export

Publish an already-trained model to Hugging Face, GGUF, or Ollama without re-running training.

bash
praisonai train export {ollama|gguf|hf} --model-dir DIR [--hf REPO] [--ollama NAME] [--quant Q] [--base-model NAME] [--config FILE] [--push|--no-push]

Point it at a 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 (add --no-push to keep it local).

Options

OptionShortTypeDefaultDescription
target (positional)—ollama \gguf \hfrequiredExport destination. Case-insensitive. An unknown target exits 1 with Use one of: ollama, gguf, hf.
--model-dir-dpathrequiredDirectory of the already-trained model (e.g. lora_model). Must be an existing directory, else exits 1.
--hf—str—Hugging Face repo id, e.g. me/mymodel. Required for hf; optional for gguf (adds a Hub push on top of the local .gguf).
--ollama—str—Ollama model name, e.g. me/mymodel. Required for ollama.
--quant—str—Quantization method for gguf/ollama. One of 35 values — 24 standard plus 11 imatrix; see Export → Valid quant values. An invalid value fails fast, listing every valid choice.
--base-model—strinferredBase model id for chat-template selection. Auto-inferred from <model-dir>/config.json:_name_or_path, falling back to the directory name.
--config-cpath—Optional config.yaml for extra export knobs (e.g. dtype, load_in_4bit). Must parse to a YAML mapping — a top-level list/scalar exits 1 with Config file must be a YAML mapping.
--mtp-draft—flagfalseAlso download the stock MTP drafter (Gemma-4 only) for fast inference. A failure here only warns; the export still succeeds.
--push / --no-push—boolpushollama target: push to ollama.com after ollama create. --no-push keeps the model local. Overrides ollama_push in --config. Ignored for hf/gguf.

Examples

bash
# Push a merged model to Hugging Face
praisonai-train export hf     --model-dir lora_model --hf     me/my-model

# Write a local GGUF (and push it to HF when --hf is given)
praisonai-train export gguf   --model-dir lora_model --quant q4_k_m
praisonai-train export gguf   --model-dir lora_model --hf     me/my-model --quant q4_k_m

# Push to Ollama (default)
praisonai-train export ollama --model-dir lora_model --ollama me/my-model --quant q4_k_m

# Keep local only — never upload
praisonai-train export ollama --model-dir lora_model --ollama my-model --quant q4_k_m --no-push

Exit codes

ExitMeaning
0Success — prints Exported model to <target>.
1Invalid target, missing --model-dir, missing destination for the chosen target, config not a YAML mapping, or any ValueError / RuntimeError / CalledProcessError raised during load or push. Errors print as a single clean line (ERROR: <msg>) — no traceback.
Export an already-trained model

The TrainModel.for_export() Python API and behaviour notes behind this command.

See praisonai train llm for the full training path that produces the model you export here.


praisonai train agents

Train agents through iterative feedback loops.

bash
praisonai train agents [OPTIONS] [AGENT_FILE]

Options

OptionShortDescriptionDefault
--iterations-nMaximum training iterations. In LLM mode, stops early when a score reaches 9.5 (use --no-early-stop to force all).3
--no-early-stop–Run all --iterations even when a score reaches 9.5.false
--human-hUse human feedback instead of LLM gradingfalse
--scenarios-sPath to scenarios JSON file–
--input-iSingle input text for training–
--expected-eExpected output for the input–
--output-oOutput directory for training data–
--model-mLLM model for gradinggpt-4o-mini
--verbose / --quiet-v / -qShow detailed progress. When --verbose, the orchestrator prints its own post-persist summary; a display-only encoding failure there is logged as a warning and does not affect the exit code.--verbose
--dry-run–Show what would happen without runningfalse
--storage-backend–Storage backend: file, sqlite, or redis://urlfile
--storage-path–Path for storage backend–

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.

Diagram

No

Yes

No

Yes

Yes

No

praisonai-train agents
–iterations N

Run iteration

Grader scores output

score >= 9.5?

iteration < N?

–no-early-stop?

Log INFO + break loop
early_stopped = True

All N iterations complete
early_stopped = False

Summary shows
Requested / Stopped Early rows

When training stops early, an INFO line is logged even in --quiet mode:

text
INFO ...orchestrator: Early stop after iteration 1/3 (score 10.0 >= 9.5 threshold). Use no_early_stop=True to run all iterations.

Reaching 9.5 on the final iteration counts as a full run — 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

bash
# Simple training with single input
praisonai train agents --input "What is Python?"

# Training with expected output
praisonai train agents --input "What is 2+2?" --expected "4"

# Training with scenarios file
praisonai train agents --scenarios scenarios.json

# Human feedback mode
praisonai train agents --input "Explain AI" --human

# More iterations
praisonai train agents --input "Hello" --iterations 5

# Force all iterations even if a score hits 9.5
praisonai-train agents --input "What is Python?" --iterations 3 --no-early-stop

# See the early-stop INFO line in the console
praisonai-train agents --input "Capital of Italy?" --iterations 3 --verbose

# With agent file
praisonai train agents my_agent.yaml --scenarios scenarios.json

Summary Rows

When training completes, the summary table always shows Total Iterations, Average / Min / Max Score, Improvement, and Status. Two extra rows appear only when the run was truncated:

RowWhen it appearsValue
Requested Iterationsrequested > completedThe value passed via --iterations
Stopped Earlymetadata.early_stopped == TrueYes (score X.X >= 9.5; use --no-early-stop to run all)

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.

bash
# SQLite backend (recommended for production)
praisonai train agents --input "Hello" --storage-backend sqlite --storage-path ~/.praisonai/train.db

# Redis backend (for distributed systems)
praisonai train agents --input "Hello" --storage-backend redis://localhost:6379

# File backend (default)
praisonai train agents --input "Hello" --storage-backend file --storage-path ~/.praisonai/train

Exit Codes

ExitMeaning
0Training completed and the session was persisted. On non-UTF-8 consoles a warning may be printed if the summary display failed to encode.
1Training failed. This includes both runtime exceptions and encoding errors that occur before the report is saved.
130Interrupted by Ctrl-C.

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.

bash
praisonai train serve [OPTIONS]

Options

OptionShortDescriptionDefault
--model-dir-dDirectory of the trained model (target GGUF auto-detected; drafter files skipped)–
--gguf–Explicit path to the target GGUF to serve–
--config-cOptional config.yaml for base-model / MTP knobs–
--base-model–Base model id used to select the MTP drafter–
--mtp-draft / --no-mtp-draft–Use the stock MTP drafter (auto: on when the family supports it)--mtp-draft
--spec-draft-n-max–Max tokens the MTP drafter proposes per step2
--port–Port for llama-server8080
--ngl–Number of layers to offload to GPU99
--benchmark–Run a one-shot speed benchmark instead of servingfalse

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.

Diagram

serve

yes

no

📦 target GGUF

Gemma-4?

🧠 fetch drafter

📡 plain serve

💨 llama-server
+ MTP

📡 llama-server

Examples

bash
# Serve a single GGUF on the default OpenAI endpoint (:8080)
praisonai train serve --gguf model.gguf

# Serve from a model directory (target GGUF auto-detected)
praisonai train serve --model-dir lora_model

# One-shot benchmark: tokens/sec + MTP draft acceptance, then exit
praisonai train serve --gguf gemma4-e4b.gguf --benchmark

praisonai train checkpoints

List the checkpoints a training run saved — answers “what did it save?” without an ls.

bash
praisonai train checkpoints [OPTIONS]

Options

OptionShortDescriptionDefault
--model-dir-dDirectory the run wrote to (its output_dir)outputs
--json-jEmit a JSON array instead of the human listingfalse

Examples

bash
# List saved checkpoints, newest step first
praisonai train checkpoints -d outputs

# Machine-readable output for scripts
praisonai train checkpoints -d outputs --json

Matches 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?”.

bash
praisonai train infer -d lora_model "Summarise this release."

Options

OptionShortDescriptionDefault
prompt (positional)–What to send the modelrequired
--model-dir-dPath to a trained adapter or model (must exist)lora_model
--max-new-tokens–Maximum new tokens to generate256
--temperature–Sampling temperature0.7
--max-seq-length–Context length used when loading the model2048
--load-in-4bit / --no-load-in-4bit–Load the model in 4-bit quantisationtrue

Examples

bash
# Simplest one-liner — reply streams to stdout
praisonai train infer -d lora_model "Summarise this release."

# Longer, more focused output
praisonai train infer -d lora_model "Write release notes." \
    --max-new-tokens 512 --temperature 0.3

Output streams via 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.

bash
praisonai train list [OPTIONS]

Options

OptionShortDescriptionDefault
--limit-nMax sessions to show20
--json-jOutput as JSONfalse
--storage-backend–Storage backend: file, sqlite, or redis://urlfile
--storage-path–Path for storage backend (file dir or sqlite db path)–

Examples

bash
# List recent sessions
praisonai train list

# Show more sessions as JSON
praisonai train list --limit 50 --json

# List sessions from a SQLite backend
praisonai train list --storage-backend sqlite --storage-path ~/.praisonai/train.db

# List sessions from Redis
praisonai train list --storage-backend redis://localhost:6379

# List sessions from a custom file directory
praisonai train list --storage-backend file --storage-path ~/.praisonai/train

Each row shows the session ID, iteration count, size, and last-modified time.


praisonai train show

Show details of a training session, including its iterations and best score.

bash
praisonai train show [OPTIONS] SESSION_ID

Options

OptionShortDescriptionDefault
--iterations-iShow detailed iteration infofalse
--json-jOutput as JSONfalse
--storage-backend–Storage backend: file, sqlite, or redis://urlfile
--storage-path–Path for storage backend (file dir or sqlite db path)–

Examples

bash
# Show session summary
praisonai train show train-abc123

# Show with detailed iterations
praisonai train show train-abc123 --iterations

# Output as JSON
praisonai train show train-abc123 --json

# Session stored in a SQLite database
praisonai train show train-abc123 \
    --storage-backend sqlite --storage-path ~/.praisonai/train.db

# Session stored in Redis
praisonai train show train-abc123 --storage-backend redis://localhost:6379

# Session stored in a custom file directory
praisonai train show train-abc123 \
    --storage-backend file --storage-path ~/.praisonai/train

The summary highlights the best iteration (★) with its score and feedback.


praisonai train apply

Apply learned suggestions from a session to an agent via hooks. Uses the best-scoring iteration by default.

bash
praisonai train apply [OPTIONS] SESSION_ID

Options

OptionShortDescriptionDefault
--agent-aPath to agent YAML file–
--iteration-nSpecific iteration numberbest score
--run-rRun agent with this prompt after applying–
--json-jOutput as JSONfalse
--storage-backend–Storage backend: file, sqlite, or redis://urlfile
--storage-path–Path for storage backend (file dir or sqlite db path)–

Examples

bash
# Apply best iteration to default agent
praisonai train apply train-abc123

# Apply a specific iteration
praisonai train apply train-abc123 --iteration 2

# Apply to an agent from a YAML file
praisonai train apply train-abc123 --agent my_agent.yaml

# Apply and run immediately
praisonai train apply train-abc123 --run "Hello, how are you?"

# Apply a session stored in SQLite
praisonai train apply train-abc123 \
    --storage-backend sqlite --storage-path ~/.praisonai/train.db

# Apply a session stored in Redis, then run
praisonai train apply train-abc123 \
    --storage-backend redis://localhost:6379 \
    --run "Hello, how are you?"

# Apply a session written to a custom file dir
praisonai train apply train-abc123 \
    --storage-backend file --storage-path ~/.praisonai/train

Standalone script

Install praisonai-train on its own to get a praisonai-train console script that exposes the same subcommands directly.

bash
pip install praisonai-train

praisonai-train agents --input "What is Python?"
praisonai-train data from-trials trials.json -o data/train.jsonl
praisonai-train list
praisonai-train show train-abc123 --iterations
praisonai-train apply train-abc123 --iteration 2 --run "Hello, how are you?"
praisonai-train export hf --model-dir lora_model --hf me/my-model

Every praisonai train <sub> example above runs as-is with the praisonai-train <sub> prefix.


See Also