Spaces:
Sleeping
Sleeping
File size: 6,815 Bytes
4475ce9 9c2d3fd 4475ce9 b64c583 33b7baa b64c583 9c2d3fd 04821b6 ce9a08b 04821b6 9c2d3fd b64c583 61782d1 9c2d3fd b64c583 ce9a08b 7bc087a 0510a0c 7bc087a ce9a08b b64c583 9c2d3fd 10b836c ce9a08b 10b836c ce9a08b 10b836c ce9a08b 10b836c ce9a08b 10b836c 9c2d3fd ce9a08b 9c2d3fd ce9a08b 9c2d3fd 10b836c 9c2d3fd 10b836c 9c2d3fd b64c583 33b7baa b64c583 9c2d3fd ce9a08b 9c2d3fd 7bc087a 33b7baa 7bc087a 9c2d3fd 33b7baa |
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
import streamlit as st
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import requests
import torch
# =======================
# RTL & UI Styling
# =======================
st.markdown(
"""
<style>
html, body, [class*="css"] {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
.stApp header, h1, h2, h3, h4, h5, h6 {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
.stMarkdown, .stMarkdown p {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
.stTextArea, .stTextInput, .stButton {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
[data-testid="stAlert"], [data-testid="stSpinnerText"] {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
section[data-testid="stSidebar"] {
direction: rtl !important;
text-align: right !important;
font-family: 'Arial', sans-serif !important;
}
</style>
""",
unsafe_allow_html=True
)
# =======================
# Classification Model
# =======================
MODEL_NAME = "imaneumabderahmane/Arabertv02-classifier-FA"
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME)
LABELS = ["LABEL_0", "LABEL_1"]
def classify_question(text):
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
outputs = model(**inputs)
pred = torch.argmax(outputs.logits, dim=1).item()
return LABELS[pred]
# =======================
# LLM first-aid check
# =======================
def llm_first_aid_check(query, api_key):
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
prompt = f"""
هل السؤال التالي يندرج ضمن الإسعافات الأولية؟ أجب فقط بـ "نعم" أو "لا":
{query}
"""
data = {
"model": "mistralai/mistral-7b-instruct",
"messages": [
{"role": "system", "content": "أنت مساعد ذكي عربي يساعد في تصنيف الأسئلة الطبية."},
{"role": "user", "content": prompt}
],
"temperature": 0,
"max_tokens": 10
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
answer = response.json()["choices"][0]["message"]["content"].strip()
return "نعم" in answer
else:
return False
# =======================
# Mistral Response
# =======================
def get_mistral_response(prompt, api_key):
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
few_shot_examples = """
أنت مساعد طبي محترف متخصص في الإسعافات الأولية. أجب دائمًا بنصائح إسعاف أولية واضحة ودقيقة وآمنة، باللغة العربية فقط.
سؤال 1: أصابتني ضربة على عظمة حاجبي الأيسر وحدوث انتفاخ بسيط. وضعت كمادات باردة. ماذا ينبغي أن أفعل أيضًا؟
جواب 1: استمر بوضع كمادات باردة لفترات قصيرة (10–15 دقيقة كل ساعة) لتخفيف الورم. ارفع رأسك عند الاستلقاء لتقليل التورم، وتجنّب الضغط على المنطقة. راقب أي تغيّر في الرؤية، فقدان للوعي، أو تقيؤ — إذا ظهرت أي من هذه الأعراض فراجع الطوارئ فورًا.
سؤال 2: كيف أتعامل مع شخص يتعرض لنوبة صرع؟
جواب 2: أبعد حوله الأشياء الحادة وحافظ على الهدوء. ضع شيئًا ناعمًا تحت رأسه، لا تُقيد حركاته، ولا تضع شيئًا في فمه. بعد انتهاء النوبة، ضع الشخص على جنبه للحفاظ على مجرى الهواء وراقبه حتى يستعيد وعيه. إذا استمرت النوبة أكثر من 5 دقائق أو تكررت، اطلب الإسعاف فورًا.
"""
user_instruction = f"""
سؤال: {prompt}
اكتب الجواب بشكل مختصر ومباشر دون تكرار أو إعادة صياغة.
الجواب:
"""
data = {
"model": "mistralai/mistral-7b-instruct",
"messages": [
{"role": "system", "content": few_shot_examples},
{"role": "user", "content": user_instruction}
],
"temperature": 0.3,
"max_tokens": 512
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"].strip()
else:
return f"⚠️ خطأ من API: {response.text}"
# =======================
# Streamlit UI
# =======================
st.title("المساعد الخاص بالإسعافات الأولية")
api_key = st.text_input("من فضلك أدخل المفتاح الخاص بك:", type="password")
user_input = st.text_area("اكتب سؤالك باللغة العربية:", height=100)
if st.button("اسأل"):
if not api_key:
st.warning("من فضلك أدخل المفتاح الخاص بك")
elif not user_input.strip():
st.warning("من فضلك اكتب سؤالك")
else:
with st.spinner("جارٍ تحليل سؤالك..."):
category = classify_question(user_input)
if category == "LABEL_1":
with st.spinner("جارٍ التحقق من صحة السؤال..."):
is_first_aid = llm_first_aid_check(user_input, api_key)
if is_first_aid:
st.success("تم التأكد من أن السؤال يتعلق بالإسعافات الأولية ✅")
with st.spinner("جارٍ التواصل مع المساعد الذكي..."):
answer = get_mistral_response(user_input, api_key)
st.write("### 💬 الجواب:")
st.write(answer)
else:
st.warning("يبدو أن السؤال لا يتعلق بالإسعافات الأولية ❌")
else:
st.error("عذرًا، يمكنني الإجابة فقط على الأسئلة المتعلقة بالإسعافات الأولية❌") |