[模板] - 仪表板聊天
高级
这是一个自动化工作流,包含 30 个节点。主要使用 N8n、Set、Code、Merge、Webhook 等节点。 AI模型使用仪表板:追踪LLM工作流的令牌指标和成本
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •OpenAI API Key
使用的节点 (30 个)
分类
未分类
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "Yu2P4qvlbmpPT3mg",
"meta": {
"instanceId": "b35269c8495db354f1459fb10ec8f343e34cd6c71fb24a004bb668ccda72b4e6",
"templateCredsSetupCompleted": true
},
"name": "[模板] - 仪表板聊天",
"tags": [],
"nodes": [
{
"id": "85c930e9-cb8a-47ad-8082-5ae97c945b4b",
"name": "当收到聊天消息时",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-320,
1264
],
"webhookId": "09b95814-ef46-410f-adfb-7ef2683d499d",
"parameters": {
"public": true,
"options": {}
},
"typeVersion": 1.3
},
{
"id": "cbd8fb15-5cf0-4993-a5f5-c732496c3efe",
"name": "AI 代理",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-96,
1264
],
"parameters": {
"text": "=Réponds à ce message : \n{{ $json.chatInput }}\n",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "e0decd9d-dc72-4283-815b-08f79b1b33b9",
"name": "简单记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-48,
1456
],
"parameters": {},
"typeVersion": 1.3
},
{
"id": "522553ba-e4eb-42d9-ae80-d6de88577792",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
1648
],
"parameters": {
"color": 3,
"width": 1968,
"height": 464,
"content": "## 🧠 迷你工作流 — 令牌追踪"
},
"typeVersion": 1
},
{
"id": "0f270c23-7f82-49b4-8bbb-4362d12fcd60",
"name": "OpenAI 聊天模型",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-224,
1456
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Eyt0iPqZCLeZxqlC",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "d36b0ff3-8367-4790-ae92-141df8205be1",
"name": "获取执行ID",
"type": "n8n-nodes-base.set",
"position": [
272,
1440
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "3677fb1a-e0b3-4468-bd10-6250ee768329",
"name": "id",
"type": "string",
"value": "={{$execution.id}}"
},
{
"id": "44775e78-8260-4316-a358-39b8b941313e",
"name": "model",
"type": "string",
"value": "={{$('OpenAI Chat Model').params.model}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6f390583-909a-4ecd-822e-12feb703ff30",
"name": "模型/令牌信息",
"type": "n8n-nodes-base.set",
"position": [
576,
1872
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "701dd054-2196-489d-8c9c-05d802ddf0d9",
"name": "model_name",
"type": "string",
"value": "={{ $('OpenAI Chat Model').params.model.value }}"
},
{
"id": "4ec60898-644f-46c4-9b14-a306c64c2da9",
"name": "completionTokens",
"type": "number",
"value": "={{ $json.data.resultData.runData['OpenAI Chat Model'][0].data.ai_languageModel[0][0].json.tokenUsage.completionTokens }}"
},
{
"id": "10c28ae4-4618-48c9-9787-63acd3fe66b3",
"name": "promptTokens",
"type": "number",
"value": "={{ $json.data.resultData.runData['OpenAI Chat Model'][0].data.ai_languageModel[0][0].json.tokenUsage.promptTokens }}"
},
{
"id": "41d5534d-dc94-4751-a233-446b039c3a43",
"name": "totalTokens",
"type": "number",
"value": "={{ $json.data.resultData.runData['OpenAI Chat Model'][0].data.ai_languageModel[0][0].json.tokenUsage.totalTokens }}"
},
{
"id": "ec0edb07-dabe-44fd-93df-a901838472c8",
"name": "executionId",
"type": "string",
"value": "={{ $json.id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a47a978e-c1aa-4f98-89b4-e25294ff9d63",
"name": "插入行2",
"type": "n8n-nodes-base.dataTable",
"position": [
496,
1440
],
"parameters": {
"columns": {
"value": {
"action": "={{ $('When chat message received').item.json.action }}",
"output": "={{ $('AI Agent').item.json.output }}",
"chatInput": "={{ $('When chat message received').item.json.chatInput }}",
"sessionId": "={{ $('When chat message received').item.json.sessionId }}",
"executionId": "={{ $json.id }}"
},
"schema": [
{
"id": "sessionId",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sessionId",
"defaultMatch": false
},
{
"id": "action",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "action",
"defaultMatch": false
},
{
"id": "output",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "output",
"defaultMatch": false
},
{
"id": "chatInput",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "chatInput",
"defaultMatch": false
},
{
"id": "completionTokens",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "completionTokens",
"defaultMatch": false
},
{
"id": "promptTokens",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "promptTokens",
"defaultMatch": false
},
{
"id": "totalTokens",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "totalTokens",
"defaultMatch": false
},
{
"id": "globalCost",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "globalCost",
"defaultMatch": false
},
{
"id": "modelName",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "modelName",
"defaultMatch": false
},
{
"id": "executionId",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "executionId",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "GyHAqQLTtmZbynYI",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/GyHAqQLTtmZbynYI",
"cachedResultName": "Template - data"
}
},
"typeVersion": 1
},
{
"id": "7b0b70b9-5b36-4e36-b811-da21af4dbaae",
"name": "获取执行记录",
"type": "n8n-nodes-base.n8n",
"position": [
352,
1872
],
"parameters": {
"options": {
"activeWorkflows": true
},
"resource": "execution",
"operation": "get",
"executionId": "={{ $json.executionId }}",
"requestOptions": {}
},
"credentials": {
"n8nApi": {
"id": "sqvLt8TzAknSm5NM",
"name": "n8n account 2"
}
},
"typeVersion": 1
},
{
"id": "cdd04485-cdbc-4015-85a1-fdd5c359f4f4",
"name": "由 Github 模型提供支持",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-320,
1872
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 30
}
]
}
},
"typeVersion": 1.2
},
{
"id": "6552176e-15d3-4886-b8b8-f463d0c49e08",
"name": "获取行数据",
"type": "n8n-nodes-base.dataTable",
"position": [
-96,
1872
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "modelName",
"condition": "isEmpty"
}
]
},
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "GyHAqQLTtmZbynYI",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/GyHAqQLTtmZbynYI",
"cachedResultName": "Template - data"
}
},
"typeVersion": 1
},
{
"id": "ca373635-6cc4-44e1-b4f5-d44ed3d487b1",
"name": "更新行数据",
"type": "n8n-nodes-base.dataTable",
"position": [
1376,
1856
],
"parameters": {
"columns": {
"value": {
"modelName": "={{ $json.model_name }}",
"globalCost": "={{ $json.globalCost }}",
"totalTokens": "={{ $json.promptTokens }}",
"promptTokens": "={{ $json.promptTokens }}",
"completionTokens": "={{ $json.completionTokens }}"
},
"schema": [
{
"id": "sessionId",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "sessionId",
"defaultMatch": false
},
{
"id": "action",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "action",
"defaultMatch": false
},
{
"id": "output",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "output",
"defaultMatch": false
},
{
"id": "chatInput",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "chatInput",
"defaultMatch": false
},
{
"id": "completionTokens",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "completionTokens",
"defaultMatch": false
},
{
"id": "promptTokens",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "promptTokens",
"defaultMatch": false
},
{
"id": "totalTokens",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "totalTokens",
"defaultMatch": false
},
{
"id": "globalCost",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "globalCost",
"defaultMatch": false
},
{
"id": "modelName",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "modelName",
"defaultMatch": false
},
{
"id": "executionId",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "executionId",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"filters": {
"conditions": [
{
"keyName": "executionId",
"keyValue": "={{ $json.executionId }}"
}
]
},
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "GyHAqQLTtmZbynYI",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/GyHAqQLTtmZbynYI",
"cachedResultName": "Template - data"
}
},
"typeVersion": 1
},
{
"id": "63788429-3fd4-423d-8b29-6b8d4101720e",
"name": "编辑字段",
"type": "n8n-nodes-base.set",
"position": [
-128,
992
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "95f26c22-8da0-4d86-91f5-ee633cc72e98",
"name": "today",
"type": "string",
"value": "={{ $today }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a3372fa9-18a2-4152-891d-2e40faf0b31f",
"name": "插入行1",
"type": "n8n-nodes-base.dataTable",
"position": [
-304,
2256
],
"parameters": {
"columns": {
"value": {
"name": "={{ $json.name }}",
"promptTokensPrice": "={{ $json.promptTokensPrice }}",
"completionTokensPrice": "={{ $json.completionTokensPrice }}"
},
"schema": [
{
"id": "name",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "name",
"defaultMatch": false
},
{
"id": "promptTokensPrice",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "promptTokensPrice",
"defaultMatch": false
},
{
"id": "completionTokensPrice",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "completionTokensPrice",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "5tsC5vulvGwYGS2g",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/5tsC5vulvGwYGS2g",
"cachedResultName": "Model - Price"
}
},
"typeVersion": 1
},
{
"id": "a61ae8a0-85a6-4e1f-b3ec-8f4248839816",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
2144
],
"parameters": {
"color": 5,
"width": 544,
"height": 272,
"content": "## 📊 n8n的LLM定价表"
},
"typeVersion": 1
},
{
"id": "c89ef6c5-8b35-45d3-8e21-b54125323bee",
"name": "获取行数据1",
"type": "n8n-nodes-base.dataTable",
"position": [
80,
992
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "GyHAqQLTtmZbynYI",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/GyHAqQLTtmZbynYI",
"cachedResultName": "Template - data"
}
},
"typeVersion": 1
},
{
"id": "9f4069e9-1d31-455c-9d4c-782ff0857ba0",
"name": "编辑字段1",
"type": "n8n-nodes-base.set",
"position": [
-80,
2256
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f52f1004-3bed-448b-9655-b6c61d238f57",
"name": "",
"type": "string",
"value": ""
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c3c21917-4e60-4545-b524-2f5bb28789bf",
"name": "遍历项目",
"type": "n8n-nodes-base.splitInBatches",
"position": [
128,
1872
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "451c7483-b793-47d9-869b-695bea8771ab",
"name": "无操作,什么都不做",
"type": "n8n-nodes-base.noOp",
"position": [
352,
1680
],
"parameters": {},
"typeVersion": 1
},
{
"id": "e9c3fa27-22b9-42f5-bf51-e51f78abbe94",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
912
],
"parameters": {
"color": 6,
"width": 1152,
"height": 256,
"content": "## 生成仪表板"
},
"typeVersion": 1
},
{
"id": "a92b9155-33e0-4d53-8e48-7d6ccd48a433",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-320,
992
],
"webhookId": "176f23d4-71b3-41e0-9364-43bea6be01d3",
"parameters": {
"path": "176f23d4-71b3-41e0-9364-43bea6be01d3",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "3ce8907e-c978-4769-942a-806cd7182351",
"name": "获取行数据3",
"type": "n8n-nodes-base.dataTable",
"position": [
784,
1744
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "5tsC5vulvGwYGS2g",
"cachedResultUrl": "/projects/E58XbkoO8SgET2Sl/datatables/5tsC5vulvGwYGS2g",
"cachedResultName": "Model - Price"
}
},
"typeVersion": 1
},
{
"id": "0d493cb2-d367-4eb7-968e-1b05e8e0dee5",
"name": "合并1",
"type": "n8n-nodes-base.merge",
"position": [
944,
1856
],
"parameters": {
"mode": "combine",
"options": {},
"advanced": true,
"mergeByFields": {
"values": [
{
"field1": "name",
"field2": "model_name"
}
]
}
},
"typeVersion": 3.2
},
{
"id": "4f7b3e8e-8b1b-4ccc-af0f-2371ca846d95",
"name": "JavaScript代码1",
"type": "n8n-nodes-base.code",
"position": [
1152,
1856
],
"parameters": {
"jsCode": "// Parcours tous les items reçus\nreturn items.map(item => {\n // Récupération des valeurs depuis l'item\n const completionTokens = item.json.completionTokens || 0;\n const promptTokens = item.json.promptTokens || 0;\n const completionTokensPrice = item.json.completionTokensPrice || 0;\n const promptTokensPrice = item.json.promptTokensPrice || 0;\n\n // Calcul du coût global\n const globalCost = (completionTokens * completionTokensPrice) + (promptTokens * promptTokensPrice);\n\n // Retourner l'item avec globalCost ajouté\n return {\n json: {\n ...item.json,\n globalCost\n }\n };\n});\n"
},
"typeVersion": 2
},
{
"id": "a5c21eed-3dcf-4a38-a341-d8bc42aaaf22",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
1200
],
"parameters": {
"color": 4,
"width": 1104,
"height": 416,
"content": "## 聊天示例:"
},
"typeVersion": 1
},
{
"id": "07c09e80-88a2-443b-bd8a-59db83d8c0a1",
"name": "无操作,不执行任何操作1",
"type": "n8n-nodes-base.noOp",
"position": [
272,
1264
],
"parameters": {},
"typeVersion": 1
},
{
"id": "10c02d77-5179-44a5-a219-213921b41377",
"name": "JavaScript代码",
"type": "n8n-nodes-base.code",
"position": [
288,
992
],
"parameters": {
"jsCode": "// === Calcul des KPI pour les conversations ===\nlet totalConversations = 0;\nlet totalCompletionTokens = 0;\nlet totalPromptTokens = 0;\nlet totalTokens = 0;\nlet totalCost = 0;\nlet sessions = new Set();\nlet modelUsage = {};\nlet conversationsParJour = [];\n\nfor (const item of items) {\n const data = item.json;\n\n totalConversations += 1;\n totalCompletionTokens += data.completionTokens || 0;\n totalPromptTokens += data.promptTokens || 0;\n totalTokens += data.totalTokens || 0;\n\n // Calcul du coût global si absent\n let globalCost = data.globalCost;\n if (globalCost === null || globalCost === undefined) {\n const completionTokensPrice = data.completionTokensPrice || 0;\n const promptTokensPrice = data.promptTokensPrice || 0;\n globalCost = (data.completionTokens || 0) * completionTokensPrice + (data.promptTokens || 0) * promptTokensPrice;\n }\n totalCost += globalCost;\n\n // Comptage des sessions uniques\n if (data.sessionId) sessions.add(data.sessionId);\n\n // Comptage messages par modèle\n const model = data.modelName || \"unknown\";\n if (!modelUsage[model]) modelUsage[model] = 0;\n modelUsage[model] += 1;\n\n // Tableau journalier\n if (data.createdAt) {\n const day = data.createdAt.split(\"T\")[0];\n let dayEntry = conversationsParJour.find(d => d.date === day);\n if (!dayEntry) {\n dayEntry = { date: day, count: 0, totalCost: 0, promptTokens: 0, completionTokens: 0 };\n conversationsParJour.push(dayEntry);\n }\n dayEntry.count += 1;\n dayEntry.totalCost += globalCost;\n dayEntry.promptTokens += data.promptTokens || 0;\n dayEntry.completionTokens += data.completionTokens || 0;\n }\n}\n\n// Tri par date\nconversationsParJour = conversationsParJour.sort((a, b) => a.date.localeCompare(b.date));\n\n// Moyennes\nconst avgTokensPerConversation = totalConversations > 0 ? (totalTokens / totalConversations).toFixed(2) : 0;\nconst avgCostPerConversation = totalConversations > 0 ? (totalCost / totalConversations).toFixed(6) : 0;\n\n// === Génération HTML ===\nconst html = `\n<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Dashboard Conversations</title>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\">\n<style>\n:root {\n --radius: 0.65rem;\n --background: #ffffff;\n --foreground: #000000;\n --card: #f8f9fa;\n --card-foreground: #000000;\n --primary: #3b82f6;\n --chart-conversations: #3b82f6;\n --chart-tokens-prompt: #3b82f6;\n --chart-tokens-completion: #10b981;\n --destructive: #ef4444;\n --muted: #9ca3af;\n --border: #e5e7eb;\n}\nbody.dark {\n --background: #0b142c;\n --foreground: #f1f5f9;\n --card: #1e293b;\n --card-foreground: #f1f5f9;\n --primary: #60a5fa;\n --chart-conversations: #60a5fa;\n --chart-tokens-prompt: #60a5fa;\n --chart-tokens-completion: #34d399;\n --destructive: #f87171;\n --muted: #64748b;\n --border: #334155;\n}\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n\n body {\n background: var(--background);\n color: var(--foreground);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n padding: 20px;\n transition: background-color 0.3s ease, color 0.3s ease;\n }\n\n .container {\n max-width: 1400px;\n margin: 0 auto;\n }\n\n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 40px;\n }\n\n .header h1 {\n font-size: 2.5rem;\n font-weight: 700;\n }\n\n .section-title-header {\n font-size: 2.5rem;\n font-weight: 600;\n margin-top: 40px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .section-title-header i {\n color: var(--chart-topup);\n font-size: 2.5rem;\n }\n\n .section-title {\n font-size: 1.5rem;\n font-weight: 600;\n margin-top: 40px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .section-title i {\n color: var(--primary);\n font-size: 1.75rem;\n }\n\n .kpi-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1rem;\n margin-bottom: 30px;\n }\n\n .kpi-card {\n background: var(--card);\n border-radius: 0.625rem;\n padding: 20px;\n border: 1px solid var(--border);\n transition: background-color 0.3s ease, border-color 0.3s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n\n .kpi-value {\n font-size: 2rem;\n font-weight: 700;\n margin-bottom: 8px;\n color: var(--card-foreground);\n transition: color 0.3s ease;\n }\n\n .kpi-positive {\n color: var(--chart-investment);\n }\n\n .kpi-negative {\n color: var(--destructive);\n }\n\n .kpi-label {\n font-size: 0.875rem;\n color: var(--muted-foreground);\n transition: color 0.3s ease;\n }\n\n .charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n }\n\n .chart-container {\n background: var(--card);\n border-radius: 0.625rem;\n padding: 20px;\n border: 1px solid var(--border);\n transition: background-color 0.3s ease, border-color 0.3s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n position: relative;\n height: 400px;\n }\n\n .chart-wrapper {\n position: relative;\n height: 100%;\n }\n\n .theme-toggle {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n user-select: none;\n }\n\n .toggle-switch {\n width: 48px;\n height: 24px;\n background: var(--border);\n border-radius: 12px;\n position: relative;\n cursor: pointer;\n transition: background-color 0.3s ease;\n }\n\n .toggle-switch::after {\n content: '';\n position: absolute;\n width: 20px;\n height: 20px;\n background: var(--card);\n border-radius: 50%;\n top: 2px;\n left: 2px;\n transition: transform 0.3s ease;\n box-shadow: 0 1px 3px rgba(0,0,0,0.3);\n }\n\n body.dark .toggle-switch::after {\n transform: translateX(24px);\n }\n\n @media (max-width: 768px) {\n .kpi-grid {\n grid-template-columns: 1fr;\n }\n .charts-grid {\n grid-template-columns: 1fr;\n }\n .header {\n flex-direction: column;\n gap: 20px;\n }\n }\n\n</style>\n</head>\n<body class=\"dark\">\n<div class=\"container\">\n <div class=\"header\">\n <h1><i class=\"fas fa-comments\"></i> Dashboard Conversations</h1>\n <div class=\"theme-toggle\" onclick=\"toggleTheme()\">\n <span>🌙</span>\n <div class=\"toggle-switch\"></div>\n <span>☀️</span>\n </div>\n </div>\n\n <div class=\"section-title\"><i class=\"fas fa-wallet\"></i> Statistiques Clés</div>\n <div class=\"kpi-grid\">\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-positive\">${totalConversations.toLocaleString('fr-FR')}</div>\n <div class=\"kpi-label\">Total Messages</div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-positive\">${sessions.size.toLocaleString('fr-FR')}</div>\n <div class=\"kpi-label\">Sessions uniques</div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-positive\">${totalTokens.toLocaleString('fr-FR')}</div>\n <div class=\"kpi-label\">Total Tokens</div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-positive\">${avgTokensPerConversation}</div>\n <div class=\"kpi-label\">Tokens moyens par message</div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-negative\">${totalCost.toFixed(6)} €</div>\n <div class=\"kpi-label\">Coût total</div>\n </div>\n <div class=\"kpi-card\">\n <div class=\"kpi-value kpi-negative\">${avgCostPerConversation} €</div>\n <div class=\"kpi-label\">Coût moyen par message</div>\n </div>\n </div>\n\n <div class=\"section-title\"><i class=\"fas fa-chart-bar\"></i> Historique Journalier</div>\n <div class=\"charts-grid\">\n <div class=\"chart-container\"><div class=\"chart-wrapper\"><canvas id=\"conversationsChart\"></canvas></div></div>\n <div class=\"chart-container\"><div class=\"chart-wrapper\"><canvas id=\"tokensChart\"></canvas></div></div>\n </div>\n</div>\n\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js\"></script>\n<script>\nconst conversationsParJour = ${JSON.stringify(conversationsParJour)};\n\nlet charts = {};\n\nfunction getCSSVariable(varName){return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();}\nfunction getThemeColors(){const isDark=document.body.classList.contains('dark'); return {textPrimary:isDark?'#f1f5f9':'#000', textSecondary:isDark?'#94a3b8':'#6b7280', gridColor:isDark?'rgba(148,163,184,0.1)':'rgba(0,0,0,0.1)', borderColor:isDark?'#475569':'#d1d5db', tooltip:isDark?'rgba(15,23,42,0.9)':'rgba(0,0,0,0.9)', chartColor:getCSSVariable('--chart-conversations'), chartPrompt:getCSSVariable('--chart-tokens-prompt'), chartCompletion:getCSSVariable('--chart-tokens-completion')}};\n\nfunction createChartOptions(label){\n const colors=getThemeColors();\n return {responsive:true, maintainAspectRatio:false, plugins:{title:{display:true,text:label,color:colors.textPrimary,font:{size:16,weight:'bold'},padding:20},legend:{display:true,position:'top'},tooltip:{backgroundColor:colors.tooltip,titleColor:'#ffffff',bodyColor:'#ffffff',borderColor:colors.borderColor,borderWidth:1,padding:12,displayColors:true}}, scales:{x:{grid:{display:true,color:colors.gridColor,drawBorder:false},ticks:{color:colors.textSecondary,font:{size:11}}},y:{grid:{display:true,color:colors.gridColor,drawBorder:false},ticks:{color:colors.textSecondary,font:{size:11}},beginAtZero:true}}};\n}\n\nfunction initCharts(){\n const colors=getThemeColors();\n const ctx=document.getElementById('conversationsChart').getContext('2d');\n charts.conversations=new Chart(ctx,{type:'bar',data:{labels:conversationsParJour.map(d=>new Date(d.date).toLocaleDateString('fr-FR',{day:'2-digit',month:'2-digit'})),datasets:[{label:'Nombre de messages',data:conversationsParJour.map(d=>d.count),backgroundColor:colors.chartColor,borderColor:colors.chartColor,borderWidth:0,borderRadius:6}]},options:createChartOptions('Messages journaliers')});\n\n // Graphique tokens empilé\n const ctxTokens=document.getElementById('tokensChart').getContext('2d');\n charts.tokens=new Chart(ctxTokens,{type:'bar',data:{labels:conversationsParJour.map(d=>new Date(d.date).toLocaleDateString('fr-FR',{day:'2-digit',month:'2-digit'})),datasets:[{label:'Prompt Tokens',data:conversationsParJour.map(d=>d.promptTokens),backgroundColor:colors.chartPrompt},{label:'Completion Tokens',data:conversationsParJour.map(d=>d.completionTokens),backgroundColor:colors.chartCompletion}]},options:{...createChartOptions('Tokens utilisés par jour'),scales:{x:{stacked:true,grid:{display:true,color:colors.gridColor,drawBorder:false},ticks:{color:colors.textSecondary,font:{size:11}}},y:{stacked:true,grid:{display:true,color:colors.gridColor,drawBorder:false},ticks:{color:colors.textSecondary,font:{size:11}},beginAtZero:true}}}});\n}\n\nfunction updateChartsTheme(){\n const colors=getThemeColors();\n if(charts.conversations){\n charts.conversations.data.datasets[0].backgroundColor=colors.chartColor;\n charts.conversations.data.datasets[0].borderColor=colors.chartColor;\n charts.conversations.options.plugins.title.color=colors.textPrimary;\n charts.conversations.options.scales.x.grid.color=colors.gridColor;\n charts.conversations.options.scales.x.ticks.color=colors.textSecondary;\n charts.conversations.options.scales.y.grid.color=colors.gridColor;\n charts.conversations.options.scales.y.ticks.color=colors.textSecondary;\n charts.conversations.options.plugins.tooltip.backgroundColor=colors.tooltip;\n charts.conversations.update();\n }\n if(charts.tokens){\n charts.tokens.data.datasets[0].backgroundColor=colors.chartPrompt;\n charts.tokens.data.datasets[1].backgroundColor=colors.chartCompletion;\n charts.tokens.options.plugins.title.color=colors.textPrimary;\n charts.tokens.options.scales.x.grid.color=colors.gridColor;\n charts.tokens.options.scales.x.ticks.color=colors.textSecondary;\n charts.tokens.options.scales.y.grid.color=colors.gridColor;\n charts.tokens.options.scales.y.ticks.color=colors.textSecondary;\n charts.tokens.options.plugins.tooltip.backgroundColor=colors.tooltip;\n charts.tokens.update();\n }\n}\n\nfunction toggleTheme(){document.body.classList.toggle('dark'); updateChartsTheme();}\ndocument.addEventListener('DOMContentLoaded',initCharts);\n</script>\n</body>\n</html>\n`;\n\n// Retourner le HTML en binaire pour la node n8n\nreturn [{ binary: { data: Buffer.from(html, 'utf8') } }];\n"
},
"typeVersion": 2
},
{
"id": "63aae3c1-6479-477f-a26b-85f3d589a6bc",
"name": "响应Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
496,
992
],
"parameters": {
"options": {},
"respondWith": "binary"
},
"typeVersion": 1.4
},
{
"id": "b2f02fbb-2604-4f60-9449-6a8fa76ee670",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-976,
912
],
"parameters": {
"width": 496,
"height": 352,
"content": "## 🤖 n8n AI工作流仪表板"
},
"typeVersion": 1
},
{
"id": "19d31dbb-e89e-40c6-853d-f898ebbe1122",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-976,
1296
],
"parameters": {
"width": 496,
"height": 464,
"content": "## ⚙️ 设置与运行"
},
"typeVersion": 1
}
],
"active": true,
"pinData": {
"Edit Fields1": [
{
"json": {
"name": "claude-4.5-sonnet",
"promptTokensPrice": 0.000003,
"completionTokensPrice": 0.000015
}
},
{
"json": {
"name": "claude-4.5-sonnet-extended-context",
"promptTokensPrice": 0.000006,
"completionTokensPrice": 0.0000225
}
},
{
"json": {
"name": "gpt-5",
"promptTokensPrice": 0.00000125,
"completionTokensPrice": 0.00001
}
},
{
"json": {
"name": "gpt-5-mini",
"promptTokensPrice": 2.5e-7,
"completionTokensPrice": 0.000002
}
},
{
"json": {
"name": "gpt-5-nano",
"promptTokensPrice": 5e-8,
"completionTokensPrice": 4e-7
}
},
{
"json": {
"name": "Gemini-2.5-Pro",
"promptTokensPrice": 0.00000125,
"completionTokensPrice": 0.00000125
}
},
{
"json": {
"name": "Gemini-1.5-Flash",
"promptTokensPrice": 7.5e-7,
"completionTokensPrice": 0.000003
}
},
{
"json": {
"name": "gpt-4o",
"promptTokensPrice": 0.0000025,
"completionTokensPrice": 0.00001
}
},
{
"json": {
"name": "gpt-4o-mini",
"promptTokensPrice": 1.5e-7,
"completionTokensPrice": 6e-7
}
},
{
"json": {
"name": "gpt-4.1-mini",
"promptTokensPrice": 4e-7,
"completionTokensPrice": 0.0000016
}
},
{
"json": {
"name": "gpt-4.1-nano",
"promptTokensPrice": 1e-7,
"completionTokensPrice": 4e-7
}
},
{
"json": {
"name": "o3-mini",
"promptTokensPrice": 0.0000011,
"completionTokensPrice": 0.0000044
}
},
{
"json": {
"name": "Gemini-2.0-Flash-Lite",
"promptTokensPrice": 7.5e-8,
"completionTokensPrice": 3e-7
}
},
{
"json": {
"name": "DeepSeek-V3",
"promptTokensPrice": 2.7e-7,
"completionTokensPrice": 0.0000011
}
},
{
"json": {
"name": "Claude-3.7-Sonnet",
"promptTokensPrice": 0.000003,
"completionTokensPrice": 0.000015
}
},
{
"json": {
"name": "gpt-oss-20b",
"promptTokensPrice": 3e-8,
"completionTokensPrice": 1.4e-7
}
}
]
},
"settings": {
"executionOrder": "v1"
},
"versionId": "d1513dc9-185a-4183-bdcd-531b250483c3",
"connections": {
"Merge1": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "No Operation, do nothing1",
"type": "main",
"index": 0
},
{
"node": "Get Excution ID",
"type": "main",
"index": 0
}
]
]
},
"Get row(s)": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Get row(s)1",
"type": "main",
"index": 0
}
]
]
},
"Get row(s)1": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Get row(s)3": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 0
}
]
]
},
"Insert row1": {
"main": [
[
{
"node": "Edit Fields1",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Update row(s)": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Get Excution ID": {
"main": [
[
{
"node": "Insert row2",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
],
[
{
"node": "Get an execution",
"type": "main",
"index": 0
}
]
]
},
"Get an execution": {
"main": [
[
{
"node": "Model/Token Info",
"type": "main",
"index": 0
}
]
]
},
"Model/Token Info": {
"main": [
[
{
"node": "Get row(s)3",
"type": "main",
"index": 0
},
{
"node": "Merge1",
"type": "main",
"index": 1
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get row(s)",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "Update row(s)",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
这是一个高级难度的通用自动化工作流。适合高级用户,包含 16+ 个节点的复杂工作流
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
Other
使用 OpenAI、LangChain 和 API 集成的工作流自动化初学者指南
使用 OpenAI、LangChain 和 API 集成的工作流自动化初学者指南
If
Set
Code
+13
33 节点Meelioo
Content Creation
[模板] AI宠物店 v8
🐶 AI宠物店助手 - 集成GPT-4o、Google日历和WhatsApp/Instagram/Facebook
If
N8n
Set
+38
244 节点Amanda Benks
Sales
AI 代理餐厅 [模板]
🤖 WhatsApp、Instagram 和 Messenger 的 AI 餐厅助手
If
N8n
Set
+37
239 节点Amanda Benks
Other
AI 智能体 - 短链接生成器
使用 GPT-4.1 和数据存储生成并管理短链接
Set
Code
Html
+10
18 节点Nghia Nguyen
Miscellaneous
为 N8N 智能体/工作流创建 OpenAI 兼容 API
为多个AI工作流创建通用OpenAI兼容API端点
If
N8n
Set
+10
21 节点Dele Odufuye
工作流信息
难度等级
高级
节点数量30
分类-
节点类型15
作者
Hugo
@hugo-miseryGrowth engineer focused on AI, data automation, and custom integrations. Use to turn complex ideas into simple, and scalable workflows with solid infrastructure
外部链接
在 n8n.io 上查看 →
分享此工作流