qwen2.5api / server.py
vykanand's picture
Fix: lazy model load on first request, add error handling
d240987
Raw
History Blame Contribute Delete
2.81 kB
#!/usr/bin/env python3
import os, sys, time, threading
from pathlib import Path
from fastapi import FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import uvicorn
MODEL_PATH = Path(os.getenv("HOME", "/home/user")) / "models" / os.getenv("MODEL_FILE", "qwen2.5-7b-instruct-q3_k_m.gguf")
MODEL_NAME = os.getenv("SERVED_MODEL_NAME", "qwen")
API_KEY = os.getenv("API_KEY", "")
app = FastAPI(title="Qwen 2.5 API")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True,
allow_methods=["*"], allow_headers=["*"])
llm = None
llm_lock = threading.Lock()
def get_llm():
global llm
if llm is not None:
return llm
with llm_lock:
if llm is not None:
return llm
print(f"Loading model from {MODEL_PATH}...", flush=True)
t0 = time.time()
from llama_cpp import Llama
llm = Llama(
model_path=str(MODEL_PATH),
n_gpu_layers=0,
n_ctx=int(os.getenv("N_CTX", "8192")),
n_threads=int(os.getenv("N_THREADS", "2")),
n_batch=int(os.getenv("N_BATCH", "256")),
n_ubatch=int(os.getenv("N_UBATCH", "128")),
verbose=False,
)
print(f"Model loaded in {time.time()-t0:.1f}s", flush=True)
return llm
class Message(BaseModel):
role: str; content: str
class ChatRequest(BaseModel):
model: str = MODEL_NAME
messages: List[Message]
max_tokens: Optional[int] = 512
temperature: Optional[float] = 0.7
async def check_auth(request: Request):
if API_KEY:
auth = request.headers.get("Authorization", "")
if auth != f"Bearer {API_KEY}":
raise HTTPException(status_code=401, detail="Invalid API key")
@app.get("/")
@app.get("/v1/models")
async def models():
return {"data": [{"id": MODEL_NAME, "object": "model", "owned_by": "local"}]}
@app.get("/health")
async def health():
return {"status": "ok"}
@app.post("/v1/chat/completions")
async def chat(req: ChatRequest, request: Request):
await check_auth(request)
instance = get_llm()
messages = [{"role": m.role, "content": m.content} for m in req.messages]
r = instance.create_chat_completion(
messages=messages, max_tokens=req.max_tokens,
temperature=req.temperature,
)
return {
"id": "chatcmpl-1", "object": "chat.completion",
"model": req.model,
"choices": [{"index": 0, "message": r["choices"][0]["message"],
"finish_reason": r["choices"][0]["finish_reason"]}]
}
if __name__ == "__main__":
print("Starting uvicorn (lazy model load)...", flush=True)
uvicorn.run(app, host="0.0.0.0", port=7860, log_level="info")