Spaces:
Running on Zero
Running on Zero
Commit ·
4fb13be
1
Parent(s): 2d7b7d3
Fix version sort + add GGUF file validation
Browse files
app.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
import os
|
| 2 |
import sys
|
| 3 |
import subprocess
|
|
|
|
| 4 |
|
| 5 |
# =============================================================
|
| 6 |
-
# 1. Bootstrap: Install
|
| 7 |
-
# Versions >= 0.3.20 use "+cpu" tag = zero CUDA dependency
|
| 8 |
# =============================================================
|
| 9 |
def bootstrap_llama_cpp():
|
| 10 |
print("Bootstrapping llama-cpp-python (CPU-only, manylinux)...")
|
|
@@ -15,33 +15,33 @@ def bootstrap_llama_cpp():
|
|
| 15 |
|
| 16 |
py_tag = f"cp{sys.version_info.major}{sys.version_info.minor}"
|
| 17 |
|
| 18 |
-
#
|
| 19 |
-
candidates = [
|
| 20 |
-
|
| 21 |
-
if p.endswith(".whl")
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
if not candidates:
|
| 29 |
-
|
| 30 |
-
candidates = [
|
| 31 |
-
p for p in files
|
| 32 |
-
if p.endswith(".whl")
|
| 33 |
-
and "linux/x86_64/cpu/" in p
|
| 34 |
-
and "/0.3." in p
|
| 35 |
-
and ("py3-none" in p or py_tag in p)
|
| 36 |
-
and "cuda" not in p.lower()
|
| 37 |
-
]
|
| 38 |
-
|
| 39 |
-
# Sort descending to pick latest version
|
| 40 |
-
candidates.sort(reverse=True)
|
| 41 |
-
if not candidates:
|
| 42 |
-
raise RuntimeError("No compatible CPU wheel found!")
|
| 43 |
|
| 44 |
-
chosen = candidates[0]
|
| 45 |
print(f"Selected wheel: {chosen}")
|
| 46 |
whl_path = hf_hub_download("AIencoder/llama-cpp-wheels", chosen, repo_type="dataset")
|
| 47 |
subprocess.check_call([
|
|
@@ -51,7 +51,6 @@ def bootstrap_llama_cpp():
|
|
| 51 |
|
| 52 |
try:
|
| 53 |
from llama_cpp import Llama
|
| 54 |
-
# Verify it actually loads (catches CUDA linkage errors)
|
| 55 |
print("llama-cpp-python already available.")
|
| 56 |
except (ImportError, RuntimeError, OSError):
|
| 57 |
bootstrap_llama_cpp()
|
|
@@ -63,11 +62,27 @@ from fastapi import FastAPI, HTTPException, Header
|
|
| 63 |
import gradio as gr
|
| 64 |
|
| 65 |
# =============================================================
|
| 66 |
-
# 2. Load GGUF Model
|
| 67 |
# =============================================================
|
| 68 |
MODEL_PATH = "Qwen3.5-0.8B.Q4_K_M.gguf"
|
| 69 |
API_KEY = os.getenv("API_KEY", "commitcon-secret-2026")
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
print(f"Loading {MODEL_PATH} via llama-cpp-python ...")
|
| 72 |
llm = Llama(
|
| 73 |
model_path=MODEL_PATH,
|
|
|
|
| 1 |
import os
|
| 2 |
import sys
|
| 3 |
import subprocess
|
| 4 |
+
import re
|
| 5 |
|
| 6 |
# =============================================================
|
| 7 |
+
# 1. Bootstrap: Install latest prebuilt CPU-only llama-cpp-python
|
|
|
|
| 8 |
# =============================================================
|
| 9 |
def bootstrap_llama_cpp():
|
| 10 |
print("Bootstrapping llama-cpp-python (CPU-only, manylinux)...")
|
|
|
|
| 15 |
|
| 16 |
py_tag = f"cp{sys.version_info.major}{sys.version_info.minor}"
|
| 17 |
|
| 18 |
+
# Collect all CPU wheels for linux x86_64, version 0.3.x
|
| 19 |
+
candidates = []
|
| 20 |
+
for p in files:
|
| 21 |
+
if not p.endswith(".whl"):
|
| 22 |
+
continue
|
| 23 |
+
if "linux/x86_64/cpu/" not in p:
|
| 24 |
+
continue
|
| 25 |
+
if "cuda" in p.lower():
|
| 26 |
+
continue
|
| 27 |
+
if py_tag not in p and "py3-none" not in p:
|
| 28 |
+
continue
|
| 29 |
+
# Extract version number
|
| 30 |
+
m = re.search(r"/0\.3\.(\d+)/", p)
|
| 31 |
+
if not m:
|
| 32 |
+
continue
|
| 33 |
+
minor = int(m.group(1))
|
| 34 |
+
if minor < 20: # Need >= 0.3.20 for Qwen3.5 support
|
| 35 |
+
continue
|
| 36 |
+
candidates.append((minor, p))
|
| 37 |
+
|
| 38 |
+
# Sort by version number descending → pick latest
|
| 39 |
+
candidates.sort(key=lambda x: x[0], reverse=True)
|
| 40 |
|
| 41 |
if not candidates:
|
| 42 |
+
raise RuntimeError("No compatible CPU wheel found for >= 0.3.20!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
chosen = candidates[0][1]
|
| 45 |
print(f"Selected wheel: {chosen}")
|
| 46 |
whl_path = hf_hub_download("AIencoder/llama-cpp-wheels", chosen, repo_type="dataset")
|
| 47 |
subprocess.check_call([
|
|
|
|
| 51 |
|
| 52 |
try:
|
| 53 |
from llama_cpp import Llama
|
|
|
|
| 54 |
print("llama-cpp-python already available.")
|
| 55 |
except (ImportError, RuntimeError, OSError):
|
| 56 |
bootstrap_llama_cpp()
|
|
|
|
| 62 |
import gradio as gr
|
| 63 |
|
| 64 |
# =============================================================
|
| 65 |
+
# 2. Verify & Load GGUF Model
|
| 66 |
# =============================================================
|
| 67 |
MODEL_PATH = "Qwen3.5-0.8B.Q4_K_M.gguf"
|
| 68 |
API_KEY = os.getenv("API_KEY", "commitcon-secret-2026")
|
| 69 |
|
| 70 |
+
# Diagnostic: check if file exists and is real (not LFS pointer)
|
| 71 |
+
if not os.path.exists(MODEL_PATH):
|
| 72 |
+
raise FileNotFoundError(f"Model file {MODEL_PATH} not found in /app/")
|
| 73 |
+
|
| 74 |
+
file_size = os.path.getsize(MODEL_PATH)
|
| 75 |
+
print(f"Model file size: {file_size / 1e6:.1f} MB")
|
| 76 |
+
|
| 77 |
+
if file_size < 1_000_000: # < 1MB means it's an LFS pointer, not the real file
|
| 78 |
+
with open(MODEL_PATH, "r", errors="ignore") as f:
|
| 79 |
+
content = f.read(200)
|
| 80 |
+
raise RuntimeError(
|
| 81 |
+
f"Model file is only {file_size} bytes — likely a Git LFS pointer, not the real weights.\n"
|
| 82 |
+
f"File content: {content}\n"
|
| 83 |
+
f"Fix: Re-upload the .gguf file using the Hugging Face web UI (Files tab → Add file → Upload)."
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
print(f"Loading {MODEL_PATH} via llama-cpp-python ...")
|
| 87 |
llm = Llama(
|
| 88 |
model_path=MODEL_PATH,
|