From ed18f9b9dd51d4a4943f8b0cefbe858f0cce7a91 Mon Sep 17 00:00:00 2001 From: Roland Tannous <115670425+rolandtannous@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:35:04 +0400 Subject: [PATCH] Flatten GGUF subdirs in export and fix metadata lookup in scanner --- studio/backend/core/export/export.py | 24 +++++++++++---------- studio/backend/utils/models/model_config.py | 19 ++++++++++------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/studio/backend/core/export/export.py b/studio/backend/core/export/export.py index 39e956eb6f..bc4e267f75 100644 --- a/studio/backend/core/export/export.py +++ b/studio/backend/core/export/export.py @@ -437,17 +437,19 @@ class ExportBackend: shutil.move(src, dest) logger.info(f"Relocated GGUF: {os.path.basename(src)} → {abs_save_dir}/") - # Also check model_save_path for any .gguf files - if os.path.isdir(model_save_path): - for src in glob.glob(os.path.join(model_save_path, "*.gguf")): - dest = os.path.join(abs_save_dir, os.path.basename(src)) - shutil.move(src, dest) - logger.info(f"Relocated GGUF: {os.path.basename(src)} → {abs_save_dir}/") - - # Clean up intermediate HF model files (safetensors, config, etc.) - # since we only need the final .gguf output - shutil.rmtree(model_save_path, ignore_errors=True) - logger.info("Cleaned up intermediate HF model files") + # Flatten any .gguf files from subdirectories into abs_save_dir. + # save_pretrained_gguf may create subdirs (e.g. model_gguf/) + # with a name different from model_save_path. + for sub in list(Path(abs_save_dir).iterdir()): + if not sub.is_dir(): + continue + for src in sub.glob("*.gguf"): + dest = os.path.join(abs_save_dir, src.name) + shutil.move(str(src), dest) + logger.info(f"Relocated GGUF: {src.name} → {abs_save_dir}/") + # Clean up the subdirectory (intermediate HF files, etc.) + shutil.rmtree(str(sub), ignore_errors=True) + logger.info(f"Cleaned up subdirectory: {sub.name}") # Write export metadata so the Chat page can identify the base model self._write_export_metadata(abs_save_dir) diff --git a/studio/backend/utils/models/model_config.py b/studio/backend/utils/models/model_config.py index a37deffff2..8bb9e60ed2 100644 --- a/studio/backend/utils/models/model_config.py +++ b/studio/backend/utils/models/model_config.py @@ -714,13 +714,18 @@ def scan_exported_models(exports_dir: str = "./exports") -> List[Tuple[str, str, elif has_gguf: export_type = "gguf" gguf_list = list(checkpoint_dir.glob("*.gguf")) - export_meta = checkpoint_dir / "export_metadata.json" - try: - if export_meta.exists(): - meta = json.loads(export_meta.read_text()) - base_model = meta.get("base_model") - except Exception: - pass + # Check checkpoint_dir first, then fall back to parent run_dir + # (export.py writes metadata to the top-level export directory) + for meta_dir in (checkpoint_dir, run_dir): + export_meta = meta_dir / "export_metadata.json" + try: + if export_meta.exists(): + meta = json.loads(export_meta.read_text()) + base_model = meta.get("base_model") + if base_model: + break + except Exception: + pass display_name = f"{run_dir.name} / {checkpoint_dir.name}" model_path = str(gguf_list[0]) if gguf_list else str(checkpoint_dir)