Vision Fine-Tuning

Fine-tune vision-language models with the same LoRA and publish rules as the LLM trainer

praisonai-train fine-tunes vision-language models on image-caption datasets, auto-selecting the vision trainer for any model whose name contains vision, -vl-, or visionmodel.

Diagram

Vision Fine-Tuning

vision / -vl- / visionmodel

otherwise

⚙️ config.yaml

🔍 Model name?

🖼️ Vision trainer

💬 LLM trainer

🧩 LoRA adapters

✅ lora_vision_model

Quick Start

  1. Write a vision config

    Point model_name at a vision model and list an image-caption dataset. A plain config trains locally and publishes nothing.

    yaml
    model_name: unsloth/Llama-3.2-11B-Vision-Instruct
    load_in_4bit: true
    max_seq_length: 2048
    
    dataset:
      - name: unsloth/Radiology_mini
        split_type: train
    
    vision_instruction: "You are an expert radiographer. Describe accurately what you see in this image."
  2. Train
    bash
    python -m praisonai_train.train_vision train --config config.yaml

How It Works

The vision trainer converts each image-caption row into a chat conversation, attaches vision-specific LoRA adapters via Unsloth’s FastVisionModel, and trains with TRL’s SFTTrainer.

Diagram
FastVisionModelVision TrainerUserFastVisionModelVision TrainerUsertrain –config config.yamlConvert image + caption to conversationget_peft_model(lora_r, lora_alpha, …)LoRA-adapted modelSFTTrainer.train()Saves lora_vision_model/

Configuration Options

These keys are read by the vision trainer. Defaults match the source so an omitted key trains as before.

LoRA & adapter targeting

KeyTypeDefaultDescription
finetune_vision_layersboolfalseTrain the vision tower’s layers.
finetune_language_layersbooltrueTrain the language layers.
finetune_attention_modulesbooltrueTrain attention modules.
finetune_mlp_modulesbooltrueTrain MLP modules.
lora_rint16LoRA rank. Honoured from config as of #4879.
lora_alphaint16LoRA alpha. Honoured from config as of #4879.
lora_dropoutfloat0LoRA dropout. Honoured from config as of #4879.
lora_biasstr"none"LoRA bias mode.
random_stateint3407PEFT seed. Honoured from config as of #4879.
use_rsloraboolfalseEnable RS-LoRA. Honoured from config as of #4879.

Run control & publishing

KeyTypeDefaultDescription
trainbooltrueSet false to skip training. YAML true and "true" both work.
huggingface_saveboolfalsePush merged LoRA to the Hub. Requires hf_model_name. Default flipped OFF in #4879 (was "true").
huggingface_save_ggufboolfalsePush GGUF quantizations to the Hub. Requires hf_model_name. Default flipped OFF in #4879.
ollama_saveboolfalsePush to Ollama. Requires ollama_model. Default flipped OFF in #4879.
hf_model_namestr—Target Hub repo. Required when huggingface_save / huggingface_save_gguf is on.
ollama_modelstr—Target Ollama model. Required when ollama_save is on.

Common Patterns

Train locally, publish nothing — omit every publish key:

yaml
model_name: unsloth/Qwen2-VL-7B-Instruct
dataset:
  - name: unsloth/Radiology_mini
    split_type: train

Train and publish a private LoRA — set the flag, its target, and keep the default private visibility:

yaml
model_name: unsloth/Llama-3.2-11B-Vision-Instruct
dataset:
  - name: unsloth/Radiology_mini
    split_type: train
huggingface_save: true
hf_model_name: me/my-vision-model

Override the LoRA rank — now honoured on the vision path:

yaml
model_name: mistral-community/pixtral-12b
lora_r: 8
lora_alpha: 8
dataset:
  - name: unsloth/Radiology_mini
    split_type: train

Best Practices

Keep publish keys out of local runs

Omit huggingface_save / huggingface_save_gguf / ollama_save entirely for local experiments — no target, no push, no crash. Set the flag and its target only when publishing.

Set LoRA keys intentionally

Drop the lora_* keys to keep the r=16, lora_alpha=16, lora_dropout=0 defaults, or set them deliberately — as of #4879 they take effect on the vision path instead of being ignored.

Match the instruction to your dataset

vision_instruction becomes the user turn for every sample. Set it to describe the task your captions answer, so the fine-tune learns the right response style.

Use YAML booleans freely

Both train: true and train: "true" work in vision configs from #4879 — the old code crashed calling .lower() on a real boolean.


Related