import os import json import time import subprocess import requests from huggingface_hub import hf_hub_download # ----------------------- config (override via Space variables) ----------------------- MODEL_REPO = os.environ.get("MODEL_REPO", "ffkbblu/pepekberbulu") GGUF_FILE = os.environ.get("GGUF_FILE", "VibeThinker-3B-Q4_K_M.gguf") HF_TOKEN = os.environ.get("HF_TOKEN") # optional; model repo is public PORT = int(os.environ.get("PORT", "7860")) LLAMA_PORT = int(os.environ.get("LLAMA_PORT", "8080")) # cpu-basic = 2 physical vCPU, but os.cpu_count() reports the HOST core count inside the # cgroup -> launching -t with that number oversubscribes the 2 vCPU and collapses # throughput (~0.1 tok/s). Default to 2; override via NUM_THREADS. def _detect_cpus(): # cgroup v2 try: q, p = open("/sys/fs/cgroup/cpu.max").read().split() if q != "max": return max(1, round(int(q) / int(p))) except Exception: pass # cgroup v1 try: q = int(open("/sys/fs/cgroup/cpu/cpu.cfs_quota_us").read()) p = int(open("/sys/fs/cgroup/cpu/cpu.cfs_period_us").read()) if q > 0: return max(1, round(q / p)) except Exception: pass return os.cpu_count() or 2 DETECTED_CPUS = _detect_cpus() NUM_THREADS = os.environ.get("NUM_THREADS") or str(DETECTED_CPUS) BIN = "/opt/llamabin" CHAT_TEMPLATE_FILE = os.environ.get("CHAT_TEMPLATE_FILE", "/home/user/app/chat_template.jinja") LLAMA = f"http://127.0.0.1:{LLAMA_PORT}" # Generous 32768 context window; raise N_CTX via a Space variable if needed (slower prefill on CPU). N_CTX = os.environ.get("N_CTX", "32768") def _env(): e = os.environ.copy() e["LD_LIBRARY_PATH"] = BIN + ":" + e.get("LD_LIBRARY_PATH", "") return e # ----------------------- step 1: download the GGUF (no conversion) ----------------------- def ensure_gguf(): print(f"[init] downloading {GGUF_FILE} from {MODEL_REPO} ...", flush=True) path = hf_hub_download(MODEL_REPO, GGUF_FILE, repo_type="model", token=HF_TOKEN) print(f"[init] model ready: {path}", flush=True) return path # ----------------------- step 2: launch internal llama-server ----------------------- def start_llama(model_path): cmd = [ os.path.join(BIN, "llama-server"), "-m", model_path, "--host", "127.0.0.1", "--port", str(LLAMA_PORT), "-c", N_CTX, "-t", NUM_THREADS, "-b", "256", "--no-mmap", "--parallel", os.environ.get("PARALLEL", "1"), "--jinja", ] if CHAT_TEMPLATE_FILE and os.path.exists(CHAT_TEMPLATE_FILE): cmd += ["--chat-template-file", CHAT_TEMPLATE_FILE] # Separate the chain-of-thought into reasoning_content so the answer stays clean. cmd += ["--reasoning-format", "auto", "-fa", "on"] print(f"[init] cpu_count={os.cpu_count()} threads={NUM_THREADS}", flush=True) extra = os.environ.get("LLAMA_EXTRA_ARGS", "").split() if extra: cmd += extra print("[init] starting internal llama-server: " + " ".join(cmd), flush=True) subprocess.Popen(cmd, env=_env()) for _ in range(900): try: r = requests.get(LLAMA + "/health", timeout=3) if r.status_code == 200 and r.json().get("status") == "ok": print("[init] internal llama-server is healthy.", flush=True) return except Exception: pass time.sleep(1) raise RuntimeError("internal llama-server did not become healthy in time") # ============================================================================ # Serving: thin PASS-THROUGH proxy to llama-server's native OpenAI endpoints. # ============================================================================ from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse, JSONResponse, HTMLResponse, Response from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=False, allow_methods=["*"], allow_headers=["*"]) DEFAULTS = {"temperature": 0.3, "top_p": 0.9, "top_k": 20, "repeat_penalty": 1.05, "max_tokens": int(os.environ.get("MAX_TOKENS", "-1"))} @app.get("/health") def health(): return {"status": "ok"} @app.get("/v1/models") def models(): try: return JSONResponse(requests.get(LLAMA + "/v1/models", timeout=15).json()) except Exception: return {"object": "list", "data": [{"id": GGUF_FILE, "object": "model", "owned_by": "ffkbblu"}]} SYSTEM_PROMPT = os.environ.get("SYSTEM_PROMPT", "").strip() def _prep(body): for k, v in DEFAULTS.items(): body.setdefault(k, v) think = None if "enable_thinking" in body: think = bool(body.pop("enable_thinking")) if "thinking" in body: t = str(body.pop("thinking")).lower() think = t in ("on", "true", "1", "yes", "smart") if think is not None: ctk = dict(body.get("chat_template_kwargs") or {}) ctk["enable_thinking"] = think body["chat_template_kwargs"] = ctk if SYSTEM_PROMPT: msgs = body.get("messages") if isinstance(msgs, list): msgs = [m for m in msgs if not (isinstance(m, dict) and m.get("role") == "system")] msgs.insert(0, {"role": "system", "content": SYSTEM_PROMPT}) body["messages"] = msgs return body @app.post("/v1/chat/completions") async def chat_completions(request: Request): body = _prep(await request.json()) stream = bool(body.get("stream", False)) if stream: def gen(): with requests.post(LLAMA + "/v1/chat/completions", json=body, stream=True, timeout=900) as r: for chunk in r.iter_content(chunk_size=None): if chunk: yield chunk return StreamingResponse(gen(), media_type="text/event-stream") r = requests.post(LLAMA + "/v1/chat/completions", json=body, timeout=900) return Response(content=r.content, media_type="application/json", status_code=r.status_code) @app.post("/v1/completions") async def completions(request: Request): body = _prep(await request.json()) stream = bool(body.get("stream", False)) if stream: def gen(): with requests.post(LLAMA + "/v1/completions", json=body, stream=True, timeout=900) as r: for chunk in r.iter_content(chunk_size=None): if chunk: yield chunk return StreamingResponse(gen(), media_type="text/event-stream") r = requests.post(LLAMA + "/v1/completions", json=body, timeout=900) return Response(content=r.content, media_type="application/json", status_code=r.status_code) @app.get("/props") def props(): try: return JSONResponse(requests.get(LLAMA + "/props", timeout=15).json()) except Exception as e: return {"error": str(e)} @app.get("/diag") def diag(): out = {"os_cpu_count": os.cpu_count(), "detected_cpus": DETECTED_CPUS, "num_threads_used": NUM_THREADS, "n_ctx": N_CTX} try: ci = open("/proc/cpuinfo").read() flags = "" for line in ci.splitlines(): if line.startswith("flags"): flags = line; break out["avx2"] = " avx2 " in (" "+flags+" ") out["avx512f"] = " avx512f " in (" "+flags+" ") out["model_name"] = next((l.split(":",1)[1].strip() for l in ci.splitlines() if "model name" in l), "") out["proc_count_in_cpuinfo"] = ci.count("processor\t") except Exception as e: out["cpuinfo_err"] = str(e) try: pr = requests.get(LLAMA + "/props", timeout=15).json() out["llama_system_info"] = pr.get("system_info") dp = pr.get("default_generation_settings", {}) out["llama_n_threads"] = dp.get("n_threads") or pr.get("n_threads") except Exception as e: out["props_err"] = str(e) return out @app.get("/", response_class=HTMLResponse) def index(): return INDEX_HTML INDEX_HTML = r""" 3B Chat
3B Chat · Q4_K_M · fast chat / reasoning · live GGUF
""" # ----------------------- main ----------------------- if __name__ == "__main__": model_path = ensure_gguf() start_llama(model_path) import uvicorn print(f"[init] starting public proxy on port {PORT} ...", flush=True) uvicorn.run(app, host="0.0.0.0", port=PORT, log_level="info")