Fsezai33 commited on
Commit
2aab1f8
·
verified ·
1 Parent(s): 700ea0b

Explain unsupported GGUF and BitConfig models

Browse files
Files changed (3) hide show
  1. README.md +2 -0
  2. app.py +12 -4
  3. model_manager.py +39 -2
README.md CHANGED
@@ -39,3 +39,5 @@ This MVP intentionally targets standard `transformers` +
39
  - A model must be downloaded before it can be loaded or used.
40
  - Large models may exceed ZeroGPU memory or take a long time to load.
41
  - Remote model code is disabled in this first version for safety and stability.
 
 
 
39
  - A model must be downloaded before it can be loaded or used.
40
  - Large models may exceed ZeroGPU memory or take a long time to load.
41
  - Remote model code is disabled in this first version for safety and stability.
42
+ - GGUF-only, vision, and other non-causal checkpoints are detected and reported
43
+ as unsupported instead of producing an opaque Transformers traceback.
app.py CHANGED
@@ -13,7 +13,12 @@ import spaces
13
  import torch
14
  import gradio as gr
15
 
16
- from model_manager import ModelCache, TransformersCausalLMRuntime, validate_model_id
 
 
 
 
 
17
 
18
 
19
  logging.basicConfig(level=logging.INFO)
@@ -47,8 +52,13 @@ def download_model(model_id: str) -> tuple[str, str]:
47
  try:
48
  model_id = validate_model_id(model_id)
49
  snapshot_path = cache.download(model_id)
 
 
 
 
 
50
  return (
51
- f"Downloaded on CPU: `{model_id}`",
52
  f"Disk cache: ready ({snapshot_path.name}).",
53
  )
54
  except Exception as exc:
@@ -62,7 +72,6 @@ def load_model_on_gpu(model_id: str) -> tuple[str, str, str]:
62
 
63
  try:
64
  model_id = validate_model_id(model_id)
65
- cache.cached_snapshot(model_id) # local-only check; never downloads here
66
  active = runtime.ensure_loaded(model_id)
67
  return (
68
  f"Loaded on ZeroGPU: `{active}`",
@@ -87,7 +96,6 @@ def chat_with_model(
87
 
88
  try:
89
  model_id = validate_model_id(model_id)
90
- cache.cached_snapshot(model_id) # a chat never performs a download
91
  tokens, temp, nucleus = _safe_generation_settings(
92
  max_new_tokens, temperature, top_p
93
  )
 
13
  import torch
14
  import gradio as gr
15
 
16
+ from model_manager import (
17
+ ModelCache,
18
+ TransformersCausalLMRuntime,
19
+ UnsupportedModelError,
20
+ validate_model_id,
21
+ )
22
 
23
 
24
  logging.basicConfig(level=logging.INFO)
 
52
  try:
53
  model_id = validate_model_id(model_id)
54
  snapshot_path = cache.download(model_id)
55
+ try:
56
+ cache.ensure_transformers_checkpoint(model_id)
57
+ status = f"Downloaded on CPU: `{model_id}`"
58
+ except UnsupportedModelError as exc:
59
+ status = f"Downloaded on CPU, but this MVP cannot Load it: {exc}"
60
  return (
61
+ status,
62
  f"Disk cache: ready ({snapshot_path.name}).",
63
  )
64
  except Exception as exc:
 
72
 
73
  try:
74
  model_id = validate_model_id(model_id)
 
75
  active = runtime.ensure_loaded(model_id)
76
  return (
77
  f"Loaded on ZeroGPU: `{active}`",
 
96
 
97
  try:
98
  model_id = validate_model_id(model_id)
 
99
  tokens, temp, nucleus = _safe_generation_settings(
100
  max_new_tokens, temperature, top_p
101
  )
model_manager.py CHANGED
@@ -8,6 +8,7 @@ weights are loaded during Space startup.
8
  from __future__ import annotations
9
 
10
  import gc
 
11
  import logging
12
  import os
13
  import re
@@ -34,6 +35,10 @@ def validate_model_id(model_id: str) -> str:
34
  return normalized
35
 
36
 
 
 
 
 
37
  class ModelCache:
38
  """A dedicated Hugging Face cache for downloaded model snapshots."""
39
 
@@ -70,6 +75,39 @@ class ModelCache:
70
  ) from exc
71
  return Path(snapshot_path)
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  def describe(self, model_id: str) -> str:
74
  """Return a short cache status for the UI."""
75
 
@@ -135,14 +173,13 @@ class TransformersCausalLMRuntime:
135
 
136
  model_id = validate_model_id(model_id)
137
  with self._lock:
 
138
  if self._model is not None and self._model_id == model_id:
139
  return model_id
140
 
141
  # Switching models always releases the old object before reading
142
  # the new checkpoint, keeping the one-model invariant explicit.
143
  self.unload()
144
- snapshot_path = self.cache.cached_snapshot(model_id)
145
-
146
  tokenizer = AutoTokenizer.from_pretrained(
147
  str(snapshot_path),
148
  local_files_only=True,
 
8
  from __future__ import annotations
9
 
10
  import gc
11
+ import json
12
  import logging
13
  import os
14
  import re
 
35
  return normalized
36
 
37
 
38
+ class UnsupportedModelError(RuntimeError):
39
+ """Raised when a repository is outside the MVP's Transformers LM scope."""
40
+
41
+
42
  class ModelCache:
43
  """A dedicated Hugging Face cache for downloaded model snapshots."""
44
 
 
75
  ) from exc
76
  return Path(snapshot_path)
77
 
78
+ def ensure_transformers_checkpoint(self, model_id: str) -> Path:
79
+ """Validate that a cached repo looks like a standard Transformers LM."""
80
+
81
+ snapshot_path = self.cached_snapshot(model_id)
82
+ files = [path for path in snapshot_path.rglob("*") if path.is_file()]
83
+ has_gguf = any(path.name.lower().endswith(".gguf") for path in files)
84
+ has_standard_weights = any(
85
+ path.name.lower().endswith((".safetensors", ".bin", ".pt", ".pth"))
86
+ or path.name.lower() in {"model.safetensors.index.json", "pytorch_model.bin.index.json"}
87
+ for path in files
88
+ )
89
+
90
+ if has_gguf and not has_standard_weights:
91
+ raise UnsupportedModelError(
92
+ "This Space currently supports standard Transformers checkpoints only. "
93
+ "The selected repository contains GGUF/quantized files; use a repo with "
94
+ "safetensors or PyTorch weights, or wait for a GGUF backend."
95
+ )
96
+
97
+ config_path = snapshot_path / "config.json"
98
+ if config_path.is_file():
99
+ try:
100
+ config = json.loads(config_path.read_text(encoding="utf-8"))
101
+ except (OSError, json.JSONDecodeError):
102
+ config = {}
103
+ if config.get("model_type") == "bit":
104
+ raise UnsupportedModelError(
105
+ "The selected repository declares model_type=bit, which is a vision "
106
+ "backbone and not a causal language model."
107
+ )
108
+
109
+ return snapshot_path
110
+
111
  def describe(self, model_id: str) -> str:
112
  """Return a short cache status for the UI."""
113
 
 
173
 
174
  model_id = validate_model_id(model_id)
175
  with self._lock:
176
+ snapshot_path = self.cache.ensure_transformers_checkpoint(model_id)
177
  if self._model is not None and self._model_id == model_id:
178
  return model_id
179
 
180
  # Switching models always releases the old object before reading
181
  # the new checkpoint, keeping the one-model invariant explicit.
182
  self.unload()
 
 
183
  tokenizer = AutoTokenizer.from_pretrained(
184
  str(snapshot_path),
185
  local_files_only=True,