# 2. Kiến trúc 2-Agent & Luồng dữ liệu (Data Flow)

Luồng xử lý từ khi người dùng upload ảnh cho đến khi nhận được kết quả cuối cùng được điều phối bằng **LangGraph** (StateGraph), quy trình như sau:

```mermaid
sequenceDiagram
    autonumber
    participant U as User / Frontend
    participant API as FastAPI (/api/image-search/chat)
    participant Graph as ImageSearchGraph (LangGraph)
    participant Planner as Vision Planner (LLM)
    participant Embed as Embedding Service (OpenAI)
    participant SR as StarRocks (DB)
    participant Responder as Vision Responder (LLM)

    U->>API: POST Base64 Images + Text Query
    API->>Graph: .chat(query, images)
    
    rect rgb(240, 248, 255)
        Note over Graph, Planner: Agent 1: Phân tích & Lập Kế Hoạch
        Graph->>Planner: Inject Multimodal Message (Text + Image URL/Base64)
        Planner-->>Graph: Tool Call (canifa_tag_search) với các attributes
    end

    rect rgb(255, 240, 245)
        Note over Graph, SR: Tool Execution: ProductSearchEngine
        Graph->>ProductSearchEngine: search(literal, inferred...)
        ProductSearchEngine->>SR: Dual-Lane Query (Exact matches)
        SR-->>ProductSearchEngine: Empty (No Exact Match)
        
        Note right of ProductSearchEngine: Fallback Cascade (Tier 3)
        ProductSearchEngine->>Embed: create_embedding_async(raw_text)
        Embed-->>ProductSearchEngine: Vector float[1536]
        ProductSearchEngine->>SR: SQL: approx_cosine_similarity(vector, {query_vector})
        SR-->>ProductSearchEngine: Top K Products (HNSW Index)
        ProductSearchEngine-->>Graph: List of Products JSON
    end

    rect rgb(240, 255, 240)
        Note over Graph, Responder: Agent 2: Định dạng Trả Lời
        Graph->>Responder: Inject Tool Results
        Responder-->>Graph: Tự nhiên hóa Response (Kèm Link & Giá)
    end

    Graph-->>API: {response, elapsed_ms, pipeline, ...}
    API-->>U: JSON Response
```

**Các State Transition trong LangGraph:**
- `planner_node` -> Kiểm tra xem LLM có gọi tool `canifa_tag_search` hay không.
- NẾU CÓ -> Chuyển sang `tools_node` -> Thực thi -> Chuyển sang `responder_node`.
- NẾU KHÔNG (ví dụ: ảnh không chứa quần áo) -> Chuyển sang `END`.