From 86e94b5844d5d9c3b9c1f29e0999adbcd541fc49 Mon Sep 17 00:00:00 2001
From: samit
Date: Sun, 8 Mar 2026 16:28:56 -0700
Subject: [PATCH 01/22] exposed trust_remote_code through the UI
---
studio/backend/core/export/export.py | 10 +++++-
studio/backend/core/inference/inference.py | 12 ++++++-
studio/backend/core/inference/orchestrator.py | 2 ++
studio/backend/core/inference/worker.py | 1 +
studio/backend/core/training/trainer.py | 19 +++++++++--
studio/backend/core/training/training.py | 1 +
studio/backend/core/training/worker.py | 1 +
studio/backend/models/export.py | 4 +++
studio/backend/models/inference.py | 4 +++
studio/backend/models/training.py | 4 +++
studio/backend/routes/export.py | 1 +
studio/backend/routes/inference.py | 1 +
studio/backend/routes/training.py | 1 +
.../src/features/chat/chat-settings-sheet.tsx | 33 ++++++++++++++-----
.../chat/hooks/use-chat-model-runtime.ts | 6 ++--
.../frontend/src/features/chat/types/api.ts | 2 ++
.../src/features/chat/types/runtime.ts | 3 ++
.../src/features/export/api/export-api.ts | 2 ++
.../src/features/training/api/mappers.ts | 1 +
.../src/features/training/types/api.ts | 2 ++
20 files changed, 94 insertions(+), 16 deletions(-)
diff --git a/studio/backend/core/export/export.py b/studio/backend/core/export/export.py
index 9e1c5cff84..bd14fb412e 100644
--- a/studio/backend/core/export/export.py
+++ b/studio/backend/core/export/export.py
@@ -138,7 +138,8 @@ class ExportBackend:
def load_checkpoint(self,
checkpoint_path: str,
max_seq_length: int = 2048,
- load_in_4bit: bool = True) -> Tuple[bool, str]:
+ load_in_4bit: bool = True,
+ trust_remote_code: bool = False) -> Tuple[bool, str]:
"""
Load a checkpoint for export.
@@ -178,6 +179,7 @@ class ExportBackend:
dtype=None,
auto_model=CsmForConditionalGeneration,
load_in_4bit=False,
+ trust_remote_code=trust_remote_code,
)
elif self._audio_type == 'whisper':
@@ -189,6 +191,7 @@ class ExportBackend:
dtype=None,
load_in_4bit=False,
auto_model=WhisperForConditionalGeneration,
+ trust_remote_code=trust_remote_code,
)
elif self._audio_type == 'snac':
@@ -198,6 +201,7 @@ class ExportBackend:
max_seq_length=max_seq_length,
dtype=None,
load_in_4bit=load_in_4bit,
+ trust_remote_code=trust_remote_code,
)
elif self._audio_type == 'bicodec':
@@ -208,6 +212,7 @@ class ExportBackend:
max_seq_length=max_seq_length,
dtype=torch.float32,
load_in_4bit=False,
+ trust_remote_code=trust_remote_code,
)
elif self._audio_type == 'dac':
@@ -217,6 +222,7 @@ class ExportBackend:
model_name=checkpoint_path,
max_seq_length=max_seq_length,
load_in_4bit=False,
+ trust_remote_code=trust_remote_code,
)
elif self.is_vision:
@@ -226,6 +232,7 @@ class ExportBackend:
max_seq_length=max_seq_length,
dtype=None,
load_in_4bit=load_in_4bit,
+ trust_remote_code=trust_remote_code,
)
tokenizer = processor # For vision models, processor acts as tokenizer
@@ -236,6 +243,7 @@ class ExportBackend:
max_seq_length=max_seq_length,
dtype=None,
load_in_4bit=load_in_4bit,
+ trust_remote_code=trust_remote_code,
)
# Check if PEFT model
diff --git a/studio/backend/core/inference/inference.py b/studio/backend/core/inference/inference.py
index 780a399637..6ced3fc2ad 100644
--- a/studio/backend/core/inference/inference.py
+++ b/studio/backend/core/inference/inference.py
@@ -63,7 +63,8 @@ class InferenceBackend:
max_seq_length: int = 2048,
dtype = None,
load_in_4bit: bool = True,
- hf_token: Optional[str] = None) -> bool:
+ hf_token: Optional[str] = None,
+ trust_remote_code: bool = False) -> bool:
"""
Load any model: base, LoRA adapter, text, or vision.
"""
@@ -110,6 +111,7 @@ class InferenceBackend:
auto_model=CsmForConditionalGeneration,
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
FastModel.for_inference(model)
self.models[model_name]["model"] = model
@@ -139,6 +141,7 @@ class InferenceBackend:
dtype=torch.float32,
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
else:
# Base model: download full HF repo, then load from /LLM subfolder
@@ -155,6 +158,7 @@ class InferenceBackend:
dtype=torch.float32,
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
FastModel.for_inference(model)
@@ -169,6 +173,7 @@ class InferenceBackend:
max_seq_length=max_seq_length,
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
FastModel.for_inference(model)
self.models[model_name]["model"] = model
@@ -184,6 +189,7 @@ class InferenceBackend:
whisper_task="transcribe",
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
FastModel.for_inference(model)
model.eval()
@@ -209,6 +215,7 @@ class InferenceBackend:
max_seq_length=max_seq_length,
load_in_4bit=False,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
FastLanguageModel.for_inference(model)
self.models[model_name]["model"] = model
@@ -240,6 +247,7 @@ class InferenceBackend:
dtype=dtype,
load_in_4bit=load_in_4bit,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
# Apply inference optimization
@@ -270,6 +278,7 @@ class InferenceBackend:
processor = AutoProcessor.from_pretrained(
processor_source,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
logger.info(f"Loaded {type(processor).__name__} from {processor_source}")
@@ -285,6 +294,7 @@ class InferenceBackend:
dtype=dtype,
load_in_4bit=load_in_4bit,
token=hf_token if hf_token and hf_token.strip() else None,
+ trust_remote_code=trust_remote_code,
)
# Apply inference optimization
diff --git a/studio/backend/core/inference/orchestrator.py b/studio/backend/core/inference/orchestrator.py
index b08ec5bb70..6910b3dc19 100644
--- a/studio/backend/core/inference/orchestrator.py
+++ b/studio/backend/core/inference/orchestrator.py
@@ -258,6 +258,7 @@ class InferenceOrchestrator:
dtype=None,
load_in_4bit: bool = True,
hf_token: Optional[str] = None,
+ trust_remote_code: bool = False,
) -> bool:
"""Load a model for inference.
@@ -282,6 +283,7 @@ class InferenceOrchestrator:
"load_in_4bit": load_in_4bit,
"hf_token": hf_token or "",
"gguf_variant": getattr(config, "gguf_variant", None),
+ "trust_remote_code": trust_remote_code,
}
# Always kill existing subprocess and spawn fresh.
diff --git a/studio/backend/core/inference/worker.py b/studio/backend/core/inference/worker.py
index 3e766b3b01..e59372c216 100644
--- a/studio/backend/core/inference/worker.py
+++ b/studio/backend/core/inference/worker.py
@@ -155,6 +155,7 @@ def _handle_load(backend, config: dict, resp_queue: Any) -> None:
max_seq_length=config.get("max_seq_length", 2048),
load_in_4bit=load_in_4bit,
hf_token=hf_token,
+ trust_remote_code=config.get("trust_remote_code", False),
)
if success:
diff --git a/studio/backend/core/training/trainer.py b/studio/backend/core/training/trainer.py
index d50431b035..40d653b69a 100644
--- a/studio/backend/core/training/trainer.py
+++ b/studio/backend/core/training/trainer.py
@@ -325,9 +325,11 @@ class UnslothTrainer:
load_in_4bit: bool = True,
hf_token: Optional[str] = None,
is_dataset_image: bool = False,
- is_dataset_audio: bool = False) -> bool:
+ is_dataset_audio: bool = False,
+ trust_remote_code: bool = False) -> bool:
"""Load model for training (supports both text and vision models)"""
self.load_in_4bit = load_in_4bit # Store for training_meta.json
+ self.trust_remote_code = trust_remote_code # For AutoProcessor etc. used during training
try:
if self.model is not None:
del self.model
@@ -446,6 +448,7 @@ class UnslothTrainer:
auto_model=CsmForConditionalGeneration,
load_in_4bit=False,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded CSM audio model")
@@ -461,6 +464,7 @@ class UnslothTrainer:
whisper_language="English",
whisper_task="transcribe",
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
# Configure generation settings (notebook lines 100-105)
self.model.generation_config.language = "<|en|>"
@@ -477,6 +481,7 @@ class UnslothTrainer:
dtype=None,
load_in_4bit=load_in_4bit,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info(f"Loaded {self._audio_type} audio model (FastLanguageModel)")
@@ -510,6 +515,7 @@ class UnslothTrainer:
dtype=torch.float32, # Spark-TTS requires float32
load_in_4bit=False,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded Spark-TTS (bicodec) model")
@@ -521,6 +527,7 @@ class UnslothTrainer:
max_seq_length=max_seq_length,
load_in_4bit=False,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded OuteTTS (dac) model (FastModel)")
@@ -534,6 +541,7 @@ class UnslothTrainer:
dtype=None,
load_in_4bit=load_in_4bit,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded audio VLM model (FastModel)")
@@ -545,6 +553,7 @@ class UnslothTrainer:
dtype=None, # Auto-detect
load_in_4bit=load_in_4bit,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded vision model")
@@ -564,6 +573,7 @@ class UnslothTrainer:
dtype=None, # Auto-detect
load_in_4bit=load_in_4bit,
token=hf_token,
+ trust_remote_code=trust_remote_code,
)
logger.info("Loaded text model")
@@ -584,7 +594,7 @@ class UnslothTrainer:
self._source_code_retried = True
print(f"\n'could not get source code' — retrying once...\n")
return self.load_model(model_name, max_seq_length, load_in_4bit, hf_token,
- is_dataset_image, is_dataset_audio)
+ is_dataset_image, is_dataset_audio, trust_remote_code)
error_msg = str(e)
error_lower = error_msg.lower()
if any(k in error_lower for k in ("gated repo", "access to it at", "401", "403", "unauthorized", "forbidden")):
@@ -983,7 +993,10 @@ class UnslothTrainer:
from datasets import Audio
import torch
- processor = AutoProcessor.from_pretrained(self.model_name)
+ processor = AutoProcessor.from_pretrained(
+ self.model_name,
+ trust_remote_code=getattr(self, "trust_remote_code", False),
+ )
# Strip pad_to_multiple_of from tokenizer init_kwargs — fine-tuned models
# (e.g. keanteng/sesame-csm-elise) save it in tokenizer_config.json, and
diff --git a/studio/backend/core/training/training.py b/studio/backend/core/training/training.py
index 5323e73ae1..cc0124ae83 100644
--- a/studio/backend/core/training/training.py
+++ b/studio/backend/core/training/training.py
@@ -176,6 +176,7 @@ class TrainingBackend:
"wandb_project": kwargs.get("wandb_project", "unsloth-training"),
"enable_tensorboard": kwargs.get("enable_tensorboard", False),
"tensorboard_dir": kwargs.get("tensorboard_dir", "runs"),
+ "trust_remote_code": kwargs.get("trust_remote_code", False),
}
# Derive load_in_4bit from training_type
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index 4c82347936..8eee8293e1 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -192,6 +192,7 @@ def run_training_process(
hf_token=hf_token,
is_dataset_image=config.get("is_dataset_image", False),
is_dataset_audio=config.get("is_dataset_audio", False),
+ trust_remote_code=config.get("trust_remote_code", False),
)
if not success or trainer.should_stop:
if trainer.should_stop:
diff --git a/studio/backend/models/export.py b/studio/backend/models/export.py
index a0526e80db..df17596185 100644
--- a/studio/backend/models/export.py
+++ b/studio/backend/models/export.py
@@ -19,6 +19,10 @@ class LoadCheckpointRequest(BaseModel):
True,
description="Whether to load the model in 4-bit quantization",
)
+ trust_remote_code: bool = Field(
+ False,
+ description="Allow loading models with custom code. Only enable for checkpoints/base models you trust.",
+ )
class ExportStatusResponse(BaseModel):
diff --git a/studio/backend/models/inference.py b/studio/backend/models/inference.py
index 0eb7a7edaf..ab5c63d8c9 100644
--- a/studio/backend/models/inference.py
+++ b/studio/backend/models/inference.py
@@ -18,6 +18,10 @@ class LoadRequest(BaseModel):
load_in_4bit: bool = Field(True, description="Load model in 4-bit quantization")
is_lora: bool = Field(False, description="Whether this is a LoRA adapter")
gguf_variant: Optional[str] = Field(None, description="GGUF quantization variant (e.g. 'Q4_K_M')")
+ trust_remote_code: bool = Field(
+ False,
+ description="Allow loading models with custom code (e.g. NVIDIA Nemotron). Only enable for repos you trust.",
+ )
class UnloadRequest(BaseModel):
diff --git a/studio/backend/models/training.py b/studio/backend/models/training.py
index 5cc8141bac..c03d7b04bf 100644
--- a/studio/backend/models/training.py
+++ b/studio/backend/models/training.py
@@ -13,6 +13,10 @@ class TrainingStartRequest(BaseModel):
hf_token: Optional[str] = Field(None, description="HuggingFace token")
load_in_4bit: bool = Field(True, description="Load model in 4-bit quantization")
max_seq_length: int = Field(2048, description="Maximum sequence length")
+ trust_remote_code: bool = Field(
+ False,
+ description="Allow loading models with custom code (e.g. NVIDIA Nemotron). Only enable for repos you trust.",
+ )
# Dataset parameters
hf_dataset: Optional[str] = Field(None, description="HuggingFace dataset identifier")
diff --git a/studio/backend/routes/export.py b/studio/backend/routes/export.py
index 7f18f50eaa..bf41cba424 100644
--- a/studio/backend/routes/export.py
+++ b/studio/backend/routes/export.py
@@ -102,6 +102,7 @@ async def load_checkpoint(
checkpoint_path=request.checkpoint_path,
max_seq_length=request.max_seq_length,
load_in_4bit=request.load_in_4bit,
+ trust_remote_code=request.trust_remote_code,
)
if not success:
diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py
index 52e5bfad72..b2f7a802a4 100644
--- a/studio/backend/routes/inference.py
+++ b/studio/backend/routes/inference.py
@@ -226,6 +226,7 @@ async def load_model(
max_seq_length=request.max_seq_length,
load_in_4bit=load_in_4bit,
hf_token=request.hf_token,
+ trust_remote_code=request.trust_remote_code,
)
if not success:
diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py
index d6726d69df..b6e6d7e111 100644
--- a/studio/backend/routes/training.py
+++ b/studio/backend/routes/training.py
@@ -191,6 +191,7 @@ async def start_training(
"wandb_project": request.wandb_project or "",
"enable_tensorboard": request.enable_tensorboard,
"tensorboard_dir": request.tensorboard_dir or "",
+ "trust_remote_code": request.trust_remote_code,
}
# Free GPU memory: shut down any running inference/export subprocesses
diff --git a/studio/frontend/src/features/chat/chat-settings-sheet.tsx b/studio/frontend/src/features/chat/chat-settings-sheet.tsx
index e70b24fb54..2ffa5a5370 100644
--- a/studio/frontend/src/features/chat/chat-settings-sheet.tsx
+++ b/studio/frontend/src/features/chat/chat-settings-sheet.tsx
@@ -170,6 +170,7 @@ export function ChatSettingsPanel({
...p.params,
systemPrompt: params.systemPrompt,
checkpoint: params.checkpoint,
+ trustRemoteCode: params.trustRemoteCode,
});
setActivePreset(name);
}
@@ -330,17 +331,31 @@ export function ChatSettingsPanel({
-
-
-
Auto title
-
- Generate short title after reply.
+
+
+
+
Auto title
+
+ Generate short title after reply.
+
+
+
+
+
+
Trust remote code
+
+ Allow models with custom code (e.g. Nemotron). Only enable for repos you trust.
+
+
+
-
diff --git a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
index eb59d5a23d..827da9d68b 100644
--- a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
+++ b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
@@ -206,6 +206,7 @@ export function useChatModelRuntime() {
await unloadModel({ model_path: currentCheckpoint });
}
+ const currentParams = useChatRuntimeStore.getState().params;
const loadResponse = await loadModel({
model_path: modelId,
hf_token: null,
@@ -213,10 +214,11 @@ export function useChatModelRuntime() {
load_in_4bit: true,
is_lora: isLora,
gguf_variant: ggufVariant ?? null,
+ trust_remote_code: currentParams.trustRemoteCode ?? false,
});
- const currentParams = useChatRuntimeStore.getState().params;
- setParams(mergeRecommendedInference(currentParams, loadResponse, modelId));
+ const paramsAfterLoad = useChatRuntimeStore.getState().params;
+ setParams(mergeRecommendedInference(paramsAfterLoad, loadResponse, modelId));
await refresh();
}
diff --git a/studio/frontend/src/features/chat/types/api.ts b/studio/frontend/src/features/chat/types/api.ts
index 4a2ed9a3f1..9999e0ce70 100644
--- a/studio/frontend/src/features/chat/types/api.ts
+++ b/studio/frontend/src/features/chat/types/api.ts
@@ -34,6 +34,8 @@ export interface LoadModelRequest {
load_in_4bit: boolean;
is_lora: boolean;
gguf_variant?: string | null;
+ /** Allow loading models with custom code (e.g. NVIDIA Nemotron). Only enable for repos you trust. */
+ trust_remote_code?: boolean;
}
export interface GgufVariantDetail {
diff --git a/studio/frontend/src/features/chat/types/runtime.ts b/studio/frontend/src/features/chat/types/runtime.ts
index a544c35f64..a1c98ada7d 100644
--- a/studio/frontend/src/features/chat/types/runtime.ts
+++ b/studio/frontend/src/features/chat/types/runtime.ts
@@ -7,6 +7,8 @@ export interface InferenceParams {
maxTokens: number;
systemPrompt: string;
checkpoint: string;
+ /** Allow loading models with custom code (e.g. NVIDIA Nemotron). Only enable for repos you trust. */
+ trustRemoteCode?: boolean;
}
export const DEFAULT_INFERENCE_PARAMS: InferenceParams = {
@@ -18,6 +20,7 @@ export const DEFAULT_INFERENCE_PARAMS: InferenceParams = {
maxTokens: 4092,
systemPrompt: "",
checkpoint: "",
+ trustRemoteCode: false,
};
export interface ChatModelSummary {
diff --git a/studio/frontend/src/features/export/api/export-api.ts b/studio/frontend/src/features/export/api/export-api.ts
index cbaa4a8145..1eac52f216 100644
--- a/studio/frontend/src/features/export/api/export-api.ts
+++ b/studio/frontend/src/features/export/api/export-api.ts
@@ -50,6 +50,8 @@ export async function loadCheckpoint(params: {
checkpoint_path: string;
max_seq_length?: number;
load_in_4bit?: boolean;
+ /** Allow loading models with custom code. Only enable for checkpoints you trust. */
+ trust_remote_code?: boolean;
}): Promise
{
const response = await authFetch("/api/export/load-checkpoint", {
method: "POST",
diff --git a/studio/frontend/src/features/training/api/mappers.ts b/studio/frontend/src/features/training/api/mappers.ts
index ca4339838c..572a650b08 100644
--- a/studio/frontend/src/features/training/api/mappers.ts
+++ b/studio/frontend/src/features/training/api/mappers.ts
@@ -32,6 +32,7 @@ export function buildTrainingStartPayload(
hf_token: config.hfToken.trim() || null,
load_in_4bit: adapterMethod ? isQlorMethod : false,
max_seq_length: config.contextLength,
+ trust_remote_code: false,
hf_dataset: hfDataset,
subset: hfDataset ? config.datasetSubset : null,
train_split: hfDataset ? config.datasetSplit : null,
diff --git a/studio/frontend/src/features/training/types/api.ts b/studio/frontend/src/features/training/types/api.ts
index 0dcb18b1bf..2e99930a2c 100644
--- a/studio/frontend/src/features/training/types/api.ts
+++ b/studio/frontend/src/features/training/types/api.ts
@@ -4,6 +4,8 @@ export interface TrainingStartRequest {
hf_token: string | null;
load_in_4bit: boolean;
max_seq_length: number;
+ /** Allow loading models with custom code. Only enable for repos you trust. */
+ trust_remote_code?: boolean;
hf_dataset: string | null;
subset: string | null;
train_split: string | null;
From 662cb1c440893df1944effec8961c89bb587ac0e Mon Sep 17 00:00:00 2001
From: samit
Date: Sun, 8 Mar 2026 16:44:41 -0700
Subject: [PATCH 02/22] Adding trust_remote_code to the orchestrator and worker
---
studio/backend/core/export/orchestrator.py | 2 ++
studio/backend/core/export/worker.py | 2 ++
2 files changed, 4 insertions(+)
diff --git a/studio/backend/core/export/orchestrator.py b/studio/backend/core/export/orchestrator.py
index ec18d3533e..790ac4b000 100644
--- a/studio/backend/core/export/orchestrator.py
+++ b/studio/backend/core/export/orchestrator.py
@@ -211,6 +211,7 @@ class ExportOrchestrator:
checkpoint_path: str,
max_seq_length: int = 2048,
load_in_4bit: bool = True,
+ trust_remote_code: bool = False,
) -> Tuple[bool, str]:
"""Load a checkpoint for export.
@@ -225,6 +226,7 @@ class ExportOrchestrator:
"checkpoint_path": checkpoint_path,
"max_seq_length": max_seq_length,
"load_in_4bit": load_in_4bit,
+ "trust_remote_code": trust_remote_code,
}
# Always kill existing subprocess and spawn fresh.
diff --git a/studio/backend/core/export/worker.py b/studio/backend/core/export/worker.py
index 9e7e72e9dd..82428e670b 100644
--- a/studio/backend/core/export/worker.py
+++ b/studio/backend/core/export/worker.py
@@ -84,6 +84,7 @@ def _handle_load(backend, cmd: dict, resp_queue: Any) -> None:
checkpoint_path = cmd["checkpoint_path"]
max_seq_length = cmd.get("max_seq_length", 2048)
load_in_4bit = cmd.get("load_in_4bit", True)
+ trust_remote_code = cmd.get("trust_remote_code", False)
try:
_send_response(resp_queue, {
@@ -96,6 +97,7 @@ def _handle_load(backend, cmd: dict, resp_queue: Any) -> None:
checkpoint_path=checkpoint_path,
max_seq_length=max_seq_length,
load_in_4bit=load_in_4bit,
+ trust_remote_code=trust_remote_code,
)
_send_response(resp_queue, {
From 2db36c0b30465c5b66399e72d1589e68b019d4e6 Mon Sep 17 00:00:00 2001
From: samit
Date: Sun, 8 Mar 2026 17:46:54 -0700
Subject: [PATCH 03/22] added auth to audio generate endpoint
---
studio/backend/routes/inference.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py
index 52e5bfad72..2a0c0f5281 100644
--- a/studio/backend/routes/inference.py
+++ b/studio/backend/routes/inference.py
@@ -430,7 +430,7 @@ async def get_status(
@router.post("/audio/generate")
-async def generate_audio(payload: ChatCompletionRequest, request: Request):
+async def generate_audio(payload: ChatCompletionRequest, request: Request, current_subject: str = Depends(get_current_subject)):
"""
Generate audio (TTS) from the latest user message.
Returns a JSON response with base64-encoded WAV audio.
From a49638c504cf7161696d84927adf4d8d5b48cfbd Mon Sep 17 00:00:00 2001
From: Manan17
Date: Mon, 9 Mar 2026 05:50:18 +0000
Subject: [PATCH 04/22] dataset upload
---
studio/backend/core/training/trainer.py | 61 ++++---
studio/backend/models/datasets.py | 12 ++
studio/backend/routes/datasets.py | 55 +++++++
.../studio/sections/dataset-section.tsx | 149 +++++++++++++-----
.../src/features/training/api/datasets-api.ts | 27 ++++
.../frontend/src/features/training/index.ts | 1 +
.../training/stores/training-config-store.ts | 3 +
.../src/features/training/types/datasets.ts | 5 +
8 files changed, 245 insertions(+), 68 deletions(-)
diff --git a/studio/backend/core/training/trainer.py b/studio/backend/core/training/trainer.py
index 7bfb8d4d7a..41d208d9f4 100644
--- a/studio/backend/core/training/trainer.py
+++ b/studio/backend/core/training/trainer.py
@@ -378,6 +378,9 @@ class UnslothTrainer:
self.is_audio = self._audio_type is not None
self.is_audio_vlm = False
+ if not self.is_audio and not self.is_audio_vlm:
+ self._cuda_audio_used = False
+
# VLM: vision model with image dataset (mutually exclusive with audio paths)
vision = is_vision_model(model_name) if not self.is_audio else False
self.is_vlm = not self.is_audio_vlm and vision and is_dataset_image
@@ -1786,18 +1789,20 @@ class UnslothTrainer:
eval_enabled = eval_steps is not None and eval_steps > 0
if local_datasets:
- # Load local datasets
- all_data = []
+ # Load local datasets using load_dataset() so the result is
+ # Arrow-backed (has cache files). Dataset.from_list() creates
+ # an in-memory dataset with no cache, which forces num_proc=1
+ # during tokenization/map because sharding requires Arrow files.
+ all_files: list[str] = []
for dataset_file in local_datasets:
# dataset_file may already be an absolute path from routes/training.py
if os.path.isabs(dataset_file):
file_path = dataset_file
else:
# Fallback: try relative to assets/datasets
- file_path = _ASSETS_DATASETS_ROOT / dataset_file
+ file_path = str(_ASSETS_DATASETS_ROOT / dataset_file)
file_path_obj = Path(file_path)
- file_path_str = str(file_path_obj)
if file_path_obj.is_dir():
parquet_dir = (
@@ -1807,36 +1812,41 @@ class UnslothTrainer:
)
parquet_files = sorted(parquet_dir.glob("*.parquet"))
if parquet_files:
- for parquet_file in parquet_files:
- df = pd.read_parquet(parquet_file)
- all_data.extend(df.to_dict("records"))
+ all_files.extend(str(p) for p in parquet_files)
continue
+ # Fall through to single-file detection for dirs with json/csv
+ candidates: list[Path] = []
+ for ext in ('.json', '.jsonl', '.csv', '.parquet'):
+ candidates.extend(sorted(file_path_obj.glob(f"*{ext}")))
+ if candidates:
+ all_files.append(str(candidates[0]))
+ continue
+ raise ValueError(f"No supported data files in directory: {file_path_obj}")
+ else:
+ all_files.append(str(file_path_obj))
- if file_path_str.endswith('.json'):
- with open(file_path_obj, 'r', encoding='utf-8') as f:
- data = json.load(f)
- if isinstance(data, list):
- all_data.extend(data)
- else:
- all_data.append(data)
- elif file_path_str.endswith('.csv'):
- df = pd.read_csv(file_path_obj)
- all_data.extend(df.to_dict('records'))
- elif file_path_str.endswith('.parquet'):
- df = pd.read_parquet(file_path_obj)
- all_data.extend(df.to_dict('records'))
- continue
+ if all_files:
+ # Determine loader type from the first file extension
+ first_ext = Path(all_files[0]).suffix.lower()
+ if first_ext in ('.json', '.jsonl'):
+ loader = 'json'
+ elif first_ext == '.csv':
+ loader = 'csv'
+ elif first_ext == '.parquet':
+ loader = 'parquet'
+ else:
+ raise ValueError(f"Unsupported local dataset format: {all_files[0]}")
- if all_data:
- dataset = Dataset.from_list(all_data)
+ dataset = load_dataset(loader, data_files=all_files, split='train')
# Check if stopped during dataset loading
if self.should_stop:
print("Stopped during dataset loading\n")
return None
- self._update_progress(status_message=f"Loaded {len(all_data)} samples from local files")
- print(f"Loaded {len(all_data)} samples from local files\n")
+ self._update_progress(status_message=f"Loaded {len(dataset)} samples from local files")
+ print(f"Loaded {len(dataset)} samples from local files\n")
+ print(f"[DEBUG] Dataset cache_files: {dataset.cache_files}\n")
elif dataset_source:
# Load from Hugging Face
@@ -2360,6 +2370,7 @@ class UnslothTrainer:
"dataset_num_proc": 1 if (self.is_audio or self.is_audio_vlm or self._cuda_audio_used) else safe_num_proc(max(1, os.cpu_count() // 4)),
"max_seq_length": training_args.get('max_seq_length', 2048),
}
+ print(f"[DEBUG] dataset_num_proc={config_args['dataset_num_proc']} (is_audio={self.is_audio}, is_audio_vlm={self.is_audio_vlm}, _cuda_audio_used={self._cuda_audio_used})")
# On Windows with transformers 5.x, disable DataLoader multiprocessing
# to avoid issues with modified sys.path (.venv_t5) in spawned workers.
diff --git a/studio/backend/models/datasets.py b/studio/backend/models/datasets.py
index 19197d99ad..ca126948bb 100644
--- a/studio/backend/models/datasets.py
+++ b/studio/backend/models/datasets.py
@@ -41,6 +41,18 @@ class CheckFormatResponse(BaseModel):
warning: Optional[str] = None
+class UploadDatasetRequest(BaseModel):
+ """Request for uploading a local training dataset file."""
+ filename: str = Field(..., description="Original filename, e.g. my_data.jsonl")
+ content_base64: str = Field(..., description="Base64-encoded file bytes")
+
+
+class UploadDatasetResponse(BaseModel):
+ """Response with stored dataset path for training."""
+ filename: str = Field(..., description="Original filename")
+ stored_path: str = Field(..., description="Absolute path stored on backend")
+
+
class LocalDatasetItem(BaseModel):
class Metadata(BaseModel):
actual_num_records: Optional[int] = None
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index 04345a944d..e01375d310 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -2,10 +2,12 @@
Datasets API routes
"""
import base64
+import binascii
import io
import json
import sys
from pathlib import Path
+from uuid import uuid4
from fastapi import APIRouter, Depends, HTTPException
import logging
@@ -36,6 +38,8 @@ from models.datasets import (
CheckFormatResponse,
LocalDatasetItem,
LocalDatasetsResponse,
+ UploadDatasetRequest,
+ UploadDatasetResponse,
)
@@ -89,6 +93,10 @@ DATA_EXTS = (
'.zip',
)
LOCAL_FILE_EXTS = ('.json', '.jsonl', '.csv', '.parquet')
+LOCAL_UPLOAD_EXTS = {".csv", ".json", ".jsonl", ".parquet"}
+DATASET_UPLOAD_DIR = (
+ Path.home() / ".cache" / "unsloth" / "training" / "dataset-uploads"
+)
BACKEND_ROOT = Path(__file__).resolve().parents[1]
LOCAL_DATASETS_ROOT = BACKEND_ROOT / "assets" / "datasets"
@@ -252,6 +260,53 @@ def _load_local_preview_slice(*, dataset_path: Path, train_split: str, preview_s
return preview_slice, total_rows
+def _sanitize_filename(filename: str) -> str:
+ name = Path(filename).name.strip().replace("\x00", "")
+ if not name:
+ return "dataset_upload"
+ return name
+
+
+def _decode_base64_payload(content_base64: str) -> bytes:
+ raw = content_base64.strip()
+ if "," in raw and raw.lower().startswith("data:"):
+ raw = raw.split(",", 1)[1]
+ try:
+ return base64.b64decode(raw, validate=True)
+ except binascii.Error as exc:
+ raise HTTPException(status_code=400, detail="Invalid base64 payload") from exc
+
+
+@router.post("/upload", response_model=UploadDatasetResponse)
+def upload_dataset(
+ payload: UploadDatasetRequest,
+ current_subject: str = Depends(get_current_subject),
+) -> UploadDatasetResponse:
+ filename = _sanitize_filename(payload.filename)
+ ext = Path(filename).suffix.lower()
+ if ext not in LOCAL_UPLOAD_EXTS:
+ allowed = ", ".join(sorted(LOCAL_UPLOAD_EXTS))
+ raise HTTPException(
+ status_code=400,
+ detail=f"Unsupported file type: {ext}. Allowed: {allowed}",
+ )
+
+ file_bytes = _decode_base64_payload(payload.content_base64)
+ if not file_bytes:
+ raise HTTPException(status_code=400, detail="Empty upload payload")
+
+ max_size_bytes = 512 * 1024 * 1024
+ if len(file_bytes) > max_size_bytes:
+ raise HTTPException(status_code=413, detail="File too large (max 512MB)")
+
+ DATASET_UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
+ stored_name = f"{uuid4().hex}_{filename}"
+ stored_path = DATASET_UPLOAD_DIR / stored_name
+ stored_path.write_bytes(file_bytes)
+
+ return UploadDatasetResponse(filename=filename, stored_path=str(stored_path))
+
+
@router.get("/local", response_model=LocalDatasetsResponse)
def list_local_datasets(
current_subject: str = Depends(get_current_subject),
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index e522aaca9b..154999ac5b 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -37,6 +37,7 @@ import {
} from "@/hooks";
import {
HfDatasetSubsetSplitSelectors,
+ uploadTrainingDataset,
useDatasetPreviewDialogStore,
useTrainingConfigStore,
} from "@/features/training";
@@ -52,7 +53,8 @@ import {
ViewIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
-import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { type ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { toast } from "sonner";
import { useShallow } from "zustand/react/shallow";
const SEARCH_INPUT_REASONS = new Set(["input-change", "input-paste", "input-clear"]);
@@ -72,7 +74,11 @@ function deriveLocalDatasetName(path: string): string {
const parts = normalized.split("/").filter(Boolean);
const parquetIndex = parts.lastIndexOf("parquet-files");
if (parquetIndex > 0) return parts[parquetIndex - 1];
- return parts[parts.length - 1] ?? path;
+ const basename = parts[parts.length - 1] ?? path;
+ // Strip UUID prefix from uploaded files (format: {32hex}_{original})
+ const uuidPrefixMatch = basename.match(/^[a-f0-9]{32}_(.+)$/);
+ if (uuidPrefixMatch) return uuidPrefixMatch[1];
+ return basename;
}
function formatUpdatedDate(timestamp: number | null): string {
@@ -286,6 +292,8 @@ export function DatasetSection() {
if (datasetSource !== "upload") return;
if (!uploadedFile) return;
if (selectedLocalDataset) return;
+ // Don't clear if this is a direct file upload (not a recipe directory)
+ if (isLikelyLocalDatasetRef(uploadedFile)) return;
selectLocalDataset(null);
}, [
datasetSource,
@@ -320,11 +328,57 @@ export function DatasetSection() {
const selectedLocalUpdatedAt = selectedLocalDataset?.updated_at ?? null;
const comboboxAnchorRef = useRef(null);
+ const fileInputRef = useRef(null);
const { scrollRef, sentinelRef } = useInfiniteScroll(
fetchMore,
hfResults.length,
);
+ const fileToBase64Payload = (file: File): Promise =>
+ new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = () => {
+ const value = String(reader.result ?? "");
+ const parts = value.split(",");
+ resolve(parts.length > 1 ? parts[1] : value);
+ };
+ reader.onerror = () => reject(new Error("Failed to read file"));
+ reader.readAsDataURL(file);
+ });
+
+ const [isUploading, setIsUploading] = useState(false);
+
+ const handleUploadButtonClick = () => {
+ fileInputRef.current?.click();
+ };
+
+ const handleDatasetFileChange = async (event: ChangeEvent) => {
+ const file = event.target.files?.[0];
+ event.target.value = "";
+ if (!file) return;
+
+ setIsUploading(true);
+ try {
+ const contentBase64 = await fileToBase64Payload(file);
+ const uploaded = await uploadTrainingDataset({
+ filename: file.name,
+ contentBase64,
+ });
+
+ selectLocalDataset(uploaded.stored_path);
+
+ toast.success("Dataset uploaded", {
+ description: uploaded.filename,
+ });
+ } catch (error) {
+ toast.error("Upload failed", {
+ description: error instanceof Error ? error.message : "Unknown error",
+ });
+ } finally {
+ setIsUploading(false);
+ }
+ };
+
return (
- ) : datasetSource === "upload" ? (
+ ) : datasetSource === "upload" && selectedLocalDataset ? (
@@ -609,45 +663,39 @@ export function DatasetSection() {
- {uploadedFile ? (
-
-
-
- 0
- ? String(selectedLocalColumns.length)
- : "--"
- }
- />
-
-
-
+
+
+
+ 0
+ ? String(selectedLocalColumns.length)
+ : "--"
+ }
+ />
+
+
- ) : (
-
- Select a local dataset to view metadata.
-
- )}
+
) : null}
@@ -839,9 +887,15 @@ export function DatasetSection() {
variant="outline"
size="sm"
className="cursor-pointer gap-1.5"
+ disabled={isUploading}
+ onClick={handleUploadButtonClick}
>
-
- Upload
+ {isUploading ? (
+
+ ) : (
+
+ )}
+ {isUploading ? "Uploading..." : "Upload"}
+ {
+ void handleDatasetFileChange(event);
+ }}
+ />
diff --git a/studio/frontend/src/features/training/api/datasets-api.ts b/studio/frontend/src/features/training/api/datasets-api.ts
index d056d92189..0f37ac53bf 100644
--- a/studio/frontend/src/features/training/api/datasets-api.ts
+++ b/studio/frontend/src/features/training/api/datasets-api.ts
@@ -1,6 +1,7 @@
import type {
CheckFormatResponse,
LocalDatasetsResponse,
+ UploadDatasetResponse,
} from "../types/datasets";
import { authFetch } from "@/features/auth";
@@ -39,6 +40,32 @@ export async function checkDatasetFormat({
return res.json();
}
+type UploadDatasetArgs = {
+ filename: string;
+ contentBase64: string;
+};
+
+export async function uploadTrainingDataset({
+ filename,
+ contentBase64,
+}: UploadDatasetArgs): Promise {
+ const res = await authFetch("/api/datasets/upload", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ filename,
+ content_base64: contentBase64,
+ }),
+ });
+
+ if (!res.ok) {
+ const body = await res.json().catch(() => null);
+ throw new Error(body?.detail || `Upload failed (${res.status})`);
+ }
+
+ return res.json();
+}
+
export async function listLocalDatasets(): Promise {
const res = await authFetch("/api/datasets/local");
if (!res.ok) {
diff --git a/studio/frontend/src/features/training/index.ts b/studio/frontend/src/features/training/index.ts
index d2fd4f2e43..9302ffe7dd 100644
--- a/studio/frontend/src/features/training/index.ts
+++ b/studio/frontend/src/features/training/index.ts
@@ -7,6 +7,7 @@ export { useTrainingActions } from "./hooks/use-training-actions";
export { useTrainingRuntimeLifecycle } from "./hooks/use-training-runtime-lifecycle";
export { HfDatasetSubsetSplitSelectors } from "./components/hf-dataset-subset-split-selectors";
export { useDatasetPreviewDialogStore } from "./stores/dataset-preview-dialog-store";
+export { uploadTrainingDataset } from "./api/datasets-api";
export { listLocalModels } from "./api/models-api";
export type { LocalModelInfo } from "./api/models-api";
export type { TrainingPhase } from "./types/runtime";
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 42f6b2a33b..3318a192d8 100644
--- a/studio/frontend/src/features/training/stores/training-config-store.ts
+++ b/studio/frontend/src/features/training/stores/training-config-store.ts
@@ -285,6 +285,9 @@ export const useTrainingConfigStore = create()(
uploadedFile,
...resetDatasetState(),
});
+ if (uploadedFile) {
+ runDatasetCheck(uploadedFile, "train");
+ }
},
setDatasetFormat: (datasetFormat) => set({ datasetFormat }),
setDataset: (dataset) => {
diff --git a/studio/frontend/src/features/training/types/datasets.ts b/studio/frontend/src/features/training/types/datasets.ts
index cee77f683b..41a71affaf 100644
--- a/studio/frontend/src/features/training/types/datasets.ts
+++ b/studio/frontend/src/features/training/types/datasets.ts
@@ -15,6 +15,11 @@ export type CheckFormatResponse = {
warning?: string | null;
};
+export type UploadDatasetResponse = {
+ filename: string;
+ stored_path: string;
+};
+
export type LocalDatasetInfo = {
metadata?: {
actual_num_records?: number | null;
From a08b73e38573edf9166bc493263ef4d33d816dbf Mon Sep 17 00:00:00 2001
From: Manan17
Date: Mon, 9 Mar 2026 07:04:02 +0000
Subject: [PATCH 05/22] remove file size limit
---
studio/backend/routes/datasets.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index e01375d310..2357cd2c0e 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -295,10 +295,6 @@ def upload_dataset(
if not file_bytes:
raise HTTPException(status_code=400, detail="Empty upload payload")
- max_size_bytes = 512 * 1024 * 1024
- if len(file_bytes) > max_size_bytes:
- raise HTTPException(status_code=413, detail="File too large (max 512MB)")
-
DATASET_UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
stored_name = f"{uuid4().hex}_{filename}"
stored_path = DATASET_UPLOAD_DIR / stored_name
From 5e36ae2629064bed6a760470ab6aedb61c1c3396 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 09:54:52 +0000
Subject: [PATCH 06/22] add trust_remote_code defaults to all model configs
---
studio/backend/assets/configs/model_defaults/default.yaml | 2 ++
.../model_defaults/ernie/unsloth_ERNIE-4.5-21B-A3B-PT.yaml | 3 +++
.../model_defaults/ernie/unsloth_ERNIE-4.5-VL-28B-A3B-PT.yaml | 2 ++
.../model_defaults/falcon/tiiuae_Falcon-H1-0.5B-Instruct.yaml | 3 +++
.../model_defaults/gemma/unsloth_codegemma-7b-bnb-4bit.yaml | 2 ++
.../model_defaults/gemma/unsloth_functiongemma-270m-it.yaml | 2 ++
.../model_defaults/gemma/unsloth_gemma-2-27b-bnb-4bit.yaml | 3 +++
.../configs/model_defaults/gemma/unsloth_gemma-2-2b.yaml | 3 +++
.../configs/model_defaults/gemma/unsloth_gemma-3-270m-it.yaml | 2 ++
.../configs/model_defaults/gemma/unsloth_gemma-3-27b-it.yaml | 2 ++
.../configs/model_defaults/gemma/unsloth_gemma-3-4b-it.yaml | 2 ++
.../configs/model_defaults/gemma/unsloth_gemma-3-4b-pt.yaml | 2 ++
.../configs/model_defaults/gemma/unsloth_gemma-3n-E4B-it.yaml | 2 ++
.../configs/model_defaults/gemma/unsloth_gemma-3n-E4B.yaml | 2 ++
.../configs/model_defaults/gpt-oss/unsloth_gpt-oss-120b.yaml | 2 ++
.../configs/model_defaults/gpt-oss/unsloth_gpt-oss-20b.yaml | 2 ++
.../granite/unsloth_granite-4.0-350m-unsloth-bnb-4bit.yaml | 2 ++
.../model_defaults/granite/unsloth_granite-4.0-h-micro.yaml | 2 ++
.../llama/unsloth_Llama-3.2-11B-Vision-Instruct.yaml | 2 ++
.../model_defaults/llama/unsloth_Llama-3.2-1B-Instruct.yaml | 3 +++
.../model_defaults/llama/unsloth_Llama-3.2-3B-Instruct.yaml | 2 ++
.../model_defaults/llama/unsloth_Llama-3.3-70B-Instruct.yaml | 2 ++
.../llama/unsloth_Meta-Llama-3.1-70B-bnb-4bit.yaml | 3 +++
.../llama/unsloth_Meta-Llama-3.1-8B-Instruct-bnb-4bit.yaml | 4 +++-
.../llama/unsloth_llama-3-8b-Instruct-bnb-4bit.yaml | 3 +++
.../model_defaults/llama/unsloth_llama-3-8b-bnb-4bit.yaml | 3 +++
.../assets/configs/model_defaults/llasa/unsloth_Llasa-3B.yaml | 2 ++
.../unsloth_Magistral-Small-2509-unsloth-bnb-4bit.yaml | 2 ++
.../mistral/unsloth_Ministral-3-3B-Instruct-2512.yaml | 2 ++
.../mistral/unsloth_Mistral-Nemo-Base-2407-bnb-4bit.yaml | 4 +++-
.../mistral/unsloth_Mistral-Small-Instruct-2409.yaml | 3 +++
.../model_defaults/mistral/unsloth_Pixtral-12B-2409.yaml | 2 ++
.../mistral/unsloth_mistral-7b-instruct-v0.3-bnb-4bit.yaml | 4 +++-
.../mistral/unsloth_mistral-7b-v0.3-bnb-4bit.yaml | 4 +++-
.../model_defaults/other/OuteAI_Llama-OuteTTS-1.0-1B.yaml | 2 ++
.../configs/model_defaults/other/Spark-TTS-0.5B_LLM.yaml | 2 ++
.../assets/configs/model_defaults/other/sesame_csm-1b.yaml | 3 +++
.../configs/model_defaults/other/unsloth_GLM-4.7-Flash.yaml | 2 ++
.../configs/model_defaults/other/unsloth_LFM2-1.2B.yaml | 2 ++
.../model_defaults/other/unsloth_Nemotron-3-Nano-30B-A3B.yaml | 2 ++
.../configs/model_defaults/other/unsloth_PaddleOCR-VL.yaml | 2 ++
.../other/unsloth_answerdotai_ModernBERT-large.yaml | 3 +++
.../model_defaults/other/unsloth_orpheus-3b-0.1-ft.yaml | 2 ++
.../model_defaults/other/unsloth_tinyllama-bnb-4bit.yaml | 3 +++
.../model_defaults/other/unsloth_whisper-large-v3.yaml | 3 +++
.../model_defaults/phi/unsloth_Phi-3-medium-4k-instruct.yaml | 4 +++-
.../model_defaults/phi/unsloth_Phi-3.5-mini-instruct.yaml | 4 +++-
.../assets/configs/model_defaults/phi/unsloth_Phi-4.yaml | 2 ++
.../qwen/imdatta0_tiny_qwen3_moe_2.8B_0.7B.yaml | 2 ++
.../assets/configs/model_defaults/qwen/unsloth_Qwen2-7B.yaml | 3 +++
.../model_defaults/qwen/unsloth_Qwen2-VL-7B-Instruct.yaml | 2 ++
.../model_defaults/qwen/unsloth_Qwen2.5-1.5B-Instruct.yaml | 3 +++
.../configs/model_defaults/qwen/unsloth_Qwen2.5-7B.yaml | 3 +++
.../qwen/unsloth_Qwen2.5-Coder-1.5B-Instruct.yaml | 3 +++
.../qwen/unsloth_Qwen2.5-Coder-14B-Instruct.yaml | 2 ++
.../qwen/unsloth_Qwen2.5-Coder-7B-Instruct-bnb-4bit.yaml | 3 +++
.../qwen/unsloth_Qwen2.5-VL-7B-Instruct-bnb-4bit.yaml | 2 ++
.../configs/model_defaults/qwen/unsloth_Qwen3-0.6B.yaml | 2 ++
.../qwen/unsloth_Qwen3-14B-Base-unsloth-bnb-4bit.yaml | 2 ++
.../assets/configs/model_defaults/qwen/unsloth_Qwen3-14B.yaml | 2 ++
.../qwen/unsloth_Qwen3-30B-A3B-Instruct-2507.yaml | 2 ++
.../assets/configs/model_defaults/qwen/unsloth_Qwen3-32B.yaml | 2 ++
.../model_defaults/qwen/unsloth_Qwen3-4B-Instruct-2507.yaml | 2 ++
.../model_defaults/qwen/unsloth_Qwen3-4B-Thinking-2507.yaml | 2 ++
.../qwen/unsloth_Qwen3-VL-8B-Instruct-unsloth-bnb-4bit.yaml | 2 ++
65 files changed, 154 insertions(+), 6 deletions(-)
diff --git a/studio/backend/assets/configs/model_defaults/default.yaml b/studio/backend/assets/configs/model_defaults/default.yaml
index ceb332bc14..d96e5077b2 100644
--- a/studio/backend/assets/configs/model_defaults/default.yaml
+++ b/studio/backend/assets/configs/model_defaults/default.yaml
@@ -2,6 +2,7 @@
# Used for models without specific configurations
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -47,6 +48,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.7
top_p: 0.95
top_k: -1
diff --git a/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-21B-A3B-PT.yaml b/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-21B-A3B-PT.yaml
index dc2f12837a..52511c6eaf 100644
--- a/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-21B-A3B-PT.yaml
+++ b/studio/backend/assets/configs/model_defaults/ernie/unsloth_ERNIE-4.5-21B-A3B-PT.yaml
@@ -3,6 +3,7 @@
# Also applies to: unsloth/ERNIE-4.5-21B-A3B-PT
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 1032449e8c..524a723dc2 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: true
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -48,6 +49,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: true
temperature: 1.5
min_p: 0.1
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 06b283c480..c45b71b4ae 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
@@ -3,6 +3,7 @@
# Also applies to: tiiuae/Falcon-H1-0.5B-Instruct, unsloth/Falcon-H1-0.5B-Instruct
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 251409c29d..62836dc0cd 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
@@ -4,6 +4,7 @@
# added inference parameters from Ollama
training:
+ trust_remote_code: false
max_seq_length: 4096
# num_epochs: 4
num_epochs: 0
@@ -44,5 +45,6 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0
top_p: 0.9
diff --git a/studio/backend/assets/configs/model_defaults/gemma/unsloth_functiongemma-270m-it.yaml b/studio/backend/assets/configs/model_defaults/gemma/unsloth_functiongemma-270m-it.yaml
index 89b1d7f938..f97a842d2a 100644
--- a/studio/backend/assets/configs/model_defaults/gemma/unsloth_functiongemma-270m-it.yaml
+++ b/studio/backend/assets/configs/model_defaults/gemma/unsloth_functiongemma-270m-it.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 4096
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 ba50f7d1f8..56f10cdc4f 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
@@ -2,6 +2,7 @@
# Based on Gemma2_(9B)-Alpaca.ipynb (same defaults for larger models)
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -41,3 +42,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 413e7465d3..f8f78f5edc 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/gemma-2-2b-bnb-4bit, google/gemma-2-2b
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 bda5471643..455407abf8 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 18392568bd..2bcdf67c15 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 434ac41b46..7c123da0b8 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 5f0a7b26ce..492c42812e 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 2
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 dd5ae51ab0..23d00df752 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 1024
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
audio_input: true
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 e53e163a04..bf5e111b7d 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 2
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
audio_input: true
inference:
+ trust_remote_code: false
temperature: 1.0
top_k: 64
top_p: 0.95
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 e2d67bcb0b..bd39e70a96 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 4096
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_p: 1.0
top_k: 0
diff --git a/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-20b.yaml b/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-20b.yaml
index aa436117a1..839e9a5b75 100644
--- a/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-20b.yaml
+++ b/studio/backend/assets/configs/model_defaults/gpt-oss/unsloth_gpt-oss-20b.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 1024
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.0
top_p: 1.0
top_k: 0
diff --git a/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-350m-unsloth-bnb-4bit.yaml b/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-350m-unsloth-bnb-4bit.yaml
index 3f2cb84a94..9557fc296f 100644
--- a/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-350m-unsloth-bnb-4bit.yaml
+++ b/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-350m-unsloth-bnb-4bit.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -46,6 +47,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.0
top_p: 1.0
top_k: 0
diff --git a/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-h-micro.yaml b/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-h-micro.yaml
index ab756fe764..ce73c6a8ee 100644
--- a/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-h-micro.yaml
+++ b/studio/backend/assets/configs/model_defaults/granite/unsloth_granite-4.0-h-micro.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -46,6 +47,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.0
top_p: 1.0
top_k: 0
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 1a7a91e56f..d9a75c391d 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 53e82c5609..3938f10627 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Llama-3.2-1B-Instruct-unsloth-bnb-4bit, meta-llama/Llama-3.2-1B-Instruct, unsloth/Llama-3.2-1B-Instruct-bnb-4bit, RedHatAI/Llama-3.2-1B-Instruct-FP8, unsloth/Llama-3.2-1B-Instruct-FP8-Block, unsloth/Llama-3.2-1B-Instruct-FP8-Dynamic
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 5
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 f73b0c09b6..82091c7d35 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 ffefb29e24..5a014a63bf 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 5f9da41a95..885f7b47fd 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Meta-Llama-3.1-8B-bnb-4bit, unsloth/Meta-Llama-3.1-8B-unsloth-bnb-4bit, meta-llama/Meta-Llama-3.1-8B, unsloth/Meta-Llama-3.1-8B, unsloth/Meta-Llama-3.1-70B, meta-llama/Meta-Llama-3.1-70B, unsloth/Meta-Llama-3.1-405B-bnb-4bit, meta-llama/Meta-Llama-3.1-405B
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 d20470b0a3..1ff06cca6f 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
@@ -3,6 +3,7 @@
# Also applies to: "unsloth/Meta-Llama-3.1-8B-Instruct-unsloth-bnb-4bit", "meta-llama/Meta-Llama-3.1-8B-Instruct", "unsloth/Meta-Llama-3.1-8B-Instruct","RedHatAI/Llama-3.1-8B-Instruct-FP8","unsloth/Llama-3.1-8B-Instruct-FP8-Block","unsloth/Llama-3.1-8B-Instruct-FP8-Dynamic"
training:
+ trust_remote_code: false
max_seq_length: 8192
# num_epochs: 4
num_epochs: 0
@@ -42,4 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 1956495f7d..95ee5ead5c 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/llama-3-8b-Instruct, meta-llama/Meta-Llama-3-8B-Instruct
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 15869497b7..a05ac86f43 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/llama-3-8b, meta-llama/Meta-Llama-3-8B
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 6bba9c9633..1f473c3af1 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -39,6 +40,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.2
top_p: 1.2
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 f9833ce705..5a53bb52eb 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -48,6 +49,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.7
min_p: 0.01
top_p: 0.95
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 ca6609cda8..c9f771fd23 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -48,6 +49,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.15
top_p: default
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 1048bd2469..abdac62c0c 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
@@ -3,6 +3,7 @@
# Also applies to: "unsloth/Mistral-Nemo-Base-2407", "mistralai/Mistral-Nemo-Base-2407", "unsloth/Mistral-Nemo-Instruct-2407-bnb-4bit", "unsloth/Mistral-Nemo-Instruct-2407", "mistralai/Mistral-Nemo-Instruct-2407",
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,4 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 26c58a61f1..149f2a24f1 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Mistral-Small-Instruct-2409-bnb-4bit, mistralai/Mistral-Small-Instruct-2409
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 bcd0d20c8c..3976cd0aa0 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 2e1c76468e..55d5dd289b 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/mistral-7b-instruct-v0.3, mistralai/Mistral-7B-Instruct-v0.3
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,4 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 37275fc37b..5b24f5b581 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
@@ -2,6 +2,7 @@
# Based on Mistral_v0.3_(7B)-Alpaca.ipynb
# Also applies to: "unsloth/mistral-7b-v0.3", "mistralai/Mistral-7B-v0.3",
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -41,4 +42,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 72b5b018e1..87b94ce67c 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
@@ -6,6 +6,7 @@
audio_type: dac
training:
+ trust_remote_code: false
eval_steps: 0
max_seq_length: 2048
# num_epochs: 4
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.4
top_k: 40
top_p: 0.9
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 d20751b0c7..03748cd5fd 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
@@ -6,6 +6,7 @@
audio_type: bicodec
training:
+ trust_remote_code: false
eval_steps: 0
max_seq_length: 2048
# num_epochs: 4
@@ -47,6 +48,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.8
top_k: 50
top_p: 1.0
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 f5f49fe1e6..5c1e180f8c 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
@@ -5,6 +5,7 @@
audio_type: csm
training:
+ trust_remote_code: false
eval_steps: 0
max_seq_length: 2048
# num_epochs: 4
@@ -45,3 +46,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_GLM-4.7-Flash.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_GLM-4.7-Flash.yaml
index a973c2d4e4..6d8be3656f 100644
--- a/studio/backend/assets/configs/model_defaults/other/unsloth_GLM-4.7-Flash.yaml
+++ b/studio/backend/assets/configs/model_defaults/other/unsloth_GLM-4.7-Flash.yaml
@@ -3,6 +3,7 @@
# Also applies to: unsloth/GLM-4.7-Flash-unsloth-bnb-4bit, unsloth/GLM-4.7-Flash-bnb-4bit, THUDM/GLM-4.7-Flash
training:
+ trust_remote_code: true
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: true
temperature: 0.7
top_p: 0.8
top_k: 20
diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_LFM2-1.2B.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_LFM2-1.2B.yaml
index b0feafbd6e..39a2fe0a5b 100644
--- a/studio/backend/assets/configs/model_defaults/other/unsloth_LFM2-1.2B.yaml
+++ b/studio/backend/assets/configs/model_defaults/other/unsloth_LFM2-1.2B.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -38,6 +39,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.3
min_p: 0.15
diff --git a/studio/backend/assets/configs/model_defaults/other/unsloth_Nemotron-3-Nano-30B-A3B.yaml b/studio/backend/assets/configs/model_defaults/other/unsloth_Nemotron-3-Nano-30B-A3B.yaml
index 2c44c91eab..663ce87d5f 100644
--- a/studio/backend/assets/configs/model_defaults/other/unsloth_Nemotron-3-Nano-30B-A3B.yaml
+++ b/studio/backend/assets/configs/model_defaults/other/unsloth_Nemotron-3-Nano-30B-A3B.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: true
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -46,6 +47,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: true
temperature: 1.0
top_p: 1.0
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 e1fbc08e4d..b7587bbd91 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: true
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -48,6 +49,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: true
temperature: 1.5
min_p: 0.1
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 cae8dd3c40..cc5d130bfa 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
@@ -2,6 +2,7 @@
# Based on bert_classification.ipynb
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 1
num_epochs: 0
@@ -41,3 +42,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 5a3c4abb48..883761675f 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
@@ -6,6 +6,7 @@
audio_type: snac
training:
+ trust_remote_code: false
eval_steps: 0
max_seq_length: 2048
# num_epochs: 4
@@ -47,6 +48,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_p: 0.95
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 c3b966fa06..35c850c71f 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
@@ -3,6 +3,7 @@
# Also applies to: TinyLlama/TinyLlama-1.1B-intermediate-step-1431k-3T
training:
+ trust_remote_code: false
max_seq_length: 4096
# num_epochs: 1
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 1906ecda51..9140878e0e 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
@@ -6,6 +6,7 @@ audio_type: whisper
audio_input: true
training:
+ trust_remote_code: false
eval_steps: 5
max_seq_length: 448
# num_epochs: 4
@@ -41,3 +42,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 14af711f78..1088df7796 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
@@ -3,6 +3,7 @@
# Also applies to: "unsloth/Phi-3-medium-4k-instruct-bnb-4bit", "microsoft/Phi-3-medium-4k-instruct",
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,4 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 b0593300ab..79812a74c4 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
@@ -3,6 +3,7 @@
# Also applies to: "unsloth/Phi-3.5-mini-instruct-bnb-4bit", "microsoft/Phi-3.5-mini-instruct"
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,4 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
-
+inference:
+ trust_remote_code: false
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 4de3d9437d..aaa4feac45 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.8
top_p: 0.95
diff --git a/studio/backend/assets/configs/model_defaults/qwen/imdatta0_tiny_qwen3_moe_2.8B_0.7B.yaml b/studio/backend/assets/configs/model_defaults/qwen/imdatta0_tiny_qwen3_moe_2.8B_0.7B.yaml
index bb75b3ce52..fa7b9c4e8b 100644
--- a/studio/backend/assets/configs/model_defaults/qwen/imdatta0_tiny_qwen3_moe_2.8B_0.7B.yaml
+++ b/studio/backend/assets/configs/model_defaults/qwen/imdatta0_tiny_qwen3_moe_2.8B_0.7B.yaml
@@ -4,6 +4,7 @@
# MoE model - includes gate_up_proj for MoE layers
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -45,6 +46,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
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 140484eb9c..3e64a6ca48 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Qwen2-7B-bnb-4bit, Qwen/Qwen2-7B
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 6cee3d0949..894751bed1 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 5ecb154e4c..1d37cc9829 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Qwen2.5-1.5B-Instruct-unsloth-bnb-4bit, Qwen/Qwen2.5-1.5B-Instruct, unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit
training:
+ trust_remote_code: false
max_seq_length: 4096
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 5bbe543517..99f3a66e23 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Qwen2.5-7B-unsloth-bnb-4bit, Qwen/Qwen2.5-7B, unsloth/Qwen2.5-7B-bnb-4bit
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 16c4367223..c48b943cba 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Qwen2.5-Coder-1.5B-Instruct-bnb-4bit, Qwen/Qwen2.5-Coder-1.5B-Instruct
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 856db0c1b3..830bfcf1cb 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 bb0b0ed1c6..db88c3b033 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
@@ -3,6 +3,7 @@
# Also applies to: unsloth/Qwen2.5-Coder-7B-Instruct, Qwen/Qwen2.5-Coder-7B-Instruct
training:
+ trust_remote_code: false
max_seq_length: 32768
# num_epochs: 4
num_epochs: 0
@@ -42,3 +43,5 @@ logging:
tensorboard_dir: "runs"
log_frequency: 10
+inference:
+ trust_remote_code: false
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 bd54b1d015..cb9bcb104b 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth notebook
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 1.5
min_p: 0.1
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 9feb6dcaae..13f066a27d 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
@@ -4,6 +4,7 @@
# added inference parameters from Ollama
training:
+ trust_remote_code: false
max_seq_length: 1024
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
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 e61c7b5045..1b942004f6 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
@@ -4,6 +4,7 @@
# added inference parameters from Ollama
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
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 c130771c32..a8ecbb4365 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
@@ -4,6 +4,7 @@
# added inference parameters from Ollama
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-30B-A3B-Instruct-2507.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-30B-A3B-Instruct-2507.yaml
index 2fb3a95c30..485dd7a111 100644
--- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-30B-A3B-Instruct-2507.yaml
+++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-30B-A3B-Instruct-2507.yaml
@@ -4,6 +4,7 @@
# MoE model - includes gate_up_proj for MoE layers
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -45,6 +46,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
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 152f4ae06a..0de64d50ae 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
@@ -4,6 +4,7 @@
# added inference parameters from Ollama
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_k: 20
top_p: 0.95
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 94fe000708..dc5940d58c 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.7
top_p: 0.80
top_k: 20
diff --git a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Thinking-2507.yaml b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Thinking-2507.yaml
index 3c325485d2..6392ee0ae9 100644
--- a/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Thinking-2507.yaml
+++ b/studio/backend/assets/configs/model_defaults/qwen/unsloth_Qwen3-4B-Thinking-2507.yaml
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -44,6 +45,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.6
top_p: 0.95
top_k: 20
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 5b47c3bdd2..ef52fad763 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
@@ -4,6 +4,7 @@
# added inference parameters from unsloth guides
training:
+ trust_remote_code: false
max_seq_length: 2048
# num_epochs: 4
num_epochs: 0
@@ -42,6 +43,7 @@ logging:
log_frequency: 10
inference:
+ trust_remote_code: false
temperature: 0.7
top_p: 0.8
top_k: 20
From a1105d8ef3eae041010db6106e4becb7652fa930 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 10:15:15 +0000
Subject: [PATCH 07/22] wire trust_remote_code from YAML configs to frontend
toggles
---
studio/backend/utils/inference/inference_config.py | 1 +
studio/frontend/src/config/training.ts | 1 +
.../src/features/chat/hooks/use-chat-model-runtime.ts | 4 ++++
studio/frontend/src/features/chat/types/api.ts | 1 +
studio/frontend/src/features/training/api/mappers.ts | 2 +-
studio/frontend/src/features/training/lib/model-defaults.ts | 4 ++++
studio/frontend/src/features/training/types/config.ts | 1 +
7 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/studio/backend/utils/inference/inference_config.py b/studio/backend/utils/inference/inference_config.py
index d6de562d33..ff82b47fa6 100644
--- a/studio/backend/utils/inference/inference_config.py
+++ b/studio/backend/utils/inference/inference_config.py
@@ -59,6 +59,7 @@ def load_inference_config(model_identifier: str) -> Dict[str, Any]:
"top_p": model_inference.get("top_p", default_inference.get("top_p", 0.95)),
"top_k": model_inference.get("top_k", default_inference.get("top_k", -1)),
"min_p": model_inference.get("min_p", default_inference.get("min_p", 0.01)),
+ "trust_remote_code": model_inference.get("trust_remote_code", default_inference.get("trust_remote_code", False)),
}
return inference_config
diff --git a/studio/frontend/src/config/training.ts b/studio/frontend/src/config/training.ts
index 4df5107022..b812dd89f1 100644
--- a/studio/frontend/src/config/training.ts
+++ b/studio/frontend/src/config/training.ts
@@ -114,6 +114,7 @@ export const DEFAULT_HYPERPARAMS = {
enableTensorboard: false,
tensorboardDir: "runs",
logFrequency: 10,
+ trustRemoteCode: false,
finetuneVisionLayers: true,
finetuneLanguageLayers: true,
finetuneAttentionModules: true,
diff --git a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
index 827da9d68b..27fc8f99e6 100644
--- a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
+++ b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts
@@ -123,6 +123,10 @@ function mergeRecommendedInference(
topP: toFiniteNumber(inference?.top_p) ?? current.topP,
topK: toFiniteNumber(inference?.top_k) ?? current.topK,
minP: toFiniteNumber(inference?.min_p) ?? current.minP,
+ trustRemoteCode:
+ typeof inference?.trust_remote_code === "boolean"
+ ? inference.trust_remote_code
+ : current.trustRemoteCode,
};
}
diff --git a/studio/frontend/src/features/chat/types/api.ts b/studio/frontend/src/features/chat/types/api.ts
index 9999e0ce70..08bdc20435 100644
--- a/studio/frontend/src/features/chat/types/api.ts
+++ b/studio/frontend/src/features/chat/types/api.ts
@@ -66,6 +66,7 @@ export interface LoadModelResponse {
top_p?: number;
top_k?: number;
min_p?: number;
+ trust_remote_code?: boolean;
};
}
diff --git a/studio/frontend/src/features/training/api/mappers.ts b/studio/frontend/src/features/training/api/mappers.ts
index 572a650b08..2a8b302d34 100644
--- a/studio/frontend/src/features/training/api/mappers.ts
+++ b/studio/frontend/src/features/training/api/mappers.ts
@@ -32,7 +32,7 @@ export function buildTrainingStartPayload(
hf_token: config.hfToken.trim() || null,
load_in_4bit: adapterMethod ? isQlorMethod : false,
max_seq_length: config.contextLength,
- trust_remote_code: false,
+ trust_remote_code: config.trustRemoteCode ?? false,
hf_dataset: hfDataset,
subset: hfDataset ? config.datasetSubset : null,
train_split: hfDataset ? config.datasetSplit : null,
diff --git a/studio/frontend/src/features/training/lib/model-defaults.ts b/studio/frontend/src/features/training/lib/model-defaults.ts
index 35ce562dbf..b9d0abccc8 100644
--- a/studio/frontend/src/features/training/lib/model-defaults.ts
+++ b/studio/frontend/src/features/training/lib/model-defaults.ts
@@ -30,6 +30,7 @@ type ModelDefaultsPatch = Partial<
| "tensorboardDir"
| "logFrequency"
| "finetuneVisionLayers"
+ | "trustRemoteCode"
| "finetuneLanguageLayers"
| "finetuneAttentionModules"
| "finetuneMLPModules"
@@ -133,6 +134,9 @@ export function mapBackendModelConfigToTrainingPatch(
patch.gradientCheckpointing = gradientCheckpointing;
}
+ const trustRemoteCode = toBoolean(training?.trust_remote_code);
+ if (trustRemoteCode !== undefined) patch.trustRemoteCode = trustRemoteCode;
+
const loraRank = toNumber(lora?.lora_r);
if (loraRank !== undefined) patch.loraRank = loraRank;
diff --git a/studio/frontend/src/features/training/types/config.ts b/studio/frontend/src/features/training/types/config.ts
index f773eee129..5d5fb7515f 100644
--- a/studio/frontend/src/features/training/types/config.ts
+++ b/studio/frontend/src/features/training/types/config.ts
@@ -63,6 +63,7 @@ export interface TrainingConfigState {
isCheckingDataset: boolean;
isDatasetImage: boolean | null;
isDatasetAudio: boolean;
+ trustRemoteCode: boolean;
finetuneVisionLayers: boolean;
finetuneLanguageLayers: boolean;
finetuneAttentionModules: boolean;
From 1ddd138da889b90dece71e81649dd6552b49f324 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 10:51:28 +0000
Subject: [PATCH 08/22] add trust_remote_code to BackendTrainingDefaults type
---
studio/frontend/src/features/training/api/models-api.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/studio/frontend/src/features/training/api/models-api.ts b/studio/frontend/src/features/training/api/models-api.ts
index d2c4f06661..d434ecde05 100644
--- a/studio/frontend/src/features/training/api/models-api.ts
+++ b/studio/frontend/src/features/training/api/models-api.ts
@@ -22,6 +22,7 @@ interface BackendTrainingDefaults {
packing?: boolean;
train_on_completions?: boolean;
gradient_checkpointing?: "none" | "true" | "unsloth";
+ trust_remote_code?: boolean;
}
interface BackendLoraDefaults {
From 4858204c62415fe775a5d1c5dfe7ea65c94e07d3 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 11:58:23 +0000
Subject: [PATCH 09/22] backend: resolve trust_remote_code from YAML when not
set by frontend
---
studio/backend/routes/inference.py | 15 ++++++++++++++-
studio/backend/routes/training.py | 10 ++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py
index b2f7a802a4..67c858f032 100644
--- a/studio/backend/routes/inference.py
+++ b/studio/backend/routes/inference.py
@@ -26,6 +26,7 @@ try:
from core.inference.llama_cpp import LlamaCppBackend
from utils.models import ModelConfig
from utils.inference import load_inference_config
+ from utils.models.model_config import load_model_defaults
except ImportError:
parent_backend = backend_path.parent / "backend"
if str(parent_backend) not in sys.path:
@@ -34,6 +35,7 @@ except ImportError:
from core.inference.llama_cpp import LlamaCppBackend
from utils.models import ModelConfig
from utils.inference import load_inference_config
+ from utils.models.model_config import load_model_defaults
from models.inference import (
LoadRequest,
@@ -220,13 +222,24 @@ async def load_model(
except Exception as e:
logger.warning(f"Could not read adapter_config.json: {e}")
+ # Resolve trust_remote_code: use True if either the request or YAML config says so.
+ # This ensures models like Nemotron that require it always get it, even if the
+ # frontend toggle hasn't been set yet.
+ trust_remote_code = request.trust_remote_code
+ if not trust_remote_code:
+ model_defaults = load_model_defaults(config.identifier)
+ yaml_trust = model_defaults.get("inference", {}).get("trust_remote_code", False)
+ if yaml_trust:
+ logger.info(f"YAML config sets trust_remote_code=True for {config.identifier}")
+ trust_remote_code = True
+
# Load the model
success = backend.load_model(
config=config,
max_seq_length=request.max_seq_length,
load_in_4bit=load_in_4bit,
hf_token=request.hf_token,
- trust_remote_code=request.trust_remote_code,
+ trust_remote_code=trust_remote_code,
)
if not success:
diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py
index b6e6d7e111..151f8d8542 100644
--- a/studio/backend/routes/training.py
+++ b/studio/backend/routes/training.py
@@ -19,12 +19,14 @@ if str(backend_path) not in sys.path:
# Import backend functions
try:
from core.training import get_training_backend
+ from utils.models.model_config import load_model_defaults
except ImportError:
# Fallback: try to import from parent directory
parent_backend = backend_path.parent / "backend"
if str(parent_backend) not in sys.path:
sys.path.insert(0, str(parent_backend))
from core.training import get_training_backend
+ from utils.models.model_config import load_model_defaults
# Auth
from auth.authentication import get_current_subject
@@ -194,6 +196,14 @@ async def start_training(
"trust_remote_code": request.trust_remote_code,
}
+ # Resolve trust_remote_code: use True if either the request or YAML config says so.
+ if not training_kwargs["trust_remote_code"]:
+ model_defaults = load_model_defaults(request.model_name)
+ yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
+ if yaml_trust:
+ logger.info(f"YAML config sets trust_remote_code=True for {request.model_name}")
+ training_kwargs["trust_remote_code"] = True
+
# Free GPU memory: shut down any running inference/export subprocesses
# before training starts (they'd compete for VRAM otherwise)
try:
From 7989cd456791eb6764db710163618c1871c7646f Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:06:55 +0000
Subject: [PATCH 10/22] respect trust_remote_code toggle, return helpful error
when required
---
studio/backend/core/training/worker.py | 16 +++++++++++++++-
studio/backend/routes/inference.py | 25 +++++++++++++------------
studio/backend/routes/training.py | 10 ----------
3 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index 8eee8293e1..1496c8255b 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -198,9 +198,23 @@ def run_training_process(
if trainer.should_stop:
event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
else:
+ error_msg = trainer.training_progress.error or "Failed to load model"
+ # Hint about trust_remote_code if YAML says this model needs it
+ if not config.get("trust_remote_code", False):
+ try:
+ from utils.models.model_config import load_model_defaults
+ model_defaults = load_model_defaults(model_name)
+ yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
+ if yaml_trust:
+ error_msg = (
+ f"Model '{model_name}' requires trust_remote_code to be enabled. "
+ f"Please enable 'Trust remote code' in Chat Settings and try again."
+ )
+ except Exception:
+ pass
event_queue.put({
"type": "error",
- "error": trainer.training_progress.error or "Failed to load model",
+ "error": error_msg,
"stack": "", "ts": time.time(),
})
return
diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py
index 67c858f032..263700a68c 100644
--- a/studio/backend/routes/inference.py
+++ b/studio/backend/routes/inference.py
@@ -222,27 +222,28 @@ async def load_model(
except Exception as e:
logger.warning(f"Could not read adapter_config.json: {e}")
- # Resolve trust_remote_code: use True if either the request or YAML config says so.
- # This ensures models like Nemotron that require it always get it, even if the
- # frontend toggle hasn't been set yet.
- trust_remote_code = request.trust_remote_code
- if not trust_remote_code:
- model_defaults = load_model_defaults(config.identifier)
- yaml_trust = model_defaults.get("inference", {}).get("trust_remote_code", False)
- if yaml_trust:
- logger.info(f"YAML config sets trust_remote_code=True for {config.identifier}")
- trust_remote_code = True
-
# Load the model
success = backend.load_model(
config=config,
max_seq_length=request.max_seq_length,
load_in_4bit=load_in_4bit,
hf_token=request.hf_token,
- trust_remote_code=trust_remote_code,
+ trust_remote_code=request.trust_remote_code,
)
if not success:
+ # Check if YAML says this model needs trust_remote_code
+ if not request.trust_remote_code:
+ model_defaults = load_model_defaults(config.identifier)
+ yaml_trust = model_defaults.get("inference", {}).get("trust_remote_code", False)
+ if yaml_trust:
+ raise HTTPException(
+ status_code=400,
+ detail=(
+ f"Model '{config.display_name}' requires trust_remote_code to be enabled. "
+ f"Please enable 'Trust remote code' in Chat Settings and try again."
+ ),
+ )
raise HTTPException(
status_code=500,
detail=f"Failed to load model: {config.display_name}"
diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py
index 151f8d8542..b6e6d7e111 100644
--- a/studio/backend/routes/training.py
+++ b/studio/backend/routes/training.py
@@ -19,14 +19,12 @@ if str(backend_path) not in sys.path:
# Import backend functions
try:
from core.training import get_training_backend
- from utils.models.model_config import load_model_defaults
except ImportError:
# Fallback: try to import from parent directory
parent_backend = backend_path.parent / "backend"
if str(parent_backend) not in sys.path:
sys.path.insert(0, str(parent_backend))
from core.training import get_training_backend
- from utils.models.model_config import load_model_defaults
# Auth
from auth.authentication import get_current_subject
@@ -196,14 +194,6 @@ async def start_training(
"trust_remote_code": request.trust_remote_code,
}
- # Resolve trust_remote_code: use True if either the request or YAML config says so.
- if not training_kwargs["trust_remote_code"]:
- model_defaults = load_model_defaults(request.model_name)
- yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
- if yaml_trust:
- logger.info(f"YAML config sets trust_remote_code=True for {request.model_name}")
- training_kwargs["trust_remote_code"] = True
-
# Free GPU memory: shut down any running inference/export subprocesses
# before training starts (they'd compete for VRAM otherwise)
try:
From c719f1ba54b040cbdae919f452c24b7d2c22c11d Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:10:24 +0000
Subject: [PATCH 11/22] training: restore YAML fallback for trust_remote_code
(no UI toggle)
---
studio/backend/core/training/worker.py | 13 -------------
studio/backend/routes/training.py | 12 ++++++++++++
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index 1496c8255b..0475152482 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -199,19 +199,6 @@ def run_training_process(
event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
else:
error_msg = trainer.training_progress.error or "Failed to load model"
- # Hint about trust_remote_code if YAML says this model needs it
- if not config.get("trust_remote_code", False):
- try:
- from utils.models.model_config import load_model_defaults
- model_defaults = load_model_defaults(model_name)
- yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
- if yaml_trust:
- error_msg = (
- f"Model '{model_name}' requires trust_remote_code to be enabled. "
- f"Please enable 'Trust remote code' in Chat Settings and try again."
- )
- except Exception:
- pass
event_queue.put({
"type": "error",
"error": error_msg,
diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py
index b6e6d7e111..c0e78d2b24 100644
--- a/studio/backend/routes/training.py
+++ b/studio/backend/routes/training.py
@@ -19,12 +19,14 @@ if str(backend_path) not in sys.path:
# Import backend functions
try:
from core.training import get_training_backend
+ from utils.models.model_config import load_model_defaults
except ImportError:
# Fallback: try to import from parent directory
parent_backend = backend_path.parent / "backend"
if str(parent_backend) not in sys.path:
sys.path.insert(0, str(parent_backend))
from core.training import get_training_backend
+ from utils.models.model_config import load_model_defaults
# Auth
from auth.authentication import get_current_subject
@@ -194,6 +196,16 @@ async def start_training(
"trust_remote_code": request.trust_remote_code,
}
+ # Training page has no trust_remote_code toggle — the value comes from
+ # YAML model defaults applied when the user selects a model. As a safety
+ # net, consult the YAML directly so models that need it always get it.
+ if not training_kwargs["trust_remote_code"]:
+ model_defaults = load_model_defaults(request.model_name)
+ yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
+ if yaml_trust:
+ logger.info(f"YAML config sets trust_remote_code=True for {request.model_name}")
+ training_kwargs["trust_remote_code"] = True
+
# Free GPU memory: shut down any running inference/export subprocesses
# before training starts (they'd compete for VRAM otherwise)
try:
From 4c5ded4c52b89b8a146e157f068e66a3f3325e9f Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:35:55 +0000
Subject: [PATCH 12/22] normalize uploaded filename extension to lowercase for
consistent downstream checks
---
studio/backend/routes/datasets.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index 2357cd2c0e..2faa7121ac 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -296,7 +296,9 @@ def upload_dataset(
raise HTTPException(status_code=400, detail="Empty upload payload")
DATASET_UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
- stored_name = f"{uuid4().hex}_{filename}"
+ # Normalize extension to lowercase so downstream suffix checks work
+ stem = Path(filename).stem
+ stored_name = f"{uuid4().hex}_{stem}{ext}"
stored_path = DATASET_UPLOAD_DIR / stored_name
stored_path.write_bytes(file_bytes)
From c998227fec6d907e6f175aefd662ce1f1ff440da Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:38:00 +0000
Subject: [PATCH 13/22] add client-side file size validation before upload
---
.../src/features/studio/sections/dataset-section.tsx | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index 154999ac5b..b81dd058f6 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -357,6 +357,14 @@ export function DatasetSection() {
event.target.value = "";
if (!file) return;
+ const MAX_SIZE_BYTES = 512 * 1024 * 1024;
+ if (file.size > MAX_SIZE_BYTES) {
+ toast.error("File too large", {
+ description: "Maximum upload size is 512 MB.",
+ });
+ return;
+ }
+
setIsUploading(true);
try {
const contentBase64 = await fileToBase64Payload(file);
From 56412f23625637354e265804fe6ad2d79980271f Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:52:45 +0000
Subject: [PATCH 14/22] include all candidate files when scanning a directory,
not just the first
---
studio/backend/core/training/trainer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/studio/backend/core/training/trainer.py b/studio/backend/core/training/trainer.py
index 41d208d9f4..5e20dfb43f 100644
--- a/studio/backend/core/training/trainer.py
+++ b/studio/backend/core/training/trainer.py
@@ -1819,7 +1819,7 @@ class UnslothTrainer:
for ext in ('.json', '.jsonl', '.csv', '.parquet'):
candidates.extend(sorted(file_path_obj.glob(f"*{ext}")))
if candidates:
- all_files.append(str(candidates[0]))
+ all_files.extend(str(c) for c in candidates)
continue
raise ValueError(f"No supported data files in directory: {file_path_obj}")
else:
From 1d06e2f54cbfd8fbaa407c046647fda95aa22e3a Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 13:55:45 +0000
Subject: [PATCH 15/22] switch dataset upload from base64 JSON to
multipart/form-data with streamed writes
---
studio/backend/models/datasets.py | 6 ---
studio/backend/routes/datasets.py | 41 +++++++++----------
.../studio/sections/dataset-section.tsx | 18 +-------
.../src/features/training/api/datasets-api.ts | 19 +++------
4 files changed, 26 insertions(+), 58 deletions(-)
diff --git a/studio/backend/models/datasets.py b/studio/backend/models/datasets.py
index ca126948bb..49d8b4c419 100644
--- a/studio/backend/models/datasets.py
+++ b/studio/backend/models/datasets.py
@@ -41,12 +41,6 @@ class CheckFormatResponse(BaseModel):
warning: Optional[str] = None
-class UploadDatasetRequest(BaseModel):
- """Request for uploading a local training dataset file."""
- filename: str = Field(..., description="Original filename, e.g. my_data.jsonl")
- content_base64: str = Field(..., description="Base64-encoded file bytes")
-
-
class UploadDatasetResponse(BaseModel):
"""Response with stored dataset path for training."""
filename: str = Field(..., description="Original filename")
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index 2faa7121ac..302ac0aa9d 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -2,13 +2,12 @@
Datasets API routes
"""
import base64
-import binascii
import io
import json
import sys
from pathlib import Path
from uuid import uuid4
-from fastapi import APIRouter, Depends, HTTPException
+from fastapi import APIRouter, Depends, HTTPException, UploadFile
import logging
# Add backend directory to path
@@ -38,7 +37,6 @@ from models.datasets import (
CheckFormatResponse,
LocalDatasetItem,
LocalDatasetsResponse,
- UploadDatasetRequest,
UploadDatasetResponse,
)
@@ -267,22 +265,12 @@ def _sanitize_filename(filename: str) -> str:
return name
-def _decode_base64_payload(content_base64: str) -> bytes:
- raw = content_base64.strip()
- if "," in raw and raw.lower().startswith("data:"):
- raw = raw.split(",", 1)[1]
- try:
- return base64.b64decode(raw, validate=True)
- except binascii.Error as exc:
- raise HTTPException(status_code=400, detail="Invalid base64 payload") from exc
-
-
@router.post("/upload", response_model=UploadDatasetResponse)
-def upload_dataset(
- payload: UploadDatasetRequest,
+async def upload_dataset(
+ file: UploadFile,
current_subject: str = Depends(get_current_subject),
) -> UploadDatasetResponse:
- filename = _sanitize_filename(payload.filename)
+ filename = _sanitize_filename(file.filename or "dataset_upload")
ext = Path(filename).suffix.lower()
if ext not in LOCAL_UPLOAD_EXTS:
allowed = ", ".join(sorted(LOCAL_UPLOAD_EXTS))
@@ -291,16 +279,25 @@ def upload_dataset(
detail=f"Unsupported file type: {ext}. Allowed: {allowed}",
)
- file_bytes = _decode_base64_payload(payload.content_base64)
- if not file_bytes:
- raise HTTPException(status_code=400, detail="Empty upload payload")
-
+ max_size_bytes = 512 * 1024 * 1024
DATASET_UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
- # Normalize extension to lowercase so downstream suffix checks work
stem = Path(filename).stem
stored_name = f"{uuid4().hex}_{stem}{ext}"
stored_path = DATASET_UPLOAD_DIR / stored_name
- stored_path.write_bytes(file_bytes)
+
+ # Stream file to disk in chunks to avoid holding entire file in memory
+ size = 0
+ with open(stored_path, "wb") as f:
+ while chunk := await file.read(1024 * 1024):
+ size += len(chunk)
+ if size > max_size_bytes:
+ stored_path.unlink(missing_ok=True)
+ raise HTTPException(status_code=413, detail="File too large (max 512MB)")
+ f.write(chunk)
+
+ if size == 0:
+ stored_path.unlink(missing_ok=True)
+ raise HTTPException(status_code=400, detail="Empty upload payload")
return UploadDatasetResponse(filename=filename, stored_path=str(stored_path))
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index b81dd058f6..a72c21100a 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -334,18 +334,6 @@ export function DatasetSection() {
hfResults.length,
);
- const fileToBase64Payload = (file: File): Promise =>
- new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () => {
- const value = String(reader.result ?? "");
- const parts = value.split(",");
- resolve(parts.length > 1 ? parts[1] : value);
- };
- reader.onerror = () => reject(new Error("Failed to read file"));
- reader.readAsDataURL(file);
- });
-
const [isUploading, setIsUploading] = useState(false);
const handleUploadButtonClick = () => {
@@ -367,11 +355,7 @@ export function DatasetSection() {
setIsUploading(true);
try {
- const contentBase64 = await fileToBase64Payload(file);
- const uploaded = await uploadTrainingDataset({
- filename: file.name,
- contentBase64,
- });
+ const uploaded = await uploadTrainingDataset(file);
selectLocalDataset(uploaded.stored_path);
diff --git a/studio/frontend/src/features/training/api/datasets-api.ts b/studio/frontend/src/features/training/api/datasets-api.ts
index 0f37ac53bf..f3098acc80 100644
--- a/studio/frontend/src/features/training/api/datasets-api.ts
+++ b/studio/frontend/src/features/training/api/datasets-api.ts
@@ -40,22 +40,15 @@ export async function checkDatasetFormat({
return res.json();
}
-type UploadDatasetArgs = {
- filename: string;
- contentBase64: string;
-};
+export async function uploadTrainingDataset(
+ file: File,
+): Promise {
+ const form = new FormData();
+ form.append("file", file);
-export async function uploadTrainingDataset({
- filename,
- contentBase64,
-}: UploadDatasetArgs): Promise {
const res = await authFetch("/api/datasets/upload", {
method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- filename,
- content_base64: contentBase64,
- }),
+ body: form,
});
if (!res.ok) {
From fbcd111a701ebeabbbec89b51d2bac4ded4066a2 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 14:01:02 +0000
Subject: [PATCH 16/22] narrow stale selection guard to only skip clearing for
uploaded files
---
.../frontend/src/features/studio/sections/dataset-section.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index a72c21100a..576b45610b 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -293,7 +293,7 @@ export function DatasetSection() {
if (!uploadedFile) return;
if (selectedLocalDataset) return;
// Don't clear if this is a direct file upload (not a recipe directory)
- if (isLikelyLocalDatasetRef(uploadedFile)) return;
+ if (uploadedFile.includes("/dataset-uploads/")) return;
selectLocalDataset(null);
}, [
datasetSource,
From c3185d5d981a1170268f1b059bfd47464d9b39f1 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 14:39:49 +0000
Subject: [PATCH 17/22] fix: allow eval-only progress events through worker
callback filter
---
studio/backend/core/training/worker.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index 0475152482..3941b27ab2 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -135,7 +135,9 @@ def run_training_process(
# Wire up progress callback → event_queue
def _on_progress(progress: TrainingProgress):
- if progress.step >= 0 and progress.loss > 0:
+ has_train_loss = progress.step >= 0 and progress.loss > 0
+ has_eval_loss = progress.eval_loss is not None
+ if has_train_loss or has_eval_loss:
event_queue.put({
"type": "progress",
"step": progress.step,
From 2a11e79b8bdbc17df518cf8840384ab9518d3f85 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 15:35:49 +0000
Subject: [PATCH 18/22] fix: restore eval_enabled early signal for subprocess
training
---
studio/backend/core/training/training.py | 3 +++
studio/backend/core/training/worker.py | 8 ++++++++
2 files changed, 11 insertions(+)
diff --git a/studio/backend/core/training/training.py b/studio/backend/core/training/training.py
index cc0124ae83..b4d33d7c35 100644
--- a/studio/backend/core/training/training.py
+++ b/studio/backend/core/training/training.py
@@ -384,6 +384,9 @@ class TrainingBackend:
self.eval_step_history.append(step)
self.eval_enabled = True
+ elif etype == "eval_configured":
+ self.eval_enabled = True
+
elif etype == "status":
self._progress.status_message = event.get("message", "")
self._progress.is_training = True
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index 3941b27ab2..f657b1c77a 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -269,6 +269,14 @@ def run_training_process(
if eval_steps is not None and float(eval_steps) <= 0:
eval_dataset = None
+ # Tell the parent process that eval is configured so the frontend
+ # shows "Waiting for first evaluation step..." instead of "not configured"
+ if eval_dataset is not None:
+ event_queue.put({
+ "type": "eval_configured",
+ "ts": time.time(),
+ })
+
if dataset is None or trainer.should_stop:
if trainer.should_stop:
event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
From 6eba6fff438b0c3b73fd8daf60c5207aa56da093 Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 16:20:00 +0000
Subject: [PATCH 19/22] fix: disable Start Training when eval_steps set without
eval split
---
.../studio/sections/training-section.tsx | 9 ++++++--
.../frontend/src/features/training/index.ts | 1 +
.../src/features/training/lib/validation.ts | 22 +++++++++++--------
3 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/studio/frontend/src/features/studio/sections/training-section.tsx b/studio/frontend/src/features/studio/sections/training-section.tsx
index 6f0297b03f..43cc2f889e 100644
--- a/studio/frontend/src/features/studio/sections/training-section.tsx
+++ b/studio/frontend/src/features/studio/sections/training-section.tsx
@@ -12,6 +12,7 @@ import {
serializeConfigToYaml,
useTrainingActions,
useTrainingConfigStore,
+ validateTrainingConfig,
} from "@/features/training";
import {
Archive04Icon,
@@ -43,7 +44,8 @@ export function TrainingSection() {
const { isStarting, startError, startTrainingRun } = useTrainingActions();
const isIncompatible =
!store.isVisionModel && store.isDatasetImage === true;
- const fileInputRef = useRef(null);
+ const configValidation = validateTrainingConfig(store);
+ const fileInputRef = useRef(null);
const handleFileUpload = (e: React.ChangeEvent) => {
const file = e.target.files?.[0];
@@ -150,7 +152,7 @@ export function TrainingSection() {
data-tour="studio-start"
className="w-full cursor-pointer bg-gradient-to-r from-emerald-500 to-teal-500 text-white hover:from-emerald-600 hover:to-teal-600"
onClick={() => void startTrainingRun()}
- disabled={isStarting || isIncompatible}
+ disabled={isStarting || isIncompatible || !configValidation.ok}
>
{isStarting ? "Starting..." : "Start Training"}
@@ -163,6 +165,9 @@ export function TrainingSection() {
Text model is not compatible with a multimodal dataset. Switch to a vision model or choose a text-only dataset.
)}
+ {!configValidation.ok && configValidation.message && !isIncompatible && (
+ {configValidation.message}
+ )}
{/* Upload / Save / Reset */}
Training Config
diff --git a/studio/frontend/src/features/training/index.ts b/studio/frontend/src/features/training/index.ts
index d2fd4f2e43..9da25f88bb 100644
--- a/studio/frontend/src/features/training/index.ts
+++ b/studio/frontend/src/features/training/index.ts
@@ -11,3 +11,4 @@ export { listLocalModels } from "./api/models-api";
export type { LocalModelInfo } from "./api/models-api";
export type { TrainingPhase } from "./types/runtime";
export { parseYamlConfig, serializeConfigToYaml } from "./lib/yaml-config";
+export { validateTrainingConfig } from "./lib/validation";
diff --git a/studio/frontend/src/features/training/lib/validation.ts b/studio/frontend/src/features/training/lib/validation.ts
index ae89cdaf51..6ca95c4b02 100644
--- a/studio/frontend/src/features/training/lib/validation.ts
+++ b/studio/frontend/src/features/training/lib/validation.ts
@@ -16,18 +16,22 @@ export function validateTrainingConfig(
if (!config.dataset) {
return { ok: false, message: "Select a Hugging Face dataset first." };
}
- return { ok: true, message: null };
- }
-
- if (config.datasetSource === "upload") {
+ } else if (config.datasetSource === "upload") {
if (!config.uploadedFile) {
return { ok: false, message: "Select a local dataset first." };
}
- return { ok: true, message: null };
+ } else {
+ return { ok: false, message: "Unsupported dataset source." };
}
- return {
- ok: false,
- message: "Unsupported dataset source.",
- };
+ // Eval steps requires an eval split to be selected
+ if (config.evalSteps > 0 && !config.datasetEvalSplit) {
+ return {
+ ok: false,
+ message:
+ "Eval Steps is set but no Eval Split is selected. Choose an Eval Split or set Eval Steps to 0.",
+ };
+ }
+
+ return { ok: true, message: null };
}
From 41351e1566fe27bc156c88c7644dd888033b145a Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 16:36:44 +0000
Subject: [PATCH 20/22] fix: split dataset 80/20 when eval split matches train
split
---
studio/backend/core/training/trainer.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/studio/backend/core/training/trainer.py b/studio/backend/core/training/trainer.py
index 22c0f34075..cfc04e572e 100644
--- a/studio/backend/core/training/trainer.py
+++ b/studio/backend/core/training/trainer.py
@@ -1868,7 +1868,8 @@ class UnslothTrainer:
# Resolve eval split from a separate HF split (explicit or auto-detected)
if eval_enabled:
- if eval_split:
+ effective_train = train_split or "train"
+ if eval_split and eval_split != effective_train:
# Explicit eval split provided - load it directly
print(f"Loading explicit eval split: '{eval_split}'\n")
eval_load_kwargs = {"path": dataset_source, "split": eval_split}
@@ -1877,6 +1878,9 @@ class UnslothTrainer:
eval_dataset = load_dataset(**eval_load_kwargs)
has_separate_eval_source = True
print(f"Loaded eval split '{eval_split}' with {len(eval_dataset)} rows\n")
+ elif eval_split and eval_split == effective_train:
+ # Same split as training — will do 80/20 split after formatting
+ print(f"Eval split '{eval_split}' is the same as train split — will split 80/20\n")
else:
# Auto-detect eval split from HF (returns a separate dataset, or None)
eval_dataset = self._auto_detect_eval_split_from_hf(
From ae89101e810124afcd560115be5b9945f81c4c2f Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 16:51:30 +0000
Subject: [PATCH 21/22] Revert "narrow stale selection guard to only skip
clearing for uploaded files"
This reverts commit fbcd111a701ebeabbbec89b51d2bac4ded4066a2.
---
.../frontend/src/features/studio/sections/dataset-section.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index 576b45610b..a72c21100a 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -293,7 +293,7 @@ export function DatasetSection() {
if (!uploadedFile) return;
if (selectedLocalDataset) return;
// Don't clear if this is a direct file upload (not a recipe directory)
- if (uploadedFile.includes("/dataset-uploads/")) return;
+ if (isLikelyLocalDatasetRef(uploadedFile)) return;
selectLocalDataset(null);
}, [
datasetSource,
From 022bafaf92f3f199f2d9b8c009ca7071f0e2e5dc Mon Sep 17 00:00:00 2001
From: Roland Tannous
Date: Mon, 9 Mar 2026 17:06:36 +0000
Subject: [PATCH 22/22] store uploaded datasets under assets/datasets/uploads
instead of ~/.cache
---
studio/backend/routes/datasets.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index 302ac0aa9d..b06fa33942 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -92,11 +92,9 @@ DATA_EXTS = (
)
LOCAL_FILE_EXTS = ('.json', '.jsonl', '.csv', '.parquet')
LOCAL_UPLOAD_EXTS = {".csv", ".json", ".jsonl", ".parquet"}
-DATASET_UPLOAD_DIR = (
- Path.home() / ".cache" / "unsloth" / "training" / "dataset-uploads"
-)
BACKEND_ROOT = Path(__file__).resolve().parents[1]
LOCAL_DATASETS_ROOT = BACKEND_ROOT / "assets" / "datasets"
+DATASET_UPLOAD_DIR = LOCAL_DATASETS_ROOT / "uploads"
def _safe_read_metadata(path: Path) -> dict | None: