# 03 — Tier-Aware Fallback Explanation: AI nói rõ khi kết quả tầng 3 (vague search)

## 📌 Idea
Khi `_cascading_search()` phải rơi xuống Tầng 3 (chỉ còn fixed filters, không có keywords/tags),
AI Responder nên **chủ động thông báo** cho user là "Không tìm thấy kết quả khớp chính xác, 
đây là các sản phẩm gợi ý trong danh mục tương tự." — thay vì trả kết quả như thể đã tìm đúng.

## 🗂 Codebase Scope
- **Root:** `d:\cnf\chatbot-canifa-feedback\backend`
- **Affected:**
  - `agent/tag_search_agent_v2/tag_search_tool.py` — `tier` field trong output JSON (đã có)
  - `agent/tag_search_agent_v2/tag_search_graph.py` — Responder node, parse tier
  - `agent/tag_search_agent_v2/prompts/` — RESPONDER_PROMPT thêm hướng dẫn tier
- **Languages:** Python 3.12+
- **Size:** S

## 📊 Current State Analysis

Tool đã return `tier` trong JSON:
```json
{
  "status": "success",
  "tier": 3,  // ← đã có!
  "products": [...]
}
```

Trong `_responder_node` (tag_search_graph.py lines 182-200), khi parse tool result:
```python
summary = f"✅ Tìm thấy {result_count} sản phẩm ({parsed.get('elapsed_ms', '?')}ms) {tier_info}"
```

**Vấn đề:** `tier_info` chỉ hiển thị trong pipeline debug, **Responder AI không biết** tier để thay đổi giọng điệu tư vấn.
→ Kết quả tầng 3 được trình bày giống tầng 1 → user không biết kết quả có thể không chính xác.

## 🎯 Goal / Definition of Done
- Khi `tier == 3` hoặc `tier == 4`:
  - Responder prefix: "Mình không tìm thấy đúng loại bạn hỏi, nhưng đây là các sản phẩm tương tự..."
  - Responder cuối: gợi ý user hỏi cụ thể hơn: "Bạn muốn tìm thêm loại áo nào ạ?"
- Khi `tier == 1`: tự tin nhất, không cần disclaimer
- Khi `tier == 2`: gợi ý có thể không match hoàn toàn từ khoá nhưng match tags
- `stock_timed_out = True` → thêm note "Thông tin tồn kho tạm thời không khả dụng"

## 📋 Execution Plan

### Phase 1: Truyền tier vào Responder context (20 phút)
- [ ] Trong `_responder_node`, khi parse ToolMessage JSON:
  ```python
  tier = parsed.get("tier", 1)
  stock_timed_out = parsed.get("stock_timed_out", False)
  ```
- [ ] Build `tier_context`:
  ```python
  if tier == 3:
      tier_context = "⚠️ TIER 3: Không tìm thấy kết quả khớp chính xác (keywords và tags không match). Đây là gợi ý trong cùng danh mục."
  elif tier == 2:
      tier_context = "✅ TIER 2: Kết quả khớp theo tags (occasion/style), có thể không match 100% từ khoá user."
  else:
      tier_context = "✅ TIER 1: Kết quả chính xác theo từ khoá user."
  ```
- [ ] Thêm `tier_context` vào `tool_summary` truyền cho Responder

### Phase 2: Cập nhật RESPONDER_PROMPT (15 phút)
- [ ] Thêm section:
  ```
  TIER HANDLING:
  - Nếu thấy "TIER 3": bắt đầu bằng "Mình chưa tìm thấy đúng món bạn hỏi, nhưng đây là các gợi ý..."
    Kết thúc bằng câu hỏi gợi ý user nói cụ thể hơn.
  - Nếu thấy "TIER 2": tự tin nhưng note nhẹ "phù hợp với dịp/phong cách bạn muốn"
  - Nếu thấy "TIER 1": tự tin 100%
  - Nếu stock_timed_out: thêm "(lưu ý: tồn kho có thể chưa cập nhật realtime)"
  ```

### Phase 3: Kiểm tra với test cases (20 phút)
- [ ] Test query vague: "cho tôi xem đồ mùa hè" → expect tier 2-3, Responder có disclaimer
- [ ] Test query cụ thể: "áo phông trắng nữ" → tier 1, không có disclaimer
- [ ] Test query lạ: "đồ siêu hero" → tier 3, có suggestion hỏi lại

## ⚠️ Risks & Side Effects
- **Over-disclaimer:** Tier 2 vẫn hữu ích → không nên disclaimer quá nặng → chỉ note nhẹ
- **Prompt length:** Thêm tier_context vào Responder context → token tăng ~100 tokens/request → acceptable

## 🔧 Tools / Scripts Needed
- Không cần tool ngoài

## ⏱ Effort Estimate
**S** — ~1 giờ. Logic đơn giản, không thay đổi data flow chính.

---
_Captured: 2026-04-28 | Type: Codebase-Aware_
