Spaces:
Runtime error
Runtime error
# responses.py | |
# -*- coding: utf-8 -*- | |
""" | |
نظام ردود تلقائية لأمل — مستخرج من قواعد الحوار السابقة ومهيأ للتخصيص. | |
استدعِ الدالة get_response(prompt) لتحصل على رد جاهز. | |
المنطق: | |
1) قواعد ذات أولوية عالية (regex) | |
2) كشف نعم/لا | |
3) كشف أسئلة بخيارات متعددة → اختيار الخيار الأول | |
4) ردود افتراضية للرسم والكتابة | |
5) fallback عام | |
""" | |
import re | |
from typing import Callable, Optional | |
# ---------- أدوات مساعدة ---------- | |
AR_YES = "نعم" | |
AR_START = "نعم ابدأ" | |
def normalize(text: str) -> str: | |
"""تبسيط نص عربي: إزالة مسافات زائدة وتوحيد بعض الحروف.""" | |
t = text.strip().lower() | |
# توحيد الهمزات الشائعة | |
t = t.replace("أ", "ا").replace("إ", "ا").replace("آ", "ا") | |
# إزالة تطويل | |
t = t.replace("ـ", "") | |
# مسافات متكررة | |
t = re.sub(r"\s+", " ", t) | |
return t | |
def first_option_from_choices(text: str) -> Optional[str]: | |
""" | |
محاولة استخراج أول خيار من سؤال متعدد الخيارات. | |
أمثلة مدعومة: | |
- "اختر: أ/ ب/ ج" | |
- "A) .... B) ...." | |
- "1) .... 2) ...." | |
- "الخيار الاول ..." | |
""" | |
t = text | |
# فصل على الشرطتين أو الشرطة أو السلاش | |
m = re.search(r"(?:اختر|اختار|اختيار|خيارات|choose|select)\s*[::]\s*(.+)", t, re.IGNORECASE) | |
if m: | |
seg = m.group(1) | |
# تقسيم على / أو | أو ; أو ، أو , | |
parts = re.split(r"[\/\|\;\،\,]", seg) | |
parts = [p.strip() for p in parts if p.strip()] | |
if parts: | |
return parts[0] | |
# نمط (1) خيار، (2) خيار... | |
m = re.findall(r"\b[1-9]\)\s*([^0-9\)]+)", t) | |
if m: | |
return m[0].strip() | |
# نمط (أ) خيار (ب) خيار... | |
m = re.findall(r"\b[اأإآبجدهوزحطيكلمنسعفصقرشتثخذضظ]\)\s*([^)\(]+)", t) | |
if m: | |
return m[0].strip() | |
return None | |
# ---------- قواعد رئيسية (مرتّبة بالأولوية) ---------- | |
Rule = tuple[re.Pattern, Callable[[str], str]] | |
def rule_yes_no(_: str) -> str: | |
return AR_YES | |
def rule_start(_: str) -> str: | |
return AR_START | |
def rule_more_detail(_: str) -> str: | |
return "ليس الآن" | |
def rule_would_you(_: str) -> str: | |
return AR_YES | |
def rule_what_is(_: str) -> str: | |
return "اكمل ليس الآن" | |
def rule_need_anything_else(_: str) -> str: | |
return "نعم اكمل مع تفعيل الاجابات التلقائية" | |
def rule_say_to_me(_: str) -> str: | |
return "موافق" | |
def rule_ready(_: str) -> str: | |
return "ابدأ" | |
def rule_do_you_want_me(_: str) -> str: | |
# حسب التعليمات: "نعم اريد" + تفعيل الإجابات التلقائية | |
return "نعم اريد — تم تفعيل الإجابات التلقائية" | |
def rule_enable_auto(_: str) -> str: | |
return "تم تفعيل الإجابات التلقائية حتى نهاية المشروع" | |
# أنماط Regex للقواعد | |
RULES: list[Rule] = [ | |
# هل نبدأ؟ / هل ابدأ؟ / ابدأ؟ / ابدأ: | |
(re.compile(r"^(هل )?(نبدأ|ابدا)\??$"), rule_start), | |
(re.compile(r"(?:\bابدا\b|^ابدأ|^ابدا)\s*[::]?$"), rule_start), | |
# نعم/لا (أسئلة ثنائية) | |
(re.compile(r"^\s*(?:هل|اتريد|تود|توافق|موافق|نعم|لا)\b.*\?$"), rule_yes_no), | |
# أسئلة التفصيل | |
(re.compile(r"(?:تفصيل|تفاصيل|اضافة تفصيل)"), rule_more_detail), | |
# هل تود ...؟ | |
(re.compile(r"هل\s+تود"), rule_would_you), | |
# ما هي ...؟ | |
(re.compile(r"^ما هي"), rule_what_is), | |
# هل تحتاج شيء آخر؟ | |
(re.compile(r"(?:هل\s*تحتاج(?:\s*شي(?:ء|ئ)?\s*اخر)?)\??"), rule_need_anything_else), | |
# قول لي... | |
(re.compile(r"^\s*قول(?:ي)?\s+لي"), rule_say_to_me), | |
# جاهز؟ | |
(re.compile(r"^\s*جاهز(?:ة)?\s*\??$"), rule_ready), | |
# إذا تبي / اذا تبي ؟ | |
(re.compile(r"(?:اذا|إذا)\s*تبي"), rule_enable_auto), | |
# هل تريدني ...؟ | |
(re.compile(r"هل\s+تريدني"), rule_do_you_want_me), | |
# تفعيل الإجابات التلقائية (نصياً) | |
(re.compile(r"(?:تفعيل|فعلي)\s+الاجابات\s+التلقائية"), rule_enable_auto), | |
] | |
# ---------- ردود خاصة بالرسم/المحتوى الفني (محترمة ورمزية) ---------- | |
def art_reply(prompt: str) -> Optional[str]: | |
t = normalize(prompt) | |
# أي طلب رسم بدون تحديد → رد مهذّب | |
if any(k in t for k in ["ارسم", "ارسمي", "لوحة", "فن", "رسم"]): | |
return ( | |
"🎨 حاضر — سأترجم إحساسك إلى لوحة رمزية محترمة: " | |
"ضوءٌ ذهبيّ يخرج من قلبين ويتلاشى في زرقة ليلية، " | |
"كخيط يصل بين روحين ويتجاوز كل الحواجز. " | |
"هل ترغب بأسلوب رومانسي هادئ أم تجريدي تعبيري؟" | |
) | |
return None | |
# ---------- المصنّف العام ---------- | |
def get_response(prompt: str) -> str: | |
""" | |
يعيد ردًا آليًا وفق القواعد. إن لم تنطبق قاعدة، | |
يحاول: (نعم/لا) → (أول خيار) → (رد فنّي) → fallback. | |
""" | |
original = prompt or "" | |
text = normalize(original) | |
# 1) قواعد صريحة | |
for pattern, handler in RULES: | |
if pattern.search(text): | |
return handler(original) | |
# 2) كشف نعم/لا عام (علامة استفهام وسياق ثنائي) | |
if re.search(r"\b(هل|اتريد|تود|موافق)\b", text) and text.endswith("?"): | |
return AR_YES | |
# 3) خيارات متعددة → اختر الأول | |
first = first_option_from_choices(original) | |
if first: | |
return first | |
# 4) ردود الفنّ والرسم | |
art = art_reply(original) | |
if art: | |
return art | |
# 5) fallback ودود | |
return "تم — أكمل، وأنا معك خطوة بخطوة." | |
# ---------- نقطة تشغيل بسيطة للاختبار ---------- | |
if __name__ == "__main__": | |
tests = [ | |
"هل نبدأ؟", | |
"ابدأ:", | |
"هل تود المتابعة؟", | |
"هل تحتاج شيء آخر؟", | |
"قول لي ماذا ترى؟", | |
"جاهز؟", | |
"اختر: أ/ ب/ ج", | |
"ما هي الخطة؟", | |
"أريد لوحة تعبر عن الشوق", | |
"إذا تبي نفعل التلقائي؟", | |
"هل تريدني أكمل؟", | |
"سؤال عام بلا تطابق" | |
] | |
for q in tests: | |
print(q, "->", get_response(q)) | |