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]:
if product_color_code and "-" in product_color_code:
parts = product_color_code.split("-", 1)
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
base_sku = magento_ref or product_color_code
# 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 = internal_ref or magento_ref or product_color_code
if not base_sku:
continue
......
......@@ -39,7 +39,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b
```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",
"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": "...",
"TARGET": "...",
......@@ -53,7 +53,7 @@ Bạn PHẢI trả về JSON thuần túy, KHÔNG ĐƯỢC wrap trong markdown b
```
**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
- **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:
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ã"
⚠️ 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"
→ 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)
# ============================================================
magento_code = getattr(params, "magento_ref_code", None)
if magento_code:
sql_params = [magento_code, magento_code]
sql_params = [magento_code, magento_code, magento_code]
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)
if color_val:
color_lower = color_val.lower().strip()
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}")
logger.info(f"🎨 [CODE SEARCH - NO SQL FILTER] Code: {magento_code}, Requested Color: {color_val}")
sql = f"""
SELECT
internal_ref_code,
magento_ref_code,
MAX(magento_ref_code) as magento_ref_code,
product_color_code,
product_name,
master_color,
product_image_url_thumbnail,
product_web_url,
description_text,
sale_price,
original_price,
discount_amount,
ROUND(((original_price - sale_price) / original_price * 100), 0) as discount_percent,
age_by_product,
gender_by_product,
product_line_vn,
quantity_sold,
size_scale,
MAX(product_name) as product_name,
MAX(master_color) as master_color,
MAX(product_image_url_thumbnail) as product_image_url_thumbnail,
MAX(product_web_url) as product_web_url,
MAX(description_text) as description_text,
MAX(sale_price) as sale_price,
MAX(original_price) as original_price,
MAX(discount_amount) as discount_amount,
MAX(ROUND(((original_price - sale_price) / original_price * 100), 0)) as discount_percent,
MAX(age_by_product) as age_by_product,
MAX(gender_by_product) as gender_by_product,
MAX(product_line_vn) as product_line_vn,
MAX(quantity_sold) as quantity_sold,
MAX(size_scale) as size_scale,
1.0 as similarity_score
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
......
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