sosa123454321's picture
Add one-click Google Colab RAG notebook
a247836 verified
Raw
History Blame Contribute Delete
7.68 kB
"""
دستیار بالینی پروتکل تشخیص دوگانه — اپ Gradio
اسپیس هاشینگ‌فیس. رابط چت + API قابل صدا زدن + جمع‌آوری بازخورد.
اجرا: python app.py (یا به‌صورت Space روی هاشینگ‌فیس بالا می‌آید)
"""
from __future__ import annotations
import logging
import os
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
log = logging.getLogger("app")
import config
from rag import retriever, pipeline, store
from monitoring.risk_engine import assess as assess_risk
from integrations import firebase_store
# ---------- آماده‌سازی ایندکس ----------
def ensure_index():
if store.exists():
log.info("ایندکس آماده پیدا شد.")
return
log.info("ایندکس موجود نیست؛ در حال ساخت...")
from scripts import build_index
build_index.main()
ensure_index()
# ---------- تابع اصلی (هم API و هم رابط چت) ----------
def answer(question: str):
"""سؤال بالینی را پاسخ می‌دهد. این تابع به‌صورت API هم در دسترس است.
Args:
question: سؤال کاربر به فارسی.
Returns:
(پاسخ، منابع، متادیتا)
"""
question = (question or "").strip()
if not question:
return "لطفاً سؤال خود را بنویسید.", "", {}
res = pipeline.answer(question)
src_lines = "\n".join(f"- {s['source']} (نوع: {s['type']}، شباهت: {s['score']})"
for s in res["sources"])
meta = {
"method": res["method"],
"num_sources": len(res["sources"]),
"latency": res["latency"],
}
return res["answer"], src_lines, meta
def save_feedback(question: str, answer_text: str, rating: int, comment: str):
path = pipeline.add_feedback(question or "", answer_text or "", rating, comment or "")
return f"✅ بازخورد ذخیره شد (فایل: {os.path.basename(path)}). از شما ممنونیم!"
def risk_api(patient_ref, psychosis, suicide, violence, withdrawal, substance_use, sleep_loss, nonadherence):
"""پایش خطر روزانه/هفتگی؛ patient_ref پیش از ذخیره هش می‌شود."""
result = assess_risk(dict(psychosis=psychosis, suicide=suicide, violence=violence,
withdrawal=withdrawal, substance_use=substance_use,
sleep_loss=sleep_loss, nonadherence=nonadherence))
if firebase_store.enabled() and (patient_ref or "").strip():
try:
result["firebaseAssessmentId"] = firebase_store.save_assessment(patient_ref.strip(), result)
result["storage"] = "firestore"
except Exception as exc:
log.exception("خطای ذخیره Firebase")
result["storageWarning"] = str(exc)
else:
result["storage"] = "disabled"
return result
# ---------- رابط کاربری ----------
import gradio as gr
CSS = """
.gradio-container {max-width: 920px !important; font-family: 'Vazirmatn', Tahoma, sans-serif;}
.title {text-align:center;}
.source-box {background:#ecf6f6; border:1px solid #d8e6e6; border-radius:10px; padding:10px;}
"""
with gr.Blocks(title="دستیار پروتکل تشخیص دوگانه", css=CSS, theme=gr.themes.Soft()) as demo:
gr.Markdown(
"# ⚕️ دستیار بالینی پروتکل تشخیص دوگانه\n"
"سایکوز / اسکیزوفرنی + اختلال مصرف مواد + BPD ± ADHD — مبتنی بر شواهد علمی "
"NICE · APA · WFSBP.\n\n"
"⚠️ این ابزار جایگزین مشاوره پزشک نیست؛ تصمیم نهایی درمان با پزشک معالج است.",
elem_classes=["title"])
with gr.Tab("💬 پرسش و پاسخ"):
q_in = gr.Textbox(label="سؤال خود را بنویسید", lines=2,
placeholder="مثلاً: کلوزاپین چه زمانی تجویز می‌شود؟")
with gr.Row():
btn = gr.Button("🩺 پاسخ بده", variant="primary")
ans_out = gr.Markdown(label="پاسخ")
src_out = gr.Markdown(label="منابع بازیابی‌شده", visible=True)
meta_out = gr.JSON(label="متادیتا (روش/تأخیر)")
btn.click(answer, inputs=q_in, outputs=[ans_out, src_out, meta_out])
q_in.submit(answer, inputs=q_in, outputs=[ans_out, src_out, meta_out])
gr.Markdown("#### 📝 ثبت بازخورد (برای آموزش بهتر مدل)")
with gr.Row():
rating = gr.Slider(1, 5, value=4, step=1, label="امتیاز پاسخ")
comment = gr.Textbox(label="توضیح", lines=1)
fb_btn = gr.Button("ثبت بازخورد")
fb_out = gr.Markdown()
fb_btn.click(save_feedback, inputs=[q_in, ans_out, rating, comment], outputs=fb_out)
with gr.Tab("📈 پایش خطر"):
gr.Markdown("### پایش روزانه یا هفتگی\nهر شاخص را از ۰ (ندارد) تا ۴ (شدید) ثبت کنید. این ابزار **دارو را خودکار تغییر نمی‌دهد**.")
patient_ref = gr.Textbox(label="کد داخلی بیمار (نام و کد ملی وارد نشود)", type="password")
labels = ["روان‌پریشی", "خودکشی", "خشونت", "ترک ماده", "مصرف ماده", "کم‌خوابی", "عدم پایبندی"]
sliders = [gr.Slider(0, 4, 0, step=1, label=x) for x in labels]
risk_btn = gr.Button("محاسبه و پیشنهاد سطح اقدام", variant="primary")
risk_out = gr.JSON(label="گزارش خطر")
risk_btn.click(risk_api, inputs=[patient_ref, *sliders], outputs=risk_out, api_name="risk")
with gr.Tab("📚 درباره پایگاه دانش"):
gr.Markdown(
"این سیستم از روی **پروتکل درمان تشخیص دوگانه**، **مقالات علمی**، "
"**سابقه بیمار** و **بازخورد کاربران** پاسخ می‌سازد.\n\n"
"- فایل‌های مقاله را در `data/articles/` \n"
"- سابقه بیمار را در `data/patient_history/` \n"
"- بازخوردها در `data/feedback/` قرار دهید و سپس ایندکس را بازسازی کنید.\n\n"
"مدل امبدینگ: چندزبانه (MiniLM). مدل مولد: سبک روی CPU رایگان. "
"اگر مدل مولد در دسترس نباشد، سیستم به‌صورت استخراجی از متن مرجع پاسخ می‌دهد."
)
with gr.Tab("🔌 API"):
gr.Markdown(
"### نحوه‌ی استفاده از API\n"
"این اپ به‌صورت خودکار یک REST API ارائه می‌دهد. مثال پایتون:\n"
"```python\n"
"from gradio_client import Client\n"
"c = Client(\"<این-اسپیس>\")\n"
"ans, sources, meta = c.predict(question=\"کلوزاپین چه زمانی؟\", api_name=\"/answer\")\n"
"print(ans)\n"
"```\n"
"همچنین می‌توانید به‌صورت POST به `/call/answer` درخواست بزنید."
)
# مونتاژ روی ۰.۰.۰.۰ برای پیش‌نمایش زنده
if __name__ == "__main__":
demo.queue().launch(server_name="0.0.0.0", server_port=int(os.getenv("PORT", "7860")),
share=os.getenv("GRADIO_SHARE", "0") == "1")