logic65 commited on
Commit
d3c524a
·
verified ·
1 Parent(s): 35b139d

Small files from the Hub, shards from the mount (size-checked); drop flash-linear-attention (no GPU at import on ZeroGPU)

Browse files
Files changed (2) hide show
  1. app.py +27 -3
  2. requirements.txt +0 -1
app.py CHANGED
@@ -1,9 +1,10 @@
1
  """Chat with Whittle-Qwen-3.8-45B-A3B on ZeroGPU.
2
 
3
- The model repo is mounted read-only at /models/w45 (no 90 GB download into the Space). The 35 B body runs on a full
4
  RTX PRO 6000 (xlarge); the 10 B n-gram table stays in CPU memory, as with llama.cpp's `-ot per_layer_token_embd=CPU`.
5
  """
6
  import os
 
7
  import threading
8
 
9
  import spaces # must come before torch/CUDA use on ZeroGPU
@@ -15,8 +16,31 @@ from whittle_load import load_whittle
15
 
16
  REPO = "logic65/Whittle-Qwen-3.8-45B-A3B"
17
  MOUNT = "/models/w45"
18
- SOURCE = MOUNT if os.path.isfile(os.path.join(MOUNT, "config.json")) else REPO
19
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  tokenizer = AutoTokenizer.from_pretrained(SOURCE)
21
  model = load_whittle(SOURCE, dtype=torch.bfloat16, device_map="cuda").eval()
22
 
 
1
  """Chat with Whittle-Qwen-3.8-45B-A3B on ZeroGPU.
2
 
3
+ The model repo is mounted read-only at /models/w45 (no 90 GB download into the Space); small files come from the Hub. The 35 B body runs on a full
4
  RTX PRO 6000 (xlarge); the 10 B n-gram table stays in CPU memory, as with llama.cpp's `-ot per_layer_token_embd=CPU`.
5
  """
6
  import os
7
+ import shutil
8
  import threading
9
 
10
  import spaces # must come before torch/CUDA use on ZeroGPU
 
16
 
17
  REPO = "logic65/Whittle-Qwen-3.8-45B-A3B"
18
  MOUNT = "/models/w45"
19
+ LOCAL = "/tmp/w45"
20
+
21
+
22
+ def prepare_local_dir() -> str:
23
+ """Small files (config, index, tokenizer, template) come straight from the Hub; the weight shards are read from the
24
+ read-only mount through symlinks, after checking every shard's size on the mount against the Hub."""
25
+ from huggingface_hub import HfApi, hf_hub_download
26
+ files = {f.path: f.size for f in HfApi().list_repo_tree(REPO) if "/" not in f.path and getattr(f, "size", None) is not None}
27
+ os.makedirs(LOCAL, exist_ok=True)
28
+ for name, size in sorted(files.items()):
29
+ dst = os.path.join(LOCAL, name)
30
+ if name.endswith(".safetensors"):
31
+ src = os.path.join(MOUNT, name)
32
+ got = os.path.getsize(src) if os.path.exists(src) else None
33
+ print(f"[mount] {name}: Hub {size:,} B, mount {got if got is None else f'{got:,} B'}", flush=True)
34
+ if got != size:
35
+ raise RuntimeError(f"{name} on the mount does not match the Hub ({got} vs {size} bytes)")
36
+ if not os.path.lexists(dst):
37
+ os.symlink(src, dst)
38
+ elif not name.endswith((".md", ".svg", ".py")) and name != ".gitattributes":
39
+ shutil.copy(hf_hub_download(REPO, name), dst)
40
+ return LOCAL
41
+
42
+
43
+ SOURCE = prepare_local_dir()
44
  tokenizer = AutoTokenizer.from_pretrained(SOURCE)
45
  model = load_whittle(SOURCE, dtype=torch.bfloat16, device_map="cuda").eval()
46
 
requirements.txt CHANGED
@@ -3,4 +3,3 @@ transformers>=5.18.0
3
  accelerate
4
  safetensors
5
  huggingface_hub>=1.0
6
- flash-linear-attention==0.5.2
 
3
  accelerate
4
  safetensors
5
  huggingface_hub>=1.0