diff --git a/studio/backend/assets/configs/model_defaults/default.yaml b/studio/backend/assets/configs/model_defaults/default.yaml index 7b918b9387..ceb332bc14 100644 --- a/studio/backend/assets/configs/model_defaults/default.yaml +++ b/studio/backend/assets/configs/model_defaults/default.yaml @@ -14,7 +14,7 @@ training: weight_decay: 0.01 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-VL-28B-A3B-PT.yaml b/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-VL-28B-A3B-PT.yaml index ef417c8410..1032449e8c 100644 --- a/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-VL-28B-A3B-PT.yaml +++ b/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-VL-28B-A3B-PT.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/falcon/tiiuae_Falcon-H1-0.5B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/falcon/tiiuae_Falcon-H1-0.5B-Instruct.yaml index d45526bcf7..eafc7065d5 100644 --- a/studio/backend/assets/configs/model_defaults/falcon/tiiuae_Falcon-H1-0.5B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/falcon/tiiuae_Falcon-H1-0.5B-Instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.01 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: false optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_codegemma-7b-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_codegemma-7b-bnb-4bit.yaml index 185b91ecf4..c4c73ac028 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_codegemma-7b-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_codegemma-7b-bnb-4bit.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-27b-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-27b-bnb-4bit.yaml index f3ed24fd2e..55f503d11b 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-27b-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-27b-bnb-4bit.yaml @@ -14,7 +14,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-2b.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-2b.yaml index 70c86dad1b..9374a2cc82 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-2b.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-2-2b.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.01 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-270m-it.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-270m-it.yaml index ccdc19111e..f1aa18e9d2 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-270m-it.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-270m-it.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-27b-it.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-27b-it.yaml index db1db080a8..e1ed581ca4 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-27b-it.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-27b-it.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-it.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-it.yaml index a4130eb8b7..bf7457831e 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-it.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-it.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-pt.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-pt.yaml index f679b86b81..5f0a7b26ce 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-pt.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3-4b-pt.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: true optim: "adamw_torch_fused" lr_scheduler_type: "cosine" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B-it.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B-it.yaml index 23ef35603d..74c58d139d 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B-it.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B-it.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B.yaml index ebad334d5e..1ca686aea7 100644 --- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B.yaml +++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_gemma-3n-E4B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: true optim: "adamw_torch_fused" lr_scheduler_type: "cosine" diff --git a/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-120b.yaml b/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-120b.yaml index da41fb3009..f8a8f5a3c9 100644 --- a/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-120b.yaml +++ b/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-120b.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-11B-Vision-Instruct.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-11B-Vision-Instruct.yaml index 6d9f2c8ccb..1a7a91e56f 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-11B-Vision-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-11B-Vision-Instruct.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-1B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-1B-Instruct.yaml index e00d5b4cb4..61a2033ee8 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-1B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-1B-Instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.01 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: true optim: "adamw_torch" lr_scheduler_type: "cosine" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-3B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-3B-Instruct.yaml index ad427a345a..7117aa5ec0 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-3B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.2-3B-Instruct.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.3-70B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.3-70B-Instruct.yaml index 8d676bbbc9..7d998ed1c8 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.3-70B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Llama-3.3-70B-Instruct.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-70B-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-70B-bnb-4bit.yaml index 6b3158da02..633869022a 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-70B-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-70B-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-8B-Instruct-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-8B-Instruct-bnb-4bit.yaml index dcf5a5f702..cbf432dacb 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-8B-Instruct-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_Meta-Llama-3.1-8B-Instruct-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-Instruct-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-Instruct-bnb-4bit.yaml index d2e398d03d..f148814e96 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-Instruct-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-Instruct-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-bnb-4bit.yaml index ad3bd0b879..bb235595f6 100644 --- a/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/llama/unsloth_llama-3-8b-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/llasa/unsloth_Llasa-3B.yaml b/studio/backend/assets/configs/model_defaults/llasa/unsloth_Llasa-3B.yaml index 41217c6c9f..b315a9aaf7 100644 --- a/studio/backend/assets/configs/model_defaults/llasa/unsloth_Llasa-3B.yaml +++ b/studio/backend/assets/configs/model_defaults/llasa/unsloth_Llasa-3B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Magistral-Small-2509-unsloth-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Magistral-Small-2509-unsloth-bnb-4bit.yaml index 882395745c..2d4832e839 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Magistral-Small-2509-unsloth-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Magistral-Small-2509-unsloth-bnb-4bit.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Ministral-3-3B-Instruct-2512.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Ministral-3-3B-Instruct-2512.yaml index 4c7ead9985..ca6609cda8 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Ministral-3-3B-Instruct-2512.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Ministral-3-3B-Instruct-2512.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Nemo-Base-2407-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Nemo-Base-2407-bnb-4bit.yaml index 99fc67dcff..934959fc83 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Nemo-Base-2407-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Nemo-Base-2407-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Small-Instruct-2409.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Small-Instruct-2409.yaml index e0146c374e..1d712a6c8f 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Small-Instruct-2409.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Mistral-Small-Instruct-2409.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Pixtral-12B-2409.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Pixtral-12B-2409.yaml index 828ba79c76..bcd0d20c8c 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_Pixtral-12B-2409.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_Pixtral-12B-2409.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "paged_adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-instruct-v0.3-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-instruct-v0.3-bnb-4bit.yaml index 74527b21af..a02f8db2f3 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-instruct-v0.3-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-instruct-v0.3-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-v0.3-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-v0.3-bnb-4bit.yaml index 26810445bf..c0762d9864 100644 --- a/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-v0.3-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/mistral/unsloth_mistral-7b-v0.3-bnb-4bit.yaml @@ -14,7 +14,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/OuteAI_Llama-OuteTTS-1.0-1B.yaml b/studio/backend/assets/configs/model_defaults/other/OuteAI_Llama-OuteTTS-1.0-1B.yaml index 9db476f4dc..7a594b7eaf 100644 --- a/studio/backend/assets/configs/model_defaults/other/OuteAI_Llama-OuteTTS-1.0-1B.yaml +++ b/studio/backend/assets/configs/model_defaults/other/OuteAI_Llama-OuteTTS-1.0-1B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/Spark-TTS-0.5B_LLM.yaml b/studio/backend/assets/configs/model_defaults/other/Spark-TTS-0.5B_LLM.yaml index bf6b1f7247..3c8215ba25 100644 --- a/studio/backend/assets/configs/model_defaults/other/Spark-TTS-0.5B_LLM.yaml +++ b/studio/backend/assets/configs/model_defaults/other/Spark-TTS-0.5B_LLM.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/sesame_csm-1b.yaml b/studio/backend/assets/configs/model_defaults/other/sesame_csm-1b.yaml index 803eeebb75..d3249ef257 100644 --- a/studio/backend/assets/configs/model_defaults/other/sesame_csm-1b.yaml +++ b/studio/backend/assets/configs/model_defaults/other/sesame_csm-1b.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_PaddleOCR-VL.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_PaddleOCR-VL.yaml index a971f080b6..e1fbc08e4d 100644 --- a/studio/backend/assets/configs/model_defaults/other/unsloth_PaddleOCR-VL.yaml +++ b/studio/backend/assets/configs/model_defaults/other/unsloth_PaddleOCR-VL.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_answerdotai_ModernBERT-large.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_answerdotai_ModernBERT-large.yaml index c79841390d..bb30a2052c 100644 --- a/studio/backend/assets/configs/model_defaults/other/unsloth_answerdotai_ModernBERT-large.yaml +++ b/studio/backend/assets/configs/model_defaults/other/unsloth_answerdotai_ModernBERT-large.yaml @@ -14,7 +14,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_orpheus-3b-0.1-ft.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_orpheus-3b-0.1-ft.yaml index de5fb640ba..94596b65b8 100644 --- a/studio/backend/assets/configs/model_defaults/other/unsloth_orpheus-3b-0.1-ft.yaml +++ b/studio/backend/assets/configs/model_defaults/other/unsloth_orpheus-3b-0.1-ft.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_tinyllama-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_tinyllama-bnb-4bit.yaml index dd4525bba3..d35ac75b81 100644 --- a/studio/backend/assets/configs/model_defaults/other/unsloth_tinyllama-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/other/unsloth_tinyllama-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.1 random_seed: 3407 packing: true - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_whisper-large-v3.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_whisper-large-v3.yaml index f0c49f363d..3a97baebd9 100644 --- a/studio/backend/assets/configs/model_defaults/other/unsloth_whisper-large-v3.yaml +++ b/studio/backend/assets/configs/model_defaults/other/unsloth_whisper-large-v3.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3-medium-4k-instruct.yaml b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3-medium-4k-instruct.yaml index c39368fbd2..3c428c3406 100644 --- a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3-medium-4k-instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3-medium-4k-instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3.5-mini-instruct.yaml b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3.5-mini-instruct.yaml index 076165c12a..8e13ef8a45 100644 --- a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3.5-mini-instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-3.5-mini-instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4-14B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4-14B-Instruct.yaml index 91d53180fa..4d67de8bab 100644 --- a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4-14B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4-14B-Instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4.yaml b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4.yaml index 3b829649a8..9159ce4dc7 100644 --- a/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4.yaml +++ b/studio/backend/assets/configs/model_defaults/phi/unsloth_Phi-4.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-7B.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-7B.yaml index 56d4f35998..e0aff114ca 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-7B.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-7B.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-VL-7B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-VL-7B-Instruct.yaml index 86cb03ff25..6cee3d0949 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-VL-7B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2-VL-7B-Instruct.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-1.5B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-1.5B-Instruct.yaml index 3a3259c8fd..1034f6d37f 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-1.5B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-1.5B-Instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 42 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-7B.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-7B.yaml index 2a8f023e76..876514e456 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-7B.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-7B.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-1.5B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-1.5B-Instruct.yaml index a92d0d6047..d41e70d25f 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-1.5B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-1.5B-Instruct.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-14B-Instruct.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-14B-Instruct.yaml index eff25af51c..4af3af5dfc 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-14B-Instruct.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-14B-Instruct.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "paged_adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-7B-Instruct-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-7B-Instruct-bnb-4bit.yaml index 3ab14078a9..ca1b355c40 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-7B-Instruct-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-Coder-7B-Instruct-bnb-4bit.yaml @@ -15,7 +15,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-VL-7B-Instruct-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-VL-7B-Instruct-bnb-4bit.yaml index 4cfa83f853..bd54b1d015 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-VL-7B-Instruct-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen2.5-VL-7B-Instruct-bnb-4bit.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-0.6B.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-0.6B.yaml index d8f9d3a73b..b1179b2ce6 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-0.6B.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-0.6B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B-Base-unsloth-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B-Base-unsloth-bnb-4bit.yaml index 7f66711413..77d7c8527e 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B-Base-unsloth-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B-Base-unsloth-bnb-4bit.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B.yaml index 0f3403e09e..7b92c767de 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-14B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-32B.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-32B.yaml index f019922017..15e8dab80e 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-32B.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-32B.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Instruct-2507.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Instruct-2507.yaml index a8552cc85c..2724719294 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Instruct-2507.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Instruct-2507.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-VL-8B-Instruct-unsloth-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-VL-8B-Instruct-unsloth-bnb-4bit.yaml index 5530047541..5b47c3bdd2 100644 --- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-VL-8B-Instruct-unsloth-bnb-4bit.yaml +++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-VL-8B-Instruct-unsloth-bnb-4bit.yaml @@ -16,7 +16,7 @@ training: weight_decay: 0.001 random_seed: 3407 packing: false - train_on_completions: false + train_on_completions: true gradient_checkpointing: "unsloth" optim: "adamw_8bit" lr_scheduler_type: "linear" diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py index 8b94ddefdc..39119f1123 100644 --- a/studio/backend/routes/datasets.py +++ b/studio/backend/routes/datasets.py @@ -70,33 +70,48 @@ def _serialize_preview_rows(rows): # --- Endpoints --- +# Recognized data-file extensions for the single-file fallback approach. +DATA_EXTS = ( + '.parquet', + '.json', '.jsonl', + '.csv', '.tsv', + '.txt', + '.arrow', + '.tar', '.tar.gz', '.tgz', + '.gz', '.zst', + '.zip', +) + + @router.post("/check-format", response_model=CheckFormatResponse) -async def check_format(request: CheckFormatRequest): +def check_format(request: CheckFormatRequest): """ Check if a dataset requires manual column mapping. - - This is a lightweight check that streams only the first N rows, - runs format detection, and (if processable) returns processed - preview samples. The full dataset is re-processed at training time. - - For HuggingFace datasets we use streaming mode so we never download - the entire dataset — only the rows we actually need are fetched. + + Strategy for HuggingFace datasets: + 1. list_repo_files → pick the first data file → load_dataset(data_files=[…]) + Avoids resolving thousands of files; typically ~2-4 s. + 2. Full streaming load_dataset as a last-resort fallback. + + Local files are loaded directly. + + Using a plain `def` (not async) so FastAPI runs this in a thread-pool, + preventing any blocking IO from freezing the event loop. """ try: from itertools import islice from datasets import Dataset, load_dataset from utils.datasets import format_dataset - + PREVIEW_SIZE = 10 - + logger.info(f"Checking format for dataset: {request.dataset_name}") - - # Load dataset + dataset_path = Path(request.dataset_name) total_rows = None - + if dataset_path.exists(): - # Local dataset — direct load is fine (files are local) + # ── Local file ────────────────────────────────────────── if dataset_path.suffix in ['.json', '.jsonl']: dataset = load_dataset('json', data_files=str(dataset_path), split=request.train_split) elif dataset_path.suffix == '.csv': @@ -111,54 +126,83 @@ async def check_format(request: CheckFormatRequest): total_rows = len(dataset) preview_slice = dataset.select(range(min(PREVIEW_SIZE, total_rows))) else: - # HuggingFace dataset — use STREAMING to avoid downloading everything - load_kwargs = {"path": request.dataset_name, "split": request.train_split, "streaming": True} - if request.subset: - load_kwargs["name"] = request.subset - if request.hf_token: - load_kwargs["token"] = request.hf_token - - streamed_ds = load_dataset(**load_kwargs) - - # Take only the first PREVIEW_SIZE rows from the stream - rows = list(islice(streamed_ds, PREVIEW_SIZE)) - if not rows: - raise HTTPException( - status_code=400, - detail="Dataset appears to be empty or could not be streamed" + # ── HuggingFace dataset ───────────────────────────────── + # Tier 1: list_repo_files → load only the first data file + preview_slice = None + + try: + from huggingface_hub import HfApi + api = HfApi() + repo_files = api.list_repo_files( + request.dataset_name, + repo_type="dataset", + token=request.hf_token or None, ) - - # Convert list-of-dicts into a proper Dataset for downstream compat - preview_slice = Dataset.from_list(rows) - # total_rows unknown in streaming mode + data_files = [f for f in repo_files if any(f.endswith(ext) for ext in DATA_EXTS)] + + if data_files: + first_file = data_files[0] + logger.info(f"Tier 1: loading single file {first_file}") + load_kwargs = { + "path": request.dataset_name, + "data_files": [first_file], + "split": "train", + "streaming": True, + } + if request.hf_token: + load_kwargs["token"] = request.hf_token + + streamed_ds = load_dataset(**load_kwargs) + rows = list(islice(streamed_ds, PREVIEW_SIZE)) + if rows: + preview_slice = Dataset.from_list(rows) + except Exception as e: + logger.warning(f"Tier 1 (single-file) failed: {e}") + + if preview_slice is None: + # Tier 2: full streaming (resolves all files — slow for large repos) + logger.info("Tier 2: falling back to full streaming load_dataset") + load_kwargs = {"path": request.dataset_name, "split": request.train_split, "streaming": True} + if request.subset: + load_kwargs["name"] = request.subset + if request.hf_token: + load_kwargs["token"] = request.hf_token + + streamed_ds = load_dataset(**load_kwargs) + + rows = list(islice(streamed_ds, PREVIEW_SIZE)) + if not rows: + raise HTTPException( + status_code=400, + detail="Dataset appears to be empty or could not be streamed" + ) + + preview_slice = Dataset.from_list(rows) total_rows = None - + # Run lightweight format check on the preview slice result = check_dataset_format(preview_slice, is_vlm=request.is_vlm) - - logger.info(f"Format check result: requires_mapping={result['requires_manual_mapping']}, format={result['detected_format']}") - + + logger.info(f"Format check result: requires_mapping={result['requires_manual_mapping']}, format={result['detected_format']}, is_multimodal={result.get('is_multimodal', False)}") + # Generate preview samples preview_samples = None if not result["requires_manual_mapping"]: - # Format detected — return processed preview try: format_result = format_dataset( preview_slice, format_type="auto", custom_format_mapping=result.get("suggested_mapping"), + num_proc=1, # Only 10 preview rows — no need for multiprocessing ) processed = format_result["dataset"] preview_samples = _serialize_preview_rows(processed) except Exception as e: logger.warning(f"Processed preview generation failed (non-fatal): {e}") - # Fall back to raw samples so frontend still has something preview_samples = _serialize_preview_rows(preview_slice) else: - # Format detection failed — return raw samples so user can - # see actual data and map columns in the frontend preview_samples = _serialize_preview_rows(preview_slice) - + return CheckFormatResponse( requires_manual_mapping=result["requires_manual_mapping"], detected_format=result["detected_format"], @@ -171,7 +215,7 @@ async def check_format(request: CheckFormatRequest): preview_samples=preview_samples, total_rows=total_rows, ) - + except HTTPException: raise except Exception as e: diff --git a/studio/backend/utils/datasets/format_detection.py b/studio/backend/utils/datasets/format_detection.py index ae1b6a388d..9283ea5d55 100644 --- a/studio/backend/utils/datasets/format_detection.py +++ b/studio/backend/utils/datasets/format_detection.py @@ -328,6 +328,11 @@ def detect_multimodal_dataset(dataset): """ Detects if dataset contains multimodal data (images/vision). + Two-pass approach: + 1. Column-name heuristic (fast): checks for keywords like 'image', 'img', 'pixel'. + 2. Value-type inspection (reliable): checks if actual values are PIL Images, + bytes with image headers, or HF Image-feature dicts. + Returns: dict: { "is_multimodal": bool, @@ -339,11 +344,16 @@ def detect_multimodal_dataset(dataset): column_names = list(sample.keys()) # Keywords that indicate multimodal/image data - multimodal_keywords = ['image', 'img', 'pixel'] + multimodal_keywords = [ + 'image', 'img', 'pixel', + 'jpg', 'jpeg', 'png', 'webp', 'bmp', 'gif', 'tiff', 'svg', + 'photo', 'pic', 'picture', 'visual', + ] multimodal_columns = [] modality_types = set() + # ── Pass 1: column-name heuristic ─────────────────────── for col_name in column_names: col_lower = col_name.lower() @@ -353,6 +363,17 @@ def detect_multimodal_dataset(dataset): modality_types.add(keyword) break # Don't check other keywords for this column + # ── Pass 2: inspect actual values ─────────────────────── + # Catches columns with non-obvious names (e.g. "jpg", "photo", "pic") + already_detected = set(multimodal_columns) + for col_name in column_names: + if col_name in already_detected: + continue + value = sample[col_name] + if _is_image_value(value): + multimodal_columns.append(col_name) + modality_types.add("image") + return { "is_multimodal": len(multimodal_columns) > 0, "multimodal_columns": multimodal_columns, @@ -360,6 +381,54 @@ def detect_multimodal_dataset(dataset): } +def _is_image_value(value) -> bool: + """Check if a single sample value looks like image data.""" + if value is None: + return False + + # PIL Image instance + try: + from PIL.Image import Image as PILImage + if isinstance(value, PILImage): + return True + except ImportError: + pass + + # HF datasets Image feature stores decoded images as PIL or dicts with + # {"bytes": b"...", "path": "..."} when not yet decoded + if isinstance(value, dict): + if "bytes" in value and "path" in value: + return True + + # Raw bytes with a known image magic header + if isinstance(value, (bytes, bytearray)): + return _has_image_header(value) + + return False + + +def _has_image_header(data: bytes) -> bool: + """Quick magic-byte check for common image formats.""" + if len(data) < 4: + return False + # JPEG + if data[:2] == b'\xff\xd8': + return True + # PNG + if data[:4] == b'\x89PNG': + return True + # GIF + if data[:3] == b'GIF': + return True + # WebP + if data[:4] == b'RIFF' and len(data) >= 12 and data[8:12] == b'WEBP': + return True + # BMP + if data[:2] == b'BM': + return True + return False + + def detect_vlm_dataset_structure(dataset): """ Detects if VLM dataset is: diff --git a/studio/frontend/src/features/studio/studio-page.tsx b/studio/frontend/src/features/studio/studio-page.tsx index e9f01901b7..26353b9b7e 100644 --- a/studio/frontend/src/features/studio/studio-page.tsx +++ b/studio/frontend/src/features/studio/studio-page.tsx @@ -37,6 +37,9 @@ export function StudioPage(): ReactElement { const ensureModelDefaultsLoaded = useTrainingConfigStore( (s) => s.ensureModelDefaultsLoaded, ); + const ensureDatasetChecked = useTrainingConfigStore( + (s) => s.ensureDatasetChecked, + ); const dialogOpen = useDatasetPreviewDialogStore((s) => s.open); const dialogMode = useDatasetPreviewDialogStore((s) => s.mode); const dialogInitial = useDatasetPreviewDialogStore((s) => s.initialData); @@ -65,7 +68,8 @@ export function StudioPage(): ReactElement { useEffect(() => { ensureModelDefaultsLoaded(); - }, [selectedModel, ensureModelDefaultsLoaded]); + ensureDatasetChecked(); + }, [selectedModel, ensureModelDefaultsLoaded, ensureDatasetChecked]); return (
diff --git a/studio/frontend/src/features/training/stores/training-config-store.ts b/studio/frontend/src/features/training/stores/training-config-store.ts index b98d2a3c7f..67317dbc09 100644 --- a/studio/frontend/src/features/training/stores/training-config-store.ts +++ b/studio/frontend/src/features/training/stores/training-config-store.ts @@ -43,12 +43,19 @@ let _datasetCheckController: AbortController | null = null; // AbortController for in-flight model default loads. let _modelConfigController: AbortController | null = null; +// Track whether the user has manually toggled trainOnCompletions +// since the last auto-set (model load or dataset change). +let _trainOnCompletionsManuallySet = false; + const NON_PERSISTED_STATE_KEYS: ReadonlySet = new Set([ "modelType", "isCheckingVision", "isLoadingModelDefaults", "modelDefaultsError", + "modelDefaultsAppliedFor", "isCheckingDataset", + "isDatasetMultimodal", + "trainOnCompletions", ]); function partializePersistedState( @@ -102,8 +109,17 @@ export const useTrainingConfigStore = create()( if (controller.signal.aborted) return; if (get().selectedModel !== modelName) return; + _trainOnCompletionsManuallySet = false; + const patch = mapBackendModelConfigToTrainingPatch(modelDetails.config); + + // If vision model + multimodal dataset already known, override + // trainOnCompletions to false regardless of backend default. + if (modelDetails.is_vision && get().isDatasetMultimodal === true) { + patch.trainOnCompletions = false; + } + set({ - ...mapBackendModelConfigToTrainingPatch(modelDetails.config), + ...patch, isVisionModel: modelDetails.is_vision, isLoadingModelDefaults: false, isCheckingVision: false, @@ -139,6 +155,40 @@ export const useTrainingConfigStore = create()( }); }; + const runDatasetCheck = (datasetName: string, split: string) => { + _datasetCheckController?.abort(); + const controller = new AbortController(); + _datasetCheckController = controller; + set({ isCheckingDataset: true }); + + const state = get(); + checkDatasetFormat({ + datasetName, + hfToken: state.hfToken.trim() || null, + subset: state.datasetSubset, + split, + }) + .then((res) => { + if (controller.signal.aborted) return; + const isMultimodal = !!res.is_multimodal; + const updates: Record = { + isDatasetMultimodal: isMultimodal, + isCheckingDataset: false, + }; + if (!_trainOnCompletionsManuallySet) { + const { isVisionModel } = get(); + if (isVisionModel && isMultimodal) { + updates.trainOnCompletions = false; + } + } + set(updates); + }) + .catch(() => { + if (controller.signal.aborted) return; + set({ isDatasetMultimodal: null, isCheckingDataset: false }); + }); + }; + return { ...initialState, setStep: (step) => set({ currentStep: step }), @@ -196,6 +246,7 @@ export const useTrainingConfigStore = create()( setDataset: (dataset) => { _datasetCheckController?.abort(); _datasetCheckController = null; + _trainOnCompletionsManuallySet = false; set({ dataset, datasetSubset: null, @@ -208,6 +259,7 @@ export const useTrainingConfigStore = create()( setDatasetSubset: (datasetSubset) => { _datasetCheckController?.abort(); _datasetCheckController = null; + _trainOnCompletionsManuallySet = false; set({ datasetSubset, datasetSplit: null, @@ -217,8 +269,6 @@ export const useTrainingConfigStore = create()( }); }, setDatasetSplit: (datasetSplit) => { - _datasetCheckController?.abort(); - _datasetCheckController = null; set({ datasetSplit, datasetManualMapping: emptyManualMapping(), @@ -233,27 +283,21 @@ export const useTrainingConfigStore = create()( : state.uploadedFile; if (!datasetName) return; - const controller = new AbortController(); - _datasetCheckController = controller; - set({ isCheckingDataset: true }); + runDatasetCheck(datasetName, datasetSplit || "train"); + }, + ensureDatasetChecked: () => { + const state = get(); + if (state.isCheckingDataset) return; + if (state.isDatasetMultimodal !== null) return; - checkDatasetFormat({ - datasetName, - hfToken: state.hfToken.trim() || null, - subset: state.datasetSubset, - split: datasetSplit || "train", - }) - .then((res) => { - if (controller.signal.aborted) return; - set({ - isDatasetMultimodal: !!res.is_multimodal, - isCheckingDataset: false, - }); - }) - .catch(() => { - if (controller.signal.aborted) return; - set({ isDatasetMultimodal: null, isCheckingDataset: false }); - }); + const datasetName = + state.datasetSource === "huggingface" + ? state.dataset + : state.uploadedFile; + if (!datasetName) return; + + const split = state.datasetSplit || "train"; + runDatasetCheck(datasetName, split); }, setDatasetManualMapping: (datasetManualMapping) => set({ datasetManualMapping }), @@ -274,8 +318,10 @@ export const useTrainingConfigStore = create()( setSaveSteps: (saveSteps) => set({ saveSteps }), setEvalSteps: (evalSteps) => set({ evalSteps }), setPacking: (packing) => set({ packing }), - setTrainOnCompletions: (trainOnCompletions) => - set({ trainOnCompletions }), + setTrainOnCompletions: (trainOnCompletions) => { + _trainOnCompletionsManuallySet = true; + set({ trainOnCompletions }); + }, setGradientCheckpointing: (gradientCheckpointing) => set({ gradientCheckpointing }), setRandomSeed: (randomSeed) => set({ randomSeed }), diff --git a/studio/frontend/src/features/training/types/config.ts b/studio/frontend/src/features/training/types/config.ts index 67f1d00edc..53beabd383 100644 --- a/studio/frontend/src/features/training/types/config.ts +++ b/studio/frontend/src/features/training/types/config.ts @@ -72,6 +72,7 @@ export interface TrainingConfigActions { setModelType: (type: ModelType) => void; setSelectedModel: (model: string | null) => void; ensureModelDefaultsLoaded: () => void; + ensureDatasetChecked: () => void; setTrainingMethod: (method: TrainingMethod) => void; setHfToken: (token: string) => void; setDatasetSource: (source: DatasetSource) => void;