Spaces:
Sleeping
Sleeping
File size: 3,220 Bytes
9398426 b245453 9398426 b245453 d1ceaf4 9398426 419498a b245453 9398426 b245453 419498a 9398426 d1ceaf4 9398426 d1ceaf4 9398426 d1ceaf4 b245453 9398426 d1ceaf4 b245453 419498a b245453 9398426 d1ceaf4 9398426 d1ceaf4 b245453 d1ceaf4 b245453 d1ceaf4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | """
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": ""}
@app.get("/health")
def health():
return {"ok": True, "version": "1.0.0", "service": "beryl-chat-api"}
@app.post("/predict")
@app.post("/run/predict")
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)
|