# Store Search Engine — Tài liệu Kỹ thuật (Algorithm 2.0)

## 1. Tổng quan

Tool `canifa_store_search` là một trong các công cụ thuộc **Tool Layer** trong kiến trúc Dual-Agent. Nhiệm vụ của nó rất đơn giản về mặt input/output:

- **Nhận vào:** Một chuỗi địa điểm từ Agent 1 (Classifier)
- **Trả ra:** Danh sách cửa hàng + cảnh báo nếu có phần địa danh không tìm thấy

---

## 2. Luồng Xử lý Toàn cảnh (Agentic Flow)

![Store Search Technical Infographic](data/30-store-search-tool/store_search_infographic.svg)

Hệ thống được thiết kế theo mô hình **Pipeline song song**, nơi dữ liệu đi qua 4 lớp lọc trước khi được trả về cho Agent Stylist.

---

## 3. Bốn lớp thuật toán "Vàng"

### 🟦 Lớp 1 — Alias Expansion (Mở rộng viết tắt)
- **Vấn đề:** Khách gõ "hn", "hcm", "bt", "sg"...
- **Giải pháp:** Bảng map thông minh 63 tỉnh thành + Slang địa phương.
- **Ví dụ:** `"hn"` → `"Hà Nội"`.

### 🟦 Lớp 2 — Phrase Sliding Window (Cửa sổ trượt cụm từ)
- **Vấn đề:** "Hà Đông" bị nhầm với "Đông Anh" nếu tìm từ đơn lẻ.
- **Giải pháp:** Sinh cụm từ liên tiếp (N-gram). Ưu tiên khớp cụm dài nhất.
- **Minh họa:** `"nội bài đông anh"` → Tìm cụm 4 chữ trước, sau đó đến cụm 3, 2.

### 🟦 Lớp 3 — Score-based SQL Ranking
- **Vấn đề:** Quá nhiều kết quả gây nhiễu.
- **Giải pháp:** Chấm điểm (Ranking) ngay trong SQL bằng `CASE WHEN`. Khớp cụm dài nhất = Điểm cao nhất.
- **Fallback:** Sử dụng **Reverse LIKE** để bắt được các địa danh khách gõ dài hơn DB.

### 🟧 Lớp 4 — Unmatched Insight (Canh gác AI - Guardrail)
**Vấn đề:** AI bịa đặt thông tin khi không tìm thấy kết quả.
**Giải pháp:** Đối soát ngược kết quả DB với Input. Phát hiện các "từ thừa" không xuất hiện trong bất kỳ store nào.

#### 📝 Cấu trúc Tool Message thực tế (JSON Payload):
Khi Tool chạy xong, nó không chỉ trả về list Store, mà còn "gói" thêm một chỉ thị nghiêm ngặt cho Agent:

```json
{
  "status": "success",
  "search_results": [
    { "name": "Canifa Phúc Yên", "address": "Số 1 Hai Bà Trưng..." }
  ],
  "unmatched_insight": {
    "missing_locations": ["Bến Tre"],
    "has_unmatched": true,
    "system_directive": "⚠️ CẢNH BÁO: Người dùng có tìm 'Bến Tre' nhưng KHÔNG có kết quả. Bạn tuyệt đối KHÔNG được bỏ qua thông tin này. Hãy thông báo rõ cho khách là hiện chưa có chi nhánh tại Bến Tre."
  }
}
```

**Tác dụng:** Khi Agent 2 nhận cái JSON này, nó thấy trường `system_directive`. Đây là "lệnh bài" buộc nó phải thừa nhận: *"Dạ, hiện em chưa có cửa hàng tại Bến Tre"*.

---

## 4. Các kịch bản xử lý thực tế (Advanced Scenarios)

### Kịch bản A: Tìm kiếm hỗn hợp (Mixed Match)
> **Khách hỏi:** *"Canifa có shop ở Bến Tre và Phúc Yên không?"*

- **Lớp 3 (SQL):** Trả về danh sách cửa hàng tại **Phúc Yên**.
- **Lớp 4 (Insight):** So sánh "Bến Tre", "Phúc Yên" với kết quả -> Thấy "Phúc Yên" đã khớp, còn **"Bến Tre" hoàn toàn biến mất**.
- **Tool Output:** 
  - `stores`: [List cửa hàng Phúc Yên]
  - `unmatched`: ["Bến Tre"]
  - `warning`: "⚠️ Canifa không có cửa hàng tại Bến Tre."

**=> Phản hồi của Agent 2:** *"Dạ, hiện tại Canifa chưa có cửa hàng tại **Bến Tre** ạ. Tuy nhiên, tại **Phúc Yên** bên em đang có các cơ sở sau..."* (Trung thực 100%, không lờ đi phần Bến Tre).

---

### Kịch bản B: Địa danh "trên trời"
> **Khách hỏi:** *"Tìm shop ở quận 1 và Nam Cực"*

- **Insight phát hiện:** "Nam Cực" là từ thừa.
- **Bot xử lý:** Chặn đứng việc Bot tự suy luận Nam Cực gần Quận 1 hoặc lờ đi. Bot buộc phải thông báo không có Nam Cực.

---

## 5. Nguyên tắc AI không tự suy luận địa lý

Đây là nguyên tắc cốt lõi trong thiết kế này để đảm bảo tính chính xác:

1. **KHÔNG tự đoán:** Agent 2 (Stylist) không được phép dùng kiến thức huấn luyện của nó để đoán địa chỉ. Nó chỉ được tin vào danh sách `stores` và `unmatched` mà Tool trả về.
2. **KHÔNG bịa đặt:** Nếu khách gõ sai chính tả mà Tool không Expand được (ví dụ gõ "Bn Tre" thay vì "Bến Tre"), Tool sẽ báo Unmatched. Bot phải báo không tìm thấy thay vì tự sửa lỗi nếu không chắc chắn.
3. **CĂN CỨ VÀO TOOL:** Tool là "đôi mắt" duy nhất của Bot về mặt địa lý. Nếu mắt Tool không thấy, Bot phải phản hồi là không thấy.

---

## 6. Tại sao thiết kế này đúng?

Thiết kế này giải quyết triệt để bài toán **Hallucination** (Ảo giác) bằng cách tách biệt:
- **Xử lý dữ liệu:** Do Tool (Rule-based + SQL) đảm nhiệm -> Chính xác tuyệt đối.
- **Viết câu trả lời:** Do AI đảm nhiệm dựa trên "sự thật" từ Tool cung cấp.

Kết quả là khách hàng luôn nhận được thông tin chính xác, kể cả khi họ hỏi những địa danh không tồn tại hoặc viết tắt phức tạp.
