# 05 — Fashion Rule Context Injection: Truyền outfit rules vào Responder

## 📌 Idea
Bảng `pg__dashboard_canifa__ai_outfit_rules` (110 rules) và `pg__dashboard_canifa__chatbot_fashion_rules`
trong SQLite chứa các quy tắc phối đồ đã được AI review. Hiện tại chỉ `outfit_matcher_worker.py`
dùng rules này để generate matches — Responder không được truyền context về **quy tắc phối đồ**.
Idea: Khi AI Responder gợi ý outfit, inject top 3 rules liên quan để tư vấn chính xác,
có cơ sở thay vì tự suy luận.

## 🗂 Codebase Scope
- **Root:** `d:\cnf\chatbot-canifa-feedback\backend`
- **Affected:**
  - `agent/tag_search_agent_v2/tag_search_tool.py` — thêm `_fetch_relevant_rules()`
  - `agent/tag_search_agent_v2/tag_search_graph.py` — truyền rules context vào Responder
  - `backend/123.db` → `pg__dashboard_canifa__ai_outfit_rules` (110 rows)
  - `backend/worker/fashion_rules.json` — possible cache layer
- **Languages:** Python 3.12+
- **Size:** M

## 📊 Current State Analysis

Schema `pg__dashboard_canifa__ai_outfit_rules` (biết từ inspect):
- Likely có: `rule_type`, `anchor_category`, `match_category`, `occasion`, `description`
- 110 rules = đầy đủ logic phối đồ Canifa

Schema `pg__dashboard_canifa__chatbot_fashion_rules` — có thể là subset human-curated.

Hiện tại Responder tư vấn phối đồ **chỉ dựa vào outfit matches** (các cặp SP cụ thể),
nhưng không có nguyên tắc phối chung. VD: Responder không biết "Áo sơ mi trắng không
nên phối với quần tối màu khi đi tiệc."

## 🎯 Goal / Definition of Done
- Function `_fetch_relevant_rules(anchor_category, occasion_tag)` trả top 3 rules match
- Rules được cache in-memory sau lần đọc đầu (110 rules nhỏ, fit in RAM)
- Thêm vào Responder context: `relevant_rules` = ["Rule 1: ...", "Rule 2: ..."]
- Responder prompt: "Dùng relevant_rules để giải thích LÝ DO gợi ý outfit, không chỉ liệt kê"
- AB test: so sánh quality tư vấn trước/sau (subjective review 20 conversations)

## 📋 Execution Plan

### Phase 1: Inspect fashion rules schema + cache (30 phút)
- [ ] Query `PRAGMA table_info` + sample 10 rows từ cả 2 bảng rules
- [ ] Xác định columns: `occasion`, `anchor_category`, `rule_text` hay gì khác
- [ ] Tạo in-memory cache: `_FASHION_RULES_CACHE: list[dict] | None = None`
- [ ] Hàm `_load_fashion_rules()` → đọc một lần khi startup

### Phase 2: Implement `_fetch_relevant_rules()` (30 phút)
- [ ] Input: `anchor_categories: list[str]`, `tags: list[str]`
- [ ] Filter rules: match khi `anchor_category` overlap với categories hoặc `occasion` match tags
- [ ] Score và sort: ưu tiên rules match nhiều điều kiện hơn
- [ ] Trả top 3 rule `description` text

### Phase 3: Inject vào tool output (20 phút)
- [ ] Gọi `_fetch_relevant_rules()` sau bước outfit match
- [ ] Thêm field `fashion_rules` vào JSON output của tool:
  ```json
  "fashion_rules": [
    "Áo sơ mi phối tốt với quần tây/chân váy khi đi làm hoặc đi tiệc",
    "Tránh phối 2 họa tiết kẻ cùng lúc"
  ]
  ```

### Phase 4: Cập nhật Responder (20 phút)
- [ ] Parse `fashion_rules` từ tool result trong `_responder_node`
- [ ] Thêm vào system context: "Quy tắc phối đồ áp dụng: [rules]"
- [ ] RESPONDER_PROMPT: "Khi gợi ý phối đồ, hãy trích dẫn quy tắc để giải thích tại sao"

## ⚠️ Risks & Side Effects
- **Context bloat:** 3 rules + outfit matches + products → token tăng ~300 tokens → cần cân nhắc
- **Rule stale:** Nếu rules trong DB được update, cache cần reload → thêm TTL 5 phút cho cache
- **Schema không rõ:** Cần Phase 1 để confirm trước khi code

## 🔧 Tools / Scripts Needed
- `inspect_db.py` để inspect schema
- `fashion_rules.json` đã có trong `worker/` — có thể là source truth thay vì DB

## ⏱ Effort Estimate
**M** — ~3 giờ (inspect + implement + test)

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