update message flow
Browse files- app/constants.py +1 -1
- app/llm.py +11 -9
- app/main.py +0 -2
- app/message_processor.py +82 -66
- app/sheets.py +15 -8
app/constants.py
CHANGED
|
@@ -191,4 +191,4 @@ FOUND_REGULATIONS_MESSAGES = [
|
|
| 191 |
"Thông tin đang được mình kiểm tra lại lần cuối, mình sẽ cập nhật sớm nhất nhé."
|
| 192 |
]
|
| 193 |
|
| 194 |
-
SHEET_RANGE = 'chat!A2:
|
|
|
|
| 191 |
"Thông tin đang được mình kiểm tra lại lần cuối, mình sẽ cập nhật sớm nhất nhé."
|
| 192 |
]
|
| 193 |
|
| 194 |
+
SHEET_RANGE = 'chat!A2:M'
|
app/llm.py
CHANGED
|
@@ -408,17 +408,19 @@ class LLMClient:
|
|
| 408 |
"""
|
| 409 |
|
| 410 |
prompt = f"""
|
| 411 |
-
|
| 412 |
-
|
| 413 |
{{
|
| 414 |
-
"muc_dich": "
|
| 415 |
-
"phuong_tien": "
|
| 416 |
-
"
|
|
|
|
| 417 |
}}
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
|
|
|
| 422 |
|
| 423 |
Câu hỏi:
|
| 424 |
\"{text}\"
|
|
|
|
| 408 |
"""
|
| 409 |
|
| 410 |
prompt = f"""
|
| 411 |
+
Nhiệm vụ: Với mỗi câu hỏi, trích xuất thông tin ra JSON theo định dạng và hướng dẫn sau. Chỉ trả về đối tượng JSON.
|
| 412 |
+
Định dạng:
|
| 413 |
{{
|
| 414 |
+
"muc_dich": "...",
|
| 415 |
+
"phuong_tien": "...",
|
| 416 |
+
"hanh_vi": "...",
|
| 417 |
+
"cau_hoi": "..."
|
| 418 |
}}
|
| 419 |
+
Hướng dẫn:
|
| 420 |
+
- "cau_hoi": Diễn đạt lại nội dung câu hỏi bằng thuật ngữ pháp lý chuẩn.
|
| 421 |
+
- "hanh_vi": Tóm tắt hành vi được mô tả trong câu hỏi
|
| 422 |
+
- "phuong_tien": Để là chuỗi rỗng "" nếu không được đề cập.
|
| 423 |
+
- "muc_dich": Phải là một trong các giá trị sau: "hỏi về mức phạt", "hỏi về quy tắc giao thông", "hỏi về báo hiệu đường bộ", "hỏi về quy trình xử lý vi phạm giao thông", "thông tin cá nhân của AI", "khác".
|
| 424 |
|
| 425 |
Câu hỏi:
|
| 426 |
\"{text}\"
|
app/main.py
CHANGED
|
@@ -59,8 +59,6 @@ supabase_client = SupabaseClient(settings.supabase_url, settings.supabase_key)
|
|
| 59 |
logger.info("[STARTUP] Khởi tạo EmbeddingClient...")
|
| 60 |
embedding_client = EmbeddingClient()
|
| 61 |
|
| 62 |
-
# Keywords to look for in messages
|
| 63 |
-
VEHICLE_KEYWORDS = ["xe máy", "ô tô", "xe đạp", "xe hơi"]
|
| 64 |
|
| 65 |
# Khởi tạo LLM client (ví dụ dùng HFS, bạn có thể đổi provider tuỳ ý)
|
| 66 |
# llm_client = create_llm_client(
|
|
|
|
| 59 |
logger.info("[STARTUP] Khởi tạo EmbeddingClient...")
|
| 60 |
embedding_client = EmbeddingClient()
|
| 61 |
|
|
|
|
|
|
|
| 62 |
|
| 63 |
# Khởi tạo LLM client (ví dụ dùng HFS, bạn có thể đổi provider tuỳ ý)
|
| 64 |
# llm_client = create_llm_client(
|
app/message_processor.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from typing import Dict, Any, List
|
| 2 |
import asyncio
|
| 3 |
import traceback
|
| 4 |
from loguru import logger
|
|
@@ -7,6 +7,7 @@ from .utils import get_random_message
|
|
| 7 |
from .facebook import FacebookClient
|
| 8 |
from app.config import get_settings
|
| 9 |
import re
|
|
|
|
| 10 |
|
| 11 |
class MessageProcessor:
|
| 12 |
def __init__(self, channel, sender_id):
|
|
@@ -63,6 +64,7 @@ class MessageProcessor:
|
|
| 63 |
'originalvehicle': '',
|
| 64 |
'originalaction': '',
|
| 65 |
'originalpurpose': '',
|
|
|
|
| 66 |
'timestamp': [timestamp],
|
| 67 |
'isdone': False
|
| 68 |
}
|
|
@@ -94,6 +96,7 @@ class MessageProcessor:
|
|
| 94 |
'originalvehicle': row.get('originalvehicle'),
|
| 95 |
'originalaction': row.get('originalaction'),
|
| 96 |
'originalpurpose': row.get('originalpurpose'),
|
|
|
|
| 97 |
'timestamp': row_timestamps,
|
| 98 |
'isdone': row.get('isdone')
|
| 99 |
}
|
|
@@ -146,22 +149,25 @@ class MessageProcessor:
|
|
| 146 |
llm_analysis = await self.channel.llm.analyze(message_text)
|
| 147 |
logger.info(f"[LLM][RAW] Kết quả trả về từ analyze: {llm_analysis}")
|
| 148 |
muc_dich = None
|
| 149 |
-
|
|
|
|
| 150 |
if isinstance(llm_analysis, dict):
|
| 151 |
keywords = [self.normalize_vehicle_keyword(llm_analysis.get('phuong_tien', ''))]
|
| 152 |
muc_dich = llm_analysis.get('muc_dich')
|
| 153 |
-
|
|
|
|
| 154 |
elif isinstance(llm_analysis, list) and len(llm_analysis) > 0:
|
| 155 |
keywords = [self.normalize_vehicle_keyword(llm_analysis[0].get('phuong_tien', ''))]
|
| 156 |
muc_dich = llm_analysis[0].get('muc_dich')
|
| 157 |
-
|
|
|
|
| 158 |
else:
|
| 159 |
keywords = extract_keywords(message_text, VEHICLE_KEYWORDS)
|
| 160 |
-
|
| 161 |
for kw in keywords:
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
logger.info(f"[DEBUG] Phương tiện: {keywords} - Hành vi: {
|
| 165 |
# await self.channel.facebook.send_message(message=f"... đang tìm kiếm quy định liên quan đến {hanh_vi_vi_pham} .....")
|
| 166 |
# 4. Update lại conversation với thông tin đầy đủ
|
| 167 |
update_kwargs = {
|
|
@@ -173,8 +179,9 @@ class MessageProcessor:
|
|
| 173 |
'originalcontent': remaining_text,
|
| 174 |
'originalattachments': attachments,
|
| 175 |
'originalvehicle': ','.join(keywords),
|
| 176 |
-
'originalaction':
|
| 177 |
'originalpurpose': muc_dich,
|
|
|
|
| 178 |
'timestamp': self.flatten_timestamp(conv['timestamp']),
|
| 179 |
'isdone': False
|
| 180 |
}
|
|
@@ -323,18 +330,20 @@ class MessageProcessor:
|
|
| 323 |
if not top or (match.get('similarity', 0) > top.get('similarity', 0)):
|
| 324 |
top = match
|
| 325 |
full_result_text += f"\n{(match.get('structure') or '').strip()}:\n"
|
| 326 |
-
tieude = (match.get('tieude') or '').strip()
|
| 327 |
-
noidung = (match.get('noidung') or '').strip()
|
| 328 |
-
hanhvi = (tieude + "\n" + noidung).strip().replace('\n', ' ')
|
| 329 |
-
full_result_text += f"Thực hiện hành vi:\n{hanhvi}"
|
| 330 |
-
canhantu = arr_to_str(match.get('canhantu'))
|
| 331 |
-
canhanden = arr_to_str(match.get('canhanden'))
|
| 332 |
-
if canhantu or canhanden:
|
| 333 |
-
|
| 334 |
-
tochuctu = arr_to_str(match.get('tochuctu'))
|
| 335 |
-
tochucden = arr_to_str(match.get('tochucden'))
|
| 336 |
-
if tochuctu or tochucden:
|
| 337 |
-
|
|
|
|
|
|
|
| 338 |
hpbsnoidung = arr_to_str(match.get('hpbsnoidung'), sep="; ")
|
| 339 |
if hpbsnoidung:
|
| 340 |
full_result_text += f"\nNgoài việc bị phạt tiền, người vi phạm còn bị: {hpbsnoidung}"
|
|
@@ -345,18 +354,21 @@ class MessageProcessor:
|
|
| 345 |
if impounding:
|
| 346 |
full_result_text += f"\nTạm giữ phương tiên: 07 ngày"
|
| 347 |
if top and (top.get('tieude') or top.get('noidung')):
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
| 360 |
hpbsnoidung = arr_to_str(top.get('hpbsnoidung'), sep="; ")
|
| 361 |
if hpbsnoidung:
|
| 362 |
top_result_text += f"\nNgoài việc bị phạt tiền, người vi phạm còn bị: {hpbsnoidung}"
|
|
@@ -387,19 +399,21 @@ class MessageProcessor:
|
|
| 387 |
logger.error(f"LLM không sẵn sàng: {e}\n{traceback.format_exc()}")
|
| 388 |
fallback = "Tóm tắt các đoạn luật liên quan:\n\n"
|
| 389 |
for i, match in enumerate(matches, 1):
|
| 390 |
-
fallback += f"
|
| 391 |
-
tieude = (match.get('tieude') or '').strip()
|
| 392 |
-
noidung = (match.get('noidung') or '').strip()
|
| 393 |
-
if tieude or noidung:
|
| 394 |
-
|
| 395 |
-
canhantu = arr_to_str(match.get('canhantu'))
|
| 396 |
-
canhanden = arr_to_str(match.get('canhanden'))
|
| 397 |
-
if canhantu or canhanden:
|
| 398 |
-
|
| 399 |
-
tochuctu = arr_to_str(match.get('tochuctu'))
|
| 400 |
-
tochucden = arr_to_str(match.get('tochucden'))
|
| 401 |
-
if tochuctu or tochucden:
|
| 402 |
-
|
|
|
|
|
|
|
| 403 |
hpbsnoidung = arr_to_str(match.get('hpbsnoidung'), sep="; ")
|
| 404 |
if hpbsnoidung:
|
| 405 |
fallback += f" - Hình phạt bổ sung: {hpbsnoidung}\n"
|
|
@@ -419,29 +433,31 @@ class MessageProcessor:
|
|
| 419 |
async def handle_muc_phat(self, conv, message_text, page_token, sender_id):
|
| 420 |
vehicle = conv.get('originalvehicle', '')
|
| 421 |
action = conv.get('originalaction', '')
|
|
|
|
| 422 |
keywords = [kw.strip() for kw in vehicle.split(',') if kw.strip()]
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
response = "Xin lỗi, tôi không tìm thấy thông tin phù hợp."
|
| 438 |
else:
|
| 439 |
-
|
| 440 |
-
response = "Xin lỗi, tôi không tìm thấy thông tin về hành vi vi phạm trong câu hỏi của bạn."
|
| 441 |
-
conv['isdone'] = True
|
| 442 |
else:
|
| 443 |
-
|
| 444 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
return response
|
| 446 |
|
| 447 |
async def handle_quy_tac(self, conv, message_text):
|
|
|
|
| 1 |
+
from typing import Dict, Any, List, Optional
|
| 2 |
import asyncio
|
| 3 |
import traceback
|
| 4 |
from loguru import logger
|
|
|
|
| 7 |
from .facebook import FacebookClient
|
| 8 |
from app.config import get_settings
|
| 9 |
import re
|
| 10 |
+
import json
|
| 11 |
|
| 12 |
class MessageProcessor:
|
| 13 |
def __init__(self, channel, sender_id):
|
|
|
|
| 64 |
'originalvehicle': '',
|
| 65 |
'originalaction': '',
|
| 66 |
'originalpurpose': '',
|
| 67 |
+
'originalquestion': '',
|
| 68 |
'timestamp': [timestamp],
|
| 69 |
'isdone': False
|
| 70 |
}
|
|
|
|
| 96 |
'originalvehicle': row.get('originalvehicle'),
|
| 97 |
'originalaction': row.get('originalaction'),
|
| 98 |
'originalpurpose': row.get('originalpurpose'),
|
| 99 |
+
'originalquestion': row.get('originalquestion'),
|
| 100 |
'timestamp': row_timestamps,
|
| 101 |
'isdone': row.get('isdone')
|
| 102 |
}
|
|
|
|
| 149 |
llm_analysis = await self.channel.llm.analyze(message_text)
|
| 150 |
logger.info(f"[LLM][RAW] Kết quả trả về từ analyze: {llm_analysis}")
|
| 151 |
muc_dich = None
|
| 152 |
+
hanh_vi = None
|
| 153 |
+
cau_hoi = None
|
| 154 |
if isinstance(llm_analysis, dict):
|
| 155 |
keywords = [self.normalize_vehicle_keyword(llm_analysis.get('phuong_tien', ''))]
|
| 156 |
muc_dich = llm_analysis.get('muc_dich')
|
| 157 |
+
hanh_vi = llm_analysis.get('hanh_vi')
|
| 158 |
+
cau_hoi = llm_analysis.get('cau_hoi')
|
| 159 |
elif isinstance(llm_analysis, list) and len(llm_analysis) > 0:
|
| 160 |
keywords = [self.normalize_vehicle_keyword(llm_analysis[0].get('phuong_tien', ''))]
|
| 161 |
muc_dich = llm_analysis[0].get('muc_dich')
|
| 162 |
+
hanh_vi = llm_analysis[0].get('hanh_vi')
|
| 163 |
+
cau_hoi = llm_analysis[0].get('cau_hoi')
|
| 164 |
else:
|
| 165 |
keywords = extract_keywords(message_text, VEHICLE_KEYWORDS)
|
| 166 |
+
cau_hoi = message_text
|
| 167 |
for kw in keywords:
|
| 168 |
+
cau_hoi = cau_hoi.replace(kw, "")
|
| 169 |
+
cau_hoi = cau_hoi.strip()
|
| 170 |
+
logger.info(f"[DEBUG] Phương tiện: {keywords} - Hành vi: {hanh_vi} - Mục đích: {muc_dich} - Câu hỏi: {cau_hoi}")
|
| 171 |
# await self.channel.facebook.send_message(message=f"... đang tìm kiếm quy định liên quan đến {hanh_vi_vi_pham} .....")
|
| 172 |
# 4. Update lại conversation với thông tin đầy đủ
|
| 173 |
update_kwargs = {
|
|
|
|
| 179 |
'originalcontent': remaining_text,
|
| 180 |
'originalattachments': attachments,
|
| 181 |
'originalvehicle': ','.join(keywords),
|
| 182 |
+
'originalaction': hanh_vi,
|
| 183 |
'originalpurpose': muc_dich,
|
| 184 |
+
'originalquestion': cau_hoi or "",
|
| 185 |
'timestamp': self.flatten_timestamp(conv['timestamp']),
|
| 186 |
'isdone': False
|
| 187 |
}
|
|
|
|
| 330 |
if not top or (match.get('similarity', 0) > top.get('similarity', 0)):
|
| 331 |
top = match
|
| 332 |
full_result_text += f"\n{(match.get('structure') or '').strip()}:\n"
|
| 333 |
+
# tieude = (match.get('tieude') or '').strip()
|
| 334 |
+
# noidung = (match.get('noidung') or '').strip()
|
| 335 |
+
# hanhvi = (tieude + "\n" + noidung).strip().replace('\n', ' ')
|
| 336 |
+
# full_result_text += f"Thực hiện hành vi:\n{hanhvi}"
|
| 337 |
+
# canhantu = arr_to_str(match.get('canhantu'))
|
| 338 |
+
# canhanden = arr_to_str(match.get('canhanden'))
|
| 339 |
+
# if canhantu or canhanden:
|
| 340 |
+
# full_result_text += f"\nCá nhân sẽ bị phạt tiền từ {canhantu} VNĐ đến {canhanden} VNĐ"
|
| 341 |
+
# tochuctu = arr_to_str(match.get('tochuctu'))
|
| 342 |
+
# tochucden = arr_to_str(match.get('tochucden'))
|
| 343 |
+
# if tochuctu or tochucden:
|
| 344 |
+
# full_result_text += f"\nTổ chức sẽ bị phạt tiền từ {tochuctu} VNĐ đến {tochucden} VNĐ"
|
| 345 |
+
fullContent = (match.get('fullContent') or '').strip()
|
| 346 |
+
full_result_text += f"{fullContent}"
|
| 347 |
hpbsnoidung = arr_to_str(match.get('hpbsnoidung'), sep="; ")
|
| 348 |
if hpbsnoidung:
|
| 349 |
full_result_text += f"\nNgoài việc bị phạt tiền, người vi phạm còn bị: {hpbsnoidung}"
|
|
|
|
| 354 |
if impounding:
|
| 355 |
full_result_text += f"\nTạm giữ phương tiên: 07 ngày"
|
| 356 |
if top and (top.get('tieude') or top.get('noidung')):
|
| 357 |
+
top_result_text += f"\n{(match.get('structure') or '').strip()}:\n"
|
| 358 |
+
# tieude = (top.get('tieude') or '').strip()
|
| 359 |
+
# noidung = (top.get('noidung') or '').strip()
|
| 360 |
+
# hanhvi = (tieude + "\n" + noidung).strip().replace('\n', ' ')
|
| 361 |
+
# top_result_text += f"Thực hiện hành vi:\n{hanhvi}"
|
| 362 |
+
# canhantu = arr_to_str(top.get('canhantu'))
|
| 363 |
+
# canhanden = arr_to_str(top.get('canhanden'))
|
| 364 |
+
# if canhantu or canhanden:
|
| 365 |
+
# top_result_text += f"\nCá nhân sẽ bị phạt tiền từ {canhantu} VNĐ đến {canhanden} VNĐ"
|
| 366 |
+
# tochuctu = arr_to_str(top.get('tochuctu'))
|
| 367 |
+
# tochucden = arr_to_str(top.get('tochucden'))
|
| 368 |
+
# if tochuctu or tochucden:
|
| 369 |
+
# top_result_text += f"\nTổ chức sẽ bị phạt tiền từ {tochuctu} VNĐ đến {tochucden} VNĐ"
|
| 370 |
+
fullContent = (match.get('fullContent') or '').strip()
|
| 371 |
+
top_result_text += f"{fullContent}"
|
| 372 |
hpbsnoidung = arr_to_str(top.get('hpbsnoidung'), sep="; ")
|
| 373 |
if hpbsnoidung:
|
| 374 |
top_result_text += f"\nNgoài việc bị phạt tiền, người vi phạm còn bị: {hpbsnoidung}"
|
|
|
|
| 399 |
logger.error(f"LLM không sẵn sàng: {e}\n{traceback.format_exc()}")
|
| 400 |
fallback = "Tóm tắt các đoạn luật liên quan:\n\n"
|
| 401 |
for i, match in enumerate(matches, 1):
|
| 402 |
+
fallback += f"\n{(match.get('structure') or '').strip()}:\n"
|
| 403 |
+
# tieude = (match.get('tieude') or '').strip()
|
| 404 |
+
# noidung = (match.get('noidung') or '').strip()
|
| 405 |
+
# if tieude or noidung:
|
| 406 |
+
# fallback += f" - Hành vi: {(tieude + ' ' + noidung).strip()}\n"
|
| 407 |
+
# canhantu = arr_to_str(match.get('canhantu'))
|
| 408 |
+
# canhanden = arr_to_str(match.get('canhanden'))
|
| 409 |
+
# if canhantu or canhanden:
|
| 410 |
+
# fallback += f" - Cá nhân bị phạt tiền từ {canhantu} VNĐ đến {canhanden} VNĐ\n"
|
| 411 |
+
# tochuctu = arr_to_str(match.get('tochuctu'))
|
| 412 |
+
# tochucden = arr_to_str(match.get('tochucden'))
|
| 413 |
+
# if tochuctu or tochucden:
|
| 414 |
+
# fallback += f" - Tổ chức bị phạt tiền từ {tochuctu} VNĐ đến {tochucden} VNĐ\n"
|
| 415 |
+
fullContent = (match.get('fullContent') or '').strip()
|
| 416 |
+
fallback += f"{fullContent}"
|
| 417 |
hpbsnoidung = arr_to_str(match.get('hpbsnoidung'), sep="; ")
|
| 418 |
if hpbsnoidung:
|
| 419 |
fallback += f" - Hình phạt bổ sung: {hpbsnoidung}\n"
|
|
|
|
| 433 |
async def handle_muc_phat(self, conv, message_text, page_token, sender_id):
|
| 434 |
vehicle = conv.get('originalvehicle', '')
|
| 435 |
action = conv.get('originalaction', '')
|
| 436 |
+
question = conv.get('originalquestion', '')
|
| 437 |
keywords = [kw.strip() for kw in vehicle.split(',') if kw.strip()]
|
| 438 |
+
#remove the requirement of having to have vehicle
|
| 439 |
+
# if keywords:
|
| 440 |
+
if question:
|
| 441 |
+
logger.info(f"[DEBUG] tạo embedding: {question}")
|
| 442 |
+
embedding = await self.channel.embedder.create_embedding(question)
|
| 443 |
+
logger.info(f"[DEBUG] embedding: {embedding[:5]} ... (total {len(embedding)})")
|
| 444 |
+
matches = self.channel.supabase.match_documents(
|
| 445 |
+
embedding,
|
| 446 |
+
# vehicle_keywords=keywords,
|
| 447 |
+
user_question=question
|
| 448 |
+
)
|
| 449 |
+
logger.info(f"[DEBUG] matches: {matches}")
|
| 450 |
+
if matches:
|
| 451 |
+
response = await self.format_search_results(message_text, matches, page_token, sender_id)
|
|
|
|
| 452 |
else:
|
| 453 |
+
response = "Xin lỗi, tôi không tìm thấy thông tin phù hợp."
|
|
|
|
|
|
|
| 454 |
else:
|
| 455 |
+
logger.info(f"[DEBUG] Không có hành vi vi phạm: {message_text}")
|
| 456 |
+
response = "Xin lỗi, tôi không tìm thấy thông tin về hành vi vi phạm trong câu hỏi của bạn."
|
| 457 |
+
conv['isdone'] = True
|
| 458 |
+
# else:
|
| 459 |
+
# response = "Vui lòng cho biết loại phương tiện bạn cần tìm (xe máy, ô tô...)"
|
| 460 |
+
# conv['isdone'] = False
|
| 461 |
return response
|
| 462 |
|
| 463 |
async def handle_quy_tac(self, conv, message_text):
|
app/sheets.py
CHANGED
|
@@ -87,14 +87,14 @@ class SheetsClient:
|
|
| 87 |
values = result.get('values', [])
|
| 88 |
history = []
|
| 89 |
for row in values:
|
| 90 |
-
row = row + [""] * (
|
| 91 |
try:
|
| 92 |
-
timestamps = json.loads(row[
|
| 93 |
except Exception:
|
| 94 |
timestamps = []
|
| 95 |
if not isinstance(timestamps, list):
|
| 96 |
timestamps = [timestamps]
|
| 97 |
-
if row[4] == user_id and row[5] == page_id and row[
|
| 98 |
history.append({
|
| 99 |
'conversation_id': row[0],
|
| 100 |
'originalcommand': row[1],
|
|
@@ -106,8 +106,9 @@ class SheetsClient:
|
|
| 106 |
'originalvehicle': row[7],
|
| 107 |
'originalaction': row[8],
|
| 108 |
'originalpurpose': row[9],
|
|
|
|
| 109 |
'timestamp': timestamps,
|
| 110 |
-
'isdone': row[
|
| 111 |
})
|
| 112 |
return history
|
| 113 |
except Exception as e:
|
|
@@ -127,6 +128,7 @@ class SheetsClient:
|
|
| 127 |
originalvehicle: str = "",
|
| 128 |
originalaction: str = "",
|
| 129 |
originalpurpose: str = "",
|
|
|
|
| 130 |
timestamp: Any = None,
|
| 131 |
isdone: bool = False
|
| 132 |
) -> Optional[Dict[str, Any]]:
|
|
@@ -179,6 +181,7 @@ class SheetsClient:
|
|
| 179 |
'originalvehicle': row[7],
|
| 180 |
'originalaction': row[8],
|
| 181 |
'originalpurpose': row[9],
|
|
|
|
| 182 |
'timestamp': row_timestamps,
|
| 183 |
'isdone': row[11].lower() == 'true' if len(row) > 11 else False
|
| 184 |
}
|
|
@@ -196,6 +199,7 @@ class SheetsClient:
|
|
| 196 |
originalvehicle,
|
| 197 |
originalaction,
|
| 198 |
originalpurpose,
|
|
|
|
| 199 |
json.dumps(timestamp),
|
| 200 |
str(isdone).lower()
|
| 201 |
]
|
|
@@ -209,7 +213,7 @@ class SheetsClient:
|
|
| 209 |
valueInputOption='RAW',
|
| 210 |
body=body
|
| 211 |
).execute()
|
| 212 |
-
logger.info(f"Thêm mới conversation: {conversation_id} | Giá trị: {dict(zip(['conversation_id','originalcommand','originalcontent','originalattachments','recipient_id','page_id','originaltext','originalvehicle','originalaction','originalpurpose','timestamp','isdone'], new_row))}")
|
| 213 |
|
| 214 |
# Return the conversation data directly
|
| 215 |
return {
|
|
@@ -223,6 +227,7 @@ class SheetsClient:
|
|
| 223 |
'originalvehicle': originalvehicle,
|
| 224 |
'originalaction': originalaction,
|
| 225 |
'originalpurpose': originalpurpose,
|
|
|
|
| 226 |
'timestamp': timestamp,
|
| 227 |
'isdone': isdone
|
| 228 |
}
|
|
@@ -264,8 +269,9 @@ class SheetsClient:
|
|
| 264 |
originalvehicle if originalvehicle else current_row[7],
|
| 265 |
originalaction if originalaction else current_row[8],
|
| 266 |
originalpurpose if originalpurpose else current_row[9],
|
|
|
|
| 267 |
json.dumps(current_timestamps),
|
| 268 |
-
str(isdone).lower() if isdone is not None else current_row[
|
| 269 |
]
|
| 270 |
update_range = f"{SHEET_RANGE.split('!')[0]}!A{sheet_row_number}"
|
| 271 |
logger.info(f"[DEBUG] Gsheet update range {update_range}")
|
|
@@ -278,7 +284,7 @@ class SheetsClient:
|
|
| 278 |
valueInputOption='RAW',
|
| 279 |
body=body
|
| 280 |
).execute()
|
| 281 |
-
changed_cols = ['conversation_id','originalcommand','originalcontent','originalattachments','recipient_id','page_id','originaltext','originalvehicle','originalaction','originalpurpose','timestamp','isdone']
|
| 282 |
for idx, (old, new) in enumerate(zip(current_row, new_row)):
|
| 283 |
if old != new:
|
| 284 |
changed_cols.append(changed_cols[idx])
|
|
@@ -296,8 +302,9 @@ class SheetsClient:
|
|
| 296 |
'originalvehicle': new_row[7],
|
| 297 |
'originalaction': new_row[8],
|
| 298 |
'originalpurpose': new_row[9],
|
|
|
|
| 299 |
'timestamp': current_timestamps,
|
| 300 |
-
'isdone': new_row[
|
| 301 |
}
|
| 302 |
return None
|
| 303 |
except Exception as e:
|
|
|
|
| 87 |
values = result.get('values', [])
|
| 88 |
history = []
|
| 89 |
for row in values:
|
| 90 |
+
row = row + [""] * (13 - len(row))
|
| 91 |
try:
|
| 92 |
+
timestamps = json.loads(row[11]) if row[11] else []
|
| 93 |
except Exception:
|
| 94 |
timestamps = []
|
| 95 |
if not isinstance(timestamps, list):
|
| 96 |
timestamps = [timestamps]
|
| 97 |
+
if row[4] == user_id and row[5] == page_id and row[12].lower() == 'false':
|
| 98 |
history.append({
|
| 99 |
'conversation_id': row[0],
|
| 100 |
'originalcommand': row[1],
|
|
|
|
| 106 |
'originalvehicle': row[7],
|
| 107 |
'originalaction': row[8],
|
| 108 |
'originalpurpose': row[9],
|
| 109 |
+
'originalquestion': row[10],
|
| 110 |
'timestamp': timestamps,
|
| 111 |
+
'isdone': row[12].lower() == 'true'
|
| 112 |
})
|
| 113 |
return history
|
| 114 |
except Exception as e:
|
|
|
|
| 128 |
originalvehicle: str = "",
|
| 129 |
originalaction: str = "",
|
| 130 |
originalpurpose: str = "",
|
| 131 |
+
originalquestion: str = "", # <-- thêm dòng này
|
| 132 |
timestamp: Any = None,
|
| 133 |
isdone: bool = False
|
| 134 |
) -> Optional[Dict[str, Any]]:
|
|
|
|
| 181 |
'originalvehicle': row[7],
|
| 182 |
'originalaction': row[8],
|
| 183 |
'originalpurpose': row[9],
|
| 184 |
+
'originalquestion': row[10],
|
| 185 |
'timestamp': row_timestamps,
|
| 186 |
'isdone': row[11].lower() == 'true' if len(row) > 11 else False
|
| 187 |
}
|
|
|
|
| 199 |
originalvehicle,
|
| 200 |
originalaction,
|
| 201 |
originalpurpose,
|
| 202 |
+
originalquestion, # <-- thêm dòng này
|
| 203 |
json.dumps(timestamp),
|
| 204 |
str(isdone).lower()
|
| 205 |
]
|
|
|
|
| 213 |
valueInputOption='RAW',
|
| 214 |
body=body
|
| 215 |
).execute()
|
| 216 |
+
logger.info(f"Thêm mới conversation: {conversation_id} | Giá trị: {dict(zip(['conversation_id','originalcommand','originalcontent','originalattachments','recipient_id','page_id','originaltext','originalvehicle','originalaction','originalpurpose','originalquestion','timestamp','isdone'], new_row))}")
|
| 217 |
|
| 218 |
# Return the conversation data directly
|
| 219 |
return {
|
|
|
|
| 227 |
'originalvehicle': originalvehicle,
|
| 228 |
'originalaction': originalaction,
|
| 229 |
'originalpurpose': originalpurpose,
|
| 230 |
+
'originalquestion': originalquestion,
|
| 231 |
'timestamp': timestamp,
|
| 232 |
'isdone': isdone
|
| 233 |
}
|
|
|
|
| 269 |
originalvehicle if originalvehicle else current_row[7],
|
| 270 |
originalaction if originalaction else current_row[8],
|
| 271 |
originalpurpose if originalpurpose else current_row[9],
|
| 272 |
+
originalquestion if originalquestion else current_row[10], # <-- thêm dòng này
|
| 273 |
json.dumps(current_timestamps),
|
| 274 |
+
str(isdone).lower() if isdone is not None else current_row[12]
|
| 275 |
]
|
| 276 |
update_range = f"{SHEET_RANGE.split('!')[0]}!A{sheet_row_number}"
|
| 277 |
logger.info(f"[DEBUG] Gsheet update range {update_range}")
|
|
|
|
| 284 |
valueInputOption='RAW',
|
| 285 |
body=body
|
| 286 |
).execute()
|
| 287 |
+
changed_cols = ['conversation_id','originalcommand','originalcontent','originalattachments','recipient_id','page_id','originaltext','originalvehicle','originalaction','originalpurpose','originalquestion','timestamp','isdone']
|
| 288 |
for idx, (old, new) in enumerate(zip(current_row, new_row)):
|
| 289 |
if old != new:
|
| 290 |
changed_cols.append(changed_cols[idx])
|
|
|
|
| 302 |
'originalvehicle': new_row[7],
|
| 303 |
'originalaction': new_row[8],
|
| 304 |
'originalpurpose': new_row[9],
|
| 305 |
+
'originalquestion': new_row[10], # <-- thêm dòng này
|
| 306 |
'timestamp': current_timestamps,
|
| 307 |
+
'isdone': new_row[12].lower() == 'true'
|
| 308 |
}
|
| 309 |
return None
|
| 310 |
except Exception as e:
|