Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -115,6 +115,8 @@ def prepare_order_draft(table_number: str, items: list[OrderItem]) -> str:
|
|
| 115 |
table_number: The table number (e.g. '3')
|
| 116 |
items: A list of ordered items, each containing a name and a quantity.
|
| 117 |
"""
|
|
|
|
|
|
|
| 118 |
items_list = []
|
| 119 |
# پردازش دفاعی برای پشتیبانی همزمان از کلاسهای Pydantic و ساختارهای دیکشنری خام
|
| 120 |
for item in items:
|
|
@@ -137,12 +139,12 @@ def prepare_order_draft(table_number: str, items: list[OrderItem]) -> str:
|
|
| 137 |
except Exception:
|
| 138 |
pass
|
| 139 |
|
| 140 |
-
global_drafts[
|
| 141 |
-
"table":
|
| 142 |
"items": items_list,
|
| 143 |
"timestamp": time.time()
|
| 144 |
}
|
| 145 |
-
return f"من پیشنویس سفارش شما رو برای میز {
|
| 146 |
|
| 147 |
def get_full_menu() -> str:
|
| 148 |
"""
|
|
@@ -180,6 +182,28 @@ def set_item_availability(item_name: str, available: bool) -> str:
|
|
| 180 |
return f"آیتم '{item_name}' در منوی کافه یافت نشد."
|
| 181 |
|
| 182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
# --- روتهای مسیریابی آدرسها ---
|
| 184 |
|
| 185 |
@app.route('/')
|
|
@@ -255,9 +279,12 @@ def api_customer_chat_stream(table_number):
|
|
| 255 |
if not active_tasks.get(table_number, True):
|
| 256 |
break
|
| 257 |
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
| 261 |
|
| 262 |
if full_generated_text:
|
| 263 |
table_chat_histories[table_number].append({"role": "model", "content": full_generated_text})
|
|
@@ -383,9 +410,26 @@ def api_admin_chat():
|
|
| 383 |
|
| 384 |
response = chat.send_message(last_user_message)
|
| 385 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 386 |
return jsonify({
|
| 387 |
"success": True,
|
| 388 |
-
"response":
|
| 389 |
})
|
| 390 |
|
| 391 |
except Exception as e:
|
|
|
|
| 115 |
table_number: The table number (e.g. '3')
|
| 116 |
items: A list of ordered items, each containing a name and a quantity.
|
| 117 |
"""
|
| 118 |
+
# اطمینان از تبدیل شماره میز به نوع رشته جهت سازگاری با کلیدهای دیکشنری
|
| 119 |
+
table_number_str = str(table_number)
|
| 120 |
items_list = []
|
| 121 |
# پردازش دفاعی برای پشتیبانی همزمان از کلاسهای Pydantic و ساختارهای دیکشنری خام
|
| 122 |
for item in items:
|
|
|
|
| 139 |
except Exception:
|
| 140 |
pass
|
| 141 |
|
| 142 |
+
global_drafts[table_number_str] = {
|
| 143 |
+
"table": table_number_str,
|
| 144 |
"items": items_list,
|
| 145 |
"timestamp": time.time()
|
| 146 |
}
|
| 147 |
+
return f"من پیشنویس سفارش شما رو برای میز {table_number_str} آماده کردم."
|
| 148 |
|
| 149 |
def get_full_menu() -> str:
|
| 150 |
"""
|
|
|
|
| 182 |
return f"آیتم '{item_name}' در منوی کافه یافت نشد."
|
| 183 |
|
| 184 |
|
| 185 |
+
# --- توابع کمکی استخراج متن ---
|
| 186 |
+
|
| 187 |
+
def get_chunk_text(chunk) -> str:
|
| 188 |
+
"""
|
| 189 |
+
استخراج ایمن متن از تکههای استریم جهت جلوگیری از خطای ValueError روی تکههای حاوی فراخوانی ابزار.
|
| 190 |
+
"""
|
| 191 |
+
try:
|
| 192 |
+
# ابتدا بخش کاندیداها بررسی میشود تا در صورت وجود متن، مستقیماً استخراج شود
|
| 193 |
+
if chunk.candidates and chunk.candidates[0].content and chunk.candidates[0].content.parts:
|
| 194 |
+
parts = chunk.candidates[0].content.parts
|
| 195 |
+
text_parts = [part.text for part in parts if hasattr(part, "text") and part.text]
|
| 196 |
+
if text_parts:
|
| 197 |
+
return "".join(text_parts)
|
| 198 |
+
except Exception:
|
| 199 |
+
pass
|
| 200 |
+
|
| 201 |
+
try:
|
| 202 |
+
return chunk.text or ""
|
| 203 |
+
except (ValueError, AttributeError):
|
| 204 |
+
return ""
|
| 205 |
+
|
| 206 |
+
|
| 207 |
# --- روتهای مسیریابی آدرسها ---
|
| 208 |
|
| 209 |
@app.route('/')
|
|
|
|
| 279 |
if not active_tasks.get(table_number, True):
|
| 280 |
break
|
| 281 |
|
| 282 |
+
# استفاده از تابع استخراج دفاعی به جای ارجاع مستقیم به chunk.text
|
| 283 |
+
chunk_text = get_chunk_text(chunk)
|
| 284 |
+
|
| 285 |
+
if chunk_text:
|
| 286 |
+
full_generated_text += chunk_text
|
| 287 |
+
yield f"data: {json.dumps({'type': 'text', 'content': chunk_text}, ensure_ascii=False)}\n\n"
|
| 288 |
|
| 289 |
if full_generated_text:
|
| 290 |
table_chat_histories[table_number].append({"role": "model", "content": full_generated_text})
|
|
|
|
| 410 |
|
| 411 |
response = chat.send_message(last_user_message)
|
| 412 |
|
| 413 |
+
# استخراج متن به صورت دفاعی در صورت اجرای ابزارها در گامهای میانی
|
| 414 |
+
admin_response_text = ""
|
| 415 |
+
try:
|
| 416 |
+
if response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
| 417 |
+
parts = response.candidates[0].content.parts
|
| 418 |
+
text_parts = [part.text for part in parts if hasattr(part, "text") and part.text]
|
| 419 |
+
if text_parts:
|
| 420 |
+
admin_response_text = "".join(text_parts)
|
| 421 |
+
except Exception:
|
| 422 |
+
pass
|
| 423 |
+
|
| 424 |
+
if not admin_response_text:
|
| 425 |
+
try:
|
| 426 |
+
admin_response_text = response.text or ""
|
| 427 |
+
except (ValueError, AttributeError):
|
| 428 |
+
admin_response_text = "تغییرات مورد نظر شما با موفقیت روی منو اعمال شد."
|
| 429 |
+
|
| 430 |
return jsonify({
|
| 431 |
"success": True,
|
| 432 |
+
"response": admin_response_text
|
| 433 |
})
|
| 434 |
|
| 435 |
except Exception as e:
|