Commit 1929f6fe authored by Vũ Hoàng Anh's avatar Vũ Hoàng Anh

feat(ai-stylist): Refactor product grouping logic; enforce internal_ref_code...

feat(ai-stylist): Refactor product grouping logic; enforce internal_ref_code mapping for variants and clamp product_ids prompt to master code only
parent 091f7146
...@@ -140,9 +140,10 @@ def format_product_results(products: list[dict]) -> list[dict]: ...@@ -140,9 +140,10 @@ def format_product_results(products: list[dict]) -> list[dict]:
if product_color_code and "-" in product_color_code: if product_color_code and "-" in product_color_code:
parts = product_color_code.split("-", 1) parts = product_color_code.split("-", 1)
color_code_only = parts[1] if len(parts) > 1 else "" color_code_only = parts[1] if len(parts) > 1 else ""
internal_ref = p.get("internal_ref_code", "")
# Use magento_ref as base SKU for grouping # Dùng internal_ref (Mã tổng) làm rễ để gom toàn bộ màu của mã đó vào 1 card duy nhất
base_sku = magento_ref or product_color_code base_sku = internal_ref or magento_ref or product_color_code
if not base_sku: if not base_sku:
continue continue
......
...@@ -39,7 +39,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b ...@@ -39,7 +39,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b
```json ```json
{{ {{
"ai_response": "Câu trả lời ngắn gọn, KHÔNG chứa mã SKU — frontend tự render product card từ product_ids", "ai_response": "Câu trả lời ngắn gọn, KHÔNG chứa mã SKU — frontend tự render product card từ product_ids",
"product_ids": ["8TS24W001", "8TS24W002"], "product_ids": ["8TS24W001", "8TS24W002"], // LƯU Ý: CHỈ LẤY 9 KÝ TỰ ĐẦU TIÊN (MÃ TỔNG). Kể cả data là 6TS25A001-SN010 thì CẤM output nguyên cục, CHỈ CẮT LẤY "6TS25A001".
"user_insight": {{ "user_insight": {{
"USER": "...", "USER": "...",
"TARGET": "...", "TARGET": "...",
...@@ -53,7 +53,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b ...@@ -53,7 +53,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b
``` ```
**LƯU Ý:** **LƯU Ý:**
- `product_ids` chỉ chứa ARRAY of STRING (mã SKU), KHÔNG phải object - `product_ids`: **BẮT BUỘC CHỈ ĐƯỢC CHỨA MÃ TỔNG (9 KÝ TỰ - VD: 6TS25A001)**. Nếu data có đuôi cắt ngang (VD: 6TS25A001-SN010) thì bạn PHẢI TỰ CẮT BỎ CÁI ĐUÔI ĐÓ ĐI, KHÔNG ĐƯỢC OUTPUT MÃ MÀU RA ĐÂY!
- `user_insight` theo đúng format 6 tầng như mục 8 - `user_insight` theo đúng format 6 tầng như mục 8
- **LUÔN DÙNG NGOẶC KÉP `{{` và `}}` CHO JSON** - **LUÔN DÙNG NGOẶC KÉP `{{` và `}}` CHO JSON**
......
...@@ -335,6 +335,7 @@ CASE 7: "Set đồ công sở cho nữ" → 2 Queries: ...@@ -335,6 +335,7 @@ CASE 7: "Set đồ công sở cho nữ" → 2 Queries:
CASE 8: "Tìm mã 6KS25S005" CASE 8: "Tìm mã 6KS25S005"
→ magento_ref_code: "6KS25S005", description: "product_name: Sản phẩm. description_text: Tìm sản phẩm theo mã" → magento_ref_code: "6KS25S005", description: "product_name: Sản phẩm. description_text: Tìm sản phẩm theo mã"
⚠️ RIÊNG TÌM THEO MÃ SKU: TUYỆT ĐỐI KHÔNG ĐƯỢC tự suy diễn màu sắc (master_color), loại sản phẩm (product_line_vn) từ các chữ cái trong mã SKU. ĐỂ NULL HẾT! (Ví dụ không được đoán TS là áo trắng).
CASE 9: "Áo cá sấu polo đi chơi" CASE 9: "Áo cá sấu polo đi chơi"
→ description: "product_name: Áo cá sấu polo. description_text: Áo cá sấu polo đi chơi năng động trẻ trung. style: Dynamic" → description: "product_name: Áo cá sấu polo. description_text: Áo cá sấu polo đi chơi năng động trẻ trung. style: Dynamic"
......
...@@ -122,39 +122,46 @@ async def build_starrocks_query(params, query_vector: list[float] | None = None) ...@@ -122,39 +122,46 @@ async def build_starrocks_query(params, query_vector: list[float] | None = None)
# ============================================================ # ============================================================
magento_code = getattr(params, "magento_ref_code", None) magento_code = getattr(params, "magento_ref_code", None)
if magento_code: if magento_code:
sql_params = [magento_code, magento_code] sql_params = [magento_code, magento_code, magento_code]
extra_where = "" extra_where = ""
# Apply master_color filter if provided (e.g., "6TS25W008 màu hồng") # GHI CHÚ QUAN TRỌNG:
# KHÔNG filter cứng master_color ở cấp độ SQL khi tìm kiếm CHÍNH XÁC THEO MÃ (Code Search).
# Lý do: Nếu mã tồn tại nhưng màu bị filter ra rỗng, AI sẽ nhận kq rỗng và bảo "Sản phẩm không tồn tại".
# Thay vào đó, ta thả nổi để lấy vể TẤT CẢ các màu hiện có của mã đó.
# AI (với system prompt) sẽ tự check dict trả về:
# "À, mã này có màu Xanh, Đỏ nhưng không có màu Hồng như khách hỏi. Mình sẽ báo cho khách chuyển màu."
color_val = getattr(params, "master_color", None) color_val = getattr(params, "master_color", None)
if color_val: if color_val:
color_lower = color_val.lower().strip() logger.info(f"🎨 [CODE SEARCH - NO SQL FILTER] Code: {magento_code}, Requested Color: {color_val}")
extra_where += " AND (LOWER(master_color) LIKE %s OR LOWER(product_color_name) LIKE %s)"
sql_params.extend([f"%{color_lower}%", f"%{color_lower}%"])
logger.info(f"🎨 [CODE SEARCH + COLOR FILTER] Code: {magento_code}, Color: {color_val}")
sql = f""" sql = f"""
SELECT SELECT
internal_ref_code, internal_ref_code,
magento_ref_code, MAX(magento_ref_code) as magento_ref_code,
product_color_code, product_color_code,
product_name, MAX(product_name) as product_name,
master_color, MAX(master_color) as master_color,
product_image_url_thumbnail, MAX(product_image_url_thumbnail) as product_image_url_thumbnail,
product_web_url, MAX(product_web_url) as product_web_url,
description_text, MAX(description_text) as description_text,
sale_price, MAX(sale_price) as sale_price,
original_price, MAX(original_price) as original_price,
discount_amount, MAX(discount_amount) as discount_amount,
ROUND(((original_price - sale_price) / original_price * 100), 0) as discount_percent, MAX(ROUND(((original_price - sale_price) / original_price * 100), 0)) as discount_percent,
age_by_product, MAX(age_by_product) as age_by_product,
gender_by_product, MAX(gender_by_product) as gender_by_product,
product_line_vn, MAX(product_line_vn) as product_line_vn,
quantity_sold, MAX(quantity_sold) as quantity_sold,
size_scale, MAX(size_scale) as size_scale,
1.0 as similarity_score 1.0 as similarity_score
FROM shared_source.magento_product_dimension_with_text_embedding FROM shared_source.magento_product_dimension_with_text_embedding
WHERE (internal_ref_code = %s OR magento_ref_code = %s){extra_where} WHERE internal_ref_code IN (
SELECT internal_ref_code
FROM shared_source.magento_product_dimension_with_text_embedding
WHERE internal_ref_code = %s OR magento_ref_code = %s OR product_color_code = %s
){extra_where}
GROUP BY internal_ref_code, product_color_code
""" """
return sql, sql_params return sql, sql_params
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment