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: