fix data update
Browse files- app/constants.py +98 -18
- app/llm.py +8 -6
- app/main.py +18 -2
app/constants.py
CHANGED
|
@@ -1,34 +1,114 @@
|
|
| 1 |
VEHICLE_KEYWORDS = [
|
| 2 |
-
|
| 3 |
-
"ô tô", "xe
|
| 4 |
-
"
|
| 5 |
-
"
|
| 6 |
-
"xe đạp máy", "xe đạp điện", "xe thô sơ", "xích lô", "xe bò", "súc vật kéo", "xe đạp",
|
| 7 |
-
"đi bộ"
|
| 8 |
-
]
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
# Mapping từ từ khóa sang tên cột trong bảng tblPhuongtien
|
| 14 |
VEHICLE_KEYWORD_TO_COLUMN = {
|
| 15 |
-
|
| 16 |
-
"xe tải": "otoTai",
|
| 17 |
"ô tô": "oto",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
"xe khách": "oto",
|
| 19 |
"ô tô khách": "oto",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
"mô tô": "moto",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
"xe máy điện": "xemaydien",
|
| 22 |
-
|
|
|
|
| 23 |
"xe gắn máy": "xeganmay",
|
| 24 |
-
"máy
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
| 27 |
"xe đạp điện": "xedapdien",
|
|
|
|
|
|
|
| 28 |
"xe thô sơ": "xethoso",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
"xích lô": "xichlo",
|
|
|
|
|
|
|
| 30 |
"xe bò": "sucvat",
|
|
|
|
| 31 |
"súc vật kéo": "sucvat",
|
| 32 |
-
"xe
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
VEHICLE_KEYWORDS = [
|
| 2 |
+
# Ô tô các loại
|
| 3 |
+
"ô tô", "xe ô tô", "xe hơi", "xe con", "xe bốn bánh", "xe 4 bánh",
|
| 4 |
+
"xe du lịch", "xe taxi", "xe khách", "ô tô khách", "xe buýt", "xe bus",
|
| 5 |
+
"ô tô tải", "xe tải", "xe ben", "xe container", "xe đông lạnh", "xe cầu", "xe cứu thương", "xe cứu hỏa",
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
+
# Xe máy, mô tô
|
| 8 |
+
"mô tô", "xe mô tô", "xe máy", "xe gắn máy", "xe hai bánh", "xe máy điện", "xe tay ga", "xe số", "xe côn",
|
| 9 |
+
"xe phân khối lớn", "phân khối lớn", "PKL",
|
| 10 |
+
|
| 11 |
+
# Xe đạp, các loại xe thô sơ
|
| 12 |
+
"xe đạp", "xe đạp máy", "xe đạp điện", "xe thô sơ", "xe ba gác", "ba gác", "xe lam", "xích lô", "xe kéo", "xe bò",
|
| 13 |
+
"xe súc vật kéo", "súc vật kéo",
|
| 14 |
+
|
| 15 |
+
# Máy kéo và xe chuyên dùng
|
| 16 |
+
"máy kéo", "xe máy kéo", "xe công nông", "xe chuyên dùng", "xe lu", "xe ủi", "xe xúc", "xe nâng",
|
| 17 |
|
| 18 |
+
# Các cách gọi dân dã, địa phương
|
| 19 |
+
"xe honda", # phổ biến ở miền Nam để chỉ xe máy
|
| 20 |
+
"xe dream", "xe cub", "xe wave", # gọi theo hãng/model nhưng hay dùng để chỉ xe máy nói chung
|
| 21 |
+
|
| 22 |
+
# Người đi bộ
|
| 23 |
+
"đi bộ", "người đi bộ", "bộ hành"
|
| 24 |
+
]
|
| 25 |
# Mapping từ từ khóa sang tên cột trong bảng tblPhuongtien
|
| 26 |
VEHICLE_KEYWORD_TO_COLUMN = {
|
| 27 |
+
# Ô tô & các biến thể
|
|
|
|
| 28 |
"ô tô": "oto",
|
| 29 |
+
"xe ô tô": "oto",
|
| 30 |
+
"xe hơi": "oto",
|
| 31 |
+
"xe con": "oto",
|
| 32 |
+
"xe bốn bánh": "oto",
|
| 33 |
+
"xe 4 bánh": "oto",
|
| 34 |
+
"xe du lịch": "oto",
|
| 35 |
+
"xe taxi": "oto",
|
| 36 |
"xe khách": "oto",
|
| 37 |
"ô tô khách": "oto",
|
| 38 |
+
"xe buýt": "oto",
|
| 39 |
+
"xe bus": "oto",
|
| 40 |
+
|
| 41 |
+
# Ô tô tải
|
| 42 |
+
"ô tô tải": "otoTai",
|
| 43 |
+
"xe tải": "otoTai",
|
| 44 |
+
"xe ben": "otoTai",
|
| 45 |
+
"xe container": "otoTai",
|
| 46 |
+
"xe đông lạnh": "otoTai",
|
| 47 |
+
"xe cầu": "otoTai",
|
| 48 |
+
"xe cứu thương": "otoTai",
|
| 49 |
+
"xe cứu hỏa": "otoTai",
|
| 50 |
+
|
| 51 |
+
# Máy kéo
|
| 52 |
+
"máy kéo": "maykeo",
|
| 53 |
+
"xe máy kéo": "maykeo",
|
| 54 |
+
"xe công nông": "maykeo",
|
| 55 |
+
|
| 56 |
+
# Xe chuyên dùng
|
| 57 |
+
"xe chuyên dùng": "xechuyendung",
|
| 58 |
+
"xe lu": "xechuyendung",
|
| 59 |
+
"xe ủi": "xechuyendung",
|
| 60 |
+
"xe xúc": "xechuyendung",
|
| 61 |
+
"xe nâng": "xechuyendung",
|
| 62 |
+
|
| 63 |
+
# Mô tô
|
| 64 |
"mô tô": "moto",
|
| 65 |
+
"xe mô tô": "moto",
|
| 66 |
+
"xe máy": "moto",
|
| 67 |
+
"xe tay ga": "moto",
|
| 68 |
+
"xe số": "moto",
|
| 69 |
+
"xe côn": "moto",
|
| 70 |
+
"xe phân khối lớn": "moto",
|
| 71 |
+
"phân khối lớn": "moto",
|
| 72 |
+
"PKL": "moto",
|
| 73 |
+
"xe honda": "moto", # dân dã
|
| 74 |
+
"xe dream": "moto",
|
| 75 |
+
"xe cub": "moto",
|
| 76 |
+
"xe wave": "moto",
|
| 77 |
+
|
| 78 |
+
# Xe máy điện
|
| 79 |
"xe máy điện": "xemaydien",
|
| 80 |
+
|
| 81 |
+
# Xe gắn máy
|
| 82 |
"xe gắn máy": "xeganmay",
|
| 83 |
+
"xe đạp máy": "xeganmay",
|
| 84 |
+
|
| 85 |
+
# Xe đạp
|
| 86 |
+
"xe đạp": "xedap",
|
| 87 |
+
|
| 88 |
+
# Xe đạp điện
|
| 89 |
"xe đạp điện": "xedapdien",
|
| 90 |
+
|
| 91 |
+
# Xe thô sơ
|
| 92 |
"xe thô sơ": "xethoso",
|
| 93 |
+
"xe ba gác": "xethoso",
|
| 94 |
+
"ba gác": "xethoso",
|
| 95 |
+
"xe lam": "xethoso",
|
| 96 |
+
|
| 97 |
+
# Xích lô
|
| 98 |
"xích lô": "xichlo",
|
| 99 |
+
|
| 100 |
+
# Súc vật kéo
|
| 101 |
"xe bò": "sucvat",
|
| 102 |
+
"xe súc vật kéo": "sucvat",
|
| 103 |
"súc vật kéo": "sucvat",
|
| 104 |
+
"xe kéo": "sucvat",
|
| 105 |
+
|
| 106 |
+
# Đi bộ
|
| 107 |
+
"đi bộ": "dibo",
|
| 108 |
+
"người đi bộ": "dibo",
|
| 109 |
+
"bộ hành": "dibo"
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
SHEET_RANGE = 'chat!A2:L'
|
| 114 |
+
EMBEDDING_DIM = 1536
|
app/llm.py
CHANGED
|
@@ -431,15 +431,17 @@ class LLMClient:
|
|
| 431 |
"""
|
| 432 |
|
| 433 |
prompt = f"""
|
| 434 |
-
Bạn là một AI chuyên phân tích ngữ nghĩa câu hỏi về giao thông
|
| 435 |
-
|
| 436 |
-
{
|
| 437 |
"muc_dich": "mục đích của câu hỏi",
|
| 438 |
"phuong_tien": "loại phương tiện giao thông (nếu có)",
|
| 439 |
-
"hanh_vi_vi_pham": "hành vi vi phạm luật giao thông"
|
| 440 |
-
}
|
|
|
|
|
|
|
| 441 |
|
| 442 |
-
Câu
|
| 443 |
\"{text}\"
|
| 444 |
""".strip()
|
| 445 |
|
|
|
|
| 431 |
"""
|
| 432 |
|
| 433 |
prompt = f"""
|
| 434 |
+
Bạn là một AI chuyên phân tích ngữ nghĩa câu hỏi về luật giao thông. Với mỗi câu đầu vào, hãy trích xuất các thông tin sau dưới dạng JSON:
|
| 435 |
+
|
| 436 |
+
{
|
| 437 |
"muc_dich": "mục đích của câu hỏi",
|
| 438 |
"phuong_tien": "loại phương tiện giao thông (nếu có)",
|
| 439 |
+
"hanh_vi_vi_pham": "hành vi vi phạm pháp luật giao thông"
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
Nếu một trường không có trong câu hỏi, hãy để giá trị là chuỗi rỗng "". Ví dụ: nếu câu không đề cập phương tiện, thì "phuong_tien": ""
|
| 443 |
|
| 444 |
+
Câu hỏi:
|
| 445 |
\"{text}\"
|
| 446 |
""".strip()
|
| 447 |
|
app/main.py
CHANGED
|
@@ -7,6 +7,7 @@ import asyncio
|
|
| 7 |
from concurrent.futures import ThreadPoolExecutor
|
| 8 |
import os
|
| 9 |
import traceback
|
|
|
|
| 10 |
|
| 11 |
from .config import Settings, get_settings
|
| 12 |
from .facebook import FacebookClient
|
|
@@ -85,6 +86,21 @@ def flatten_timestamp(ts):
|
|
| 85 |
flat.append(t)
|
| 86 |
return flat
|
| 87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
@app.get("/")
|
| 89 |
async def root():
|
| 90 |
"""Endpoint root để kiểm tra trạng thái app."""
|
|
@@ -278,11 +294,11 @@ async def process_message(message_data: Dict[str, Any]):
|
|
| 278 |
muc_dich = None
|
| 279 |
hanh_vi_vi_pham = None
|
| 280 |
if isinstance(llm_analysis, dict):
|
| 281 |
-
keywords = [llm_analysis.get('phuong_tien', '')
|
| 282 |
muc_dich = llm_analysis.get('muc_dich')
|
| 283 |
hanh_vi_vi_pham = llm_analysis.get('hanh_vi_vi_pham')
|
| 284 |
elif isinstance(llm_analysis, list) and len(llm_analysis) > 0:
|
| 285 |
-
keywords = [llm_analysis[0].get('phuong_tien', '')
|
| 286 |
muc_dich = llm_analysis[0].get('muc_dich')
|
| 287 |
hanh_vi_vi_pham = llm_analysis[0].get('hanh_vi_vi_pham')
|
| 288 |
else:
|
|
|
|
| 7 |
from concurrent.futures import ThreadPoolExecutor
|
| 8 |
import os
|
| 9 |
import traceback
|
| 10 |
+
import difflib
|
| 11 |
|
| 12 |
from .config import Settings, get_settings
|
| 13 |
from .facebook import FacebookClient
|
|
|
|
| 86 |
flat.append(t)
|
| 87 |
return flat
|
| 88 |
|
| 89 |
+
def normalize_vehicle_keyword(keyword: str) -> str:
|
| 90 |
+
"""
|
| 91 |
+
Chuẩn hoá giá trị phương tiện về đúng từ khoá gần nhất trong VEHICLE_KEYWORDS.
|
| 92 |
+
Nếu không khớp, trả về keyword gốc.
|
| 93 |
+
"""
|
| 94 |
+
if not keyword:
|
| 95 |
+
return ""
|
| 96 |
+
matches = difflib.get_close_matches(keyword.lower(), [k.lower() for k in VEHICLE_KEYWORDS], n=1, cutoff=0.6)
|
| 97 |
+
if matches:
|
| 98 |
+
# Trả về đúng case trong VEHICLE_KEYWORDS
|
| 99 |
+
for k in VEHICLE_KEYWORDS:
|
| 100 |
+
if k.lower() == matches[0]:
|
| 101 |
+
return k
|
| 102 |
+
return keyword
|
| 103 |
+
|
| 104 |
@app.get("/")
|
| 105 |
async def root():
|
| 106 |
"""Endpoint root để kiểm tra trạng thái app."""
|
|
|
|
| 294 |
muc_dich = None
|
| 295 |
hanh_vi_vi_pham = None
|
| 296 |
if isinstance(llm_analysis, dict):
|
| 297 |
+
keywords = [normalize_vehicle_keyword(llm_analysis.get('phuong_tien', ''))]
|
| 298 |
muc_dich = llm_analysis.get('muc_dich')
|
| 299 |
hanh_vi_vi_pham = llm_analysis.get('hanh_vi_vi_pham')
|
| 300 |
elif isinstance(llm_analysis, list) and len(llm_analysis) > 0:
|
| 301 |
+
keywords = [normalize_vehicle_keyword(llm_analysis[0].get('phuong_tien', ''))]
|
| 302 |
muc_dich = llm_analysis[0].get('muc_dich')
|
| 303 |
hanh_vi_vi_pham = llm_analysis[0].get('hanh_vi_vi_pham')
|
| 304 |
else:
|