# 05 — 3 Katmanlı Intent Router

## Ne İş Yapar?

Her ziyaretçi mesajı için "bu mesaj LLM'e gitmeli mi, yoksa daha ucuz bir yolla çözülebilir mi?" kararını verir. %80+ trafik LLM'e gitmeden <600ms'de cevaplanır.

---

## Karar Ağacı

```
Mesaj geldi
    │
    ▼
┌─────────────────────────┐
│  Katman 1: RuleMatcher  │  ~1-5ms
│  Regex / keyword        │
└────────┬────────────────┘
         │ Hit?
         ├── Evet → Hazır cevap / marker dön (LLM yok)
         │
         ▼ Hayır
┌──────────────────────────────┐
│  Katman 2: SemanticRouter    │  ~400-600ms
│  Gemini embedding + cosine  │
└────────┬─────────────────────┘
         │ Skor > 0.78?
         ├── Evet → Intent'e göre fast-path (LLM yok)
         │
         ▼ Hayır
┌──────────────────────────┐
│  Katman 3: LLM           │  ~1-3s (streaming ile algıda <500ms)
│  Gemini Flash Lite       │
│  + RAG context           │
│  + tool-use              │
└──────────────────────────┘
```

---

## Katman 1 — RuleMatcher (Regex)

Kesin ve kısa kalıplar için. Türkçe normalize edilerek eşleştirilir (ş→s, ğ→g vb.).

```python
RULES = {
    "greeting": {
        "patterns": [
            r"^(merhaba|selam|iyi gunler|hello|hi|hey)\b",
            r"^(gunaydin|iyi aksamlar)\b",
        ],
        "reply": "Merhaba! Size nasıl yardımcı olabilirim?",
    },
    "thanks": {
        "patterns": [r"^(tesekkurler|tesekkur ederim|sagol|thanks)\b"],
        "reply": "Rica ederim! Başka bir konuda yardımcı olabilir miyim?",
    },
    "bye": {
        "patterns": [r"^(gorusuruz|hoscakal|bye|bb)\b"],
        "reply": "İyi günler! Tekrar bekleriz.",
    },
    "catalog": {
        "patterns": [r"^(katalog|urun listesi)\b"],
        "reply": "__CATALOG__",   # Orchestrator search_products tool'unu tetikler
    },
    "who_are_you": {
        "patterns": [r"^(sen kimsin|kimsin sen|bot musun|gercek misin)\??$"],
        "reply": "__INTRO__",
    },
    "capability": {
        "patterns": [r"^(neler yapabilirsin|ne yapabilirsin|yardim et|help)\??$"],
        "reply": "...",
    },
    "cart_clear": {
        "patterns": [r"^(sepeti bosalt|sepetimi temizle)\??$"],
        "reply": "__CART_CLEAR__",
    },
    "contact_request": {
        "patterns": [r"^(insanla konusmak|operatore bag)\b"],
        "reply": "__ESCALATE__",
    },
    "affirmation": {
        "patterns": [r"^(evet|tamam|olur|ok|iyi|dogru|harika)\b"],
        "reply": None,  # Context'e bağlı — orchestrator işler
    },
}
```

---

## Katman 2 — SemanticRouter (Embedding)

Her intent için 3-5 doğal Türkçe "anchor" cümle tanımlanır. Mesaj embed edilir, anchor'larla cosine hesaplanır.

```python
SEMANTIC_INTENTS = {
    "catalog": {
        "reply": "__CATALOG__",
        "phrases": [
            "Ürünleriniz nelerdir",
            "Ne satıyorsunuz",
            "Kaç çeşit ürününüz var",
            "Neler önerirsin",
            "Ürün çeşitlerinizi görmek istiyorum",
        ],
    },
    "greeting": {
        "reply": "Merhaba! Size nasıl yardımcı olabilirim?",
        "phrases": [
            "Selamlar nasılsınız",
            "Günaydın efendim",
            "İyi günler size",
        ],
    },
    "contact_request": {
        "reply": "__ESCALATE__",
        "phrases": [
            "Müşteri temsilcisine bağlanmak istiyorum",
            "Biriyle konuşabilir miyim",
            "İnsan desteği alabilir miyim",
        ],
    },
    "pricing_question": {
        "reply": "__SEARCH_PRODUCTS__",
        "phrases": [
            "Fiyatlarınız nedir",
            "Ne kadara satıyorsunuz",
            "En ucuz ürününüz hangisi",
        ],
    },
    "who_are_you": {
        "reply": "__INTRO__",
        "phrases": [
            "Kendini tanıtır mısın",
            "Sen bir bot musun",
            "Kimle konuşuyorum",
        ],
    },
}

SEMANTIC_THRESHOLD = 0.78  # Bu skorun altında LLM'e git
ANCHOR_CACHE_TTL = 7 * 24 * 3600  # 7 gün
```

Anchor embedding'leri uygulama başlangıcında (warm-up) Redis'e yüklenir. Her yeni intent eklenince `celery beat: flovy:warm-anchors` çalıştırılır.

---

## Katman 3 — LLM (Gemini Flash Lite)

Gerçek üretken sorular, ürün aramaları, karmaşık sorular burada işlenir.

```
Tool-use loop (max 2 tur):

Tur 1:
  prompt = system + memory + rag + history + user_message + tool_schemas
  → LLM cevabı: text veya tool_call

  Eğer tool_call:
    - requiresConfirmation=false → execute et, result'ı prompt'a ekle
    - requiresConfirmation=true → FlovyToolCall(status=unconfirmed) yaz, UI'a onayla bloğu gönder

Tur 2 (tool execute edildiyse):
  prompt = tur1_prompt + tool_result
  → LLM'den doğal dil cevabı

Fast-path (LLM tur 2'yi atla):
  - search_products count=0 → "Bu kriterlere uygun ürün bulunamadı"
  - add_to_cart success → cart UI bloğu direkt dön
  - create_pay_link success → paylink URL direkt dön
```

---

## Marker Sistemi (Orchestrator)

Rule/Semantic router "ne yapılacağını" marker ile belirtir, FlovyService işler:

| Marker | Eylem |
|---|---|
| `__CATALOG__` | search_products tool'u boş query ile çağır |
| `__SEARCH_PRODUCTS__` | search_products tool'u user mesajını query olarak kullan |
| `__INTRO__` | Brand'ın adıyla kişisel intro mesajı üret |
| `__ESCALATE__` | escalate_to_human tool'unu çağır |
| `__CART_CLEAR__` | Session metadata'daki cart'ı temizle |

---

## Performans Sonuçları (Mevcut Sistemden)

| Mesaj | Süre | Katan |
|---|---|---|
| "merhaba" | 3ms | Regex |
| "sepeti boşalt" | 2ms | Regex |
| "ürünleriniz nelerdir?" | 472ms | Semantic |
| "kendini tanıtır mısın" | 549ms | Semantic |
| "kırmızı tişört var mı?" | ~1-2s | LLM + streaming |
| "bana kazak öner, 300 TL altı" | ~2-3s | LLM + tool |

**Hedef:** %80+ sorgu <600ms.

---

## Yeni Intent Ekleme

Tek bir dosyada anchor cümle ekle, `warm-anchors` çalıştır — regex yazmana gerek yok:

```python
"shipping_info": {
    "reply": "Kargo genellikle 2-3 iş gününde teslim edilir. "
             "500 TL üzeri siparişlerde kargo ücretsizdir.",
    "phrases": [
        "Kargo ne zaman gelir",
        "Kaç günde teslim edilir",
        "Kargo ücreti nedir",
        "Ne zaman elime geçer",
    ],
},
```
