Spaces:
Sleeping
Sleeping
File size: 3,651 Bytes
04d834e 2b16a8f 04d834e 102da90 04d834e f90a567 0acb0f4 04d834e 421ec04 04d834e f90a567 0acb0f4 04d834e f90a567 0acb0f4 f90a567 5fc7a0b f90a567 5fc7a0b f90a567 5fc7a0b 04d834e 0acb0f4 04d834e 0acb0f4 f90a567 0acb0f4 f90a567 421ec04 0acb0f4 f926909 79ce28a 8bb8d36 04d834e | 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 87 88 89 90 | import os, time, html
import requests
import gradio as gr
# ---------- Config (set in HF Space → Settings → Secrets) ----------
# If you don't set NGROK_URL in Secrets, we'll use your current tunnel as a fallback.
NGROK_URL = os.environ.get("NGROK_URL", "https://bd8de44dca7e.ngrok-free.app/answer").strip()
BACKEND_TOKEN = os.environ.get("BACKEND_TOKEN", "").strip() # optional: Bearer token
REQUEST_TIMEOUT = float(os.environ.get("REQUEST_TIMEOUT", "30")) # seconds
HEADERS = {"Content-Type": "application/json"}
if BACKEND_TOKEN:
HEADERS["Authorization"] = f"Bearer {BACKEND_TOKEN}"
def _resolve_backend_url(raw: str) -> str:
url = (raw or "").strip().rstrip("/")
if not url:
return ""
if not url.endswith("/answer"):
url = f"{url}/answer"
return url
def _endpoints():
"""Return (answer_url, command_url) from NGROK_URL, tolerant if it already has /answer."""
answer_url = _resolve_backend_url(NGROK_URL)
base = answer_url.rsplit("/", 1)[0] if answer_url.endswith("/answer") else answer_url
command_url = f"{base}/command"
return answer_url, command_url
def _normalize_matches(matches):
out = []
if isinstance(matches, list):
for m in matches:
if isinstance(m, (list, tuple)) and len(m) >= 2:
q = str(m[0]); d = float(m[1])
elif isinstance(m, dict):
q = str(m.get("question") or m.get("q") or m.get("text") or "")
d = float(m.get("distance", m.get("score", 0.0)))
else:
q = str(m); d = 0.0
out.append((q, d))
return out
def chat_handler(message, history, threshold):
answer_url, command_url = _endpoints()
if not answer_url:
return "⚠️ يجب ضبط المتغير السري `NGROK_URL`."
try:
# Slash command → send to /command
if message.strip().startswith("/"):
r = requests.post(command_url, json={"cmd": message}, headers=HEADERS, timeout=REQUEST_TIMEOUT)
r.raise_for_status()
data = r.json() if r.content else {}
return data.get("output", "—")
# Normal question → send to /answer
payload = {"question": message, "threshold": threshold}
t0 = time.time()
r = requests.post(answer_url, json=payload, headers=HEADERS, timeout=REQUEST_TIMEOUT)
r.raise_for_status()
data = r.json() if r.content else {}
answer = data.get("answer") or data.get("message") or "لا توجد إجابة."
# matches = _normalize_matches(data.get("matches", []))
latency = time.time() - t0
# lines = "\n".join([f"{i+1}. \"{q}\" (distance: {d:.4f})" for i, (q, d) in enumerate(matches[:5])])
# ... after we parse `answer` and compute `latency`
md = (
f"**الإجابة**\n\n{answer}\n\n"
f"<sub>زمن الاستجابة: {latency:.2f}s</sub>"
)
return md
except Exception as e:
return f"تعذر الاتصال بالخادم: {e}"
demo = gr.ChatInterface(
fn=chat_handler,
title="نظام الأسئلة والإجابات لجهاز الخدمة المدنية",
description="اكتب سؤالك أو استخدم أوامر مثل: `/datasets`, `/use <name>`, `/train`, `/threshold 0.55`, `/probs : <سؤال>`",
additional_inputs=[gr.Slider(minimum=0.0, maximum=2.0, step=0.1, value=0.6, label="عتبة المسافة")],
)
demo.queue(default_concurrency_limit=8, max_size=32)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", "7860")))
|