Spaces:
Sleeping
Sleeping
| """ | |
| Beryl Chat API — FastAPI raw inference proxy (Docker Space) | |
| Calls api-inference.huggingface.co directly (resolves inside HF network). | |
| POST /run/predict → { data: [messages_json, model_key] } | |
| """ | |
| import os, json, requests | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import JSONResponse | |
| HF_TOKEN = os.environ.get("HF_TOKEN", "") | |
| # Featherless AI provider via HF Router — resolves everywhere, supports Qwen/Mistral | |
| HF_API = "https://router.huggingface.co/featherless-ai/v1/chat/completions" | |
| HEADERS = {"Authorization": f"Bearer {HF_TOKEN}", "Content-Type": "application/json"} | |
| MODELS = { | |
| "qwen": "Qwen/Qwen2.5-72B-Instruct", | |
| "qwen7b": "Qwen/Qwen2.5-7B-Instruct", | |
| "glm": "Qwen/Qwen2.5-7B-Instruct", | |
| "hermes": "NousResearch/Hermes-3-Llama-3.1-8B", | |
| "auto": "Qwen/Qwen2.5-7B-Instruct", | |
| } | |
| EMOTION_KW = ["feel","lonely","sad","love","companion","miss", | |
| "emotional","relationship","heart","care","hurt"] | |
| app = FastAPI(title="Beryl Chat API") | |
| def route_model(messages: list, model_key: str) -> str: | |
| if model_key and model_key not in ("auto", ""): | |
| return MODELS.get(model_key, MODELS["auto"]) | |
| last = (messages[-1].get("content","") if messages else "").lower() | |
| return MODELS["glm"] if any(k in last for k in EMOTION_KW) else MODELS["auto"] | |
| def do_chat(messages: list, model_key: str) -> dict: | |
| model = route_model(messages, model_key) | |
| payload = { | |
| "model": model, | |
| "messages": messages, | |
| "max_tokens": 600, | |
| "temperature": 0.78, | |
| "stream": False, | |
| } | |
| r = requests.post(HF_API, headers=HEADERS, json=payload, timeout=30) | |
| if r.status_code == 200: | |
| data = r.json() | |
| return { | |
| "response": data["choices"][0]["message"]["content"], | |
| "model": model.split("/")[-1], | |
| "ok": True, | |
| } | |
| # Fallback: try Qwen2.5-7B if primary model unavailable/quota | |
| if r.status_code in (429, 503, 400) and model != MODELS["qwen7b"]: | |
| payload["model"] = MODELS["qwen7b"] | |
| r2 = requests.post(HF_API, headers=HEADERS, json=payload, timeout=30) | |
| if r2.status_code == 200: | |
| data2 = r2.json() | |
| return { | |
| "response": data2["choices"][0]["message"]["content"], | |
| "model": "Qwen2.5-7B-Instruct", | |
| "ok": True, | |
| } | |
| return {"ok": False, "error": f"HTTP {r.status_code}: {r.text[:200]}", "response": ""} | |
| def health(): | |
| return {"ok": True, "version": "1.0.0", "service": "beryl-chat-api"} | |
| async def predict(request: Request): | |
| try: | |
| body = await request.json() | |
| data = body.get("data", []) | |
| messages_json = data[0] if len(data) > 0 else "[]" | |
| model_key = data[1] if len(data) > 1 else "auto" | |
| messages = json.loads(messages_json) | |
| result = do_chat(messages, model_key) | |
| return JSONResponse({"data": [json.dumps(result)]}) | |
| except Exception as e: | |
| err = json.dumps({"ok": False, "error": str(e), "response": ""}) | |
| return JSONResponse({"data": [err]}, status_code=200) | |