23v commited on
Commit
4117f63
·
verified ·
1 Parent(s): 01c4919

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -218
app.py DELETED
@@ -1,218 +0,0 @@
1
- from __future__ import annotations
2
- import glob
3
- import os
4
- import subprocess
5
- import time
6
-
7
- from fastapi import Request
8
- from fastapi.responses import StreamingResponse
9
- from gradio import Server
10
- import httpx
11
-
12
- app = Server()
13
-
14
- try:
15
- import spaces
16
- HAS_SPACES = True
17
- except ImportError:
18
- HAS_SPACES = False
19
-
20
- @spaces.GPU if HAS_SPACES else lambda f: f
21
- def whygpu():
22
- pass
23
-
24
-
25
- def build_latest_llama_server():
26
- binary_path = os.path.abspath("llama.cpp/build/bin/llama-server")
27
- if os.path.exists(binary_path):
28
- return binary_path
29
-
30
- print("Building latest llama.cpp from master source...")
31
-
32
- if not os.path.exists("llama.cpp"):
33
- subprocess.run(["git", "clone", "https://github.com/unslothai/llama.cpp.git"], check=True)
34
- else:
35
- subprocess.run(["git", "pull"], cwd="llama.cpp", check=True)
36
-
37
- # NOTE: no longer fetching/checking out the "mtp" branch (pull/144) here.
38
- # That branch was specific to Qwen3.8-Flash-Next's MTP support and has
39
- # nothing to do with GLM-5.3-Flash's architecture (glm5next). Keeping it
40
- # would make llama.cpp fail to load this model. unslothai/llama.cpp's
41
- # default branch already carries GLM-5.3-Flash support (PR ggml-org#27754
42
- # is merged into their regular mix builds), so a plain clone/pull is
43
- # enough. Everything else below is unchanged from your original.
44
-
45
- env = os.environ.copy()
46
- if "/usr/local/cuda/bin" not in env.get("PATH", ""):
47
- env["PATH"] = f"/usr/local/cuda/bin:{env.get('PATH', '')}"
48
-
49
- cmake_cmd = [
50
- "cmake",
51
- "-B",
52
- "build",
53
- "-DCMAKE_BUILD_TYPE=Release",
54
- "-DGGML_NATIVE=ON",
55
- "-DGGML_OPENMP=ON",
56
- "-DGGML_AVX512=ON",
57
- ]
58
-
59
- subprocess.run(cmake_cmd, cwd="llama.cpp", env=env, check=True)
60
- subprocess.run(
61
- ["cmake", "--build", "build", "--config", "Release", "-j", str(os.cpu_count() or 4), "--target", "llama-server"],
62
- cwd="llama.cpp",
63
- env=env,
64
- check=True,
65
- )
66
-
67
- if not os.path.exists(binary_path):
68
- raise RuntimeError("Failed to build llama-server binary!")
69
-
70
- return binary_path
71
-
72
-
73
- # ---------------------------------------------------------------------------
74
- # Model: GLM-5.3-Flash (Z.ai), GGUF build by unsloth.
75
- #
76
- # Why this model: as of the strongest *practically self-hostable* open-weight
77
- # agent model with an MIT license is GLM-5.3-Flash (320B total / 18B active,
78
- # natively multimodal, hybrid sparse+linear attention). It leads open-weight
79
- # results on agentic/coding benchmarks (Terminal-Bench 2.1, DeepSWE,
80
- # Toolathlon-Verified) and is reported to approach Claude Opus 4.8 on
81
- # coding/agentic tasks. Moonshot's Kimi K3 (2.8T) currently benchmarks a
82
- # notch higher, but needs ~600GB+ of RAM/VRAM even at its smallest quant —
83
- # not realistic for a single-GPU Space, so it isn't used here.
84
- #
85
- # QUANT: pick the smallest quant that fits your box. Sizes (unsloth Dynamic
86
- # GGUF): UD-IQ1_S ≈93GB, UD-IQ1_M ≈98GB, UD-IQ2_XXS ≈102GB, UD-Q2_K_XL ≈109GB,
87
- # UD-Q3_K_XL ≈148GB, UD-Q4_K_XL ≈200GB. Even the smallest quant will not fit
88
- # on a free/ZeroGPU Space's default disk — you need a machine with enough
89
- # disk + RAM (llama.cpp can stream/offload experts to CPU RAM and disk, it
90
- # doesn't all need to be in VRAM, but it does need to fit somewhere).
91
- # ---------------------------------------------------------------------------
92
- MODEL_REPO = "unsloth/GLM-5.3-Flash-GGUF"
93
- MODEL_QUANT = "UD-IQ1_S" # smallest available quant; raise if you have the disk/RAM
94
-
95
-
96
- def download_model_shards(repo_id: str, quant_dir: str) -> str:
97
- """Downloads every shard of a (possibly multi-part) GGUF quant and
98
- returns the path to the first shard, which is what llama-server needs
99
- (it auto-discovers the rest of the shards next to it)."""
100
- from huggingface_hub import snapshot_download
101
-
102
- local_dir = snapshot_download(
103
- repo_id=repo_id,
104
- allow_patterns=[f"{quant_dir}/*"],
105
- )
106
- shard_dir = os.path.join(local_dir, quant_dir)
107
- shards = sorted(glob.glob(os.path.join(shard_dir, "*-00001-of-*.gguf")))
108
- if not shards:
109
- # not sharded — just one file in the folder
110
- shards = sorted(glob.glob(os.path.join(shard_dir, "*.gguf")))
111
- if not shards:
112
- raise RuntimeError(f"No GGUF files found under {shard_dir}")
113
- return shards[0]
114
-
115
-
116
- def download_mmproj(repo_id: str) -> str:
117
- """GLM-5.3-Flash is natively multimodal; grab the F16 mmproj file so
118
- image input works with -mm, same as your original -mm usage."""
119
- from huggingface_hub import hf_hub_download
120
-
121
- return hf_hub_download(repo_id=repo_id, filename="mmproj-F16.gguf")
122
-
123
-
124
- def start_llama_server():
125
- binary_path = build_latest_llama_server()
126
-
127
- model_path = download_model_shards(MODEL_REPO, MODEL_QUANT)
128
- mmproj_path = download_mmproj(MODEL_REPO)
129
- # No separate draft_path/-md here: unlike Qwen3.8-Flash-Next, GLM-5.3-Flash
130
- # doesn't ship (or need) a separate MTP draft GGUF - MTP is built into the
131
- # main file via the llama.cpp PR mentioned above. There is no matching
132
- # file to download from the repo, so the old draft_path download and the
133
- # (already-commented-out) "-md" flag are simply gone rather than pointing
134
- # at a file that doesn't exist.
135
-
136
- binary_dir = os.path.dirname(os.path.abspath(binary_path))
137
- env = os.environ.copy()
138
- env["LD_LIBRARY_PATH"] = f"{binary_dir}:{env.get('LD_LIBRARY_PATH', '')}"
139
-
140
- cmd = [
141
- binary_path,
142
- "-m", model_path,
143
- "-mm", mmproj_path,
144
- "--port", "8000",
145
- "--host", "127.0.0.1",
146
- "-t", "16",
147
- "-tb", "16",
148
- "-fa", "on",
149
- "--parallel", "1",
150
- "--load-mode", "dio",
151
- # "--cache-type-k", "q4_0",
152
- # "--cache-type-v", "q4_0",
153
- "--jinja",
154
- "--temp", "1.0",
155
- "--top-p", "0.95",
156
- "--top-k", "20",
157
- "--min-p", "0.0",
158
- "--presence-penalty", "0.0",
159
- "--repeat-penalty", "1.0",
160
- ]
161
-
162
- process = subprocess.Popen(cmd, env=env)
163
- time.sleep(5)
164
- return process
165
-
166
-
167
- @app.middleware("http")
168
- async def proxy_middleware(request: Request, call_next):
169
- path = request.url.path
170
- if path.startswith("/gradio_api"):
171
- return await call_next(request)
172
-
173
- url = f"http://127.0.0.1:8000{path}"
174
-
175
- headers = {
176
- k: v for k, v in request.headers.items()
177
- if k.lower() not in ("host", "content-length", "accept-encoding")
178
- }
179
- body = await request.body()
180
-
181
- client = httpx.AsyncClient(timeout=httpx.Timeout(600.0, connect=120.0))
182
- req = client.build_request(
183
- method=request.method,
184
- url=url,
185
- headers=headers,
186
- params=request.query_params,
187
- content=body,
188
- )
189
-
190
- try:
191
- response = await client.send(req, stream=True)
192
- except Exception as e:
193
- await client.aclose()
194
- return StreamingResponse(iter([f"Proxy Error: {e}".encode()]), status_code=502)
195
-
196
- async def stream_and_close():
197
- try:
198
- async for chunk in response.aiter_raw():
199
- yield chunk
200
- finally:
201
- await response.aclose()
202
- await client.aclose()
203
-
204
- res_headers = {
205
- k: v for k, v in response.headers.items()
206
- if k.lower() not in ("content-length", "transfer-encoding", "connection")
207
- }
208
-
209
- return StreamingResponse(
210
- stream_and_close(),
211
- status_code=response.status_code,
212
- headers=res_headers,
213
- )
214
-
215
-
216
- if __name__ == "__main__":
217
- start_llama_server()
218
- app.launch(show_error=True)