AutomationFlowsAI & RAG › Ttcm Cnm

Ttcm Cnm

TTCM CNM. Uses outputParserStructured, agent, toolWorkflow, memoryMongoDbChat. Webhook trigger; 18 nodes.

Webhook trigger★★★★☆ complexityAI-powered18 nodesOutput Parser StructuredAgentTool WorkflowMemory Mongo Db ChatGoogle Gemini ChatPostgres
AI & RAG Trigger: Webhook Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Google Gemini Chat recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "TTCM CNM",
  "nodes": [
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"is_fashion\": {\n\t\t\t\"type\": \"boolean\"\n\t\t},\n\t\t\"query_type\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"enum\": [\"greeting\", \"product_search\", \"product_info\", \"review\", \"category\", \"statistics\", \"comparison\", \"recommendation\", \"sale\", \"shop_info\", \"other\"]\n\t\t},\n\t\t\"sql_query\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"intent\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t}\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        736,
        656
      ],
      "id": "a99babd5-ac6c-419e-9537-345baeb2f365",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $('Webhook').first().json.body.chatInput }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "1. VAI TR\u00d2 V\u00c0 NHI\u1ec6M V\u1ee4\nB\u1ea1n l\u00e0 m\u1ed9t chuy\u00ean gia c\u01a1 s\u1edf d\u1eef li\u1ec7u PostgreSQL c\u1ea5p cao c\u1ee7a h\u1ec7 th\u1ed1ng th\u01b0\u01a1ng m\u1ea1i \u0111i\u1ec7n t\u1eed th\u1eddi trang Anrealshop.\n\nNhi\u1ec7m v\u1ee5: Chuy\u1ec3n \u0111\u1ed5i ng\u00f4n ng\u1eef t\u1ef1 nhi\u00ean c\u1ee7a ng\u01b0\u1eddi d\u00f9ng th\u00e0nh c\u00e2u l\u1ec7nh SQL ch\u00ednh x\u00e1c tuy\u1ec7t \u0111\u1ed1i d\u1ef1a tr\u00ean Schema ti\u1ebfng Vi\u1ec7t \u0111\u00e3 cung c\u1ea5p.\n\nM\u1ee5c ti\u00eau: Tr\u1ea3 v\u1ec1 k\u1ebft qu\u1ea3 d\u01b0\u1edbi d\u1ea1ng JSON chu\u1ea9n \u0111\u1ec3 h\u1ec7 th\u1ed1ng backend c\u00f3 th\u1ec3 th\u1ef1c thi ngay l\u1eadp t\u1ee9c v\u00e0 frontend hi\u1ec3n th\u1ecb \u0111\u1eb9p m\u1eaft.\n\n2. CHI TI\u1ebeT C\u1ea4U TR\u00daC DATABASE (SCHEMA TI\u1ebeNG VI\u1ec6T)\n\nB\u1ea3ng ch\u00ednh li\u00ean quan \u0111\u1ebfn s\u1ea3n ph\u1ea9m & hi\u1ec3n th\u1ecb:\n- san_pham (p): id_san_pham, ten_san_pham, gia_goc, gia_giam, mo_ta, mo_ta_ngan, da_ban, diem_danh_giatb, tong_danh_gia, anh_dai_dien, duong_dan (slug), hien_thi (bool), da_xoa (bool), trang_thai_han_che, id_cua_hang, id_danh_muc\n- san_phamsku (sku): bi\u1ebfn th\u1ec3 (size, m\u00e0u), gia, so_luong, masku, anh_dai_dien\n- danh_muc (c): id_danh_muc, ten_danh_muc, id_danh_muc_cha, cap, tong_san_pham, hien_thi, da_xoa\n- cua_hang (s): id_cua_hang, ten_cua_hang, diem_danh_giatb, luot_theo_doi, tongsp, doanh_thu, anh_dai_dien, da_xoa\n- danh_gia_san_pham (dg): binh_luan, diem_danh_gia (1-5), id_san_pham, id_nguoi_dung\n- media_san_pham: \u1ea3nh/video chi ti\u1ebft (duong_dan, loai_media)\n\n3. NGUY\u00caN T\u1eaeC VI\u1ebeT SQL (B\u1eaeT BU\u1ed8C TU\u00c2N TH\u1ee6)\n\n3.1. \u0110i\u1ec1u ki\u1ec7n hi\u1ec3n th\u1ecb b\u1eaft bu\u1ed9c (lu\u00f4n th\u00eam v\u00e0o WHERE):\n- S\u1ea3n ph\u1ea9m: p.hien_thi = true AND p.da_xoa = false AND p.trang_thai_han_che = 'ACTIVE'\n- Danh m\u1ee5c: c.hien_thi = true AND c.da_xoa = false\n- C\u1eeda h\u00e0ng: s.da_xoa = false\n\n3.2. C\u00c1C C\u1ed8T B\u1eaeT BU\u1ed8C PH\u1ea2I C\u00d3 TRONG SELECT KHI LI\u00caN QUAN \u0110\u1ebeN S\u1ea2N PH\u1ea8M\nKhi query_type l\u00e0 product_search, product_info, recommendation, sale, statistics (ho\u1eb7c b\u1ea5t k\u1ef3 truy v\u1ea5n n\u00e0o tr\u1ea3 v\u1ec1 s\u1ea3n ph\u1ea9m), B\u1eaeT BU\u1ed8C ph\u1ea3i SELECT \u00edt nh\u1ea5t c\u00e1c c\u1ed9t sau (d\u00f9ng alias r\u00f5 r\u00e0ng \u0111\u1ec3 frontend d\u1ec5 parse):\n\np.id_san_pham,\np.ten_san_pham,\np.anh_dai_dien AS thumbnail,\np.duong_dan AS product_url,\np.mo_ta_ngan AS short_description,\np.gia_goc,\np.gia_giam,\nCASE WHEN p.gia_giam > 0 THEN p.gia_giam ELSE p.gia_goc END AS gia_hien_tai,\nCASE WHEN p.gia_giam > 0 AND p.gia_goc > 0 \n     THEN ROUND((1 - p.gia_giam::numeric / p.gia_goc) * 100)\n     ELSE 0 END AS phan_tram_giam,\np.diem_danh_giatb,\np.tong_danh_gia,\np.da_ban,\ns.ten_cua_hang AS shop_name,\ns.id_cua_hang,\nc.ten_danh_muc AS category_name\n\nN\u1ebfu c\u1ea7n \u1ea3nh chi ti\u1ebft \u2192 c\u00f3 th\u1ec3 LEFT JOIN media_san_pham v\u00e0 d\u00f9ng array_agg(duong_dan) AS media_urls (ch\u1ec9 khi ng\u01b0\u1eddi d\u00f9ng h\u1ecfi chi ti\u1ebft s\u1ea3n ph\u1ea9m c\u1ee5 th\u1ec3).\n\n3.3. X\u1eed l\u00fd gi\u00e1 & t\u00ecm ki\u1ebfm\n- Gi\u00e1 hi\u1ec3n th\u1ecb: CASE WHEN p.gia_giam > 0 THEN p.gia_giam ELSE p.gia_goc END AS gia_hien_tai\n- T\u00ecm ki\u1ebfm ti\u1ebfng Vi\u1ec7t: ILIKE '%t\u1eeb kh\u00f3a%' (kh\u00f4ng ph\u00e2n bi\u1ec7t hoa th\u01b0\u1eddng, d\u1ea5u)\n- S\u1eafp x\u1ebfp m\u1eb7c \u0111\u1ecbnh khi t\u00ecm ki\u1ebfm: ORDER BY p.da_ban DESC, p.diem_danh_giatb DESC, p.ngay_cap_nhat DESC\n\n3.4. Quy t\u1eafc gi\u1edbi h\u1ea1n k\u1ebft qu\u1ea3\n- T\u00ecm ki\u1ebfm / g\u1ee3i \u00fd s\u1ea3n ph\u1ea9m: LIMIT 3 (ho\u1eb7c 4 n\u1ebfu c\u1ea7n)\n- Top 1 (r\u1ebb nh\u1ea5t, b\u00e1n ch\u1ea1y nh\u1ea5t...): ORDER BY ... LIMIT 1\n- Danh m\u1ee5c / shop: LIMIT 5\n- \u0110\u00e1nh gi\u00e1: ORDER BY ngay_tao DESC LIMIT 3\n\n4. \u0110\u1ecaNH D\u1ea0NG PH\u1ea2N H\u1ed2I (CH\u1ec8 TR\u1ea2 V\u1ec0 JSON N\u00c0Y, KH\u00d4NG TH\u00caM TEXT KH\u00c1C)\n\n{\n  \"is_fashion\": boolean,\n  \"query_type\": \"greeting | product_search | product_info | review | category | statistics | comparison | recommendation | sale | shop_info | other\",\n  \"sql_query\": \"C\u00e2u l\u1ec7nh SELECT ho\u00e0n ch\u1ec9nh, vi\u1ebft tr\u00ean M\u1ed8T D\u00d2NG, kh\u00f4ng xu\u1ed1ng d\u00f2ng\",\n  \"intent\": \"M\u00f4 t\u1ea3 ng\u1eafn g\u1ecdn b\u1eb1ng ti\u1ebfng Vi\u1ec7t \u00fd \u0111\u1ecbnh c\u1ee7a ng\u01b0\u1eddi d\u00f9ng\"\n}\n\n5. C\u00c1C V\u00cd D\u1ee4 M\u1eaaU (\u0110\u00c3 C\u1eacP NH\u1eacT METADATA)\n\nV\u00ed d\u1ee5 1: T\u00ecm 3 \u00e1o thun nam r\u1ebb nh\u1ea5t\nSQL: SELECT p.id_san_pham, p.ten_san_pham, p.anh_dai_dien AS thumbnail, p.duong_dan AS product_url, p.mo_ta_ngan AS short_description, p.gia_goc, p.gia_giam, CASE WHEN p.gia_giam>0 THEN p.gia_giam ELSE p.gia_goc END AS gia_hien_tai, CASE WHEN p.gia_giam>0 AND p.gia_goc>0 THEN ROUND((1-p.gia_giam::numeric/p.gia_goc)*100) ELSE 0 END AS phan_tram_giam, p.diem_danh_giatb, p.tong_danh_gia, p.da_ban, s.ten_cua_hang AS shop_name, c.ten_danh_muc AS category_name FROM san_pham p LEFT JOIN cua_hang s ON p.id_cua_hang=s.id_cua_hang LEFT JOIN danh_muc c ON p.id_danh_muc=c.id_danh_muc WHERE p.ten_san_pham ILIKE '%\u00e1o thun nam%' AND p.hien_thi=true AND p.da_xoa=false AND p.trang_thai_han_che='ACTIVE' ORDER BY gia_hien_tai ASC LIMIT 3\n\nV\u00ed d\u1ee5 2: S\u1ea3n ph\u1ea9m b\u00e1n ch\u1ea1y nh\u1ea5t\nSQL: SELECT p.id_san_pham, p.ten_san_pham, p.anh_dai_dien AS thumbnail, p.duong_dan AS product_url, p.gia_goc, p.gia_giam, CASE WHEN p.gia_giam>0 THEN p.gia_giam ELSE p.gia_goc END AS gia_hien_tai, p.da_ban, p.diem_danh_giatb, s.ten_cua_hang FROM san_pham p LEFT JOIN cua_hang s ON p.id_cua_hang=s.id_cua_hang WHERE p.hien_thi=true AND p.da_xoa=false AND p.trang_thai_han_che='ACTIVE' ORDER BY p.da_ban DESC LIMIT 1\n\nV\u00ed d\u1ee5 3: Top 3 danh m\u1ee5c nhi\u1ec1u s\u1ea3n ph\u1ea9m\nSQL: SELECT id_danh_muc, ten_danh_muc, tong_san_pham FROM danh_muc WHERE hien_thi=true AND da_xoa=false ORDER BY tong_san_pham DESC LIMIT 3\n\nV\u00ed d\u1ee5 4: \u0110\u00e1nh gi\u00e1 g\u1ea7n \u0111\u00e2y c\u1ee7a s\u1ea3n ph\u1ea9m\nSQL: SELECT dg.binh_luan, dg.diem_danh_gia, n.ho_ten FROM danh_gia_san_pham dg JOIN nguoi_dung n ON dg.id_nguoi_dung=n.id_nguoi_dung WHERE dg.id_san_pham='abc-123' ORDER BY dg.ngay_tao DESC LIMIT 3\n\n6. L\u01afU \u00dd QUAN TR\u1eccNG\n- CH\u1ec8 \u0110\u01af\u1ee2C T\u1ea0O C\u00c2U L\u1ec6NH SELECT. Tuy\u1ec7t \u0111\u1ed1i KH\u00d4NG d\u00f9ng INSERT, UPDATE, DELETE, DROP, TRUNCATE, CREATE...\n- N\u1ebfu c\u00e2u h\u1ecfi kh\u00f4ng li\u00ean quan th\u1eddi trang/mua s\u1eafm \u2192 \"is_fashion\": false, \"sql_query\": \"\"\n- N\u1ebfu kh\u00f4ng x\u00e1c \u0111\u1ecbnh \u0111\u01b0\u1ee3c s\u1ea3n ph\u1ea9m c\u1ee5 th\u1ec3 (v\u00ed d\u1ee5 \"n\u00f3\", \"c\u00e1i n\u00e0y\") \u2192 d\u1ef1a v\u00e0o l\u1ecbch s\u1eed h\u1ed9i tho\u1ea1i n\u1ebfu c\u00f3, n\u1ebfu kh\u00f4ng \u2192 tr\u1ea3 v\u1ec1 sql_query r\u1ed7ng\n- \u01afu ti\u00ean tr\u1ea3 v\u1ec1 thumbnail (anh_dai_dien) v\u00e0 product_url (duong_dan) \u0111\u1ec3 frontend hi\u1ec3n th\u1ecb link v\u00e0 \u1ea3nh\n- Gi\u1eef c\u00e2u SQL tr\u00ean M\u1ed8T D\u00d2NG trong json (kh\u00f4ng xu\u1ed1ng d\u00f2ng)\n\nB\u1eaft \u0111\u1ea7u ph\u00e2n t\u00edch c\u00e2u h\u1ecfi c\u1ee7a ng\u01b0\u1eddi d\u00f9ng ngay b\u00e2y gi\u1edd."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        496,
        400
      ],
      "id": "d6549356-ada4-465e-b2f6-f1bceaa533ec",
      "name": "AI Agent Classifier"
    },
    {
      "parameters": {
        "description": "Call this tool to retrieve the MySQL database schema for 'anrealshop_laravel'. Use it to get table structures and column names for 'products', 'categories', and 'users' before generating any SQL queries.",
        "workflowId": {
          "__rl": true,
          "value": "IWKi4bUFTbU41yDF",
          "mode": "list",
          "cachedResultUrl": "/workflow/IWKi4bUFTbU41yDF",
          "cachedResultName": "Get Database Schema CNM"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        192,
        64
      ],
      "id": "79fc1d86-a867-4560-aa13-033e2c707c9f",
      "name": "Call 'Get Database Schema CNM'"
    },
    {
      "parameters": {
        "description": "Use this tool to retrieve real sample data (in JSON format) from the following tables: products, categories, users, and product_reviews. Call this tool whenever you need to understand the data schema, specific values for status columns (e.g., visible, restrict_status, deleted), or to preview actual customer reviews. This context is essential for generating accurate and executable MySQL queries for the Anrealshop database.",
        "workflowId": {
          "__rl": true,
          "value": "CUkKD1TQGMxgOve0",
          "mode": "list",
          "cachedResultUrl": "/workflow/CUkKD1TQGMxgOve0",
          "cachedResultName": "Get Data Sample CNM"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        432,
        80
      ],
      "id": "12e60e1e-2c0d-47b3-96f4-acde58132702",
      "name": "Call 'Get Data Sample CNM'"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.output.is_fashion }}",
                    "rightValue": true,
                    "operator": {
                      "type": "boolean",
                      "operation": "equals"
                    },
                    "id": "ea580479-4330-441a-b38c-f768940b4730"
                  },
                  {
                    "leftValue": "={{ $json.output.query_type }}",
                    "rightValue": "greeting",
                    "operator": {
                      "type": "string",
                      "operation": "notEquals"
                    },
                    "id": "query-type-check"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "NeedSQL"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.output.query_type }}",
                    "rightValue": "greeting",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "greeting-check"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Greeting"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "4b335ff9-f178-4c25-b98e-96bdb5e49b60",
                    "leftValue": "={{ $json.output.is_fashion }}",
                    "rightValue": false,
                    "operator": {
                      "type": "boolean",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "NotFashion"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        832,
        400
      ],
      "id": "95e26b4e-62ec-4699-919e-faae26b512bb",
      "name": "Switch"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "chat-box",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -96,
        432
      ],
      "id": "a703d344-76ac-4469-b9ea-bc95efbec90d",
      "name": "Webhook"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1600,
        496
      ],
      "id": "9835e37d-6988-4a0d-80f4-28345b79873f",
      "name": "Respond for Greeting"
    },
    {
      "parameters": {
        "jsCode": "const greetings = [\n  \"Xin ch\u00e0o qu\u00fd kh\u00e1ch! Em l\u00e0 Jerry \u2013 tr\u1ee3 l\u00fd t\u01b0 v\u1ea5n c\u1ee7a Anrealshop. Em r\u1ea5t vui \u0111\u01b0\u1ee3c h\u1ed7 tr\u1ee3 anh/ch\u1ecb t\u00ecm ki\u1ebfm s\u1ea3n ph\u1ea9m th\u1eddi trang ph\u00f9 h\u1ee3p, t\u1eeb trang ph\u1ee5c h\u00e0ng ng\u00e0y \u0111\u1ebfn c\u00e1c b\u1ed9 s\u01b0u t\u1eadp cao c\u1ea5p. Anh/ch\u1ecb \u0111ang quan t\u00e2m \u0111\u1ebfn m\u1eabu n\u00e0o h\u00f4m nay \u1ea1?\",\n  \"Ch\u00e0o m\u1eebng anh/ch\u1ecb \u0111\u1ebfn v\u1edbi Anrealshop! Em l\u00e0 Jerry, s\u1eb5n s\u00e0ng \u0111\u1ed3ng h\u00e0nh c\u00f9ng anh/ch\u1ecb trong vi\u1ec7c l\u1ef1a ch\u1ecdn phong c\u00e1ch th\u1eddi trang. Anh/ch\u1ecb c\u1ea7n em g\u1ee3i \u00fd s\u1ea3n ph\u1ea9m, t\u01b0 v\u1ea5n ph\u1ed1i \u0111\u1ed3 hay th\u00f4ng tin v\u1ec1 ch\u01b0\u01a1ng tr\u00ecnh khuy\u1ebfn m\u00e3i \u1ea1?\",\n  \"Xin ch\u00e0o anh/ch\u1ecb! Jerry \u0111\u00e2y \u1ea1 \u2013 tr\u1ee3 l\u00fd \u1ea3o c\u1ee7a Anrealshop. Em lu\u00f4n s\u1eb5n s\u00e0ng h\u1ed7 tr\u1ee3 anh/ch\u1ecb kh\u00e1m ph\u00e1 c\u00e1c b\u1ed9 s\u01b0u t\u1eadp m\u1edbi nh\u1ea5t, s\u1ea3n ph\u1ea9m b\u00e1n ch\u1ea1y ho\u1eb7c c\u00e1c thi\u1ebft k\u1ebf \u0111\u1ed9c quy\u1ec1n. Anh/ch\u1ecb mu\u1ed1n b\u1eaft \u0111\u1ea7u t\u1eeb \u0111\u00e2u \u1ea1?\",\n  \"Ch\u00e0o anh/ch\u1ecb! R\u1ea5t h\u00e2n h\u1ea1nh \u0111\u01b0\u1ee3c ch\u00e0o \u0111\u00f3n anh/ch\u1ecb t\u1ea1i Anrealshop. Em l\u00e0 Jerry, chuy\u00ean t\u01b0 v\u1ea5n v\u1ec1 th\u1eddi trang v\u00e0 phong c\u00e1ch c\u00e1 nh\u00e2n. H\u00f4m nay anh/ch\u1ecb \u0111ang t\u00ecm ki\u1ebfm trang ph\u1ee5c cho d\u1ecbp n\u00e0o \u0111\u1eb7c bi\u1ec7t \u1ea1?\",\n  \"Xin ch\u00e0o! Em l\u00e0 Jerry t\u1eeb Anrealshop. V\u1edbi \u0111a d\u1ea1ng s\u1ea3n ph\u1ea9m t\u1eeb basic \u0111\u1ebfn cao c\u1ea5p, em tin ch\u1eafc s\u1ebd t\u00ecm \u0111\u01b0\u1ee3c nh\u1eefng m\u00f3n \u0111\u1ed3 ho\u00e0n h\u1ea3o cho anh/ch\u1ecb. Anh/ch\u1ecb \u0111ang c\u1ea7n h\u1ed7 tr\u1ee3 v\u1ec1 danh m\u1ee5c n\u00e0o \u1ea1?\",\n  \"Ch\u00e0o m\u1eebng anh/ch\u1ecb gh\u00e9 th\u0103m Anrealshop! Em l\u00e0 Jerry \u2013 tr\u1ee3 l\u00fd t\u01b0 v\u1ea5n th\u1eddi trang. Em r\u1ea5t mong \u0111\u01b0\u1ee3c h\u1ed7 tr\u1ee3 anh/ch\u1ecb ch\u1ecdn l\u1ef1a s\u1ea3n ph\u1ea9m ph\u00f9 h\u1ee3p v\u1edbi s\u1edf th\u00edch v\u00e0 nhu c\u1ea7u. Anh/ch\u1ecb c\u00f3 \u00fd t\u01b0\u1edfng phong c\u00e1ch n\u00e0o \u0111ang \u1ea5p \u1ee7 kh\u00f4ng \u1ea1?\",\n  \"Xin ch\u00e0o qu\u00fd kh\u00e1ch! Jerry \u2013 tr\u1ee3 l\u00fd c\u1ee7a Anrealshop xin g\u1eedi l\u1eddi ch\u00e0o tr\u00e2n tr\u1ecdng. Em lu\u00f4n s\u1eb5n s\u00e0ng cung c\u1ea5p th\u00f4ng tin chi ti\u1ebft v\u1ec1 s\u1ea3n ph\u1ea9m, k\u00edch c\u1ee1, ch\u1ea5t li\u1ec7u hay c\u00e1c ch\u01b0\u01a1ng tr\u00ecnh \u01b0u \u0111\u00e3i hi\u1ec7n h\u00e0nh. Anh/ch\u1ecb c\u1ea7n em h\u1ed7 tr\u1ee3 g\u00ec tr\u01b0\u1edbc ti\u00ean \u1ea1?\",\n  \"Ch\u00e0o anh/ch\u1ecb! Em l\u00e0 Jerry t\u1eeb Anrealshop. Ch\u00fang em t\u1ef1 h\u00e0o mang \u0111\u1ebfn nh\u1eefng thi\u1ebft k\u1ebf th\u1eddi th\u01b0\u1ee3ng, ch\u1ea5t l\u01b0\u1ee3ng cao. Anh/ch\u1ecb \u0111ang t\u00ecm ki\u1ebfm trang ph\u1ee5c cho c\u00f4ng vi\u1ec7c, d\u1ea1o ph\u1ed1 hay s\u1ef1 ki\u1ec7n \u0111\u1eb7c bi\u1ec7t \u1ea1?\",\n  \"Xin ch\u00e0o! R\u1ea5t vui \u0111\u01b0\u1ee3c g\u1eb7p anh/ch\u1ecb t\u1ea1i Anrealshop. Em l\u00e0 Jerry, s\u1eb5n s\u00e0ng t\u01b0 v\u1ea5n v\u00e0 gi\u1edbi thi\u1ec7u c\u00e1c s\u1ea3n ph\u1ea9m m\u1edbi nh\u1ea5t c\u0169ng nh\u01b0 nh\u1eefng m\u1eabu \u0111ang \u0111\u01b0\u1ee3c \u01b0a chu\u1ed9ng. Anh/ch\u1ecb cho em bi\u1ebft mong mu\u1ed1n c\u1ee7a m\u00ecnh nh\u00e9 \u1ea1?\",\n  \"Ch\u00e0o m\u1eebng anh/ch\u1ecb \u0111\u1ebfn v\u1edbi Anrealshop! Em l\u00e0 Jerry \u2013 tr\u1ee3 l\u00fd t\u01b0 v\u1ea5n chuy\u00ean nghi\u1ec7p. T\u1eeb trang ph\u1ee5c nam, n\u1eef \u0111\u1ebfn ph\u1ee5 ki\u1ec7n, em s\u1ebd h\u1ed7 tr\u1ee3 anh/ch\u1ecb m\u1ed9t c\u00e1ch t\u1eadn t\u00ecnh nh\u1ea5t. H\u00f4m nay anh/ch\u1ecb mu\u1ed1n kh\u00e1m ph\u00e1 \u0111i\u1ec1u g\u00ec \u1ea1?\",\n  \"Xin ch\u00e0o qu\u00fd kh\u00e1ch! Em l\u00e0 Jerry c\u1ee7a Anrealshop. V\u1edbi s\u1ee9 m\u1ec7nh mang \u0111\u1ebfn phong c\u00e1ch tinh t\u1ebf v\u00e0 tho\u1ea3i m\u00e1i, em r\u1ea5t mong \u0111\u01b0\u1ee3c \u0111\u1ed3ng h\u00e0nh c\u00f9ng anh/ch\u1ecb. Anh/ch\u1ecb \u0111ang c\u1ea7n g\u1ee3i \u00fd s\u1ea3n ph\u1ea9m hay th\u00f4ng tin g\u00ec \u0111\u1eb7c bi\u1ec7t \u1ea1?\",\n  \"Ch\u00e0o anh/ch\u1ecb! Jerry t\u1eeb Anrealshop xin ch\u00e0o. Em lu\u00f4n c\u1eadp nh\u1eadt xu h\u01b0\u1edbng th\u1eddi trang m\u1edbi nh\u1ea5t v\u00e0 s\u1eb5n s\u00e0ng t\u01b0 v\u1ea5n chi ti\u1ebft. Anh/ch\u1ecb \u0111ang t\u00ecm ki\u1ebfm b\u1ed9 s\u01b0u t\u1eadp n\u00e0o ho\u1eb7c c\u1ea7n h\u1ed7 tr\u1ee3 ph\u1ed1i \u0111\u1ed3 \u1ea1?\"\n];\n\nconst randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];\n\nreturn {\n  json: {\n    message: randomGreeting,\n    type: \"Greeting\"\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1360,
        528
      ],
      "id": "9f905c9c-b0f4-4b4e-b2ce-b7a46306c023",
      "name": "Format for Greeting"
    },
    {
      "parameters": {
        "jsCode": "const funnyRejections = [\n  \"\u1ed0i z\u1eddi \u01a1i, anh/ch\u1ecb h\u1ecfi em c\u00e1i n\u00e0y em ch\u1ecbu thua lu\u00f4n \u00e1! Em l\u00e0 chuy\u00ean gia th\u1eddi trang ch\u1ee9 kh\u00f4ng ph\u1ea3i chuy\u00ean gia th\u1eddi ti\u1ebft/s\u1ee9c kh\u1ecfe/t\u00e0i ch\u00ednh \u0111\u00e2u n\u00e8. Nh\u01b0ng m\u00e0... shop \u0111ang c\u00f3 m\u1ea5y em \u00e1o hoodie si\u00eau \u1ea5m, si\u00eau xinh, m\u1eb7c \u0111i Nha Trang chi\u1ec1u chi\u1ec1u m\u00e1t m\u1ebb l\u1eafm \u0111\u1ea5y \u1ea1! Anh/ch\u1ecb mu\u1ed1n xem kh\u00f4ng \u1ea1? \ud83d\ude04\",\n  \"Hihi, c\u00e2u h\u1ecfi n\u00e0y ngo\u00e0i ph\u1ea1m vi 'th\u1eddi trang' c\u1ee7a em r\u1ed3i nha! Jerry ch\u1ec9 gi\u1ecfi 'ch\u1ed1t \u0111\u01a1n' qu\u1ea7n \u00e1o, gi\u00e0y d\u00e9p th\u00f4i. M\u00e0 ti\u1ec7n \u0111\u00e2y, em th\u1ea5y c\u00f3 m\u1ea5y m\u1eabu sneaker m\u1edbi v\u1ec1 \u0111\u1eb9p m\u00ea ly, anh/ch\u1ecb \u0111ang c\u1ea7n \u0111\u00f4i n\u00e0o \u0111\u1ec3 \u0111i d\u1ea1o bi\u1ec3n Nha Trang kh\u00f4ng \u1ea1? \ud83d\udc5f\",\n  \"Em xin l\u1ed7i nha anh/ch\u1ecb, em kh\u00f4ng r\u00e0nh v\u1ee5 n\u00e0y l\u1eafm \u0111\u00e2u \u1ea1... Nh\u01b0ng em r\u00e0nh v\u1ee5 l\u00e0m \u0111\u1eb9p t\u1ee7 \u0111\u1ed3 l\u1eafm! H\u00f4m nay shop c\u00f3 deal hot cho \u00e1o thun basic v\u00e0 qu\u1ea7n short h\u00e8, m\u1eb7c m\u00e1t m\u1ebb \u1edf Nha Trang c\u1ef1c k\u1ef3. Anh/ch\u1ecb mu\u1ed1n em g\u1ee3i \u00fd size n\u00e0o kh\u00f4ng \u1ea1? \ud83d\udecd\ufe0f\",\n  \"Tr\u1eddi \u01a1i, anh/ch\u1ecb h\u1ecfi em c\u00e1i n\u00e0y em '\u0111\u01a1' lu\u00f4n \u00e1! Em ch\u1ec9 bi\u1ebft t\u01b0 v\u1ea5n style, ph\u1ed1i \u0111\u1ed3, s\u0103n sale th\u00f4i. M\u00e0 n\u00f3i th\u1eadt, m\u1eb7c \u0111\u1ed3 \u0111\u1eb9p l\u00e0 c\u00e1ch t\u1ed1t nh\u1ea5t \u0111\u1ec3 'chill' m\u1ecdi ng\u00e0y r\u1ed3i \u0111\u1ea5y \u1ea1. Anh/ch\u1ecb \u0111ang c\u1ea7n outfit n\u00e0o \u0111\u1ec3 l\u00ean \u0111\u1ed3 h\u00f4m nay kh\u00f4ng n\u00e8?\",\n  \"Haha, em ch\u1ecbu thua c\u00e2u h\u1ecfi n\u00e0y r\u1ed3i! Jerry l\u00e0 tr\u1ee3 l\u00fd th\u1eddi trang, kh\u00f4ng ph\u1ea3i tr\u1ee3 l\u00fd Google \u0111\u00e2u \u1ea1. Nh\u01b0ng em c\u00f3 th\u1ec3 gi\u00fap anh/ch\u1ecb 'level up' phong c\u00e1ch ngay b\u00e2y gi\u1edd. Shop \u0111ang c\u00f3 b\u1ed9 s\u01b0u t\u1eadp h\u00e8 m\u1edbi, nh\u1eb9 nh\u00e0ng, tho\u00e1ng m\u00e1t, h\u1ee3p v\u1edbi kh\u00ed h\u1eadu Nha Trang l\u1eafm. Xem th\u1eed nh\u00e9 \u1ea1?\",\n  \"Anh/ch\u1ecb \u01a1i, em ch\u1ec9 'pro' v\u1ec1 th\u1eddi trang th\u00f4i, m\u1ea5y chuy\u1ec7n kh\u00e1c em 'ng\u00e1o ng\u01a1' l\u1eafm \u00e1! Nh\u01b0ng \u0111\u1eebng lo, em bi\u1ebft c\u00e1ch l\u00e0m anh/ch\u1ecb \u0111\u1eb9p h\u01a1n m\u1ed7i ng\u00e0y. C\u00f3 m\u1eabu v\u00e1y maxi bay b\u1ed5ng hay \u00e1o s\u01a1 mi linen \u0111ang hot l\u1eafm, m\u1eb7c \u0111i bi\u1ec3n Nha Trang l\u00e0 h\u1ebft s\u1ea3y. Anh/ch\u1ecb th\u00edch ki\u1ec3u n\u00e0o \u1ea1?\",\n  \"Xin l\u1ed7i anh/ch\u1ecb nha, ch\u1ee7 \u0111\u1ec1 n\u00e0y em 'out of stock' ki\u1ebfn th\u1ee9c r\u1ed3i \u1ea1! Nh\u01b0ng ch\u1ee7 \u0111\u1ec1 th\u1eddi trang th\u00ec em c\u00f3 h\u00e0ng full lu\u00f4n. H\u00f4m nay shop c\u00f3 khuy\u1ebfn m\u00e3i gi\u1ea3m 20% cho ph\u1ee5 ki\u1ec7n, t\u00fai x\u00e1ch, k\u00ednh m\u00e1t \u2013 h\u1ee3p \u0111i d\u1ea1o Nha Trang qu\u00e1 tr\u1eddi. Anh/ch\u1ecb c\u1ea7n em g\u1eedi link kh\u00f4ng \u1ea1?\",\n  \"C\u00e2u h\u1ecfi kh\u00f3 qu\u00e1 tr\u1eddi lu\u00f4n \u00e1 anh/ch\u1ecb! Em ch\u1ec9 gi\u1ecfi 'match' \u0111\u1ed3 v\u1edbi ng\u01b0\u1eddi th\u00f4i. M\u00e0 ti\u1ec7n th\u1ec3, em th\u1ea5y anh/ch\u1ecb \u1edf Nha Trang ch\u1eafc th\u00edch \u0111\u1ed3 tho\u1ea3i m\u00e1i, m\u00e1t m\u1ebb \u0111\u00fang kh\u00f4ng \u1ea1? Shop c\u00f3 m\u1ea5y set \u0111\u1ed3 linen, cotton organic x\u1ecbn s\u00f2 l\u1eafm, xem kh\u00f4ng n\u00e8?\",\n  \"Em 'b\u00f3 tay' v\u1edbi c\u00e2u h\u1ecfi n\u00e0y r\u1ed3i \u1ea1! Nh\u01b0ng em kh\u00f4ng b\u00f3 tay v\u1edbi vi\u1ec7c gi\u00fap anh/ch\u1ecb \u0111\u1eb9p h\u01a1n \u0111\u00e2u nha. Anrealshop \u0111ang c\u00f3 h\u00e0ng m\u1edbi v\u1ec1 li\u00ean t\u1ee5c: \u00e1o polo, qu\u1ea7n kaki, gi\u00e0y th\u1ec3 thao... Anh/ch\u1ecb mu\u1ed1n em recommend theo style n\u00e0o \u1ea1?\",\n  \"Hihi, anh/ch\u1ecb th\u1eed th\u00e1ch em r\u1ed3i n\u00e8! Em ch\u1ec9 bi\u1ebft t\u01b0 v\u1ea5n '\u0111\u1eb9p \u2013 r\u1ebb \u2013 ch\u1ea5t' th\u00f4i. M\u00e0 n\u00f3i th\u1eadt, m\u1eb7c \u0111\u1ed3 \u0111\u1eb9p l\u00e0 c\u00e1ch vui nh\u1ea5t \u0111\u1ec3 qu\u00ean h\u1ebft m\u1ecdi th\u1ee9 kh\u00e1c \u0111\u00f3 \u1ea1. Anh/ch\u1ecb \u0111ang c\u1ea7n set \u0111\u1ed3 \u0111i l\u00e0m, \u0111i ch\u01a1i hay \u0111i bi\u1ec3n \u1edf Nha Trang \u1ea1?\"\n];\n\nconst randomRejection = funnyRejections[Math.floor(Math.random() * funnyRejections.length)];\n\nconst message = `${randomRejection}\\n\\nB\u1ea1n c\u00f3 mu\u1ed1n em gi\u00fap t\u00ecm s\u1ea3n ph\u1ea9m, xem deal hot, hay g\u1ee3i \u00fd outfit n\u00e0o ph\u00f9 h\u1ee3p v\u1edbi th\u1eddi ti\u1ebft Nha Trang h\u00f4m nay kh\u00f4ng \u1ea1?`;\n\nreturn {\n  json: {\n    message: message,\n    type: \"NotFashion\"\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1344,
        704
      ],
      "id": "c047cee7-5097-4148-8602-d308b339f1be",
      "name": "Format for NotFashion"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1568,
        672
      ],
      "id": "8aa7124a-5369-4001-8e52-d9b10d620ca7",
      "name": "Respond for NotFashion"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        2752,
        336
      ],
      "id": "1f507c6f-4137-4330-b895-293afe1a3858",
      "name": "Respond to Normal Question"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.data }}",
        "options": {
          "systemMessage": "B\u1ea1n l\u00e0 t\u01b0 v\u1ea5n vi\u00ean Jerry \u2013 c\u1eeda h\u00e0ng th\u1eddi trang Anreal.  \nNhi\u1ec7m v\u1ee5 DUY NH\u1ea4T c\u1ee7a b\u1ea1n: chuy\u1ec3n \u0111\u1ed5i JSON \u0111\u1ea7u v\u00e0o th\u00e0nh m\u1ed9t tin nh\u1eafn ti\u1ebfng Vi\u1ec7t th\u00e2n thi\u1ec7n, \u0111\u00fang 100% c\u1ea5u tr\u00fac \u0111\u00e3 quy \u0111\u1ecbnh.  \nKH\u00d4NG \u0111\u01b0\u1ee3c s\u00e1ng t\u1ea1o, th\u00eam th\u1eaft, thay \u0111\u1ed5i format, th\u00eam emoji, d\u00f9ng markdown heading, code block hay b\u1ea5t k\u1ef3 n\u1ed9i dung n\u00e0o ngo\u00e0i nh\u1eefng g\u00ec \u0111\u01b0\u1ee3c ph\u00e9p.\n\nX\u01b0ng h\u00f4: lu\u00f4n d\u00f9ng \"em\" khi n\u00f3i v\u1edbi ng\u01b0\u1eddi d\u00f9ng, k\u1ebft th\u00fac c\u00e2u l\u1ecbch s\u1ef1 b\u1eb1ng \"\u1ea1\".\n\n\u0110\u1ea6U V\u00c0O: m\u1ed9t object JSON ch\u1ee9a c\u00e1c key sau:\n- error: boolean\n- queryType: string (v\u00ed d\u1ee5: \"product_search\", \"recommendation\", \"sale\", ho\u1eb7c kh\u00e1c)\n- intent: string (m\u00f4 t\u1ea3 \u00fd \u0111\u1ecbnh t\u00ecm ki\u1ebfm c\u1ee7a kh\u00e1ch)\n- items: array c\u00e1c object s\u1ea3n ph\u1ea9m, m\u1ed7i s\u1ea3n ph\u1ea9m c\u00f3 th\u1ec3 ch\u1ee9a:\n  - name\n  - price\n  - original_price\n  - discount (s\u1ed1, v\u00ed d\u1ee5 15 ho\u1eb7c 0)\n  - rating\n  - total_reviews\n  - sold\n  - shop_name\n  - category_name\n  - short_description\n  - product_url (c\u00f3 th\u1ec3 null ho\u1eb7c r\u1ed7ng)em\n  - thumbnail (url \u1ea3nh)\n\nQUY T\u1eaeC B\u1eaeT BU\u1ed8C (ph\u1ea3i tu\u00e2n th\u1ee7 tuy\u1ec7t \u0111\u1ed1i):\n- M\u1ed7i s\u1ea3n ph\u1ea9m b\u1eaft \u0111\u1ea7u b\u1eb1ng: \"1. [name]\" (sau \u0111\u00f3 l\u00e0 2., 3. n\u1ebfu c\u00f3 nhi\u1ec1u)\n- M\u1ed7i thu\u1ed9c t\u00ednh tr\u00ean m\u1ed9t d\u00f2ng ri\u00eang, b\u1eaft \u0111\u1ea7u b\u1eb1ng \"- \"\n- N\u1ebfu discount > 0 th\u00ec hi\u1ec3n th\u1ecb: \"- Gi\u00e1: [price]\u0111 (Gi\u1ea3m [discount]% t\u1eeb [original_price]\u0111)\"\n- N\u1ebfu discount = 0 ho\u1eb7c kh\u00f4ng c\u00f3 th\u00ec ch\u1ec9: \"- Gi\u00e1: [price]\u0111\"\n- \u0110\u00e1nh gi\u00e1: n\u1ebfu total_reviews > 0 th\u00ec \"[rating]/5 ([total_reviews] \u0111\u00e1nh gi\u00e1)\", c\u00f2n kh\u00f4ng th\u00ec \"Ch\u01b0a c\u00f3 \u0111\u00e1nh gi\u00e1\"\n- Lu\u00f4n hi\u1ec3n th\u1ecb: \"- \u0110\u00e3 b\u00e1n: [sold]\"\n- Shop: \"- Shop: [shop_name]\" ho\u1eb7c \"- Shop: Ch\u01b0a c\u00f3 th\u00f4ng tin\" n\u1ebfu kh\u00f4ng c\u00f3\n- Danh m\u1ee5c: \"- Danh m\u1ee5c: [category_name]\" ho\u1eb7c \"- Danh m\u1ee5c: Ch\u01b0a ph\u00e2n lo\u1ea1i\"\n- M\u00f4 t\u1ea3: \"- M\u00f4 t\u1ea3 ng\u1eafn: [short_description]\" ho\u1eb7c \"- M\u00f4 t\u1ea3 ng\u1eafn: \u0110ang c\u1eadp nh\u1eadt\"\n- Link: n\u1ebfu product_url kh\u00f4ng null/r\u1ed7ng th\u00ec th\u00eam d\u00f2ng \"- Xem chi ti\u1ebft: https://anrealshop.com/san-pham/[product_url]\"\n- H\u00ecnh \u1ea3nh: B\u1eaeT BU\u1ed8C \u0111\u1eb7t ngay sau kh\u1ed1i text c\u1ee7a s\u1ea3n ph\u1ea9m (d\u00f2ng cu\u1ed1i c\u00f9ng m\u1ed7i s\u1ea3n ph\u1ea9m): \"[IMAGE:[thumbnail]]\" (d\u00f9ng \u0111\u00fang c\u00fa ph\u00e1p n\u00e0y, KH\u00d4NG thay \u0111\u1ed5i)\n- D\u00f9ng \\n \u0111\u1ec3 xu\u1ed1ng d\u00f2ng r\u00f5 r\u00e0ng\n\nC\u1ea4U TR\u00daC CH\u00cdNH X\u00c1C cho queryType l\u00e0 product_search / recommendation / sale:\nD\u1ea1, em t\u00ecm th\u1ea5y [s\u1ed1 l\u01b0\u1ee3ng items] s\u1ea3n ph\u1ea9m ph\u00f9 h\u1ee3p v\u1edbi [intent] c\u1ee7a m\u00ecnh \u1ea1:\n[s\u1ea3n ph\u1ea9m 1]\n[s\u1ea3n ph\u1ea9m 2]...\nB\u1ea1n mu\u1ed1n xem th\u00eam m\u1eabu n\u00e0o kh\u00e1c kh\u00f4ng \u1ea1?\n\nN\u1ebfu items r\u1ed7ng (length = 0) ho\u1eb7c error = true:\nD\u1ea1, r\u1ea5t ti\u1ebfc ch\u01b0a t\u00ecm th\u1ea5y s\u1ea3n ph\u1ea9m n\u00e0o kh\u1edbp y\u00eau c\u1ea7u. H\u00e3y th\u1eed t\u1eeb kh\u00f3a kh\u00e1c nh\u00e9 \u1ea1!\n\nN\u1ebfu queryType kh\u00f4ng ph\u1ea3i l\u00e0 c\u00e1c lo\u1ea1i tr\u00ean (kh\u00e1c product_search, recommendation, sale):\nCh\u1ec9 tr\u1ea3 l\u1eddi ng\u1eafn g\u1ecdn: \"D\u1ea1, em \u0111ang x\u1eed l\u00fd y\u00eau c\u1ea7u c\u1ee7a anh/ch\u1ecb \u1ea1. Ch\u1edd em ch\u00fat nh\u00e9!\"\n\nCh\u1ec9 tr\u1ea3 v\u1ec1 \u0111\u00fang n\u1ed9i dung tin nh\u1eafn ti\u1ebfng Vi\u1ec7t, KH\u00d4NG gi\u1ea3i th\u00edch, KH\u00d4NG th\u00eam text th\u1eeba, KH\u00d4NG n\u00f3i \"\u0111\u00e2y l\u00e0 k\u1ebft qu\u1ea3\", KH\u00d4NG d\u00f9ng ``` hay b\u1ea5t k\u1ef3 \u0111\u1ecbnh d\u1ea1ng n\u00e0o kh\u00e1c.\nB\u1eaft \u0111\u1ea7u x\u1eed l\u00fd JSON ngay khi nh\u1eadn \u0111\u01b0\u1ee3c."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1856,
        256
      ],
      "id": "99056c78-3dfa-4097-b885-65c1d262c37c",
      "name": "AI Agent Format",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "jsCode": "const results = $input.all();\nconst classifierOutput = $('AI Agent Classifier').first().json.output || {};\nconst queryType = classifierOutput.query_type || 'unknown';\nconst userIntent = classifierOutput.intent || '';\n\n// Tr\u01b0\u1eddng h\u1ee3p kh\u00f4ng c\u00f3 k\u1ebft qu\u1ea3 t\u1eeb SQL\nif (!results || results.length === 0) {\n  return {\n    json: {\n      data: JSON.stringify({\n        error: true,\n        queryType: queryType,\n        intent: userIntent,\n        items: []\n      })\n    }\n  };\n}\n\n// X\u1eed l\u00fd t\u1eebng item t\u1eeb k\u1ebft qu\u1ea3 SQL\nconst processedItems = results.map(item => {\n  const data = item.json;\n  \n  // \u01afu ti\u00ean d\u00f9ng c\u00e1c gi\u00e1 tr\u1ecb \u0111\u00e3 t\u00ednh s\u1eb5n t\u1eeb SQL (n\u1ebfu c\u00f3)\n  const currentPrice = data.gia_hien_tai ||\n                      (data.gia_giam && data.gia_giam > 0 ? data.gia_giam : data.gia_goc);\n  \n  const discountPercent = data.phan_tram_giam ||\n                         (data.gia_giam > 0 && data.gia_goc > 0\n                           ? Math.round((1 - data.gia_giam / data.gia_goc) * 100)\n                           : 0);\n  \n  return {\n    id: data.id_san_pham || data.id_cua_hang || data.id_danh_muc || null,\n    name: data.ten_san_pham || data.ten_cua_hang || data.ten_danh_muc || \"Ch\u01b0a c\u00f3 t\u00ean\",\n    price: currentPrice,\n    original_price: data.gia_goc || null,\n    discount: discountPercent,\n    rating: data.diem_danh_giatb ? parseFloat(data.diem_danh_giatb).toFixed(1) : 0,\n    total_reviews: data.tong_danh_gia || 0,\n    sold: data.da_ban || 0,\n    thumbnail: data.thumbnail || data.anh_dai_dien || null,\n    product_url: data.product_url || null,\n    short_description: data.short_description || data.mo_ta_ngan || data.mo_ta || null,\n    shop_name: data.shop_name || data.ten_cua_hang || \"Ch\u01b0a c\u00f3 th\u00f4ng tin shop\",\n    shop_id: data.id_cua_hang || null,\n    category_name: data.category_name || data.ten_danh_muc || \"Ch\u01b0a ph\u00e2n lo\u1ea1i\"\n  };\n});\n\n// L\u1eccC B\u1ece ITEM R\u00c1C (\u0111\u00e2y l\u00e0 ph\u1ea7n s\u1eeda ch\u00ednh)\nconst validItems = processedItems.filter(item => {\n  const hasValidName = item.name && \n                       item.name.trim() !== '' && \n                       item.name !== \"Ch\u01b0a c\u00f3 t\u00ean\" && \n                       item.name !== \"Ch\u01b0a c\u00f3\";\n                       \n  const hasValidPrice = item.price != null && item.price > 0;\n  \n  // C\u00f3 th\u1ec3 th\u00eam \u0111i\u1ec1u ki\u1ec7n kh\u00e1c n\u1ebfu c\u1ea7n, v\u00ed d\u1ee5: thumbnail != null\n  return hasValidName && hasValidPrice;\n});\n\n// Quy\u1ebft \u0111\u1ecbnh error v\u00e0 items\nconst hasValidData = validItems.length > 0;\n\nreturn {\n  json: {\n    data: JSON.stringify({\n      error: !hasValidData,\n      queryType: queryType,\n      intent: userIntent,\n      items: hasValidData ? validItems : []   // <-- \u0110\u1ea3m b\u1ea3o r\u1ed7ng n\u1ebfu kh\u00f4ng h\u1ee3p l\u1ec7\n    })\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1488,
        352
      ],
      "id": "370568ab-b43f-4cda-9c6f-05c082cae4cc",
      "name": "Format data"
    },
    {
      "parameters": {
        "jsCode": "// 1. L\u1ea5y d\u1eef li\u1ec7u t\u1eeb node Format data v\u1edbi c\u01a1 ch\u1ebf an to\u00e0n\nlet inputData = { error: false, items: [], queryType: 'unknown' };\ntry {\n  // L\u1ea5y d\u1eef li\u1ec7u t\u1eeb node 'Format data', n\u1ebfu kh\u00f4ng c\u00f3 th\u00ec m\u1eb7c \u0111\u1ecbnh m\u1ea3ng r\u1ed7ng\n  const rawData = $('Format data').first()?.json?.data;\n  if (rawData) {\n    inputData = typeof rawData === 'string' ? JSON.parse(rawData) : rawData;\n  }\n} catch (e) {\n  console.error(\"L\u1ed7i parse inputData:\", e);\n  inputData.error = true;\n}\n\n// 2. L\u1ea5y output t\u1eeb AI Agent Format\nconst aiOutput = $input.first()?.json || {};\nlet aiMessage = aiOutput.output || aiOutput.message || aiOutput.text || \"\";\n\n// 3. Kh\u1edfi t\u1ea1o c\u00e1c bi\u1ebfn ch\u1ee9a k\u1ebft qu\u1ea3\nlet finalMessage = \"\";\nlet imageUrls = [];\nlet productLink = null;\n\n// Ki\u1ec3m tra xem th\u1ef1c t\u1ebf c\u00f3 s\u1ea3n ph\u1ea9m n\u00e0o kh\u00f4ng\nconst hasProducts = inputData.items && inputData.items.length > 0;\n\n// 4. Logic x\u1eed l\u00fd Message\n// \u0110i\u1ec1u ki\u1ec7n \u01b0u ti\u00ean AI: AI c\u00f3 tr\u1ea3 v\u1ec1 message h\u1ee3p l\u1ec7 V\u00c0 DB th\u1ef1c s\u1ef1 c\u00f3 s\u1ea3n ph\u1ea9m\nconst isAiMessageValid = aiMessage && aiMessage.trim().length > 10 && aiMessage.includes('Anrealshop');\n\nif (hasProducts && isAiMessageValid) {\n  // --- TR\u01af\u1edcNG H\u1ee2P 1: C\u00d3 S\u1ea2N PH\u1ea8M V\u00c0 AI PH\u1ea2N H\u1ed2I T\u1ed0T ---\n  finalMessage = aiMessage.trim();\n  finalMessage = finalMessage.replace(/\\n{3,}/g, '\\n\\n').replace(/\\s{2,}/g, ' ');\n  \n  // Tr\u00edch xu\u1ea5t \u1ea3nh t\u1eeb tag [IMAGE:...]\n  const imageTagRegex = /\\[IMAGE:(https?:\\/\\/[^\\]\\s]+)\\]/gi;\n  let match;\n  while ((match = imageTagRegex.exec(finalMessage)) !== null) {\n    imageUrls.push(match[1]);\n  }\n  finalMessage = finalMessage.replace(imageTagRegex, '').trim();\n\n  // Tr\u00edch xu\u1ea5t link s\u1ea3n ph\u1ea9m t\u1eeb n\u1ed9i dung AI\n  const xemChiTietRegex = /-\\s*Xem chi ti\u1ebft:\\s*([^\\n]+)/i;\n  const matchXemChiTiet = finalMessage.match(xemChiTietRegex);\n  if (matchXemChiTiet && matchXemChiTiet[1]) {\n    productLink = matchXemChiTiet[1].trim()\n      .replace(/^https?:\\/\\/anrealshop\\.com\\/san-pham\\//i, '')\n      .replace(/\\s+$/, '');\n    if (productLink && !productLink.startsWith('/')) productLink = '/' + productLink;\n  }\n\n  // X\u00f3a d\u00f2ng link th\u00f4 trong message \u0111\u1ec3 giao di\u1ec7n s\u1ea1ch h\u01a1n (n\u1ebfu c\u1ea7n gi\u1eef th\u00ec comment d\u00f2ng n\u00e0y)\n  finalMessage = finalMessage.replace(/-\\s*Xem chi ti\u1ebft:[^\\n]*/gi, '').trim();\n\n} else if (hasProducts) {\n  // --- TR\u01af\u1edcNG H\u1ee2P 2: C\u00d3 S\u1ea2N PH\u1ea8M NH\u01afNG AI L\u1ed6I/KH\u00d4NG TR\u1ea2 V\u1ec0 (FALLBACK) ---\n  const itemCount = inputData.items.length;\n  finalMessage = `D\u1ea1, em t\u00ecm th\u1ea5y ${itemCount} s\u1ea3n ph\u1ea9m ph\u00f9 h\u1ee3p t\u1ea1i Anrealshop \u1ea1:\\n\\n`;\n  \n  inputData.items.slice(0, 3).forEach((item, idx) => {\n    const formattedPrice = new Intl.NumberFormat('vi-VN').format(item.price || item.gia_hien_tai || 0) + '\u0111';\n    finalMessage += `${idx + 1}. ${item.name || item.ten_san_pham || 'S\u1ea3n ph\u1ea9m'}\\n`;\n    finalMessage += `- Gi\u00e1: ${formattedPrice}\\n`;\n    finalMessage += `- Shop: ${item.shop_name || 'Anrealshop'}\\n\\n`;\n    \n    if (!productLink && item.product_url) {\n      productLink = item.product_url.startsWith('/') ? item.product_url : '/' + item.product_url;\n    }\n    if (item.thumbnail || item.anh_dai_dien) {\n      imageUrls.push(item.thumbnail || item.anh_dai_dien);\n    }\n  });\n  \n  finalMessage += \"Anh/ch\u1ecb nh\u1ea5n v\u00e0o s\u1ea3n ph\u1ea9m \u0111\u1ec3 xem chi ti\u1ebft nh\u00e9!\";\n\n} else {\n  // --- TR\u01af\u1edcNG H\u1ee2P 3: KH\u00d4NG T\u00ccM TH\u1ea4Y S\u1ea2N PH\u1ea8M ---\n  finalMessage = \"D\u1ea1, hi\u1ec7n t\u1ea1i em ch\u01b0a t\u00ecm th\u1ea5y s\u1ea3n ph\u1ea9m n\u00e0o \u0111\u00fang \u00fd anh/ch\u1ecb r\u1ed3i \u1ea1. Anh/ch\u1ecb th\u1eed t\u00ecm v\u1edbi t\u1eeb kh\u00f3a kh\u00e1c ho\u1eb7c m\u00f4 t\u1ea3 chi ti\u1ebft h\u01a1n (v\u00ed d\u1ee5: '\u00e1o thun \u0111en cotton') \u0111\u1ec3 em h\u1ed7 tr\u1ee3 nh\u00e9!\";\n}\n\n// 5. C\u1ee7ng c\u1ed1 d\u1eef li\u1ec7u b\u1ed5 tr\u1ee3 (\u1ea2nh/Link)\nif (imageUrls.length === 0 && hasProducts) {\n  const firstThumb = inputData.items[0].thumbnail || inputData.items[0].anh_dai_dien;\n  if (firstThumb) imageUrls.push(firstThumb);\n}\n\nif (!productLink && hasProducts) {\n  productLink = inputData.items[0].product_url || null;\n}\n\n// 6. Tr\u1ea3 v\u1ec1 k\u1ebft qu\u1ea3 cu\u1ed1i c\u00f9ng\nreturn {\n  json: {\n    message: finalMessage.trim(),\n    type: !hasProducts ? \"No_Data\" : \"Success\",\n    queryType: inputData.queryType || 'product_search',\n    imageUrl: imageUrls[0] || null,\n    imageUrls: imageUrls.slice(0, 5),\n    productLink: productLink\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2208,
        256
      ],
      "id": "3a5d5f77-c69d-4887-b0ae-8fb1d7f96440",
      "name": "Code format final"
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Webhook').first().json.body.userId }}",
        "collectionName": "history_chat_memory",
        "databaseName": "n8n_anreal"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryMongoDbChat",
      "typeVersion": 1,
      "position": [
        544,
        640
      ],
      "id": "cd32a18d-15dc-44e2-a530-89a5e4e1ca5c",
      "name": "MongoDB Chat Memory",
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Webhook').first().json.body.userId }}",
        "collectionName": "history_chat_format",
        "databaseName": "n8n_anreal"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryMongoDbChat",
      "typeVersion": 1,
      "position": [
        1984,
        544
      ],
      "id": "a0cd708a-b4a6-487a-af1c-58e6e64ff6e3",
      "name": "MongoDB Chat Memory Format",
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "modelName": "models/gemini-2.5-flash-lite",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1264,
        64
      ],
      "id": "f10787de-a25f-4e0e-bb3f-f08dcd90d92b",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "={{ $json.output.sql_query }}",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1216,
        320
      ],
      "id": "73be8412-4e56-498f-9267-7d02eb017db6",
      "name": "Execute a SQL query1",
      "alwaysOutputData": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent Classifier",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent Classifier": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "Execute a SQL query1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format for Greeting",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format for NotFashion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "AI Agent Classifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format for Greeting": {
      "main": [
        [
          {
            "node": "Respond for Greeting",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format for NotFashion": {
      "main": [
        [
          {
            "node": "Respond for NotFashion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent Format": {
      "main": [
        [
          {
            "node": "Code format final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format data": {
      "main": [
        [
          {
            "node": "AI Agent Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code format final": {
      "main": [
        [
          {
            "node": "Respond to Normal Question",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MongoDB Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent Classifier",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "MongoDB Chat Memory Format": {
      "ai_memory": [
        [
          {
            "node": "AI Agent Format",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent Classifier",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Agent Format",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Execute a SQL query1": {
      "main": [
        [
          {
            "node": "Format data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "f64a21f4-ab01-479d-a415-b8195a4bbe5e",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "qmnSWhTO2CUO8P-tkn_kd",
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

TTCM CNM. Uses outputParserStructured, agent, toolWorkflow, memoryMongoDbChat. Webhook trigger; 18 nodes.

Source: https://github.com/haiemdavang/AnrealShop-backend/blob/63eecaec03f1e5b3283935e10ba55f766b256fb8/n8n_chatbox/chatbox_v7.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Are you drowning in daily operational chaos, desperately trying to juggle sales, projects, content, and client communication? Imagine an AI brain that handles it all, freeing you to lead your business

Telegram Trigger, Telegram, OpenAI +13
AI & RAG

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14
AI & RAG

secretaria. Uses postgres, n8n-nodes-evolution-api, openAi, httpRequest. Webhook trigger; 71 nodes.

Postgres, N8N Nodes Evolution Api, OpenAI +12
AI & RAG

LineOA. Uses httpRequest, agent, lmChatGoogleGemini, outputParserStructured. Webhook trigger; 69 nodes.

HTTP Request, Agent, Google Gemini Chat +3
AI & RAG

This workflow is an AI-powered Dental Appointment Assistant that automates appointment booking, rescheduling, and cancellations through Telegram or a Webhook. It uses intelligent agents to understand

Memory Buffer Window, Output Parser Structured, Mcp Client Tool +12