praisonai-train Package
Train agents or fine-tune LLMs without installing the full PraisonAI wrapper
Train agents or fine-tune LLMs without installing the full PraisonAI wrapper.
The praisonai-train PyPI package (import: praisonai_train) is Tier 2c — it sits on top of praisonaiagents and gives you the train CLI group and a standalone praisonai-train console script.
The PraisonAI Desktop app wraps praisonai-train llm in a Train tab — live loss chart, log, and reconnect-safe progress.
Quick Start
- Agent Training
Improve an agent iteratively — no ML dependencies required.
python from praisonaiagents import Agent agent = Agent(instructions="You are a helpful assistant.")bash pip install praisonai-train praisonai-train agents --input "What is Python?" - LLM Fine-tuning
Add the
[llm]extra to pull the modern Unsloth/torch stack (unsloth>=2025.9.1,trl>=0.18.2,transformers>=4.51.3,torch>=2.6.0). The trainer uses each model’s own chat template, sochat_templateis optional.bash pip install "praisonai-train[llm]"Llama
bash praisonai-train llm dataset.json \ --model unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bitGemma
bash praisonai-train llm dataset.json \ --model unsloth/gemma-2-2b-it-bnb-4bitQwen
bash praisonai-train llm dataset.json \ --model unsloth/Qwen2.5-0.5B-Instruct-bnb-4bitFrom a config file
Preview a run before you spend GPU time —
--dry-runprints the resolved config and exits without loading the trainer. The tuning flags override the file (file first, flags on top).bash # Preview the resolved config before spending GPU time praisonai-train llm -c config.yaml --lora-r 32 --epochs 2 --dry-run # Then run it — flags override the file praisonai-train llm -c config.yaml --lora-r 32 --epochs 2Send it to a remote GPU box
No GPU on this machine? Add
--remote-hostand the run happens on another box over SSH — the same as aremote:block in YAML or the desktop “Run on” dropdown. Set up key auth once withssh-copy-id gpubox.bash praisonai-train llm dataset.json \ --model unsloth/gemma-2-2b-it-bnb-4bit \ --remote-host gpuboxThe log streams while training; Ctrl-C stops the remote run. See Remote in one step.
- Serve a trained model
Serve a fine-tuned GGUF over an OpenAI-compatible endpoint — Gemma-4 auto-fetches its MTP drafter for lossless fast inference.
bash praisonai-train serve --gguf model.ggufSee Serve & MTP Fast-Inference for the full walkthrough.
Beginner-safe defaults
A minimal fine-tuning config trains locally and pushes nowhere unless you opt in.
model_name: "unsloth/gemma-2-2b-it-bnb-4bit"
max_seq_length: 2048
dataset:
- name: "yahma/alpaca-cleaned"
num_samples: 20 # subset for a fast smoke test# Trains locally, saves LoRA to lora_model/, no push.
praisonai-train llm dataset.yamlFour headline safety guarantees (PraisonAI #3279):
- A minimal config trains locally — publishing to Hugging Face or Ollama is opt-in (set the flag and its target).
assistant_only_loss: autonever crashes on a stock Gemma / Qwen / Llama template — it now masks via Unsloth turn markers when the template lacks{% generation %}, and falls back to full-sequence SFT only when neither route is available.- Unknown / misnamed keys warn instead of crashing — a typo logs
WARNING: ignoring unknown config key '...'and training continues. - Environment preflight — missing or out-of-date training deps are now caught before the first heavy import; the CLI prints one
pip install -U ...line that fixes them all. - An unknown
model_namewarns, it doesn’t fail — the trainer prints one line pointing atpraisonai-train models(with a “did you mean?” suggestion when there’s a close match) and continues, because unsloth also loads models it doesn’t map.
Just before training, the trainer prints a run-summary block confirming the resolved model, example count, loss mask, steps, and output dir — see Train → Run summary.
Supported dataset shapes
Point praisonai-train llm at any of these shapes and it formats rows for training automatically — no rename: block needed.
| Shape | Example row | How the trainer handles it |
|---|---|---|
Chat — conversations | {"conversations":[{"role":"user",...},{"role":"assistant",...}]} | Standardised (ShareGPT) and formatted with the chat template |
Chat — messages | {"messages":[{"role":"user",...},{"role":"assistant",...}]} | Renamed to conversations automatically, then handled the same way |
| Alpaca | {"instruction":"...","input":"...","output":"..."} | Alpaca formatter |
| Raw text | {"text":"..."} | Trained on as-is |
A dataset that already has a conversations column is left alone (no rename, no overwrite). Preference-tuning runs (method: dpo / orpo / kto / grpo) keep their own required columns unchanged.
When to Use praisonai-train vs praisonai train
Install the standalone package when you only need training; use the wrapper’s praisonai train when you already run the full stack.
Both entry points expose the same commands: every praisonai train <sub> also runs as praisonai-train <sub>.
CLI Subcommands
Eleven subcommands cover dataset tooling, benchmarking, fine-tuning, model discovery, serving, export, and agent training.
| Subcommand | Purpose | ||
|---|---|---|---|
praisonai-train generate [--config FILE] | Synthesize an instruction dataset from a teacher LLM | ||
praisonai-train validate DATASET [--out FILE] | Quality-check / filter an instruction dataset | ||
praisonai-train data from-trials REPORT | Export passing trial attempts to a trainer-ready SFT dataset | ||
praisonai-train benchmark -d DEPLOYMENT ... | Rank deployments by generation speed | ||
praisonai-train llm DATASET | Fine-tune an LLM via Unsloth (as of PR #4317, the wrapper route praisonai train llm also actually launches the trainer instead of falling through to a chat prompt) | ||
praisonai-train models [SEARCH] | List the models the trainer knows how to load — with --json / -n and * starting-point markers | ||
| `praisonai-train export {ollama\ | gguf\ | hf}` | Publish an already-trained model without re-running training |
praisonai-train agents [AGENT_FILE] | Iteratively train an agent | ||
praisonai-train serve --gguf FILE [--benchmark] | Serve a fine-tuned GGUF over an OpenAI-compatible endpoint (auto-fetches the MTP drafter on Gemma-4) | ||
praisonai-train list | List training sessions | ||
praisonai-train show SESSION_ID | Show a session’s iterations and best score | ||
praisonai-train apply SESSION_ID | Apply learned suggestions to an agent |
See Train CLI for full flags.
Supported models
praisonai-train llm fine-tunes any Unsloth-supported model. The full list — ~246 repos on a recent unsloth release, including every 4-bit key and its 16-bit mirror — is discoverable from the CLI itself:
praisonai-train models # everything, capped at 40
praisonai-train models gemma # filter by family
praisonai-train models 7b # or by size
praisonai-train models --json # machine-readable
praisonai-train models -n 0 # the full listRows marked * are the curated starting set — one current base per major family, sized to fit a single 24 GB GPU in 4-bit. Pick one of these if you haven’t chosen yet:
| Model family | Curated --model | Optional chat_template |
|---|---|---|
| Llama | unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit | llama-3.1 / llama-3 |
| Qwen | unsloth/Qwen2.5-7B-Instruct-bnb-4bit | qwen-2.5 / qwen-3 |
| Gemma | unsloth/gemma-2-9b-it-bnb-4bit | gemma / gemma-2 |
| Mistral | unsloth/mistral-7b-instruct-v0.3-bnb-4bit | mistral |
| Phi | unsloth/Phi-3.5-mini-instruct-bnb-4bit | phi-3 |
| Qwen (small) | unsloth/Qwen2.5-3B-Instruct-bnb-4bit | qwen-2.5 |
| Gemma (small) | unsloth/gemma-2-2b-it-bnb-4bit | gemma / gemma-2 |
The trainer uses each model’s own chat template, so chat_template is optional — set it only to override.
Common Patterns
Fine-tune a non-Llama base (Gemma / Qwen)
Point --model at any Gemma or Qwen base — the trainer uses each model’s own chat template automatically.
pip install "praisonai-train[llm]"
# Gemma 2 (uses the model's own template automatically)
praisonai-train llm dataset.json \
--model unsloth/gemma-2-2b-it-bnb-4bit
# Qwen 2.5
praisonai-train llm dataset.json \
--model unsloth/Qwen2.5-0.5B-Instruct-bnb-4bitFine-tune on 2 GPUs with checkpointing
Launch under torchrun and add a handful of checkpoint keys — an interrupted run resumes from the latest. See Multi-GPU.
# config.yaml
model_name: "unsloth/gemma-2-2b-it-bnb-4bit"
max_seq_length: 2048
dataset:
- name: "yahma/alpaca-cleaned"
save_strategy: "steps"
save_steps: 50
resume_from_checkpoint: truetorchrun --nproc_per_node=2 -m praisonai_train.train.llm.trainer train --config config.yamlTrain, review, apply
Run a training session, inspect the iterations, then bake the best one into your agent.
# --iterations N is a max — training stops early on a score >= 9.5 in LLM mode
praisonai-train agents --input "Explain AI" --human
praisonai-train list
praisonai-train show train-abc123 --iterations
praisonai-train apply train-abc123 --run "Explain AI"Apply in Python
Apply a session’s suggestions to an agent directly.
from praisonaiagents import Agent
from praisonai_train.train.agents import apply_training
agent = Agent(instructions="You are a helpful assistant.")
apply_training(agent, session_id="train-abc123")Train on any console
The same commands run identically on macOS, Linux, and Windows — no encoding configuration needed.
# Works identically on macOS/Linux/Windows — no encoding config needed
from praisonaiagents import Agent
agent = Agent(instructions="You are a helpful assistant.")# On a Windows cp1252 console, the summary renders as plain ASCII
# and the session is still persisted for later review.
praisonai-train agents --input "What is Python?"
praisonai-train show train-abc123Force all iterations
Benchmarks, regression tests, and demos that need to observe the feedback loop across every iteration should pass --no-early-stop (CLI) or no_early_stop=True (Python) so the 9.5 threshold is bypassed.
# CLI — always runs all 3 iterations
praisonai-train agents --input "What is Python?" --iterations 3 --no-early-stopfrom praisonaiagents import Agent
from praisonai_train.train.agents import AgentTrainer, TrainingScenario
agent = Agent(instructions="You are a helpful assistant.")
trainer = AgentTrainer(agent=agent, iterations=3, no_early_stop=True)
trainer.scenarios.append(TrainingScenario(input_text="What is Python?"))
report = trainer.run()Without this flag, --iterations behaves as a maximum in LLM-as-Judge mode — training stops as soon as any iteration scores ≥ 9.5.
Exporting an already-trained model
Publish a lora_model/ you trained earlier — no dataset, no re-training.
- Push to Hugging Face
bash praisonai-train export hf --model-dir lora_model --hf me/my-model - Export a GGUF
Writes a local
.gguf; add--hfto also push it to the Hub.bash praisonai-train export gguf --model-dir lora_model --hf me/my-model --quant q4_k_m - Push to Ollama
bash praisonai-train export ollama --model-dir lora_model --ollama me/my-model --quant q4_k_m
Export doesn't need a dataset
for_export() skips the training-only validation, so an export-only run needs no dataset: — and no config file at all.
Chat template is inferred
The base model (for chat-template selection) is read from <model-dir>/config.json:_name_or_path, falling back to the directory name. Override it with --base-model.
Quantization is validated up front
--quant accepts the same values as the LLM training path (q4_k_m, q5_k_m, q8_0, q4_0, q4_1, q5_0, q5_1, q3_k_m, q6_k, f16, bf16, q2_k). A typo fails fast, listing every valid choice.
Ollama needs a namespaced model + registered key
The model must be namespaced <username>/<name>, and your public key must be registered at https://ollama.com/settings/keys. An unauthorized push tells you exactly where to click and prints your local ~/.ollama/id_ed25519.pub.
Python API
Export-only, straight from a config dict — no dataset required.
from praisonai_train import TrainModel
trainer = TrainModel.for_export({
"model_name": "unsloth/gemma-2-2b-it-bnb-4bit",
"final_model_dir": "lora_model",
"hf_model_name": "me/my-model",
"quantization_method": "q4_k_m",
})
model, tokenizer = trainer.load_model()
trainer.model, trainer.hf_tokenizer = model, tokenizer
trainer.save_model_merged() # merged HF push
# or trainer.push_model_gguf() # GGUF-to-HF push
# or trainer.create_and_push_ollama_model() # Ollama pushSee praisonai train export for every flag and exit code.
Windows & non-UTF-8 Consoles
praisonai-train agents renders its summary table with emoji (✅ PASSED, ❌ NEEDS WORK, ★ best-iteration marker) when stdout supports UTF-8, and automatically falls back to ASCII (PASSED, NEEDS WORK, *) when it doesn’t. It detects the console’s encoding at runtime.
Exit Codes
praisonai-train agents reports three distinct outcomes.
| Exit | Meaning |
|---|---|
0 | Training completed and the report was persisted (praisonai-train list will show it). A warning is printed if only the console display failed to encode. |
1 | Training itself failed — the run raised an exception (including encoding errors that hit before save_report) or arguments were invalid. No report is persisted. |
130 | Interrupted by Ctrl-C. |
Best Practices
Install the base package for agent training
pip install praisonai-train pulls praisonaiagents plus litellm (needed for LLM-as-Judge grading) — enough for agents, list, show, and apply. Add [llm] only when you need Unsloth fine-tuning.
Use the standalone script when you don't want the wrapper
The praisonai-train console script exposes the full train group without installing praisonai. Ideal for lightweight training-only environments.
Old imports keep working
Existing praisonai.train.*, praisonai.train_vision, and praisonai.upload_vision imports still resolve to the same module objects in praisonai_train. Nothing to migrate.
Let the tokenizer's native template win
For LLM fine-tuning, only set chat_template for models without one, or to force a specific one. Forcing llama-3.1 on Gemma/Qwen was the old default and silently corrupted training — the trainer now uses each model’s own template by default. See Train → Chat Template.
Update to the modern Unsloth stack
The [llm] extra now requires unsloth>=2025.9.1, trl>=0.18.2, transformers>=4.51.3, and torch>=2.6.0. If you had pinned trl<0.9.0, upgrade — the pre-0.9 TRL API is no longer supported. As of PraisonAI PR #4365, the trainer refuses to import a stale stack at all and tells you the exact pip install -U ... to run.
Fix a GPU out-of-memory run in order
When a fine-tuning run stops with “The GPU ran out of memory”, lower max_seq_length first (biggest lever), then enable use_gradient_checkpointing: unsloth, then halve per_device_train_batch_size while doubling gradient_accumulation_steps, and switch to a 4-bit base model only as a last resort. See Train → GPU out of memory for the full walkthrough.
Related
Training overview and fine-tuning setup.
Desktop → TrainingPrefer a UI? Run a fine-tune from the Desktop app’s Train tab.
Train CLIFull flag reference for every subcommand.
Preference TrainingFine-tune on preferences with DPO, ORPO, and KTO.
Serve & MTP Fast-InferenceServe a GGUF over OpenAI HTTP with lossless MTP speculative decoding.
OllamaPublish and run fine-tuned models locally with Ollama.
Dataset ToolingGenerate and quality-check instruction datasets.
Speed BenchmarkRank deployments by generation speed before you fine-tune.
Multi-GPU TrainingFine-tune across multiple GPUs with torchrun.
Remote in One StepSend a run to a remote GPU box with --remote-host, remote: YAML, or the desktop dropdown.
Save, resume, and keep the best checkpoint.
Installation ExtrasThe train install matrix.
Package TiersHow the six packages stack.
Windows Terminal EncodingFix Rich crashes and ASCII rendering on legacy Windows consoles.