════════════════════════════════════════════════════════════════
  TAG SEARCH AGENT — Kiến trúc tìm kiếm sản phẩm CANIFA
════════════════════════════════════════════════════════════════

📅 Cập nhật: 2026-04-05

═══ 1. TỔNG QUAN ═══

Tag Search Agent là hệ thống tìm kiếm sản phẩm thông minh cho chatbot
CANIFA. AI nhận câu hỏi tự nhiên từ khách → phân tích → gọi tool SQL
→ trả kết quả sản phẩm phù hợp.

Flow:  Khách hỏi → LLM phân tích → tag_search_tool → SQL → Postgres → Kết quả


═══ 2. CÁC FILE CHÍNH ═══

┌─────────────────────────┬────────────────────────────────────────┐
│ File                    │ Vai trò                                │
├─────────────────────────┼────────────────────────────────────────┤
│ tag_search_graph.py     │ LangGraph graph + System Prompt cho AI │
│ tag_search_tool.py      │ Pydantic schema + SQL builder + Tool   │
│ __init__.py             │ Export module                          │
└─────────────────────────┴────────────────────────────────────────┘


═══ 3. SEARCH ARCHITECTURE: 3-TẦNG FALLBACK ═══

  Tầng 1: KEYWORDS + TAGS + FIXED FILTERS
      ↓ (0 kết quả?)
  Tầng 2: TAGS + FIXED FILTERS  (bỏ keywords)
      ↓ (0 kết quả?)
  Tầng 3: CHỈ FIXED FILTERS     (bỏ cả tags)

  FIXED FILTERS = product_type + color + gender + price (luôn giữ, không bỏ)


═══ 4. INPUT SCHEMA (TagSearchInput) ═══

  ① KEYWORDS (list[str]) — từ khoá lấy từ mô tả SP hoặc câu hỏi khách
     Ưu tiên: từ đặc biệt như "30/4", "cờ đỏ sao vàng", "cotton"...
     Tối đa 2 keywords.

  ② TAGS (list[str]) — AI suy luận từ ngữ cảnh
     DANH SÁCH CỐ ĐỊNH (CHỈ 12 GIÁ TRỊ, KHÔNG TỰ NGHĨ RA):
     đi tiệc, đi học, đi chơi, dạo phố, mặc nhà, đi ngủ,
     thể thao, đi dã ngoại, đi biển, đi làm, giữ ấm, thoáng mát
     ⚠️ "đi ăn nhà hàng" ❌ → "đi tiệc" ✅
     ⚠️ "đi picnic" ❌ → "đi dã ngoại" ✅

  ③ PRODUCT_TYPE (list[str]) — CLOSED LIST, CHỈ 14 GIÁ TRỊ:
     ┌──────────────────────────┐
     │ Áo phông                 │
     │ Áo len                   │
     │ Áo nỉ                    │
     │ Áo Polo                  │
     │ Áo Sơ mi                 │
     │ Áo kiểu                  │
     │ Áo khoác chống nắng      │
     │ Cardigan                 │
     │ Váy liền                 │
     │ Chân váy                 │
     │ Quần nỉ                  │
     │ Quần dài                 │
     │ Quần soóc                │
     │ Pyjama                   │
     └──────────────────────────┘
     ⚠️ AI KHÔNG ĐƯỢC tự nghĩ ra loại mới!
        "đồ đông" ❌  →  ["Áo len", "Áo nỉ", "Quần nỉ"] ✅
        "đồ hè"   ❌  →  ["Áo phông", "Quần soóc"]       ✅
        "bộ thể thao" ❌ → ["Áo phông", "Quần soóc"]     ✅
     ⚠️ AUTO-EXPAND từ khái quát:
        "áo"  → ["Áo phông", "Áo Polo", "Áo Sơ mi", "Áo kiểu"]
        "quần" → ["Quần dài", "Quần soóc", "Quần nỉ"]
        "váy"  → ["Váy liền", "Chân váy"]
     ❌ TUYỆT ĐỐI KHÔNG để product_type=[] khi khách đã nhắc loại đồ!

  ④ CÁC FILTER KHÁC:
     - gender_by_product: women, men, boy, girl, unisex, newborn
     - master_color: Màu sắc (AI suy luận: "30/4" → đỏ)
     - price_min / price_max: đơn vị VND
     - discovery_mode: "new" | "best_seller"
     - magento_ref_code: mã SKU cụ thể


═══ 5. QUY TẮC QUAN TRỌNG ═══

  ✅ Tags + Product_type CHỈ chọn từ danh sách cố định
  ✅ Nếu khách nói "áo" → auto-expand thành nhiều loại áo
  ✅ Nếu khách hỏi mơ hồ ("cả gia đình", "cho mọi người")
     → HỎI LẠI: "Bạn muốn tìm cho ai ạ?" TRƯỚC khi gọi tool
  ❌ KHÔNG tự nghĩ ra tags mới (VD: "đi ăn nhà hàng")
  ❌ KHÔNG tự nghĩ ra product_type mới (VD: "đồ đông")
  ❌ KHÔNG để product_type=[] khi khách đã nhắc loại đồ


═══ 6. VÍ DỤ MAPPING ═══

  Câu hỏi khách              →  AI gửi tool_call
  ─────────────────────────────────────────────────────────────
  "Váy đi tiệc cho bé"       →  tags=["đi tiệc"]
                                 product_type=["Váy liền", "Chân váy"]
                                 gender="girl"

  "Áo mặc 30/4"              →  keywords=["30/4"]
                                 tags=["đi chơi"]
                                 product_type=["Áo phông", "Áo kiểu"]
                                 color="đỏ"

  "Bộ thể thao nam"          →  tags=["thể thao"]
                                 product_type=["Áo phông", "Quần soóc"]
                                 gender="men"

  "Đồ mùa đông cho bé gái"  →  tags=["giữ ấm"]
                                 product_type=["Áo len", "Áo nỉ", "Quần nỉ"]
                                 gender="girl"

  "Hàng mới bán chạy"        →  product_type=[]
                                 discovery_mode="best_seller"

  "Áo đi ăn nhà hàng cho nữ" →  tags=["đi tiệc"]  (KHÔNG phải "đi ăn nhà hàng")
                                 product_type=["Áo phông", "Áo Polo", "Áo Sơ mi", "Áo kiểu"]
                                 gender="women"

  "Có áo cho cả gia đình k?" →  HỎI LẠI: "Bạn muốn tìm cho ai ạ?"


═══ 6. SQL GENERATION ═══

  product_type là list → sinh OR clauses:

  WHERE (
    (LOWER(product_name) LIKE '%áo len%' OR LOWER(ultra_description_text) LIKE '%áo len%')
    OR
    (LOWER(product_name) LIKE '%áo nỉ%' OR LOWER(ultra_description_text) LIKE '%áo nỉ%')
    OR
    (LOWER(product_name) LIKE '%quần nỉ%' OR LOWER(ultra_description_text) LIKE '%quần nỉ%')
  )
  AND gender_by_product IN ('female', 'unisex')
  AND ...


═══ 7. API ENDPOINTS ═══

  POST /api/tag-search/chat     → Chat với AI agent
  GET  /api/tag-search/inventory → Thống kê kho hàng (count, giá, màu, tags)


═══ 8. TECH STACK ═══

  - Backend:  FastAPI + LangGraph + LangChain
  - LLM:      GPT-4.1-nano (OpenAI)
  - Database: PostgreSQL (law_bot)
  - Schema:   Pydantic v2
  - Frontend: Vanilla HTML/JS/CSS


════════════════════════════════════════════════════════════════
  END OF DOCUMENTATION
════════════════════════════════════════════════════════════════
