fugthchat commited on
Commit
2d6102e
·
verified ·
1 Parent(s): fe62b09

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -128
app.py DELETED
@@ -1,128 +0,0 @@
1
- )
2
- answer = result["choices"][0]["message"].get("content") or ""
3
- return {
4
- "answer": answer.strip(),
5
- "task": p.task,
6
- "usage": result.get("usage", {}),
7
- }
8
-
9
- async def inference_worker(app: FastAPI) -> None:
10
- while True:
11
- job: WorkItem = await app.state.queue.get()
12
- try:
13
- if job.future.cancelled():
14
- continue
15
- app.state.active_model = job.model
16
- start = time.perf_counter()
17
- queue_ms = round((start - job.created) * 1000)
18
- engine = app.state.engines[job.model]
19
- generated = await asyncio.to_thread(run_inference, engine, job)
20
- inference_ms = round((time.perf_counter() - start) * 1000)
21
- app.state.completed += 1
22
- if not job.future.done():
23
- job.future.set_result({
24
- "request_id": job.id,
25
- "model": job.model,
26
- "task": generated["task"],
27
- "answer": generated["answer"],
28
- "usage": generated["usage"],
29
- "queue_ms": queue_ms,
30
- "inference_ms": inference_ms,
31
- "total_ms": round((time.perf_counter() - job.created) * 1000),
32
- })
33
- except Exception:
34
- # Never print prompts, context, or full exceptions in production logs.
35
- log.exception("Inference failed for request %s", job.id)
36
- if not job.future.done():
37
- job.future.set_exception(RuntimeError("Inference failed"))
38
- finally:
39
- app.state.active_model = None
40
- app.state.queue.task_done()
41
-
42
- @asynccontextmanager
43
- async def lifespan(app: FastAPI):
44
- app.state.engines = {}
45
- app.state.errors = {}
46
- app.state.queue = asyncio.Queue(maxsize=MAX_QUEUE_SIZE)
47
- app.state.active_model = None
48
- app.state.completed = 0
49
- app.state.default_model = DEFAULT_MODEL
50
- for name in LOAD_MODELS:
51
- try:
52
- app.state.engines[name] = await asyncio.to_thread(load_one, name)
53
- log.info("Model ready: %s", name)
54
- except Exception as exc:
55
- log.exception("Model failed to load: %s", name)
56
- app.state.errors[name] = type(exc).__name__
57
- app.state.worker = asyncio.create_task(inference_worker(app))
58
- try:
59
- yield
60
- finally:
61
- app.state.worker.cancel()
62
- try:
63
- await app.state.worker
64
- except asyncio.CancelledError:
65
- pass
66
-
67
- app = FastAPI(title="MEPLIFEOS / FUGTH AI Gateway", version="1.2.0", lifespan=lifespan)
68
-
69
- def check_secret(provided: str | None, variable: str) -> None:
70
- expected = os.getenv(variable, "")
71
- if not expected:
72
- raise HTTPException(status_code=503, detail=f"Server secret {variable} is not configured")
73
- if not provided or not secrets.compare_digest(provided, expected):
74
- raise HTTPException(status_code=401, detail="Invalid API key")
75
-
76
- def require_client_key(x_api_key: str | None = Header(default=None, alias="X-API-Key")):
77
- check_secret(x_api_key, "FUGTH_API_KEY")
78
-
79
- def require_admin_key(x_admin_key: str | None = Header(default=None, alias="X-Admin-Key")):
80
- check_secret(x_admin_key, "FUGTH_ADMIN_KEY")
81
-
82
- @app.get("/", include_in_schema=False)
83
- def homepage():
84
- return FileResponse("/app/index.html")
85
-
86
- @app.get("/health")
87
- def health():
88
- available = list(app.state.engines)
89
- return {
90
- "ready": bool(available),
91
- "loaded_models": available,
92
- "load_errors": app.state.errors,
93
- "default_model": app.state.default_model,
94
- "queued": app.state.queue.qsize(),
95
- "max_queue_size": MAX_QUEUE_SIZE,
96
- "active_model": app.state.active_model,
97
- "completed_requests": app.state.completed,
98
- "api_key_configured": bool(os.getenv("FUGTH_API_KEY")),
99
- }
100
-
101
- @app.post("/v1/chat", dependencies=[Depends(require_client_key)])
102
- async def chat(payload: ChatRequest):
103
- selected = payload.model or app.state.default_model
104
- if selected not in app.state.engines:
105
- raise HTTPException(503, detail=f"Model {selected} is not loaded")
106
- if app.state.queue.full():
107
- raise HTTPException(429, detail="Inference queue full; retry later", headers={"Retry-After": "15"})
108
- job = WorkItem(payload, selected)
109
- try:
110
- app.state.queue.put_nowait(job)
111
- except asyncio.QueueFull:
112
- raise HTTPException(429, detail="Inference queue full; retry later", headers={"Retry-After": "15"})
113
- try:
114
- return await asyncio.wait_for(job.future, timeout=REQUEST_TIMEOUT)
115
- except asyncio.TimeoutError:
116
- job.future.cancel() # Workers skip queued requests whose clients timed out.
117
- raise HTTPException(504, detail="Generation timed out; try a shorter request")
118
- except RuntimeError:
119
- raise HTTPException(500, detail="Inference failed; check Space logs")
120
- except asyncio.CancelledError:
121
- job.future.cancel()
122
- raise
123
-
124
- @app.post("/admin/default-model", dependencies=[Depends(require_admin_key)])
125
- def change_default(body: DefaultModelRequest):
126
- if body.model not in app.state.engines:
127
- raise HTTPException(503, detail="Requested model is not loaded")
128
- app.state.default_model = body.model