Spaces:
Runtime error
Runtime error
File size: 6,995 Bytes
905fa58 |
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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# 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))
|