ADKBase / app.py
Mr-Help's picture
Update app.py
f4c9eff verified
raw
history blame
9.01 kB
import openai
import os
from dotenv import load_dotenv, dotenv_values
from fastapi import FastAPI, Request
from pydantic import BaseModel
from fastapi.responses import RedirectResponse, HTMLResponse
from fastapi.responses import JSONResponse
import urllib.parse
import requests
# Load environment variables (assuming your API key is stored in a `.env` file)
load_dotenv()
api_key = os.environ.get('HUGGINGFACEHUB_API_TOKEN')
# OpenAI API configuration (specific to Meta-Llama-3-8B)
model_link = "meta-llama/Meta-Llama-3-8B-Instruct"
base_url = "https://router.huggingface.co/v1"
app = FastAPI()
class Message(BaseModel):
message: str
@app.get("/", response_class=HTMLResponse)
async def read_root():
return """Welcome to Up to 12 Chat Processor"""
@app.post("/processtext")
async def receive_updates(request: Request):
data = await request.json()
print("Received Update:", data)
result = process_text(data.get("message", ""))
print("Assistant:", result)
# ضمان إن الرجوع JSON دايمًا
return JSONResponse(content=result)
import re
INTENTS = {
"GREETING": "تحية/بداية محادثة",
"COURSES_MENU": "طلب قائمة الكورسات",
"COURSE_TYPE_DETAILS": "سؤال عن نوع كورس محدد",
"CENTER_INFO": "سؤال عن المركز",
"CHILDREN_COURSES": "كورس أطفال",
"ONLINE_COURSES": "كورسات أونلاين",
"WEEKEND_COURSES": "كورسات ويكند",
"HUMAN_AGENT": "طلب خدمة عملاء/موظف",
"OTHER": "غير معروف/خارج النطاق",
}
def detect_intent(text: str) -> str:
t = (text or "").strip().lower()
# 1) Greetings
if re.search(r"\b(hi|hello|hey|start)\b", t) or any(x in t for x in ["اهلا", "أهلا", "السلام", "هاي", "مرحبا", "ابدأ", "ابدء"]):
return "GREETING"
# 2) Human agent
if any(x in t for x in ["خدمة العملاء", "موظف", "حد يرد", "اكلم", "اتواصل", "رقم", "واتساب", "support", "agent"]):
return "HUMAN_AGENT"
# 3) Courses menu / asking about courses generally
if any(x in t for x in ["كورسات", "دورات", "courses", "الكورسات المتاحة", "عايز كورس", "عايز اتعلم", "الالماني عندكم", "الماني"]):
return "COURSES_MENU"
# 4) Specific course types
# Express / Intensive / Regular / Weekend / Online / Children
if any(x in t for x in ["express", "اكسبريس", "سريع", "super intensive"]):
return "COURSE_TYPE_DETAILS"
if any(x in t for x in ["intensive", "انتنسب", "مكثف", "مكثفة"]):
return "COURSE_TYPE_DETAILS"
if any(x in t for x in ["regular", "ريجولار", "عادي", "منتظم"]):
return "COURSE_TYPE_DETAILS"
if any(x in t for x in ["weekend", "ويكند", "الجمعة", "السبت", "عطلة"]):
return "WEEKEND_COURSES"
if any(x in t for x in ["online", "اونلاين", "أونلاين", "زووم", "من البيت"]):
return "ONLINE_COURSES"
if any(x in t for x in ["children", "kids", "اطفال", "أطفال", "طفل", "سن", "سنين"]):
return "CHILDREN_COURSES"
# 5) Center info
if any(x in t for x in ["المركز", "adk", "ädk", "فروع", "branch", "اتأسس", "تاريخ", "goethe", "معتمد"]):
return "CENTER_INFO"
return "OTHER"
KB_TEXT = """
المركز:
(ÄDK)- Egyptian-German Cultural Centre was established in 1998. With various branches in Cairo, ÄDK offers German language courses for adults from A1 to C1 and for children from A1 to B1. Over the years thousands have graduated and have learned in ÄDK. In addition to our language courses, ÄDK organizes cultural projects independently, or in conjunction with the Goethe institute.
ÄDK is the first institute to be accredited from the Goethe institute in the Middle East and North Africa region.
أنواع الكورسات:
1) Express Courses:
- Super intensive courses لتعلم الألماني بسرعة وكفاءة. Challenging وتحتاج مجهود.
- ممكن تحجز Stage كاملة (A1-A2-B1).
- 3 محاضرات في الأسبوع، كل محاضرة 4 ساعات.
- مدة الـ stage: شهرين ونصف.
2) Intensive Courses:
- ممكن تحجز Stage كاملة (A1-A2-B1).
- محاضرتين في الأسبوع، كل محاضرة 4 ساعات.
- مدة الـ stage: 3 شهور ونصف.
3) Regular Courses:
- ممكن تحجز كل level لوحده من (A1.1 إلى B1.3).
- محاضرتين في الأسبوع، كل محاضرة 4 ساعات.
- مدة الكورس: شهر ونصف.
4) Weekend Courses:
- للناس اللي مش فاضيين خلال الأسبوع بسبب شغل/دراسة.
- بتتبع نفس outline وساعات الـ Regular (intensive و normal).
5) Online Courses:
- attending online.
6) Children Courses:
- من 5 سنوات حتى 15 سنة.
- الهدف: تنمية مهارات الطفل واللغة وتشجيع التفكير الحر والنقدي والاستقلالية.
"""
def build_system_prompt(intent: str) -> str:
return f"""
أنت مساعد واتساب لمركز ÄDK لتعليم اللغة الألمانية.
اكتب بالعربي المصري بطريقة ودودة وطبيعية ومحترمة، وجُمل قصيرة.
قواعد أسلوب (مهم جدًا):
- ممنوع أخطاء لغوية مثل: "اقترحك" أو "يهتم بيك". استخدم: "أقترح" / "أنسب" / "تحب" / "ممكن".
- استخدم ضمير المخاطب الصحيح: "إنت/حضرتك" (اختر واحد واثبت عليه). استخدم "إنت" هنا.
- أسئلة الاختيار تكون بصيغة سليمة: "تحب كورس أي نوع؟" أو "إنت مهتم بأي كورس؟" وليس "يهتم بيك".
- متبعتش تحية زي مرحباً او أهلاً. رد مباشرة على رسالة العميل حسب نوعها
قواعد المحتوى:
- استخدم فقط المعلومات الموجودة في "قاعدة المعرفة" أدناه.
- ممنوع تخترع أسعار/مواعيد/فروع/أماكن/تفاصيل غير موجودة.
- ممنوع تقارن بمنافسين أو تقدم معلومات عامة خارج قاعدة المعرفة.
لو المستخدم سأل عن معلومة غير موجودة في قاعدة المعرفة:
- لا تقل صراحة "المعلومة مش عندي" ولا تستخدم صيغة اعتذار طويلة.
- استخدم صياغة لطيفة توصل نفس المعنى بدون إحراج، مثل:
1) "تمام — هخلي فريق خدمة العملاء يتواصل معاك ويوضح لك التفاصيل."
2) "خلّيني أسجّل استفسارك، وخدمة العملاء هيردّوا عليك بالتفاصيل."
3) "عشان أديك إجابة دقيقة، هحوّل سؤالك لخدمة العملاء."
- في النهاية اسأل سؤال واحد يساعد خدمة العملاء: (اسمك/رقمك/أقرب فرع/تفضل أونلاين ولا حضور).
*لو الرقم جاي من واتساب مش محتاج تسأل عنه.*
توجيهات حسب الـ Intent:
- GREETING: رحّب + اعرض 3 اختيارات واضحة.
- COURSES_MENU: اعرض الأنواع المتاحة فقط (Regular/Express/Intensive/Weekend/Online/Children) واسأل: "تحب تعرف تفاصيل أنهي نوع؟"
- COURSE_TYPE_DETAILS / ONLINE_COURSES / WEEKEND_COURSES / CHILDREN_COURSES: اذكر التفاصيل من قاعدة المعرفة فقط، ثم اسأل سؤال متابعة واحد.
- CENTER_INFO: اذكر معلومات المركز من قاعدة المعرفة فقط، ثم اسأل لو محتاج يتواصل مع خدمة العملاء.
إخراج الرد:
- الرد يكون نص فقط.
- لا تكتب JSON ولا عناوين تقنية ولا نقاط كثيرة (حد أقصى 5 سطور).
- لا تذكر كلمة "قاعدة المعرفة".
الـ Intent الحالي: {intent}
قاعدة المعرفة:
{KB_TEXT}
""".strip()
def process_text(user_text: str):
client = openai.OpenAI(api_key=api_key, base_url=base_url)
intent = detect_intent(user_text)
system_prompt = build_system_prompt(intent)
try:
resp = client.chat.completions.create(
model=model_link,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_text},
],
max_tokens=500,
temperature=0.2,
stream=False,
)
answer = resp.choices[0].message.content.strip()
# لو تحب ترجع intent كمان (مفيد للـ webhook logic)
return {"ok": True, "intent": intent, "reply": answer}
except Exception as e:
return {"ok": False, "error": str(e)}