Export a trained model
Publish an already-trained model to Hugging Face, GGUF, or Ollama without re-running training
Publish a model you already trained to Hugging Face, GGUF, or Ollama — no re-training, one command.
Quick Start
You already have a trained model in lora_model/. Pick a target and publish.
- Publish to Hugging Face
Merge and push FP16 weights to a Hub repo.
bash praisonai-train export hf --model-dir lora_model --hf me/my-model - Publish a GGUF build
Write a local
.gguf— add--hfto also push it to the Hub.bash # Local .gguf only praisonai-train export gguf --model-dir lora_model --quant q4_k_m # Local .gguf + push to the Hub praisonai-train export gguf --model-dir lora_model --hf me/my-model --quant q4_k_m - Publish to Ollama
Create and push a quantized model to
ollama.com, or keep it on your machine with--no-push.bash # Push to ollama.com (default) praisonai-train export ollama --model-dir lora_model --ollama me/my-model --quant q4_k_m # Create locally only — do not upload to ollama.com praisonai-train export ollama --model-dir lora_model --ollama my-model --quant q4_k_m --no-push
When to use this
You already trained a model (e.g. lora_model/ exists) and don’t want to spend an hour re-running training just to publish it to a different target, fix a chat_template, or try a different quantization. export loads the trained weights once and publishes them.
How It Works
Export skips the training-only preflight, so it runs on CPU — there’s nothing to fine-tune. The base model name drives chat-template selection so the exported model isn’t garbled.
CLI flags
| Flag | Short | Purpose | Default | ||
|---|---|---|---|---|---|
TARGET (positional) | — | ollama \ | gguf \ | hf | required |
--model-dir | -d | Directory of the already-trained model | required | ||
--config | -c | Optional config.yaml for extra export knobs | — | ||
--ollama | — | Ollama model name, e.g. me/my-model | — | ||
--hf | — | Hugging Face repo id, e.g. me/my-model | — | ||
--quant | — | Quantization method for gguf/ollama, e.g. q4_k_m | — | ||
--base-model | — | Base model id (for chat-template selection) | inferred | ||
--mtp-draft | — | Also fetch the stock MTP drafter (Gemma-4 only) for fast inference | false | ||
--push / --no-push | — | ollama: push to ollama.com after ollama create (--no-push keeps it local) | push |
How the base model is inferred
The base model name selects the chat template, so the exported model formats prompts correctly. Resolution order:
--base-modelif passed.- else
model_namein--config. - else
_name_or_pathfrom<model-dir>/config.json. - else the model-dir name itself.
Prerequisites
Hugging Face export
HF_TOKEN env var or a cached huggingface-cli login. The token must have write scope and the repo must be under your own username.
export HF_TOKEN=hf_...
# or
huggingface-cli loginOllama export
ollamaCLI installed (from https://ollama.com).- Your signing key registered at https://ollama.com/settings/keys — public key lives at
~/.ollama/id_ed25519.pub. Not needed with--no-push. - Enough free space on
$OLLAMA_MODELS(defaults to~/.ollama/models).
No GPU needed
CUDA is not required for export-only. CPU is fine because there is nothing to fine-tune.
Valid --quant values
Any of these 35 quantization methods (from VALID_QUANTIZATION_METHODS — 24 standard plus 11 imatrix).
Standard (24)
bf16 f16 f32 fast_quantized not_quantized quantized
q2_k q2_k_l q3_k_l q3_k_m q3_k_s q3_k_xs
q4_0 q4_1 q4_k q4_k_m q4_k_s
q5_0 q5_1 q5_k q5_k_m q5_k_s
q6_k q8_0IMatrix — large-model / laptop-fit (11)
Importance-matrix quants let a 30B model fit on a laptop. Unsloth resolves the matrix itself, downloading it from unsloth/<base>-GGUF when none is supplied.
iq1_m iq1_s iq2_m iq2_s iq2_xs iq2_xxs
iq3_m iq3_s iq3_xxs iq4_nl iq4_xsSee Unsloth Surface for the “which quant should I pick” decision guide.
Failure modes → clean errors
Every known failure prints a single actionable message instead of a raw traceback.
| You’ll see | What happened | Fix |
|---|---|---|
Hugging Face rejected the token (401)... | HF token invalid/expired | huggingface-cli login or export HF_TOKEN=hf_... with a write token |
No write access to '<repo>' (403)... | Repo not under your username, or token lacks write scope | Set --hf me/my-model (your username); regenerate a write token |
Ollama rejected the push (unauthorized)... (your public key printed inline) | Ollama signing key not registered | Add the printed ~/.ollama/id_ed25519.pub key at https://ollama.com/settings/keys |
Not enough disk for the Ollama model: X GB free on '...', need ~Y GB | $OLLAMA_MODELS volume too small | export OLLAMA_MODELS=/big/disk/ollama-models |
ollama serve did not become ready in 15 seconds. ollama serve output: ... | Daemon failed to start (port busy, bad OLLAMA_HOST) | Inspect the stderr shown in the message |
quantization_method 'q4km' is not valid. Choose one of: ... | Typo in --quant | Pick a value from the list above |
Keep an Ollama export local
Trained on private data? Pass --no-push (or set ollama_push: false in config.yaml). The command still runs ollama create and prints the local tag, so ollama run <tag> works immediately — nothing is uploaded to ollama.com.
praisonai-train export ollama --model-dir lora_model --ollama my-model --no-push
# Created local Ollama model `my-model:latest` (not pushed). Run it with: ollama run my-model:latest| Key | Type | Default | Description |
|---|---|---|---|
ollama_push | bool | true | When false, stop after ollama create and keep the model local (no upload to ollama.com). Honoured by the LLM and vision trainers, including ollama_save: true during training. |
Precedence: --push / --no-push on the CLI > ollama_push in config.yaml > default (push).
Python API
Script exports with the TrainModel.for_export() classmethod — it builds an export-only trainer (no dataset required) and validates the quantization up front.
from praisonai_train.train.llm.trainer import TrainModel
trainer = TrainModel.for_export({
"final_model_dir": "lora_model",
"model_name": "unsloth/gemma-2-2b-it-bnb-4bit",
"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() # Hugging Face merged 16-bit
# trainer.save_model_gguf() # local GGUF
# trainer.push_model_gguf() # push GGUF to the Hub
# trainer.create_and_push_ollama_model() # Ollama (add "ollama_push": False to keep it local)Hub push options
These keys flow through config.yaml (not CLI flags today) into every push_to_hub_merged / push_to_hub_gguf call. Pass them in the --config file or the for_export({...}) dict.
| Key | Type | Default | Description |
|---|---|---|---|
hf_private | bool | true | Push as a private repo. Set false to publish publicly. |
save_method | string | "merged_16bit" | Passed to Unsloth’s push_to_hub_merged. |
commit_message | string | — | Optional Hub commit message. Only sent when set. |
tags | list[string] | — | Optional Hub repo tags. Only sent when set. |
imatrix_file | str | — | Path to a precomputed importance matrix; forwarded to push_to_hub_gguf. Only sent when set — Unsloth auto-fetches one from unsloth/<base>-GGUF otherwise. |
Best Practices
Namespace repos to your own username
Set --hf me/my-model (not a bare name). A namespaced repo id is treated as a Hub target, never a local directory to delete.
Quantize at export time
Pass --quant q4_k_m so the model is packed small. Ollama exports run ollama create --quantize, avoiding a huge FP16 intermediate.
Set the base model when in doubt
If the exported model’s output looks garbled, pass --base-model explicitly (e.g. unsloth/gemma-2-2b-it-bnb-4bit) so the right chat template is used.
Related
List what a run saved, then export the step you pick.
Infer CLIPrompt a model you just trained and watch it stream.
TrainFull fine-tuning flow and config.yaml reference.
Train CLIEvery praisonai train subcommand, including export.
Install matrix for the standalone trainer.
Multi-GPU TrainingFine-tune across every GPU with torchrun.
Hub Privacy & Upload OptionsPrivate-by-default pushes, save method, commit message, and tags.
Unsloth SurfaceModel access, PEFT selectors, offline merge, and the full 35-quant list.
Remote GPU TrainingTrain on another box over SSH, then fetch and export the adapter.