kltn21110 commited on
Commit
906cd3f
·
verified ·
1 Parent(s): 5c93c5b

Update function/function_agent/multi_agent.py

Browse files
Files changed (1) hide show
  1. function/function_agent/multi_agent.py +949 -949
function/function_agent/multi_agent.py CHANGED
@@ -1,950 +1,950 @@
1
- import asyncio
2
- import json
3
- import os,sys
4
- BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../"))
5
- sys.path.insert(0, BASE_DIR)
6
- from function.file import extract_file as extract_file
7
- import function.filter.filter_role as filter_role_1
8
- import function.filter.filter_sql_injection as filter_sql_injection_1
9
- import function.filter.result as query_result_1
10
- import function.chat as chat_sql
11
- import function.gemini_response.response_general as res_general
12
- import function.gemini_response.response_hello as res_hello
13
- import cloudinary
14
- import cloudinary.uploader
15
- from typing import List,Any
16
- import cloudinary
17
- from cloudinary.utils import cloudinary_url
18
- from cloudinary import uploader
19
- from typing import Optional
20
- import asyncio
21
- from models.Database_Entity import StopSignal
22
-
23
-
24
- async def check_should_stop(chat_id: str, stop_event:Optional[asyncio.Event]):
25
- # Trường hợp dừng qua RAM (in-memory)
26
- await asyncio.sleep(0.1)
27
- if stop_event and stop_event.is_set():
28
- print("🛑 Dừng qua stop_event.")
29
- return {"status": "cancelled"}
30
-
31
- # Trường hợp dừng qua MongoDB
32
- await asyncio.sleep(0.1)
33
- if StopSignal.objects(chat_history= chat_id, is_stopped=True).first():
34
- print("🛑 Dừng vì có StopSignal trong DB.")
35
- return {"status": "cancelled"}
36
-
37
- return None
38
-
39
- # Dán nguyên chuỗi URL này vào
40
- cloudinary.config(
41
- cloud_name = "dgj8n2ggn",
42
- api_key = "287331723817617",
43
- api_secret = "MAI7dpoikIy-ap7IjPCiwfRgMQ0",
44
- secure=True
45
- )
46
-
47
- def upload_images_to_cloudinary_and_markdown(folder_path):
48
- markdown_images = ""
49
- image_files = [
50
- f for f in os.listdir(folder_path)
51
- if f.lower().endswith(('.png', '.jpg', '.jpeg'))
52
- ]
53
-
54
- for img in image_files:
55
- img_path = os.path.join(folder_path, img)
56
- try:
57
- upload_result = cloudinary.uploader.upload(img_path)
58
- print(img_path)
59
- image_url = upload_result.get("secure_url")
60
- print(image_url)
61
- if image_url:
62
- markdown_images += f"![{img}]({image_url})\n\n"
63
- except Exception as e:
64
- print(f"❌ Upload lỗi với ảnh {img}: {e}")
65
- return markdown_images
66
-
67
-
68
- async def agent_information(task,user_id,languages, role, chat_id,token,stop_event: Optional[asyncio.Event]):
69
- result_check = await check_should_stop(chat_id,stop_event)
70
- if result_check:
71
- return result_check
72
- text_all= extract_file.extract_data2()
73
- result_check = await check_should_stop(chat_id,stop_event)
74
- if result_check:
75
- return result_check
76
- task = filter_sql_injection_1.normalize_query(task)
77
- print("text: ",text_all)
78
- result_check = await check_should_stop(chat_id,stop_event)
79
- if result_check:
80
- return result_check
81
- return extract_file.handle_query_upgrade_keyword_old(f"{task}",text_all,"demohmdrinks")
82
-
83
-
84
- async def agent_hello(task,user_id,languages, role,chat_id,token,stop_event: Optional[asyncio.Event]):
85
- result_check = await check_should_stop(chat_id,stop_event)
86
- if result_check:
87
- return result_check
88
- result = await res_hello.response_hello(task)
89
- result_check = await check_should_stop(chat_id,stop_event)
90
- if result_check:
91
- return result_check
92
- return result
93
-
94
-
95
- from mongoengine import connect
96
- from dotenv import load_dotenv
97
- load_dotenv()
98
- MONGO_URI = os.getenv("MONGO_URI", "")
99
- connect("chatbot_hmdrinks", host=MONGO_URI)
100
-
101
- from models.Database_Entity import User, ChatHistory, DetailChat
102
- def get_chat_history(chat_history_id):
103
- messages = DetailChat.objects(chat_history=chat_history_id).order_by('timestamp')
104
- history_text = ""
105
- for msg in messages:
106
- history_text += f"Người dùng hỏi: {msg.you_message}\n"
107
- history_text += f"Trợ lý: {msg.ai_message}\n\n"
108
- return history_text.strip()
109
-
110
-
111
- from mongoengine import connect
112
- from dotenv import load_dotenv
113
- load_dotenv()
114
- MONGO_URI = os.getenv("MONGO_URI", "")
115
- connect("chatbot_hmdrinks", host=MONGO_URI)
116
- import sys
117
- import os
118
-
119
- project_root = os.path.abspath(os.path.join(os.getcwd(), '..', '..', '..'))
120
-
121
- if project_root not in sys.path:
122
- sys.path.append(project_root)
123
- from models.Database_Entity import User, ChatHistory, DetailChat,ChatCart, CartProduct
124
- import base64
125
- from advance_shopping.prompt import context_prompt, multitool_prompt, user_intent
126
-
127
- from advance_shopping.call_gemini import tool_call
128
- from advance_shopping.server_java import server_java
129
- from advance_shopping.function import test as test_func
130
-
131
-
132
- def get_chat_history(chat_history_id):
133
- messages = DetailChat.objects(chat_history=chat_history_id).order_by('timestamp')
134
- print(DetailChat._meta) # in ra cấu hình model
135
-
136
- history_text = ""
137
- for msg in messages:
138
- history_text += f"Người dùng: {msg.you_message}\n"
139
- history_text += f"Trợ lý: {msg.ai_message}\n\n"
140
- return history_text.strip()
141
-
142
-
143
- from bson import ObjectId
144
- def chat_history_has_unconfirmed_cart(chat_history_id: str) -> bool:
145
- """
146
- Trả về True nếu trong đoạn chat có giỏ hàng chưa được xác nhận đặt hàng.
147
- Trả về False nếu không có giỏ hàng, hoặc tất cả giỏ hàng đã được xác nhận.
148
- """
149
- return ChatCart.objects(
150
- chat_history=ObjectId(chat_history_id),
151
- status="pending"
152
- ).count() > 0
153
-
154
-
155
- from bson import ObjectId
156
-
157
-
158
- def process_data(structured_data, data):
159
- list_data1 = structured_data[:]
160
- print("data",data)
161
- if data == "None":
162
- return structured_data
163
- if isinstance(data, list) and not data:
164
- print("✅ Đây là một list rỗng.")
165
- return structured_data
166
- if data:
167
- for item in data:
168
- action = item.get("action", "").lower()
169
- name = item.get("name", "").strip().lower()
170
- size = item.get("size", "").strip().lower()
171
- size_old = item.get("size_old", "").strip().lower() if "size_old" in item else None
172
-
173
- matched = False
174
- if action == "update" and size_old:
175
- for item_old in list_data1:
176
- name_old = item_old.get("name", "").strip().lower()
177
- size_old_in_list = item_old.get("size", "").strip().lower()
178
-
179
- if name == name_old and size_old == size_old_in_list:
180
- matched = True
181
- # Cập nhật các trường
182
- for key in ["quantity", "size"]:
183
- if key in item:
184
- item_old[key] = item[key]
185
- break
186
-
187
- else:
188
- for item_old in list_data1:
189
- name_old = item_old.get("name", "").strip().lower()
190
- size_old_in_list = item_old.get("size", "").strip().lower()
191
-
192
- if name == name_old and size == size_old_in_list:
193
- matched = True
194
-
195
- if action == "delete":
196
- list_data1.remove(item_old)
197
- break
198
-
199
- elif action == "update":
200
- for key in ["quantity", "size"]:
201
- if key in item:
202
- item_old[key] = item[key]
203
- break
204
- elif action == "add":
205
- if "quantity" in item:
206
- item_old["quantity"] = int(item_old.get("quantity", 0)) + int(item["quantity"])
207
- break
208
-
209
- if not matched and action == "add":
210
- item_to_add = {k: v for k, v in item.items() if k != "action"}
211
- list_data1.append(item_to_add)
212
- filtered_list = []
213
- for item in list_data1:
214
- if (item.get("name") not in [None, "", "None"]):
215
- filtered_list.append(item)
216
- return filtered_list
217
-
218
-
219
- def get_last_ai_message(chat_history_id: str) -> str:
220
- last_detail = DetailChat.objects(
221
- chat_history=ObjectId(chat_history_id),
222
- ai_message__ne=None
223
- ).order_by('-timestamp').first()
224
-
225
- return last_detail.ai_message if last_detail else "None"
226
-
227
-
228
- # async def agent_sql(task,user_id,languages, role, chat_id,token,stop_event: Optional[asyncio.Event] = None):
229
- # check_analyze = filter_sql_injection_1.filter_task_analyze(task)
230
- # check_restore_delete = filter_sql_injection_1.filter_question_remove_restore(task)
231
- # prompt_check_shopping = ""
232
- # print(check_restore_delete)
233
- # if check_restore_delete == True:
234
- # return "Bạn không được phép khôi phục hoặc xóa dữ liệu. Vui lòng kiểm tra lại câu hỏi của bạn."
235
- # print(check_analyze)
236
- # if check_analyze == False:
237
- # result_final = ""
238
- # cart_status = ""
239
- # if chat_history_has_unconfirmed_cart(chat_id) is True:
240
- # cart_status = "Yes (Đang Pending)"
241
- # else:
242
- # cart_status = "No (Không có)"
243
-
244
- # print(cart_status)
245
- # prompt_check_shopping = user_intent.build_detailed_user_intent_prompt(user_question=task,
246
- # chat_history=get_chat_history(chat_id),
247
- # cart_status=cart_status)
248
- # check_shopping = tool_call.generate(prompt_check_shopping)
249
- # print(check_shopping)
250
- # type = check_shopping["type"]
251
- # if str(type) == "shopping_question":
252
- # tools = ["confirm_order", "insert_cart", "update_cart", "delete_item_cart", "deleted all cart"]
253
- # last_ai_message = get_last_ai_message(chat_id)
254
- # context_prompt = multitool_prompt.build_multi_tool_prompt(question=last_ai_message,tools=tools,user_answer=task)
255
- # data_context = {}
256
- # try:
257
- # data_context = tool_call.generate(context_prompt)
258
- # if not data_context["question"]:
259
- # data_context = tool_call.generate(context_prompt)
260
- # except:
261
- # data_context = tool_call.generate(context_prompt)
262
- # if not data_context["question"]:
263
- # data_context = tool_call.generate(context_prompt)
264
- # print("data_context: ",data_context)
265
- # question_new = data_context["question"]
266
- # latest_unconfirmed_cart = ChatCart.objects(
267
- # chat_history=chat_id,
268
- # status="pending"
269
- # ).order_by('-created_at').first()
270
- # previous_data = []
271
- # if latest_unconfirmed_cart:
272
- # for product in latest_unconfirmed_cart.cart_products:
273
- # product_dict = product.to_mongo().to_dict()
274
- # if "_id" in product_dict:
275
- # product_dict["_id"] = str(product_dict["_id"])
276
- # previous_data.append(product_dict)
277
-
278
-
279
- # data = test_func.classify_data(input = f"""{question_new}""", structured_data=previous_data)
280
- # list_data = list()
281
- # print(data)
282
- # if data == "None" or data == '':
283
- # data = list()
284
- # else:
285
- # try:
286
- # list_data = json.loads(data)
287
- # except:
288
- # list_data = list()
289
- # print("List data:", list_data)
290
- # print("Preious_data", previous_data)
291
- # previous_data = list(previous_data)
292
- # list_data1 = previous_data
293
- # clean_list = list()
294
- # full_test = ""
295
- # result = []
296
- # print(list_data)
297
- # try:
298
- # print("Nhay vo test2")
299
- # result = process_data(list_data1, list_data)
300
- # except:
301
- # if data is None or data == "None":
302
- # print("Nhay vo test1")
303
- # result = process_data(list_data1, [])
304
- # clean_cart_products = []
305
- # chat_cart = ChatCart()
306
- # if list_data:
307
- # annotated_list, clean_list, full_test = test_func.validate_product_list(data_list=result,server_java=server_java)
308
- # print(result)
309
- # print(clean_list)
310
-
311
- # results = []
312
- # if data_context["question_normal"]:
313
-
314
- # for key, q in data_context["question_normal"].items():
315
- # task_1 = filter_sql_injection_1.normalize_query(q)
316
- # filtered_input = filter_sql_injection_1.filter_sql_injection(task_1)
317
- # filtered_role_input = filter_role_1.filter_role(filtered_input)
318
- # result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
319
- # result_final = query_result_1.query_result(task, result)
320
- # results.append({"question": q, "result": result_final})
321
-
322
- # result_final += str(results)
323
-
324
- # for item in clean_list:
325
- # # Đảm bảo quantity là số nguyên
326
- # product = CartProduct(
327
- # name=item.get('name'),
328
- # size=item.get('size'),
329
- # quantity=int(item.get('quantity', 1))
330
- # )
331
- # clean_cart_products.append(product)
332
- # print("Clean_cart", clean_cart_products)
333
- # print("Full test", full_test)
334
-
335
-
336
- # if latest_unconfirmed_cart:
337
- # print("🛒 Đã có giỏ hàng 'pending' trước đó. Đang cập nhật lại sản phẩm...")
338
- # latest_unconfirmed_cart.cart_products = clean_cart_products
339
- # latest_unconfirmed_cart.save()
340
- # chat_cart = latest_unconfirmed_cart
341
- # else:
342
- # print("Chưa có giỏ hàng 'pending'. Đang tạo mới...")
343
- # chat_cart = ChatCart(
344
- # chat_history=chat_id,
345
- # cart_products=clean_cart_products,
346
- # status="pending"
347
- # )
348
- # chat_cart.save()
349
- # if full_test:
350
- # return full_test + f"Hãy tạo ra câu hỏi để người dùng thay đổi ý định mua sản phẩm. Ngoài ra luôn hiển thị lại tình trạng giỏ của người dùng: giỏ hàng{clean_list}" + str(results)
351
-
352
- # if check_shopping.get("is_delete_cart") == "Yes":
353
- # print("🗑️ Đang xóa toàn bộ sản phẩm trong giỏ hàng...")
354
- # chat_cart.cart_products = []
355
- # chat_cart.status = "failed"
356
- # chat_cart.save()
357
- # result_final += "Đã xóa toàn bộ sản phẩm trong giỏ hàng..."
358
- # if check_shopping.get("is_view_cart") == "Yes":
359
- # print("👀 Đang xem giỏ hàng...")
360
- # chat_cart = ChatCart.objects(chat_history=chat_id, status="pending").first()
361
-
362
- # if not chat_cart or not chat_cart.cart_products:
363
- # print("🛒 Giỏ hàng hiện đang trống.")
364
- # result_final += "🛒 Giỏ hàng hiện đang trống.\n"
365
- # else:
366
- # message_lines = ["🛒 Danh sách sản phẩm trong giỏ:"]
367
- # for product in chat_cart.cart_products:
368
- # print(f"- Tên sản phẩm: {product.name} | Số Lượng: {product.quantity} | Size(Kích cỡ): {product.size}")
369
- # message_lines.append(
370
- # f"- Tên sản phẩm: {product.name} | Số Lượng: {product.quantity} | Size(Kích cỡ): {product.size}"
371
- # )
372
- # data = "\n".join(message_lines)
373
- # result_final += data + "\n"
374
-
375
-
376
-
377
- # if check_shopping["is_confirm_order"] == "Yes":
378
- # try:
379
- # print("🔹 [STEP 1] Tạo giỏ hàng mới...")
380
- # data = server_java.create_cart(int(user_id), token)
381
- # cart_id = data.get("cartId")
382
- # print(f"✅ Giỏ hàng tạo thành công: cart_id = {cart_id}")
383
- # except Exception as e:
384
- # print(f"❌ Lỗi khi tạo giỏ hàng: {e}")
385
- # cart_id = None
386
-
387
- # if cart_id:
388
- # for idx, item in enumerate(clean_cart_products, 1):
389
- # try:
390
- # print(f"\n🔹 [STEP 2.{idx}] Tìm kiếm sản phẩm: {item['name']} (size: {item['size']})...")
391
- # pro_id, pro_name, size_check, stock_check, price_check = server_java.search_product(
392
- # keyword=item["name"], size=item["size"]
393
- # )
394
- # print(f"✅ Tìm thấy sản phẩm '{pro_name}' (ID: {pro_id}, Size: {size_check})")
395
-
396
- # print(f"🔹 [STEP 3.{idx}] Thêm sản phẩm vào giỏ hàng...")
397
- # data1 = server_java.insert_cartItem(user_id, cart_id, pro_id, size_check, item["quantity"], token)
398
- # print(f"✅ Đã thêm sản phẩm '{pro_name}' vào giỏ hàng.")
399
- # except Exception as e:
400
- # print(f"❌ Lỗi khi xử lý sản phẩm thứ {idx}: {e}")
401
- # continue # vẫn tiếp tục vòng lặp cho sản phẩm tiếp theo
402
-
403
- # try:
404
- # print("\n🔹 [STEP 4] Tạo đơn hàng từ giỏ hàng...")
405
- # create_orders = server_java.create_orders(user_id=user_id, cartId=cart_id, token=token)
406
- # order_id = create_orders["body"]["orderId"]
407
- # print(f"✅ Đơn hàng được tạo: order_id = {order_id}")
408
- # except Exception as e:
409
- # print(f"❌ Lỗi khi tạo đơn hàng: {e}")
410
- # order_id = None
411
-
412
- # if order_id:
413
- # try:
414
- # print("🔹 [STEP 5] Xác nhận đơn hàng với AI...")
415
- # confirm_order = server_java.confirm_orders_AI(user_id=user_id, token=token, orderId=order_id)
416
- # print("✅ Phản hồi xác nhận đơn hàng từ AI:")
417
- # print(confirm_order["body"])
418
- # if confirm_order["body"] == "Confirm success":
419
- # chat_cart.status = "confirmed"
420
- # chat_cart.confirmed_order = True
421
- # chat_cart.save()
422
- # from urllib.parse import urlencode
423
- # base_url = "https://vnexpress.net/tin-tuc-24h"
424
- # params = {
425
- # "order_id": order_id,
426
- # "token": token,
427
- # "user_id": user_id
428
- # }
429
- # link_payment = f"https://vnexpress.net/tin-tuc-24h?order_id={order_id}&token={token}&user_id={user_id}"
430
-
431
-
432
-
433
- # return "Yêu cầu: " + str(task) + f". Yêu cầu của bạn đã thành công. Tình trạng giỏ hiện tại (Luôn luôn hiển thị lại trạng thái này để người dùng biết giỏ của họ) {clean_list}. Bạn đã xác nhận thanh toán thành công sẽ tiến hành chuyển sang link thanh toán{link_payment}. Vui lòng thực hiện thanh toán trên trang này trong vòng 30 phút tối đa" + str(results)
434
- # else:
435
- # chat_cart.status = "failed"
436
- # chat_cart.confirmed_order = False
437
- # chat_cart.save()
438
-
439
- # except Exception as e:
440
- # print(f"❌ Lỗi khi xác nhận đơn hàng với AI: {e}")
441
- # chat_cart.status = "failed"
442
- # chat_cart.confirmed_order = False
443
- # chat_cart.save()
444
-
445
- # if check_shopping["is_confirm_order"] == "No" and len(clean_cart_products) != 0 :
446
- # result_final += "Yêu cầu: " + str(task) + f". Yêu cầu của bạn đã thành công. Tình trạng giỏ hiện tại(Luôn luôn hiển thị lại trạng thái này để người dùng biết giỏ của họ): {clean_list}" + "kết quả thực thi:" + str(results)
447
-
448
- # return result_final
449
- # else:
450
- # task = filter_sql_injection_1.normalize_query(task)
451
- # filtered_input = filter_sql_injection_1.filter_sql_injection(task)
452
- # filtered_role_input = filter_role_1.filter_role(filtered_input)
453
- # result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
454
- # result_final = query_result_1.query_result(task, result)
455
- # return result_final
456
- # else:
457
- # result = ""
458
- # task = filter_sql_injection_1.normalize_query(task)
459
- # filtered_input = filter_sql_injection_1.filter_sql_injection(task)
460
- # filtered_role_input = filter_role_1.filter_role(filtered_input)
461
- # output = await chat_sql.generate_and_save_code(filtered_role_input, user_id, role, languages)
462
- # if isinstance(output, tuple):
463
- # result, path_image = output
464
- # else:
465
- # result = output
466
- # path_image = None
467
-
468
- # if path_image and os.path.exists(path_image):
469
- # images_md = upload_images_to_cloudinary_and_markdown(path_image)
470
- # if images_md:
471
- # result = f"### Tất cả Hình ảnh sinh ra:\n\n{images_md}\n\n{result}"
472
- # return result
473
-
474
-
475
- #
476
- # ----- PHẦN 2: HÀM AGENT_SQL ĐÃ TÁI CẤU TRÚC -----
477
- #
478
-
479
- # --- Các hàm trợ giúp (Helper Functions) ---
480
- from typing import Optional
481
- async def _handle_shopping_intent(task: str, user_id: int, chat_id: Any, token: str, languages,role, stop_event: Optional[asyncio.Event]) -> str:
482
- """
483
- Xử lý các tác vụ liên quan đến mua sắm: xem giỏ, thêm/sửa/xóa, xác nhận đơn hàng.
484
- """
485
- result_check = await check_should_stop(chat_id, stop_event)
486
- if result_check:
487
- return result_check
488
- try:
489
- result_check = await check_should_stop(chat_id, stop_event)
490
- if result_check:
491
- return result_check
492
- cart_status = "Yes (Đang Pending)" if chat_history_has_unconfirmed_cart(chat_id) else "No (Không có)"
493
- prompt_context = multitool_prompt.build_multi_tool_prompt(
494
- question=get_last_ai_message(chat_id),
495
- tools=["confirm_order", "insert_cart", "update_cart", "delete_item_cart", "deleted all cart"],
496
- user_answer=task
497
- )
498
- data_context = tool_call.generate(prompt_context)
499
- print(f"DEBUG: data_context: {data_context}")
500
-
501
- # 2. Lấy giỏ hàng đang chờ xử lý hoặc tạo mới
502
- result_check = await check_should_stop(chat_id, stop_event)
503
- if result_check:
504
- return result_check
505
-
506
- latest_unconfirmed_cart = ChatCart.objects(chat_history=chat_id, status="pending").order_by('-created_at').first()
507
- if latest_unconfirmed_cart:
508
- chat_cart = latest_unconfirmed_cart
509
- previous_cart_items = [p.to_mongo().to_dict() for p in chat_cart.cart_products]
510
- print("INFO: Đã tìm thấy giỏ hàng 'pending', sẽ cập nhật.")
511
- else:
512
- chat_cart = ChatCart(chat_history=chat_id, status="pending")
513
- previous_cart_items = []
514
- print("INFO: Không tìm thấy giỏ hàng 'pending', sẽ tạo mới.")
515
-
516
- #Backup data
517
- chat_cart.backup_cart_products = chat_cart.cart_products.copy()
518
- chat_cart.backup_status = chat_cart.status
519
- chat_cart.backup_confirmed_order = chat_cart.confirmed_order
520
- chat_cart.save()
521
-
522
- # 3. Trích xuất và xử lý thông tin sản phẩm từ câu hỏi của người dùng
523
- result_check = await check_should_stop(chat_id, stop_event)
524
- if result_check:
525
- return result_check
526
- new_items_str = test_func.classify_data(input=f"{data_context.get('question', '')}", structured_data=previous_cart_items)
527
- new_items_list = json.loads(new_items_str) if new_items_str and new_items_str != "None" else []
528
- updated_cart_list = process_data(previous_cart_items, new_items_list)
529
-
530
- # 4. Xác thực sản phẩm và cập nhật giỏ hàng trong DB
531
- result_check = await check_should_stop(chat_id, stop_event)
532
- if result_check:
533
- return result_check
534
- annotated_list, clean_list, validation_message = test_func.validate_product_list(data_list=updated_cart_list, server_java=server_java)
535
-
536
- # clean_cart_products = [CartProduct(**item) for item in clean_list]
537
- clean_cart_products = []
538
- for item in clean_list:
539
- # Đảm bảo quantity là số nguyên
540
- product = CartProduct(
541
- name=item.get('name'),
542
- size=item.get('size'),
543
- quantity=int(item.get('quantity', 1))
544
- )
545
- clean_cart_products.append(product)
546
- print("Clean_cart", clean_cart_products)
547
- chat_cart.cart_products = clean_cart_products
548
- chat_cart.save()
549
- print(f"INFO: Giỏ hàng đã được cập nhật với {len(clean_cart_products)} sản phẩm.")
550
-
551
- # 5. Xử lý các câu hỏi phụ (nếu có)
552
- result_check = await check_should_stop(chat_id, stop_event)
553
- if result_check:
554
- return result_check
555
- other_results = []
556
- if data_context.get("question_normal"):
557
- for q_key, q_text in data_context["question_normal"].items():
558
- result_check = await check_should_stop(chat_id, stop_event)
559
- if result_check:
560
- return result_check
561
- result = await _handle_simple_query(q_text, user_id, languages, role, stop_event, chat_id)
562
- other_results.append({"question": q_text, "result": result})
563
-
564
- result_check = await check_should_stop(chat_id, stop_event)
565
- if result_check:
566
- return result_check
567
- response_parts = []
568
- if validation_message:
569
- response_parts.append(validation_message)
570
-
571
- final_cart_state_msg = f"Tình trạng giỏ hàng hiện tại của bạn: {clean_list}"
572
- result_check = await check_should_stop(chat_id, stop_event)
573
- if result_check:
574
- return result_check
575
-
576
- shopping_intent = tool_call.generate(user_intent.build_detailed_user_intent_prompt(
577
- user_question=task, chat_history=get_chat_history(chat_id), cart_status=cart_status
578
- ))
579
-
580
- result_check = await check_should_stop(chat_id, stop_event)
581
- if result_check:
582
- return result_check
583
- if shopping_intent.get("is_delete_cart") == "Yes":
584
- chat_cart.cart_products = []
585
- chat_cart.status = "failed"
586
- chat_cart.save()
587
- response_parts.append("Đã xóa toàn bộ sản phẩm trong giỏ hàng.")
588
- final_cart_state_msg = "Tình trạng giỏ hàng hiện tại của bạn: Giỏ hàng trống."
589
- elif shopping_intent.get("is_view_cart") == "Yes":
590
- result_check = await check_should_stop(chat_id, stop_event)
591
- if result_check:
592
- return result_check
593
- response_parts.append("Đây là giỏ hàng của bạn.")
594
- elif shopping_intent.get("is_confirm_order") == "Yes":
595
- result_check = await check_should_stop(chat_id, stop_event)
596
- if result_check:
597
- return result_check
598
- if not chat_cart.cart_products:
599
- return "Giỏ hàng của bạn đang trống. Vui lòng thêm sản phẩm trước khi xác nhận đơn hàng."
600
- result_check = await check_should_stop(chat_id, stop_event)
601
- if result_check:
602
- return result_check
603
- confirmation_result = await _execute_order_confirmation(user_id, token, chat_cart, stop_event,chat_id)
604
- confirmation_result_str = ""
605
- result_check = await check_should_stop(chat_id, stop_event)
606
- if result_check:
607
- chat_cart.status = chat_cart.backup_status
608
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
609
- chat_cart.save()
610
- if confirmation_result[1]:
611
- server_java.confirm_cancel_AI(int(user_id),token,confirmation_result[1])
612
- server_java.remove_all_cartItem(int(user_id), confirmation_result[2], token)
613
- confirmation_result_str = confirmation_result[0]
614
- else:
615
- confirmation_result_str = confirmation_result
616
- return result_check
617
-
618
- response_parts.append(str(confirmation_result))
619
- else:
620
- response_parts.append(f"Yêu cầu '{task}' của bạn đã được xử lý.")
621
-
622
- response_parts.append(final_cart_state_msg)
623
- if other_results:
624
- response_parts.append(f"Kết quả cho các câu hỏi khác: {other_results}")
625
-
626
- return " ".join(response_parts)
627
- except asyncio.CancelledError as e:
628
- print(f"STOP: {e}")
629
- if 'chat_cart' in locals():
630
- if chat_cart.backup_cart_products:
631
- chat_cart.cart_products = chat_cart.backup_cart_products
632
- chat_cart.status = chat_cart.backup_status
633
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
634
- chat_cart.save()
635
- print("INFO: Đã khôi phục giỏ hàng từ bản backup do bị hủy.")
636
- return "Quá trình đã bị dừng theo yêu cầu. Giỏ hàng đã được khôi phục như ban đầu."
637
- # except Exception as e:
638
- # print(f"ERROR in _handle_shopping_intent: {e}")
639
- # return "Đã có lỗi xảy ra trong quá trình xử lý yêu cầu mua sắm của bạn. Vui lòng thử lại."
640
-
641
-
642
- # async def rollback_cart_and_order(chat_cart: ChatCart, user_id: int, token: str):
643
- # try:
644
- # if chat_cart.temp_order_id:
645
- # server_java.delete_order(chat_cart.temp_order_id, token)
646
- # print(f"INFO: Đã rollback đơn hàng {chat_cart.temp_order_id}")
647
- # if chat_cart.temp_cart_id:
648
- # server_java.delete_cart(chat_cart.temp_cart_id, token)
649
- # print(f"INFO: Đã rollback giỏ hàng {chat_cart.temp_cart_id}")
650
- # chat_cart.status = "cancelled"
651
- # chat_cart.save()
652
- # except Exception as e:
653
- # print(f"WARNING: Lỗi khi rollback: {e}")
654
-
655
-
656
- async def rollback_cart_and_order(chat_cart: ChatCart, user_id: int, token: str,order_id):
657
- try:
658
- if chat_cart.temp_order_id:
659
- server_java.delete_order(chat_cart.temp_order_id, token)
660
- print(f"INFO: Đã rollback đơn hàng {chat_cart.temp_order_id}")
661
- if chat_cart.temp_cart_id:
662
- server_java.delete_cart(chat_cart.temp_cart_id, token)
663
- print(f"INFO: Đã rollback giỏ hàng {chat_cart.temp_cart_id}")
664
- chat_cart.status = "cancelled"
665
- chat_cart.save()
666
- except Exception as e:
667
- print(f"WARNING: Lỗi khi rollback: {e}")
668
-
669
-
670
- async def _execute_order_confirmation(user_id: int, token: str, chat_cart: ChatCart, stop_event: Optional[asyncio.Event],chat_id:str= ""):
671
- """
672
- Thực hiện quy trình 5 bước để xác nhận đơn hàng với server_java.
673
- """
674
- try:
675
-
676
- #Backup data
677
- chat_cart.backup_status = chat_cart.status
678
- chat_cart.backup_confirmed_order = chat_cart.confirmed_order
679
- chat_cart.save()
680
-
681
- print("INFO: Bắt đầu quy trình xác nhận đơn hàng.")
682
-
683
- result_check = await check_should_stop(chat_id, stop_event)
684
- if result_check:
685
- chat_cart.status = chat_cart.backup_status
686
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
687
- chat_cart.save()
688
- return result_check
689
- cart_data = server_java.create_cart(int(user_id), token)
690
- cart_id = cart_data.get("cartId")
691
- if not cart_id: raise Exception("Không thể tạo giỏ hàng trên hệ thống.")
692
- print(f"SUCCESS: Tạo giỏ hàng tạm thành công: cart_id = {cart_id}")
693
-
694
- # Step 2 & 3: Add items to cart
695
- for item in chat_cart.cart_products:
696
- result_check = await check_should_stop(chat_id, stop_event)
697
- if result_check:
698
- chat_cart.status = chat_cart.backup_status
699
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
700
- chat_cart.save()
701
- rollback = server_java.remove_all_cartItem(int(user_id), cart_id, token)
702
- return result_check
703
- pro_id, _, size_check, _, _ = server_java.search_product(keyword=item.name, size=item.size)
704
- server_java.insert_cartItem(user_id, cart_id, pro_id, size_check, item.quantity, token)
705
- print(f"SUCCESS: Đã thêm '{item.name}' vào giỏ hàng tạm.")
706
-
707
- # Step 4: Create Order
708
- result_check = await check_should_stop(chat_id, stop_event)
709
- if result_check:
710
- chat_cart.status = "pending"
711
- chat_cart.confirmed_order = False
712
- chat_cart.save()
713
- server_java.remove_all_cartItem(int(user_id), cart_id, token)
714
- return result_check
715
- order_data = server_java.create_orders(user_id=user_id, cartId=cart_id, token=token)
716
- order_id = order_data["body"]["orderId"]
717
- if not order_id: raise Exception("Không thể tạo đơn hàng từ giỏ hàng.")
718
- print(f"SUCCESS: Tạo đơn hàng thành công: order_id = {order_id}")
719
-
720
- # Step 5: Confirm Order
721
- result_check = await check_should_stop(chat_id, stop_event)
722
- if result_check:
723
- chat_cart.status = chat_cart.backup_status
724
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
725
- chat_cart.save()
726
- server_java.confirm_cancel_AI(int(user_id),token,order_id)
727
- server_java.remove_all_cartItem(int(user_id), cart_id, token)
728
- return result_check
729
- confirm_data = server_java.confirm_orders_AI(user_id=user_id, token=token, orderId=order_id)
730
- if confirm_data.get("body") == "Confirm success":
731
- chat_cart.status = "confirmed"
732
- chat_cart.confirmed_order = True
733
- chat_cart.order_id = order_id
734
- chat_cart.cart_id = cart_id
735
- chat_cart.save()
736
- link_payment = f"http://localhost:5173/payment?order_id={order_id}&token={token}&user_id={user_id}"
737
- data = f"Đơn hàng của bạn đã được xác nhận thành công. Vui lòng truy cập link sau để thanh toán trong vòng 30 phút: {link_payment}(Vui lòng không bỏ sót link này)"
738
- return data, order_id, cart_id
739
- else:
740
- print(f"Hệ thống không thể xác nhận đơn hàng. Phản hồi: {confirm_data.get('body')}")
741
-
742
- result_check = await check_should_stop(chat_id, stop_event)
743
- if result_check:
744
- chat_cart.status = chat_cart.backup_status
745
- chat_cart.confirmed_order = chat_cart.backup_confirmed_order
746
- chat_cart.save()
747
- server_java.confirm_cancel_AI(int(user_id),token,order_id)
748
- server_java.remove_all_cartItem(int(user_id), cart_id, token)
749
-
750
- except Exception as e:
751
- print(f"ERROR in _execute_order_confirmation: {e}")
752
- chat_cart.status = "failed"
753
- chat_cart.save()
754
- return f"Đã xảy ra lỗi khi xác nhận đơn hàng: {e}. Giỏ hàng của bạn vẫn được lưu."
755
-
756
-
757
- async def _handle_simple_query(task: str, user_id: int, languages: List[str], role: str,stop_event: Optional[asyncio.Event],chat_id: str = "") -> str:
758
- """Xử lý một câu hỏi SQL đơn giản."""
759
- result_check = await check_should_stop(chat_id, stop_event)
760
- if result_check:
761
- return result_check
762
- normalized_task = filter_sql_injection_1.normalize_query(task)
763
- result_check = await check_should_stop(chat_id, stop_event)
764
- if result_check:
765
- return result_check
766
- filtered_input = filter_sql_injection_1.filter_sql_injection(normalized_task)
767
- result_check = await check_should_stop(chat_id, stop_event)
768
- if result_check:
769
- return result_check
770
- filtered_role_input = filter_role_1.filter_role(filtered_input)
771
- result_check = await check_should_stop(chat_id, stop_event)
772
- if result_check:
773
- return result_check
774
- query_result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
775
- result_check = await check_should_stop(chat_id, stop_event)
776
- if result_check:
777
- return result_check
778
- return query_result_1.query_result(task, query_result)
779
-
780
-
781
- async def _handle_analysis_intent(task: str, user_id: int, languages: List[str], role: str, stop_event: Optional[asyncio.Event],chat_id: str = "") -> str:
782
- """Xử lý các tác vụ yêu cầu phân tích, sinh code và vẽ biểu đồ."""
783
- result_check = await check_should_stop(chat_id, stop_event)
784
- if result_check:
785
- return result_check
786
-
787
- normalized_task = filter_sql_injection_1.normalize_query(task)
788
- filtered_input = filter_sql_injection_1.filter_sql_injection(normalized_task)
789
- filtered_role_input = filter_role_1.filter_role(filtered_input)
790
-
791
- result_check = await check_should_stop(chat_id, stop_event)
792
- if result_check:
793
- return result_check
794
- output = await chat_sql.generate_and_save_code(
795
- filtered_role_input,
796
- user_id,
797
- role,
798
- languages,
799
- stop_event,
800
- chat_id=chat_id
801
- )
802
-
803
-
804
-
805
- result_check = await check_should_stop(chat_id, stop_event)
806
- if result_check:
807
- return result_check
808
- result, path_image = output if isinstance(output, tuple) else (output, None)
809
-
810
- if path_image and os.path.exists(path_image):
811
- result_check = await check_should_stop(chat_id, stop_event)
812
- if result_check:
813
- return result_check # Trả về kết quả đã có
814
-
815
- images_md = upload_images_to_cloudinary_and_markdown(path_image)
816
- if images_md:
817
- result = f"### Biểu đồ được tạo:\n\n{images_md}\n\n{result}"
818
-
819
- return result
820
-
821
-
822
- # --- Hàm chính (Main Function) ---
823
-
824
- async def agent_sql(task: str, user_id: int, languages: str, role: str, chat_id: Any, token: str, stop_event: Optional[asyncio.Event] = None):
825
- """
826
- Hàm chính điều phối các tác vụ, có khả năng dừng giữa chừng.
827
- """
828
- # KIỂM TRA DỪNG NGAY LẬP TỨC
829
- result_check = await check_should_stop(chat_id, stop_event)
830
- if result_check:
831
- return result_check
832
-
833
- # 1. KIỂM TRA AN TOÀN BAN ĐẦU
834
- if filter_sql_injection_1.filter_question_remove_restore(task):
835
- return "Bạn không được phép khôi phục hoặc xóa dữ liệu. Vui lòng kiểm tra lại câu hỏi của bạn."
836
-
837
- # 2. PHÂN LOẠI Ý ĐỊNH CHÍNH: PHÂN TÍCH (cần sinh code) vs HỎI ĐÁP/MUA SẮM
838
- is_analysis_task = filter_sql_injection_1.filter_task_analyze(task)
839
-
840
- result_check = await check_should_stop(chat_id, stop_event)
841
- if result_check:
842
- return result_check
843
- if is_analysis_task:
844
- print("INFO: Nhận diện ý định PHÂN TÍCH.")
845
- if result_check:
846
- return result_check
847
- data = await _handle_analysis_intent(task, user_id, languages, role, stop_event,chat_id)
848
- if result_check:
849
- return result_check
850
- return data, False
851
-
852
-
853
- # 3. PHÂN LOẠI Ý ĐỊNH PHỤ: MUA SẮM vs HỎI ĐÁP THÔNG THƯỜNG
854
- result_check = await check_should_stop(chat_id, stop_event)
855
- if result_check:
856
- return result_check
857
- cart_status = "Yes (Đang Pending)" if chat_history_has_unconfirmed_cart(chat_id) else "No (Không có)"
858
- prompt_check_shopping = user_intent.build_detailed_user_intent_prompt(
859
- user_question=task,
860
- chat_history=get_chat_history(chat_id),
861
- cart_status=cart_status
862
- )
863
-
864
- result_check = await check_should_stop(chat_id, stop_event)
865
- if result_check:
866
- return result_check
867
-
868
- intent_result = tool_call.generate(prompt_check_shopping)
869
- result_check = await check_should_stop(chat_id, stop_event)
870
- if result_check:
871
- return result_check
872
- if str(intent_result.get("type")) == "shopping_question":
873
- print("INFO: Nhận diện ý định MUA SẮM.")
874
- result = await _handle_shopping_intent(task, user_id, chat_id, token, languages, role, stop_event)
875
- result = query_result_1.query_result(task, result)
876
- return result, True
877
- else:
878
- print("INFO: Nhận diện ý định HỎI ĐÁP THÔNG THƯỜNG.")
879
- result = await _handle_simple_query(task, user_id, languages, role, stop_event,chat_id)
880
- result = query_result_1.query_result(task, result)
881
- return result, False
882
-
883
-
884
- async def agent_general(task, user_id, languages, role, chat_id, token, stop_event):
885
- task = filter_sql_injection_1.normalize_query(task)
886
- # Kiểm tra stop event trước khi gọi xử lý nặng
887
- result_check = await check_should_stop(chat_id, stop_event)
888
- if result_check:
889
- return result_check
890
- # Gọi xử lý chính
891
- result_task = asyncio.create_task(res_general.response_general(task))
892
- # Chờ xử lý, nhưng cũng kiểm tra stop event
893
- while not result_task.done():
894
- if stop_event.is_set():
895
- print("Tín hiệu stop trong quá trình xử lý. Hủy task.")
896
- result_task.cancel()
897
- try:
898
- await result_task
899
- except asyncio.CancelledError:
900
- print("Task đã bị huỷ.")
901
- return None
902
- await asyncio.sleep(0.1) # Cho các task khác thời gian chạy
903
-
904
-
905
- function_mapping = {
906
- "question_hello": agent_hello,
907
- "question_information": agent_information,
908
- "question_sql": agent_sql,
909
- "question_general": agent_general
910
-
911
- }
912
-
913
-
914
- from typing import Optional
915
- async def process_toolcalls_with_order(toolcalls,token, stop_event: Optional[asyncio.Event] = None, chat_id:str = ""):
916
- task_results = {}
917
- ordered_results = {}
918
- filtered_toolcalls = [tc for tc in toolcalls if tc["name"] in function_mapping]
919
- for tc in filtered_toolcalls:
920
-
921
- orig_name = tc["name"]
922
- task_func = function_mapping.get(orig_name)
923
- if task_func is None:
924
- continue
925
- task_param = tc["args"].get("query", "")
926
- user_id = tc.get("user_id", "unknown_user")
927
- role = tc.get("role", "unknown_role")
928
- language = tc.get("language", "unknown_language")
929
- chat_id = tc.get("chat_id","unknow")
930
- if asyncio.iscoroutinefunction(task_func):
931
- result = await task_func(task_param, user_id, language,role,chat_id,token,stop_event)
932
- else:
933
- result = task_func(task_param, user_id, language,role,chat_id,token,stop_event)
934
- if isinstance(result, tuple) and len(result) == 2:
935
- result, is_shopping = result
936
- else:
937
- result = result
938
- is_shopping = False
939
- # Lưu kết quả theo id của tool_call
940
- task_results[tc["id"]] = {
941
- "result": result,
942
- "user_id": user_id,
943
- "role": role,
944
- "language": language,
945
- "is_shopping": is_shopping
946
- }
947
-
948
-
949
- ordered_results = {tc["id"]: task_results.get(tc["id"], {"result": "Không có kết quả"}) for tc in filtered_toolcalls}
950
  return ordered_results
 
1
+ import asyncio
2
+ import json
3
+ import os,sys
4
+ BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../"))
5
+ sys.path.insert(0, BASE_DIR)
6
+ from function.file import extract_file as extract_file
7
+ import function.filter.filter_role as filter_role_1
8
+ import function.filter.filter_sql_injection as filter_sql_injection_1
9
+ import function.filter.result as query_result_1
10
+ import function.chat as chat_sql
11
+ import function.gemini_response.response_general as res_general
12
+ import function.gemini_response.response_hello as res_hello
13
+ import cloudinary
14
+ import cloudinary.uploader
15
+ from typing import List,Any
16
+ import cloudinary
17
+ from cloudinary.utils import cloudinary_url
18
+ from cloudinary import uploader
19
+ from typing import Optional
20
+ import asyncio
21
+ from models.Database_Entity import StopSignal
22
+
23
+
24
+ async def check_should_stop(chat_id: str, stop_event:Optional[asyncio.Event]):
25
+ # Trường hợp dừng qua RAM (in-memory)
26
+ await asyncio.sleep(0.1)
27
+ if stop_event and stop_event.is_set():
28
+ print("🛑 Dừng qua stop_event.")
29
+ return {"status": "cancelled"}
30
+
31
+ # Trường hợp dừng qua MongoDB
32
+ await asyncio.sleep(0.1)
33
+ if StopSignal.objects(chat_history= chat_id, is_stopped=True).first():
34
+ print("🛑 Dừng vì có StopSignal trong DB.")
35
+ return {"status": "cancelled"}
36
+
37
+ return None
38
+
39
+ # Dán nguyên chuỗi URL này vào
40
+ cloudinary.config(
41
+ cloud_name = "dgj8n2ggn",
42
+ api_key = "287331723817617",
43
+ api_secret = "MAI7dpoikIy-ap7IjPCiwfRgMQ0",
44
+ secure=True
45
+ )
46
+
47
+ def upload_images_to_cloudinary_and_markdown(folder_path):
48
+ markdown_images = ""
49
+ image_files = [
50
+ f for f in os.listdir(folder_path)
51
+ if f.lower().endswith(('.png', '.jpg', '.jpeg'))
52
+ ]
53
+
54
+ for img in image_files:
55
+ img_path = os.path.join(folder_path, img)
56
+ try:
57
+ upload_result = cloudinary.uploader.upload(img_path)
58
+ print(img_path)
59
+ image_url = upload_result.get("secure_url")
60
+ print(image_url)
61
+ if image_url:
62
+ markdown_images += f"![{img}]({image_url})\n\n"
63
+ except Exception as e:
64
+ print(f"❌ Upload lỗi với ảnh {img}: {e}")
65
+ return markdown_images
66
+
67
+
68
+ async def agent_information(task,user_id,languages, role, chat_id,token,stop_event: Optional[asyncio.Event]):
69
+ result_check = await check_should_stop(chat_id,stop_event)
70
+ if result_check:
71
+ return result_check
72
+ text_all= extract_file.extract_data2()
73
+ result_check = await check_should_stop(chat_id,stop_event)
74
+ if result_check:
75
+ return result_check
76
+ task = filter_sql_injection_1.normalize_query(task)
77
+ print("text: ",text_all)
78
+ result_check = await check_should_stop(chat_id,stop_event)
79
+ if result_check:
80
+ return result_check
81
+ return extract_file.handle_query_upgrade_keyword_old(f"{task}",text_all,"demohmdrinks")
82
+
83
+
84
+ async def agent_hello(task,user_id,languages, role,chat_id,token,stop_event: Optional[asyncio.Event]):
85
+ result_check = await check_should_stop(chat_id,stop_event)
86
+ if result_check:
87
+ return result_check
88
+ result = await res_hello.response_hello(task)
89
+ result_check = await check_should_stop(chat_id,stop_event)
90
+ if result_check:
91
+ return result_check
92
+ return result
93
+
94
+
95
+ from mongoengine import connect
96
+ from dotenv import load_dotenv
97
+ load_dotenv()
98
+ MONGO_URI = os.getenv("MONGO_URI", "")
99
+ connect("chatbot_hmdrinks", host=MONGO_URI)
100
+
101
+ from models.Database_Entity import User, ChatHistory, DetailChat
102
+ def get_chat_history(chat_history_id):
103
+ messages = DetailChat.objects(chat_history=chat_history_id).order_by('timestamp')
104
+ history_text = ""
105
+ for msg in messages:
106
+ history_text += f"Người dùng hỏi: {msg.you_message}\n"
107
+ history_text += f"Trợ lý: {msg.ai_message}\n\n"
108
+ return history_text.strip()
109
+
110
+
111
+ from mongoengine import connect
112
+ from dotenv import load_dotenv
113
+ load_dotenv()
114
+ MONGO_URI = os.getenv("MONGO_URI", "")
115
+ connect("chatbot_hmdrinks", host=MONGO_URI)
116
+ import sys
117
+ import os
118
+
119
+ project_root = os.path.abspath(os.path.join(os.getcwd(), '..', '..', '..'))
120
+
121
+ if project_root not in sys.path:
122
+ sys.path.append(project_root)
123
+ from models.Database_Entity import User, ChatHistory, DetailChat,ChatCart, CartProduct
124
+ import base64
125
+ from advance_shopping.prompt import context_prompt, multitool_prompt, user_intent
126
+
127
+ from advance_shopping.call_gemini import tool_call
128
+ from advance_shopping.server_java import server_java
129
+ from advance_shopping.function import test as test_func
130
+
131
+
132
+ def get_chat_history(chat_history_id):
133
+ messages = DetailChat.objects(chat_history=chat_history_id).order_by('timestamp')
134
+ print(DetailChat._meta) # in ra cấu hình model
135
+
136
+ history_text = ""
137
+ for msg in messages:
138
+ history_text += f"Người dùng: {msg.you_message}\n"
139
+ history_text += f"Trợ lý: {msg.ai_message}\n\n"
140
+ return history_text.strip()
141
+
142
+
143
+ from bson import ObjectId
144
+ def chat_history_has_unconfirmed_cart(chat_history_id: str) -> bool:
145
+ """
146
+ Trả về True nếu trong đoạn chat có giỏ hàng chưa được xác nhận đặt hàng.
147
+ Trả về False nếu không có giỏ hàng, hoặc tất cả giỏ hàng đã được xác nhận.
148
+ """
149
+ return ChatCart.objects(
150
+ chat_history=ObjectId(chat_history_id),
151
+ status="pending"
152
+ ).count() > 0
153
+
154
+
155
+ from bson import ObjectId
156
+
157
+
158
+ def process_data(structured_data, data):
159
+ list_data1 = structured_data[:]
160
+ print("data",data)
161
+ if data == "None":
162
+ return structured_data
163
+ if isinstance(data, list) and not data:
164
+ print("✅ Đây là một list rỗng.")
165
+ return structured_data
166
+ if data:
167
+ for item in data:
168
+ action = item.get("action", "").lower()
169
+ name = item.get("name", "").strip().lower()
170
+ size = item.get("size", "").strip().lower()
171
+ size_old = item.get("size_old", "").strip().lower() if "size_old" in item else None
172
+
173
+ matched = False
174
+ if action == "update" and size_old:
175
+ for item_old in list_data1:
176
+ name_old = item_old.get("name", "").strip().lower()
177
+ size_old_in_list = item_old.get("size", "").strip().lower()
178
+
179
+ if name == name_old and size_old == size_old_in_list:
180
+ matched = True
181
+ # Cập nhật các trường
182
+ for key in ["quantity", "size"]:
183
+ if key in item:
184
+ item_old[key] = item[key]
185
+ break
186
+
187
+ else:
188
+ for item_old in list_data1:
189
+ name_old = item_old.get("name", "").strip().lower()
190
+ size_old_in_list = item_old.get("size", "").strip().lower()
191
+
192
+ if name == name_old and size == size_old_in_list:
193
+ matched = True
194
+
195
+ if action == "delete":
196
+ list_data1.remove(item_old)
197
+ break
198
+
199
+ elif action == "update":
200
+ for key in ["quantity", "size"]:
201
+ if key in item:
202
+ item_old[key] = item[key]
203
+ break
204
+ elif action == "add":
205
+ if "quantity" in item:
206
+ item_old["quantity"] = int(item_old.get("quantity", 0)) + int(item["quantity"])
207
+ break
208
+
209
+ if not matched and action == "add":
210
+ item_to_add = {k: v for k, v in item.items() if k != "action"}
211
+ list_data1.append(item_to_add)
212
+ filtered_list = []
213
+ for item in list_data1:
214
+ if (item.get("name") not in [None, "", "None"]):
215
+ filtered_list.append(item)
216
+ return filtered_list
217
+
218
+
219
+ def get_last_ai_message(chat_history_id: str) -> str:
220
+ last_detail = DetailChat.objects(
221
+ chat_history=ObjectId(chat_history_id),
222
+ ai_message__ne=None
223
+ ).order_by('-timestamp').first()
224
+
225
+ return last_detail.ai_message if last_detail else "None"
226
+
227
+
228
+ # async def agent_sql(task,user_id,languages, role, chat_id,token,stop_event: Optional[asyncio.Event] = None):
229
+ # check_analyze = filter_sql_injection_1.filter_task_analyze(task)
230
+ # check_restore_delete = filter_sql_injection_1.filter_question_remove_restore(task)
231
+ # prompt_check_shopping = ""
232
+ # print(check_restore_delete)
233
+ # if check_restore_delete == True:
234
+ # return "Bạn không được phép khôi phục hoặc xóa dữ liệu. Vui lòng kiểm tra lại câu hỏi của bạn."
235
+ # print(check_analyze)
236
+ # if check_analyze == False:
237
+ # result_final = ""
238
+ # cart_status = ""
239
+ # if chat_history_has_unconfirmed_cart(chat_id) is True:
240
+ # cart_status = "Yes (Đang Pending)"
241
+ # else:
242
+ # cart_status = "No (Không có)"
243
+
244
+ # print(cart_status)
245
+ # prompt_check_shopping = user_intent.build_detailed_user_intent_prompt(user_question=task,
246
+ # chat_history=get_chat_history(chat_id),
247
+ # cart_status=cart_status)
248
+ # check_shopping = tool_call.generate(prompt_check_shopping)
249
+ # print(check_shopping)
250
+ # type = check_shopping["type"]
251
+ # if str(type) == "shopping_question":
252
+ # tools = ["confirm_order", "insert_cart", "update_cart", "delete_item_cart", "deleted all cart"]
253
+ # last_ai_message = get_last_ai_message(chat_id)
254
+ # context_prompt = multitool_prompt.build_multi_tool_prompt(question=last_ai_message,tools=tools,user_answer=task)
255
+ # data_context = {}
256
+ # try:
257
+ # data_context = tool_call.generate(context_prompt)
258
+ # if not data_context["question"]:
259
+ # data_context = tool_call.generate(context_prompt)
260
+ # except:
261
+ # data_context = tool_call.generate(context_prompt)
262
+ # if not data_context["question"]:
263
+ # data_context = tool_call.generate(context_prompt)
264
+ # print("data_context: ",data_context)
265
+ # question_new = data_context["question"]
266
+ # latest_unconfirmed_cart = ChatCart.objects(
267
+ # chat_history=chat_id,
268
+ # status="pending"
269
+ # ).order_by('-created_at').first()
270
+ # previous_data = []
271
+ # if latest_unconfirmed_cart:
272
+ # for product in latest_unconfirmed_cart.cart_products:
273
+ # product_dict = product.to_mongo().to_dict()
274
+ # if "_id" in product_dict:
275
+ # product_dict["_id"] = str(product_dict["_id"])
276
+ # previous_data.append(product_dict)
277
+
278
+
279
+ # data = test_func.classify_data(input = f"""{question_new}""", structured_data=previous_data)
280
+ # list_data = list()
281
+ # print(data)
282
+ # if data == "None" or data == '':
283
+ # data = list()
284
+ # else:
285
+ # try:
286
+ # list_data = json.loads(data)
287
+ # except:
288
+ # list_data = list()
289
+ # print("List data:", list_data)
290
+ # print("Preious_data", previous_data)
291
+ # previous_data = list(previous_data)
292
+ # list_data1 = previous_data
293
+ # clean_list = list()
294
+ # full_test = ""
295
+ # result = []
296
+ # print(list_data)
297
+ # try:
298
+ # print("Nhay vo test2")
299
+ # result = process_data(list_data1, list_data)
300
+ # except:
301
+ # if data is None or data == "None":
302
+ # print("Nhay vo test1")
303
+ # result = process_data(list_data1, [])
304
+ # clean_cart_products = []
305
+ # chat_cart = ChatCart()
306
+ # if list_data:
307
+ # annotated_list, clean_list, full_test = test_func.validate_product_list(data_list=result,server_java=server_java)
308
+ # print(result)
309
+ # print(clean_list)
310
+
311
+ # results = []
312
+ # if data_context["question_normal"]:
313
+
314
+ # for key, q in data_context["question_normal"].items():
315
+ # task_1 = filter_sql_injection_1.normalize_query(q)
316
+ # filtered_input = filter_sql_injection_1.filter_sql_injection(task_1)
317
+ # filtered_role_input = filter_role_1.filter_role(filtered_input)
318
+ # result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
319
+ # result_final = query_result_1.query_result(task, result)
320
+ # results.append({"question": q, "result": result_final})
321
+
322
+ # result_final += str(results)
323
+
324
+ # for item in clean_list:
325
+ # # Đảm bảo quantity là số nguyên
326
+ # product = CartProduct(
327
+ # name=item.get('name'),
328
+ # size=item.get('size'),
329
+ # quantity=int(item.get('quantity', 1))
330
+ # )
331
+ # clean_cart_products.append(product)
332
+ # print("Clean_cart", clean_cart_products)
333
+ # print("Full test", full_test)
334
+
335
+
336
+ # if latest_unconfirmed_cart:
337
+ # print("🛒 Đã có giỏ hàng 'pending' trước đó. Đang cập nhật lại sản phẩm...")
338
+ # latest_unconfirmed_cart.cart_products = clean_cart_products
339
+ # latest_unconfirmed_cart.save()
340
+ # chat_cart = latest_unconfirmed_cart
341
+ # else:
342
+ # print("Chưa có giỏ hàng 'pending'. Đang tạo mới...")
343
+ # chat_cart = ChatCart(
344
+ # chat_history=chat_id,
345
+ # cart_products=clean_cart_products,
346
+ # status="pending"
347
+ # )
348
+ # chat_cart.save()
349
+ # if full_test:
350
+ # return full_test + f"Hãy tạo ra câu hỏi để người dùng thay đổi ý định mua sản phẩm. Ngoài ra luôn hiển thị lại tình trạng giỏ của người dùng: giỏ hàng{clean_list}" + str(results)
351
+
352
+ # if check_shopping.get("is_delete_cart") == "Yes":
353
+ # print("🗑️ Đang xóa toàn bộ sản phẩm trong giỏ hàng...")
354
+ # chat_cart.cart_products = []
355
+ # chat_cart.status = "failed"
356
+ # chat_cart.save()
357
+ # result_final += "Đã xóa toàn bộ sản phẩm trong giỏ hàng..."
358
+ # if check_shopping.get("is_view_cart") == "Yes":
359
+ # print("👀 Đang xem giỏ hàng...")
360
+ # chat_cart = ChatCart.objects(chat_history=chat_id, status="pending").first()
361
+
362
+ # if not chat_cart or not chat_cart.cart_products:
363
+ # print("🛒 Giỏ hàng hiện đang trống.")
364
+ # result_final += "🛒 Giỏ hàng hiện đang trống.\n"
365
+ # else:
366
+ # message_lines = ["🛒 Danh sách sản phẩm trong giỏ:"]
367
+ # for product in chat_cart.cart_products:
368
+ # print(f"- Tên sản phẩm: {product.name} | Số Lượng: {product.quantity} | Size(Kích cỡ): {product.size}")
369
+ # message_lines.append(
370
+ # f"- Tên sản phẩm: {product.name} | Số Lượng: {product.quantity} | Size(Kích cỡ): {product.size}"
371
+ # )
372
+ # data = "\n".join(message_lines)
373
+ # result_final += data + "\n"
374
+
375
+
376
+
377
+ # if check_shopping["is_confirm_order"] == "Yes":
378
+ # try:
379
+ # print("🔹 [STEP 1] Tạo giỏ hàng mới...")
380
+ # data = server_java.create_cart(int(user_id), token)
381
+ # cart_id = data.get("cartId")
382
+ # print(f"✅ Giỏ hàng tạo thành công: cart_id = {cart_id}")
383
+ # except Exception as e:
384
+ # print(f"❌ Lỗi khi tạo giỏ hàng: {e}")
385
+ # cart_id = None
386
+
387
+ # if cart_id:
388
+ # for idx, item in enumerate(clean_cart_products, 1):
389
+ # try:
390
+ # print(f"\n🔹 [STEP 2.{idx}] Tìm kiếm sản phẩm: {item['name']} (size: {item['size']})...")
391
+ # pro_id, pro_name, size_check, stock_check, price_check = server_java.search_product(
392
+ # keyword=item["name"], size=item["size"]
393
+ # )
394
+ # print(f"✅ Tìm thấy sản phẩm '{pro_name}' (ID: {pro_id}, Size: {size_check})")
395
+
396
+ # print(f"🔹 [STEP 3.{idx}] Thêm sản phẩm vào giỏ hàng...")
397
+ # data1 = server_java.insert_cartItem(user_id, cart_id, pro_id, size_check, item["quantity"], token)
398
+ # print(f"✅ Đã thêm sản phẩm '{pro_name}' vào giỏ hàng.")
399
+ # except Exception as e:
400
+ # print(f"❌ Lỗi khi xử lý sản phẩm thứ {idx}: {e}")
401
+ # continue # vẫn tiếp tục vòng lặp cho sản phẩm tiếp theo
402
+
403
+ # try:
404
+ # print("\n🔹 [STEP 4] Tạo đơn hàng từ giỏ hàng...")
405
+ # create_orders = server_java.create_orders(user_id=user_id, cartId=cart_id, token=token)
406
+ # order_id = create_orders["body"]["orderId"]
407
+ # print(f"✅ Đơn hàng được tạo: order_id = {order_id}")
408
+ # except Exception as e:
409
+ # print(f"❌ Lỗi khi tạo đơn hàng: {e}")
410
+ # order_id = None
411
+
412
+ # if order_id:
413
+ # try:
414
+ # print("🔹 [STEP 5] Xác nhận đơn hàng với AI...")
415
+ # confirm_order = server_java.confirm_orders_AI(user_id=user_id, token=token, orderId=order_id)
416
+ # print("✅ Phản hồi xác nhận đơn hàng từ AI:")
417
+ # print(confirm_order["body"])
418
+ # if confirm_order["body"] == "Confirm success":
419
+ # chat_cart.status = "confirmed"
420
+ # chat_cart.confirmed_order = True
421
+ # chat_cart.save()
422
+ # from urllib.parse import urlencode
423
+ # base_url = "https://vnexpress.net/tin-tuc-24h"
424
+ # params = {
425
+ # "order_id": order_id,
426
+ # "token": token,
427
+ # "user_id": user_id
428
+ # }
429
+ # link_payment = f"https://vnexpress.net/tin-tuc-24h?order_id={order_id}&token={token}&user_id={user_id}"
430
+
431
+
432
+
433
+ # return "Yêu cầu: " + str(task) + f". Yêu cầu của bạn đã thành công. Tình trạng giỏ hiện tại (Luôn luôn hiển thị lại trạng thái này để người dùng biết giỏ của họ) {clean_list}. Bạn đã xác nhận thanh toán thành công sẽ tiến hành chuyển sang link thanh toán{link_payment}. Vui lòng thực hiện thanh toán trên trang này trong vòng 30 phút tối đa" + str(results)
434
+ # else:
435
+ # chat_cart.status = "failed"
436
+ # chat_cart.confirmed_order = False
437
+ # chat_cart.save()
438
+
439
+ # except Exception as e:
440
+ # print(f"❌ Lỗi khi xác nhận đơn hàng với AI: {e}")
441
+ # chat_cart.status = "failed"
442
+ # chat_cart.confirmed_order = False
443
+ # chat_cart.save()
444
+
445
+ # if check_shopping["is_confirm_order"] == "No" and len(clean_cart_products) != 0 :
446
+ # result_final += "Yêu cầu: " + str(task) + f". Yêu cầu của bạn đã thành công. Tình trạng giỏ hiện tại(Luôn luôn hiển thị lại trạng thái này để người dùng biết giỏ của họ): {clean_list}" + "kết quả thực thi:" + str(results)
447
+
448
+ # return result_final
449
+ # else:
450
+ # task = filter_sql_injection_1.normalize_query(task)
451
+ # filtered_input = filter_sql_injection_1.filter_sql_injection(task)
452
+ # filtered_role_input = filter_role_1.filter_role(filtered_input)
453
+ # result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
454
+ # result_final = query_result_1.query_result(task, result)
455
+ # return result_final
456
+ # else:
457
+ # result = ""
458
+ # task = filter_sql_injection_1.normalize_query(task)
459
+ # filtered_input = filter_sql_injection_1.filter_sql_injection(task)
460
+ # filtered_role_input = filter_role_1.filter_role(filtered_input)
461
+ # output = await chat_sql.generate_and_save_code(filtered_role_input, user_id, role, languages)
462
+ # if isinstance(output, tuple):
463
+ # result, path_image = output
464
+ # else:
465
+ # result = output
466
+ # path_image = None
467
+
468
+ # if path_image and os.path.exists(path_image):
469
+ # images_md = upload_images_to_cloudinary_and_markdown(path_image)
470
+ # if images_md:
471
+ # result = f"### Tất cả Hình ảnh sinh ra:\n\n{images_md}\n\n{result}"
472
+ # return result
473
+
474
+
475
+ #
476
+ # ----- PHẦN 2: HÀM AGENT_SQL ĐÃ TÁI CẤU TRÚC -----
477
+ #
478
+
479
+ # --- Các hàm trợ giúp (Helper Functions) ---
480
+ from typing import Optional
481
+ async def _handle_shopping_intent(task: str, user_id: int, chat_id: Any, token: str, languages,role, stop_event: Optional[asyncio.Event]) -> str:
482
+ """
483
+ Xử lý các tác vụ liên quan đến mua sắm: xem giỏ, thêm/sửa/xóa, xác nhận đơn hàng.
484
+ """
485
+ result_check = await check_should_stop(chat_id, stop_event)
486
+ if result_check:
487
+ return result_check
488
+ try:
489
+ result_check = await check_should_stop(chat_id, stop_event)
490
+ if result_check:
491
+ return result_check
492
+ cart_status = "Yes (Đang Pending)" if chat_history_has_unconfirmed_cart(chat_id) else "No (Không có)"
493
+ prompt_context = multitool_prompt.build_multi_tool_prompt(
494
+ question=get_last_ai_message(chat_id),
495
+ tools=["confirm_order", "insert_cart", "update_cart", "delete_item_cart", "deleted all cart"],
496
+ user_answer=task
497
+ )
498
+ data_context = tool_call.generate(prompt_context)
499
+ print(f"DEBUG: data_context: {data_context}")
500
+
501
+ # 2. Lấy giỏ hàng đang chờ xử lý hoặc tạo mới
502
+ result_check = await check_should_stop(chat_id, stop_event)
503
+ if result_check:
504
+ return result_check
505
+
506
+ latest_unconfirmed_cart = ChatCart.objects(chat_history=chat_id, status="pending").order_by('-created_at').first()
507
+ if latest_unconfirmed_cart:
508
+ chat_cart = latest_unconfirmed_cart
509
+ previous_cart_items = [p.to_mongo().to_dict() for p in chat_cart.cart_products]
510
+ print("INFO: Đã tìm thấy giỏ hàng 'pending', sẽ cập nhật.")
511
+ else:
512
+ chat_cart = ChatCart(chat_history=chat_id, status="pending")
513
+ previous_cart_items = []
514
+ print("INFO: Không tìm thấy giỏ hàng 'pending', sẽ tạo mới.")
515
+
516
+ #Backup data
517
+ chat_cart.backup_cart_products = chat_cart.cart_products.copy()
518
+ chat_cart.backup_status = chat_cart.status
519
+ chat_cart.backup_confirmed_order = chat_cart.confirmed_order
520
+ chat_cart.save()
521
+
522
+ # 3. Trích xuất và xử lý thông tin sản phẩm từ câu hỏi của người dùng
523
+ result_check = await check_should_stop(chat_id, stop_event)
524
+ if result_check:
525
+ return result_check
526
+ new_items_str = test_func.classify_data(input=f"{data_context.get('question', '')}", structured_data=previous_cart_items)
527
+ new_items_list = json.loads(new_items_str) if new_items_str and new_items_str != "None" else []
528
+ updated_cart_list = process_data(previous_cart_items, new_items_list)
529
+
530
+ # 4. Xác thực sản phẩm và cập nhật giỏ hàng trong DB
531
+ result_check = await check_should_stop(chat_id, stop_event)
532
+ if result_check:
533
+ return result_check
534
+ annotated_list, clean_list, validation_message = test_func.validate_product_list(data_list=updated_cart_list, server_java=server_java)
535
+
536
+ # clean_cart_products = [CartProduct(**item) for item in clean_list]
537
+ clean_cart_products = []
538
+ for item in clean_list:
539
+ # Đảm bảo quantity là số nguyên
540
+ product = CartProduct(
541
+ name=item.get('name'),
542
+ size=item.get('size'),
543
+ quantity=int(item.get('quantity', 1))
544
+ )
545
+ clean_cart_products.append(product)
546
+ print("Clean_cart", clean_cart_products)
547
+ chat_cart.cart_products = clean_cart_products
548
+ chat_cart.save()
549
+ print(f"INFO: Giỏ hàng đã được cập nhật với {len(clean_cart_products)} sản phẩm.")
550
+
551
+ # 5. Xử lý các câu hỏi phụ (nếu có)
552
+ result_check = await check_should_stop(chat_id, stop_event)
553
+ if result_check:
554
+ return result_check
555
+ other_results = []
556
+ if data_context.get("question_normal"):
557
+ for q_key, q_text in data_context["question_normal"].items():
558
+ result_check = await check_should_stop(chat_id, stop_event)
559
+ if result_check:
560
+ return result_check
561
+ result = await _handle_simple_query(q_text, user_id, languages, role, stop_event, chat_id)
562
+ other_results.append({"question": q_text, "result": result})
563
+
564
+ result_check = await check_should_stop(chat_id, stop_event)
565
+ if result_check:
566
+ return result_check
567
+ response_parts = []
568
+ if validation_message:
569
+ response_parts.append(validation_message)
570
+
571
+ final_cart_state_msg = f"Tình trạng giỏ hàng hiện tại của bạn: {clean_list}"
572
+ result_check = await check_should_stop(chat_id, stop_event)
573
+ if result_check:
574
+ return result_check
575
+
576
+ shopping_intent = tool_call.generate(user_intent.build_detailed_user_intent_prompt(
577
+ user_question=task, chat_history=get_chat_history(chat_id), cart_status=cart_status
578
+ ))
579
+
580
+ result_check = await check_should_stop(chat_id, stop_event)
581
+ if result_check:
582
+ return result_check
583
+ if shopping_intent.get("is_delete_cart") == "Yes":
584
+ chat_cart.cart_products = []
585
+ chat_cart.status = "failed"
586
+ chat_cart.save()
587
+ response_parts.append("Đã xóa toàn bộ sản phẩm trong giỏ hàng.")
588
+ final_cart_state_msg = "Tình trạng giỏ hàng hiện tại của bạn: Giỏ hàng trống."
589
+ elif shopping_intent.get("is_view_cart") == "Yes":
590
+ result_check = await check_should_stop(chat_id, stop_event)
591
+ if result_check:
592
+ return result_check
593
+ response_parts.append("Đây là giỏ hàng của bạn.")
594
+ elif shopping_intent.get("is_confirm_order") == "Yes":
595
+ result_check = await check_should_stop(chat_id, stop_event)
596
+ if result_check:
597
+ return result_check
598
+ if not chat_cart.cart_products:
599
+ return "Giỏ hàng của bạn đang trống. Vui lòng thêm sản phẩm trước khi xác nhận đơn hàng."
600
+ result_check = await check_should_stop(chat_id, stop_event)
601
+ if result_check:
602
+ return result_check
603
+ confirmation_result = await _execute_order_confirmation(user_id, token, chat_cart, stop_event,chat_id)
604
+ confirmation_result_str = ""
605
+ result_check = await check_should_stop(chat_id, stop_event)
606
+ if result_check:
607
+ chat_cart.status = chat_cart.backup_status
608
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
609
+ chat_cart.save()
610
+ if confirmation_result[1]:
611
+ server_java.confirm_cancel_AI(int(user_id),token,confirmation_result[1])
612
+ server_java.remove_all_cartItem(int(user_id), confirmation_result[2], token)
613
+ confirmation_result_str = confirmation_result[0]
614
+ else:
615
+ confirmation_result_str = confirmation_result
616
+ return result_check
617
+
618
+ response_parts.append(str(confirmation_result))
619
+ else:
620
+ response_parts.append(f"Yêu cầu '{task}' của bạn đã được xử lý.")
621
+
622
+ response_parts.append(final_cart_state_msg)
623
+ if other_results:
624
+ response_parts.append(f"Kết quả cho các câu hỏi khác: {other_results}")
625
+
626
+ return " ".join(response_parts)
627
+ except asyncio.CancelledError as e:
628
+ print(f"STOP: {e}")
629
+ if 'chat_cart' in locals():
630
+ if chat_cart.backup_cart_products:
631
+ chat_cart.cart_products = chat_cart.backup_cart_products
632
+ chat_cart.status = chat_cart.backup_status
633
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
634
+ chat_cart.save()
635
+ print("INFO: Đã khôi phục giỏ hàng từ bản backup do bị hủy.")
636
+ return "Quá trình đã bị dừng theo yêu cầu. Giỏ hàng đã được khôi phục như ban đầu."
637
+ # except Exception as e:
638
+ # print(f"ERROR in _handle_shopping_intent: {e}")
639
+ # return "Đã có lỗi xảy ra trong quá trình xử lý yêu cầu mua sắm của bạn. Vui lòng thử lại."
640
+
641
+
642
+ # async def rollback_cart_and_order(chat_cart: ChatCart, user_id: int, token: str):
643
+ # try:
644
+ # if chat_cart.temp_order_id:
645
+ # server_java.delete_order(chat_cart.temp_order_id, token)
646
+ # print(f"INFO: Đã rollback đơn hàng {chat_cart.temp_order_id}")
647
+ # if chat_cart.temp_cart_id:
648
+ # server_java.delete_cart(chat_cart.temp_cart_id, token)
649
+ # print(f"INFO: Đã rollback giỏ hàng {chat_cart.temp_cart_id}")
650
+ # chat_cart.status = "cancelled"
651
+ # chat_cart.save()
652
+ # except Exception as e:
653
+ # print(f"WARNING: Lỗi khi rollback: {e}")
654
+
655
+
656
+ async def rollback_cart_and_order(chat_cart: ChatCart, user_id: int, token: str,order_id):
657
+ try:
658
+ if chat_cart.temp_order_id:
659
+ server_java.delete_order(chat_cart.temp_order_id, token)
660
+ print(f"INFO: Đã rollback đơn hàng {chat_cart.temp_order_id}")
661
+ if chat_cart.temp_cart_id:
662
+ server_java.delete_cart(chat_cart.temp_cart_id, token)
663
+ print(f"INFO: Đã rollback giỏ hàng {chat_cart.temp_cart_id}")
664
+ chat_cart.status = "cancelled"
665
+ chat_cart.save()
666
+ except Exception as e:
667
+ print(f"WARNING: Lỗi khi rollback: {e}")
668
+
669
+
670
+ async def _execute_order_confirmation(user_id: int, token: str, chat_cart: ChatCart, stop_event: Optional[asyncio.Event],chat_id:str= ""):
671
+ """
672
+ Thực hiện quy trình 5 bước để xác nhận đơn hàng với server_java.
673
+ """
674
+ try:
675
+
676
+ #Backup data
677
+ chat_cart.backup_status = chat_cart.status
678
+ chat_cart.backup_confirmed_order = chat_cart.confirmed_order
679
+ chat_cart.save()
680
+
681
+ print("INFO: Bắt đầu quy trình xác nhận đơn hàng.")
682
+
683
+ result_check = await check_should_stop(chat_id, stop_event)
684
+ if result_check:
685
+ chat_cart.status = chat_cart.backup_status
686
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
687
+ chat_cart.save()
688
+ return result_check
689
+ cart_data = server_java.create_cart(int(user_id), token)
690
+ cart_id = cart_data.get("cartId")
691
+ if not cart_id: raise Exception("Không thể tạo giỏ hàng trên hệ thống.")
692
+ print(f"SUCCESS: Tạo giỏ hàng tạm thành công: cart_id = {cart_id}")
693
+
694
+ # Step 2 & 3: Add items to cart
695
+ for item in chat_cart.cart_products:
696
+ result_check = await check_should_stop(chat_id, stop_event)
697
+ if result_check:
698
+ chat_cart.status = chat_cart.backup_status
699
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
700
+ chat_cart.save()
701
+ rollback = server_java.remove_all_cartItem(int(user_id), cart_id, token)
702
+ return result_check
703
+ pro_id, _, size_check, _, _ = server_java.search_product(keyword=item.name, size=item.size)
704
+ server_java.insert_cartItem(user_id, cart_id, pro_id, size_check, item.quantity, token)
705
+ print(f"SUCCESS: Đã thêm '{item.name}' vào giỏ hàng tạm.")
706
+
707
+ # Step 4: Create Order
708
+ result_check = await check_should_stop(chat_id, stop_event)
709
+ if result_check:
710
+ chat_cart.status = "pending"
711
+ chat_cart.confirmed_order = False
712
+ chat_cart.save()
713
+ server_java.remove_all_cartItem(int(user_id), cart_id, token)
714
+ return result_check
715
+ order_data = server_java.create_orders(user_id=user_id, cartId=cart_id, token=token)
716
+ order_id = order_data["body"]["orderId"]
717
+ if not order_id: raise Exception("Không thể tạo đơn hàng từ giỏ hàng.")
718
+ print(f"SUCCESS: Tạo đơn hàng thành công: order_id = {order_id}")
719
+
720
+ # Step 5: Confirm Order
721
+ result_check = await check_should_stop(chat_id, stop_event)
722
+ if result_check:
723
+ chat_cart.status = chat_cart.backup_status
724
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
725
+ chat_cart.save()
726
+ server_java.confirm_cancel_AI(int(user_id),token,order_id)
727
+ server_java.remove_all_cartItem(int(user_id), cart_id, token)
728
+ return result_check
729
+ confirm_data = server_java.confirm_orders_AI(user_id=user_id, token=token, orderId=order_id)
730
+ if confirm_data.get("body") == "Confirm success":
731
+ chat_cart.status = "confirmed"
732
+ chat_cart.confirmed_order = True
733
+ chat_cart.order_id = order_id
734
+ chat_cart.cart_id = cart_id
735
+ chat_cart.save()
736
+ link_payment = f"https://hmdrinks-t8e3-giahans-projects.vercel.app/payment?order_id={order_id}&token={token}&user_id={user_id}"
737
+ data = f"Đơn hàng của bạn đã được xác nhận thành công. Vui lòng truy cập link sau để thanh toán trong vòng 30 phút: {link_payment}(Vui lòng không bỏ sót link này)"
738
+ return data, order_id, cart_id
739
+ else:
740
+ print(f"Hệ thống không thể xác nhận đơn hàng. Phản hồi: {confirm_data.get('body')}")
741
+
742
+ result_check = await check_should_stop(chat_id, stop_event)
743
+ if result_check:
744
+ chat_cart.status = chat_cart.backup_status
745
+ chat_cart.confirmed_order = chat_cart.backup_confirmed_order
746
+ chat_cart.save()
747
+ server_java.confirm_cancel_AI(int(user_id),token,order_id)
748
+ server_java.remove_all_cartItem(int(user_id), cart_id, token)
749
+
750
+ except Exception as e:
751
+ print(f"ERROR in _execute_order_confirmation: {e}")
752
+ chat_cart.status = "failed"
753
+ chat_cart.save()
754
+ return f"Đã xảy ra lỗi khi xác nhận đơn hàng: {e}. Giỏ hàng của bạn vẫn được lưu."
755
+
756
+
757
+ async def _handle_simple_query(task: str, user_id: int, languages: List[str], role: str,stop_event: Optional[asyncio.Event],chat_id: str = "") -> str:
758
+ """Xử lý một câu hỏi SQL đơn giản."""
759
+ result_check = await check_should_stop(chat_id, stop_event)
760
+ if result_check:
761
+ return result_check
762
+ normalized_task = filter_sql_injection_1.normalize_query(task)
763
+ result_check = await check_should_stop(chat_id, stop_event)
764
+ if result_check:
765
+ return result_check
766
+ filtered_input = filter_sql_injection_1.filter_sql_injection(normalized_task)
767
+ result_check = await check_should_stop(chat_id, stop_event)
768
+ if result_check:
769
+ return result_check
770
+ filtered_role_input = filter_role_1.filter_role(filtered_input)
771
+ result_check = await check_should_stop(chat_id, stop_event)
772
+ if result_check:
773
+ return result_check
774
+ query_result = await chat_sql.execute_query_user(filtered_role_input, user_id, languages, role)
775
+ result_check = await check_should_stop(chat_id, stop_event)
776
+ if result_check:
777
+ return result_check
778
+ return query_result_1.query_result(task, query_result)
779
+
780
+
781
+ async def _handle_analysis_intent(task: str, user_id: int, languages: List[str], role: str, stop_event: Optional[asyncio.Event],chat_id: str = "") -> str:
782
+ """Xử lý các tác vụ yêu cầu phân tích, sinh code và vẽ biểu đồ."""
783
+ result_check = await check_should_stop(chat_id, stop_event)
784
+ if result_check:
785
+ return result_check
786
+
787
+ normalized_task = filter_sql_injection_1.normalize_query(task)
788
+ filtered_input = filter_sql_injection_1.filter_sql_injection(normalized_task)
789
+ filtered_role_input = filter_role_1.filter_role(filtered_input)
790
+
791
+ result_check = await check_should_stop(chat_id, stop_event)
792
+ if result_check:
793
+ return result_check
794
+ output = await chat_sql.generate_and_save_code(
795
+ filtered_role_input,
796
+ user_id,
797
+ role,
798
+ languages,
799
+ stop_event,
800
+ chat_id=chat_id
801
+ )
802
+
803
+
804
+
805
+ result_check = await check_should_stop(chat_id, stop_event)
806
+ if result_check:
807
+ return result_check
808
+ result, path_image = output if isinstance(output, tuple) else (output, None)
809
+
810
+ if path_image and os.path.exists(path_image):
811
+ result_check = await check_should_stop(chat_id, stop_event)
812
+ if result_check:
813
+ return result_check # Trả về kết quả đã có
814
+
815
+ images_md = upload_images_to_cloudinary_and_markdown(path_image)
816
+ if images_md:
817
+ result = f"### Biểu đồ được tạo:\n\n{images_md}\n\n{result}"
818
+
819
+ return result
820
+
821
+
822
+ # --- Hàm chính (Main Function) ---
823
+
824
+ async def agent_sql(task: str, user_id: int, languages: str, role: str, chat_id: Any, token: str, stop_event: Optional[asyncio.Event] = None):
825
+ """
826
+ Hàm chính điều phối các tác vụ, có khả năng dừng giữa chừng.
827
+ """
828
+ # KIỂM TRA DỪNG NGAY LẬP TỨC
829
+ result_check = await check_should_stop(chat_id, stop_event)
830
+ if result_check:
831
+ return result_check
832
+
833
+ # 1. KIỂM TRA AN TOÀN BAN ĐẦU
834
+ if filter_sql_injection_1.filter_question_remove_restore(task):
835
+ return "Bạn không được phép khôi phục hoặc xóa dữ liệu. Vui lòng kiểm tra lại câu hỏi của bạn."
836
+
837
+ # 2. PHÂN LOẠI Ý ĐỊNH CHÍNH: PHÂN TÍCH (cần sinh code) vs HỎI ĐÁP/MUA SẮM
838
+ is_analysis_task = filter_sql_injection_1.filter_task_analyze(task)
839
+
840
+ result_check = await check_should_stop(chat_id, stop_event)
841
+ if result_check:
842
+ return result_check
843
+ if is_analysis_task:
844
+ print("INFO: Nhận diện ý định PHÂN TÍCH.")
845
+ if result_check:
846
+ return result_check
847
+ data = await _handle_analysis_intent(task, user_id, languages, role, stop_event,chat_id)
848
+ if result_check:
849
+ return result_check
850
+ return data, False
851
+
852
+
853
+ # 3. PHÂN LOẠI Ý ĐỊNH PHỤ: MUA SẮM vs HỎI ĐÁP THÔNG THƯỜNG
854
+ result_check = await check_should_stop(chat_id, stop_event)
855
+ if result_check:
856
+ return result_check
857
+ cart_status = "Yes (Đang Pending)" if chat_history_has_unconfirmed_cart(chat_id) else "No (Không có)"
858
+ prompt_check_shopping = user_intent.build_detailed_user_intent_prompt(
859
+ user_question=task,
860
+ chat_history=get_chat_history(chat_id),
861
+ cart_status=cart_status
862
+ )
863
+
864
+ result_check = await check_should_stop(chat_id, stop_event)
865
+ if result_check:
866
+ return result_check
867
+
868
+ intent_result = tool_call.generate(prompt_check_shopping)
869
+ result_check = await check_should_stop(chat_id, stop_event)
870
+ if result_check:
871
+ return result_check
872
+ if str(intent_result.get("type")) == "shopping_question":
873
+ print("INFO: Nhận diện ý định MUA SẮM.")
874
+ result = await _handle_shopping_intent(task, user_id, chat_id, token, languages, role, stop_event)
875
+ result = query_result_1.query_result(task, result)
876
+ return result, True
877
+ else:
878
+ print("INFO: Nhận diện ý định HỎI ĐÁP THÔNG THƯỜNG.")
879
+ result = await _handle_simple_query(task, user_id, languages, role, stop_event,chat_id)
880
+ result = query_result_1.query_result(task, result)
881
+ return result, False
882
+
883
+
884
+ async def agent_general(task, user_id, languages, role, chat_id, token, stop_event):
885
+ task = filter_sql_injection_1.normalize_query(task)
886
+ # Kiểm tra stop event trước khi gọi xử lý nặng
887
+ result_check = await check_should_stop(chat_id, stop_event)
888
+ if result_check:
889
+ return result_check
890
+ # Gọi xử lý chính
891
+ result_task = asyncio.create_task(res_general.response_general(task))
892
+ # Chờ xử lý, nhưng cũng kiểm tra stop event
893
+ while not result_task.done():
894
+ if stop_event.is_set():
895
+ print("Tín hiệu stop trong quá trình xử lý. Hủy task.")
896
+ result_task.cancel()
897
+ try:
898
+ await result_task
899
+ except asyncio.CancelledError:
900
+ print("Task đã bị huỷ.")
901
+ return None
902
+ await asyncio.sleep(0.1) # Cho các task khác thời gian chạy
903
+
904
+
905
+ function_mapping = {
906
+ "question_hello": agent_hello,
907
+ "question_information": agent_information,
908
+ "question_sql": agent_sql,
909
+ "question_general": agent_general
910
+
911
+ }
912
+
913
+
914
+ from typing import Optional
915
+ async def process_toolcalls_with_order(toolcalls,token, stop_event: Optional[asyncio.Event] = None, chat_id:str = ""):
916
+ task_results = {}
917
+ ordered_results = {}
918
+ filtered_toolcalls = [tc for tc in toolcalls if tc["name"] in function_mapping]
919
+ for tc in filtered_toolcalls:
920
+
921
+ orig_name = tc["name"]
922
+ task_func = function_mapping.get(orig_name)
923
+ if task_func is None:
924
+ continue
925
+ task_param = tc["args"].get("query", "")
926
+ user_id = tc.get("user_id", "unknown_user")
927
+ role = tc.get("role", "unknown_role")
928
+ language = tc.get("language", "unknown_language")
929
+ chat_id = tc.get("chat_id","unknow")
930
+ if asyncio.iscoroutinefunction(task_func):
931
+ result = await task_func(task_param, user_id, language,role,chat_id,token,stop_event)
932
+ else:
933
+ result = task_func(task_param, user_id, language,role,chat_id,token,stop_event)
934
+ if isinstance(result, tuple) and len(result) == 2:
935
+ result, is_shopping = result
936
+ else:
937
+ result = result
938
+ is_shopping = False
939
+ # Lưu kết quả theo id của tool_call
940
+ task_results[tc["id"]] = {
941
+ "result": result,
942
+ "user_id": user_id,
943
+ "role": role,
944
+ "language": language,
945
+ "is_shopping": is_shopping
946
+ }
947
+
948
+
949
+ ordered_results = {tc["id"]: task_results.get(tc["id"], {"result": "Không có kết quả"}) for tc in filtered_toolcalls}
950
  return ordered_results