codeBOKER commited on
Commit
e72602f
·
1 Parent(s): 6070e36

Refactor webhook handling and AI call flow

Browse files

Avoid duplicate message persistence, streamline Telegram webhook processing, and run Hugging Face completion calls through an executor-based async wrapper.

Made-with: Cursor

Files changed (2) hide show
  1. ai_service.py +19 -58
  2. telegram_handlers.py +29 -50
ai_service.py CHANGED
@@ -48,70 +48,31 @@ TOOLS = [
48
  }
49
  ]
50
 
51
- async def get_ai_response(user_query: str, telegram_id: int = None):
52
- if not pc or not index or not hf_client:
53
- return "عذراً، خدمة الذكاء الاصطناعي غير متوفرة حالياً."
54
-
55
- print(f"User query: {user_query}")
56
  conversation_history = []
57
- if telegram_id and db_manager:
58
- db_manager.save_message(telegram_id, user_query, "user")
59
- # جلب آخر 6 رسائل لتوفير السياق للموديل
60
  raw_history = db_manager.get_history(telegram_id, limit=6)
61
  for msg in raw_history:
62
- conversation_history.append({"role": msg['role'], "content": msg['content']})
63
- else:
64
- conversation_history.append({"role": "user", "content": user_query})
65
 
66
-
67
  messages = [{"role": "system", "content": PROMPT}] + conversation_history
68
-
69
- print(f"getting response from Messages: {messages}")
70
- response = hf_client.chat.completions.create(
71
- model=MODEL_NAME,
72
- messages=messages,
73
- tools=TOOLS,
74
- tool_choice="auto",
75
- temperature=0.1
76
- )
77
-
78
- response_message = response.choices[0].message
79
- tool_calls = getattr(response_message, 'tool_calls', None)
80
-
81
 
82
- if tool_calls:
83
- print(f"tool_calls: {tool_calls}")
84
- for tool_call in tool_calls:
85
- function_args = json.loads(tool_call.function.arguments)
86
- search_query = function_args.get("query")
87
-
88
-
89
- extracted_context = await search_bank_knowledge(search_query)
90
-
91
-
92
- messages.append(response_message)
93
- messages.append({
94
- "role": "tool",
95
- "tool_call_id": tool_call.id,
96
- "name": "search_bank_knowledge",
97
- "content": extracted_context
98
- })
99
-
100
-
101
- final_response = hf_client.chat.completions.create(
102
- model=MODEL_NAME,
103
  messages=messages,
104
- temperature=0.3
 
105
  )
106
- ai_final_content = final_response.choices[0].message.content
107
- else:
108
- print(f"response_message: {response_message}")
109
- ai_final_content = response_message.content
110
-
111
- print(f"ai_final_content: {ai_final_content}")
112
- cleaned_response = clean_ai_response(ai_final_content)
113
-
114
- if telegram_id and db_manager:
115
- db_manager.save_message(telegram_id, cleaned_response, "assistant")
116
 
117
- return cleaned_response
 
 
48
  }
49
  ]
50
 
51
+ async def get_ai_response(user_query: str, telegram_id: int):
52
+ # جلب التاريخ من قاعدة البيانات فقط (بدون إعادة حفظ الرسالة الحالية)
 
 
 
53
  conversation_history = []
54
+ if db_manager:
 
 
55
  raw_history = db_manager.get_history(telegram_id, limit=6)
56
  for msg in raw_history:
57
+ # تأكد أن المحتوى ليس فارغاً
58
+ if msg.get('content'):
59
+ conversation_history.append({"role": msg['role'], "content": msg['content']})
60
 
61
+ # بناء الرسائل
62
  messages = [{"role": "system", "content": PROMPT}] + conversation_history
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ # إذا كان hf_client متزامن، يفضل تشغيله هكذا لتجنب التوقف:
65
+ import asyncio
66
+ loop = asyncio.get_event_loop()
67
+
68
+ # تنفيذ طلب الموديل
69
+ def call_hf():
70
+ return hf_client.chat.completions.create(
71
+ model=HF_MODEL,
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  messages=messages,
73
+ temperature=0.1,
74
+ max_tokens=800
75
  )
 
 
 
 
 
 
 
 
 
 
76
 
77
+ completion = await loop.run_in_executor(None, call_hf)
78
+ return clean_ai_response(completion.choices[0].message.content)
telegram_handlers.py CHANGED
@@ -20,64 +20,43 @@ class WebhookData(BaseModel):
20
 
21
  async def telegram_webhook(data: WebhookData):
22
  try:
23
- if data.message:
24
- telegram_id = data.message.chat.id
25
- user_text = data.message.text
26
-
27
- # Extract user info
28
- username = data.message.chat.username
29
- first_name = data.message.chat.first_name
30
- last_name = data.message.chat.last_name
31
 
32
- if user_text:
33
- # Save user message to database if available
34
- if db_manager:
35
- db_manager.save_message(telegram_id, user_text, "user")
36
- db_manager.create_or_update_user(telegram_id, username, first_name, last_name)
37
-
38
- # Get the intelligent response with conversation history
39
- ai_answer = await get_ai_response(user_text, telegram_id)
40
-
41
- # Save assistant response to database if available
42
- if db_manager:
43
- db_manager.save_message(telegram_id, ai_answer, "assistant")
44
-
45
- # Send back to Telegram if TELEGRAM_URL is available
46
- if TELEGRAM_URL:
47
- async with httpx.AsyncClient(verify=False) as client:
48
- await client.post(
49
- TELEGRAM_URL,
50
- headers={"Host": "api.telegram.org"},
51
- json={
52
- "chat_id": telegram_id,
53
- "text": ai_answer,
54
- "parse_mode": "Markdown"
55
- }
56
- )
57
-
58
- return {"status": "ok"}
59
- except Exception as e:
60
- return {"status": "error", "message": str(e)}
61
-
62
- async def test_webhook(data: WebhookData):
63
- try:
64
- if not data.message:
65
- return {"error": "Missing 'message' field in request"}
66
-
67
  telegram_id = data.message.chat.id
68
  user_text = data.message.text
69
 
70
- # Save user message to database if available
 
 
 
 
 
 
71
  if db_manager:
 
72
  db_manager.save_message(telegram_id, user_text, "user")
73
 
74
- # Get response with conversation history
75
- response = await get_ai_response(user_text, telegram_id)
76
 
77
- # Save assistant response to database if available
78
  if db_manager:
79
- db_manager.save_message(telegram_id, response, "assistant")
80
 
81
- return {"response": response}
 
 
 
 
 
 
 
 
 
 
 
 
82
  except Exception as e:
83
- return {"error": str(e)}
 
 
20
 
21
  async def telegram_webhook(data: WebhookData):
22
  try:
23
+ if not data.message or not data.message.text:
24
+ return {"status": "ok"}
 
 
 
 
 
 
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  telegram_id = data.message.chat.id
27
  user_text = data.message.text
28
 
29
+ # معلومات المستخدم
30
+ username = data.message.chat.username
31
+ first_name = data.message.chat.first_name
32
+
33
+ print(f"--- Processing message from {first_name} ---")
34
+
35
+ # 1. تحديث بيانات المستخدم وحفظ رسالته (مرة واحدة فقط هنا)
36
  if db_manager:
37
+ db_manager.create_or_update_user(telegram_id, username, first_name, data.message.chat.last_name)
38
  db_manager.save_message(telegram_id, user_text, "user")
39
 
40
+ # 2. جلب الرد (تأكد من إزالة حفظ الرسالة المتكرر داخل get_ai_response)
41
+ ai_answer = await get_ai_response(user_text, telegram_id)
42
 
43
+ # 3. حفظ رد البوت
44
  if db_manager:
45
+ db_manager.save_message(telegram_id, ai_answer, "assistant")
46
 
47
+ # 4. الإرسال لتليجرام (تم تنظيفه من الهيدرز الزائدة)
48
+ if TELEGRAM_URL:
49
+ async with httpx.AsyncClient(timeout=30.0) as client:
50
+ payload = {
51
+ "chat_id": telegram_id,
52
+ "text": ai_answer,
53
+ "parse_mode": "Markdown"
54
+ }
55
+ # حذفنا Host Header و verify=False (إلا لو كنت متأكداً من حاجتك لها)
56
+ response = await client.post(TELEGRAM_URL, json=payload)
57
+ print(f"Telegram response status: {response.status_code}")
58
+
59
+ return {"status": "ok"}
60
  except Exception as e:
61
+ print(f"Error in webhook: {str(e)}")
62
+ return {"status": "error", "message": str(e)}