{
    "title": "Text-to-SQL & Data Analyst",
    "description": "Chi tiết luồng kiến trúc chuyển đổi ngôn ngữ tự nhiên thành câu lệnh SQL phức tạp, thực thi trên StarRocks và tổng hợp Insight bán hàng.",
    "diagram": "diagrams/text-to-sql.svg",
    "sections": [
        {
            "title": "1. Tổng quan (Overview)",
            "type": "text",
            "content": "Module Text-to-SQL cho phép Ban Giám Đốc hoặc Data Analyst chat trực tiếp với Database bằng ngôn ngữ tự nhiên. Điểm đặc biệt của kiến trúc này là <b>Schema Awareness</b> và <b>Self-Correction</b>. Thay vì nhồi nhét hàng trăm bảng vào một prompt (gây quá tải token), AI tự động tìm kiếm bảng phù hợp và tự động sửa lỗi SQL nếu query bị crash."
        },
        {
            "title": "2. Kiến trúc & Luồng dữ liệu (Data Flow)",
            "type": "text",
            "content": "Quá trình sinh SQL đi qua 4 Node chính trong LangGraph:<br><br><b>1. Table Selection Node:</b> AI phân tích câu hỏi (VD: <i>\"Top 5 mẫu áo bán chạy nhất tháng trước\"</i>) và quyết định gọi ra Schema của bảng <code>orders</code>, <code>order_items</code> và <code>products</code>.<br><b>2. SQL Generation Node:</b> AI sinh ra câu SQL theo Dialect của StarRocks (tương thích cú pháp MySQL). Lớp Guardrails được cài vào đây để chặn câu lệnh <code>DROP</code>, <code>DELETE</code>, <code>UPDATE</code>.<br><b>3. Execution Node:</b> Hệ thống chạy câu SQL trên Database thông qua Read-Only User. Nếu thành công, trả về JSON data. Nếu lỗi (VD: sai tên cột), chuyển sang bước Self-Correction.<br><b>4. Self-Correction Node:</b> AI đọc thông báo lỗi từ Database (Ví dụ: <i>Column 'revenue' not found</i>), tự sửa câu SQL và thử chạy lại tối đa 3 lần."
        },
        {
            "title": "3. AI Data Analyst (Insight Extraction)",
            "type": "text",
            "content": "Sau khi Data SQL được trả về dưới dạng list of dicts, thay vì dump nguyên JSON cho user, dữ liệu sẽ được đẩy qua <b>Analyst Node</b>. Nhiệm vụ của Node này:<br>- <b>Summarization:</b> Tóm tắt số liệu thành một đoạn chắt lọc (Ví dụ: \"Doanh thu tháng 10 đạt 500 củ, tăng 20%\").<br>- <b>Insight Mining:</b> Bóc tách các xu hướng ẩn (Ví dụ: \"Màu xanh navy đang chiếm 60% doanh số\").<br>- <b>Visualization Suggestion:</b> Gợi ý UI render biểu đồ (Bar, Pie, Line) tùy vào đặc thù dữ liệu."
        },
        {
            "title": "4. API SQL & Insights",
            "type": "api",
            "endpoints": [
                { "method": "POST", "path": "/api/sql/chat", "description": "End-to-End Chat: Sinh SQL, Execute, Tóm tắt Insight." },
                { "method": "POST", "path": "/api/sql/generate", "description": "Chỉ sinh SQL thô (Phục vụ tool cho Data Engineer)." },
                { "method": "GET", "path": "/api/sql/user-insight/{id}", "description": "Trích xuất hồ sơ phân tích hành vi của 1 user cụ thể." }
            ]
        },
        {
            "title": "5. Code Snippet Thực Tế (Guardrails)",
            "type": "code",
            "language": "python",
            "code": "import re\nfrom fastapi import HTTPException\n\ndef validate_generated_sql(sql_query: str) -> str:\n    \"\"\"Ngăn chặn AI sinh câu lệnh phá hoại Database\"\"\"\n    sql_upper = sql_query.upper()\n    \n    # Danh sách từ khóa cấm kỵ (DML/DDL)\n    forbidden_keywords = [\"DROP\", \"DELETE\", \"UPDATE\", \"INSERT\", \"ALTER\", \"TRUNCATE\", \"GRANT\"]\n    \n    for keyword in forbidden_keywords:\n        # Regex check keyword tồn tại như một từ độc lập\n        if re.search(fr'\\b{keyword}\\b', sql_upper):\n            logger.error(f\"🚨 SECURITY ALERT: AI attempted {keyword} operation\")\n            raise HTTPException(status_code=403, detail=\"Query contains forbidden operations\")\n            \n    return sql_query"
        },
        {
            "title": "6. Troubleshooting & Gotchas",
            "type": "text",
            "content": "<b>🚫 Lỗi Token Limit Exceeded:</b><br>Khi query trả về hàng chục ngàn dòng dữ liệu (Ví dụ: <i>\"Lấy tất cả đơn hàng năm 2025\"</i>), Analyst Node sẽ quá tải Token. Cần luôn tiêm <code>LIMIT 50</code> vào Prompt hoặc yêu cầu AI sinh SQL kiểu Aggregation (GROUP BY) thay vì lấy raw data.<br><br><b>🚫 Vấn đề ảo giác Cột (Hallucinated Columns):</b><br>AI có thể tự bịa ra cột <code>created_at</code> trong khi bảng chỉ có <code>order_date</code>. Giải pháp: Ở bước Table Selection, phải inject chính xác DDL schema (Tên cột, Kiểu dữ liệu, Comment) vào prompt của LLM."
        }
    ]
}
