无需结构化输出解析器即可从AI代理获得可靠的结构化输出 - 使用OpenAI和Switch节点
高级
这是一个Engineering, AI领域的自动化工作流,包含 16 个节点。主要使用 Set, Switch, Agent, ChatTrigger, LmChatOpenAi 等节点,结合人工智能技术实现智能自动化。 无需结构化输出解析器即可从AI代理获得可靠的结构化输出 - 使用OpenAI和Switch节点
前置要求
- •OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
无法加载工作流预览
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "",
"meta": {
"instanceId": ""
},
"name": "无需结构化输出解析器即可从 AI Agent 获得可靠的结构化输出 - 使用 OpenAI 和 Switch 节点",
"tags": [],
"nodes": [
{
"id": "",
"name": "AI 代理",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-400,
760
],
"parameters": {
"text": "={{ $json.chatInput }}",
"options": {
"maxIterations": 10,
"systemMessage": "=You are a helpful assistant specialized in nutrition. \nYour task is to provide accurate nutritional information for a given food item. \nYou must return your answer strictly in the form of a JSON object matching the following schema:\n\n{\n \"type\": \"object\",\n \"properties\": {\n \"alimentName\": {\n \"type\": \"string\",\n \"description\": \"The name of the food item, in English\"\n },\n \"averageCalories\": {\n \"type\": \"number\",\n \"description\": \"Average calories per 100g or standard portion (kcal)\"\n },\n \"proteins\": {\n \"type\": \"number\",\n \"description\": \"Amount of protein per 100g or portion (grams)\"\n },\n \"carbohydrates\": {\n \"type\": \"number\",\n \"description\": \"Total amount of carbohydrates per 100g or portion (grams), including fiber and sugars\"\n },\n \"sugar\": {\n \"type\": \"number\",\n \"description\": \"Amount of total sugars (subset of carbohydrates) per 100g or portion (grams)\"\n },\n \"fiber\": {\n \"type\": \"number\",\n \"description\": \"Amount of dietary fiber (subset of carbohydrates) per 100g or portion (grams)\"\n },\n \"fat\": {\n \"type\": \"number\",\n \"description\": \"Amount of fat per 100g or portion (grams)\"\n },\n \"sodium\": {\n \"type\": \"number\",\n \"description\": \"Amount of sodium per 100g or portion (milligrams)\"\n },\n \"healthyScore\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 10,\n \"description\": \"A healthiness score from 0 (very unhealthy) to 10 (very healthy), based on nutritional guidelines\"\n }\n },\n \"required\": [\n \"alimentName\",\n \"averageCalories\",\n \"proteins\",\n \"carbohydrates\",\n \"sugar\",\n \"fiber\",\n \"fat\",\n \"sodium\",\n \"healthyScore\"\n ]\n}\n\n\nIf the user input is not a valid food item, or if you are unsure whether it is a real food, then instead return:\n\n{\n \"error\": \"invalid_input\",\n \"message\": \"The provided input does not appear to be a valid food item.\"\n}\n\n----\n\n⚠️ If you fail to produce output in the correct schema, the Schema Error Prompt below will contain an error message. You will need to follow the instructions it provides:\n\n## Schema Error Prompt:\n\n{{ $json.schemaErrorPrompt }}\n\n",
"returnIntermediateSteps": true
},
"promptType": "define"
},
"executeOnce": false,
"typeVersion": 1.8
},
{
"id": "",
"name": "当收到聊天消息时",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-800,
760
],
"webhookId": "",
"parameters": {
"mode": "webhook",
"public": true,
"options": {
"responseMode": "responseNode"
},
"authentication": "basicAuth"
},
"credentials": {
"httpBasicAuth": {
"id": "",
"name": ""
}
},
"typeVersion": 1.1
},
{
"id": "",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-400,
920
],
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "=gpt-4.1-nano"
},
"options": {
"temperature": 0.8,
"responseFormat": "json_object"
}
},
"credentials": {
"openAiApi": {
"id": "",
"name": "OpenAi Connection"
}
},
"typeVersion": 1.2
},
{
"id": "",
"name": "简单记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-260,
920
],
"parameters": {},
"typeVersion": 1.3
},
{
"id": "",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
860,
760
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "invalidSchema",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.output.error !== undefined && $json.aiRunIndex < 3 }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "validSchema",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.output.alimentName }}",
"rightValue": ""
}
]
},
"renameOutput": true
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"typeVersion": 3.2
},
{
"id": "",
"name": "验证输出 + 设置 `aiRunIndex`",
"type": "n8n-nodes-base.set",
"onError": "continueRegularOutput",
"position": [
260,
760
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "",
"name": "output",
"type": "object",
"value": "={{ \n(() => {\n\tlet raw = $json.output;\n\n\tif (typeof raw === 'string') {\n\t\traw = raw\n\t\t\t.replace(/^\\s*```json/i, '')\n\t\t\t.replace(/```$/i, '')\n\t\t\t.trim();\n\t\ttry { raw = JSON.parse(raw); }\n\t\tcatch { return { error: 'invalid_json' }; }\n\t}\n\n\t// Allow alternative valid response when input is not a valid food item\n\tif (\n\t\traw.error === 'invalid_input' &&\n\t\traw.message === 'The provided input does not appear to be a valid food item.'\n\t) {\n\t\treturn JSON.stringify(raw, null, 2);\n\t}\n\n\t// Check required keys\n\tconst requiredKeys = [\n\t\t'alimentName',\n\t\t'averageCalories',\n\t\t'proteins',\n\t\t'carbohydrates',\n\t\t'sugar',\n\t\t'fiber',\n\t\t'fat',\n\t\t'sodium',\n\t\t'healthyScore'\n\t];\n\n\tfor (const key of requiredKeys) {\n\t\tif (!(key in raw)) {\n\t\t\treturn { error: 'missing_key', key };\n\t\t}\n\t}\n\n\t// Type checks\n\tif (typeof raw.alimentName !== 'string')\n\t\treturn { error: 'invalid_type', key: 'alimentName', expected: 'string' };\n\n\tif (typeof raw.averageCalories !== 'number')\n\t\treturn { error: 'invalid_type', key: 'averageCalories', expected: 'number' };\n\n\tif (typeof raw.proteins !== 'number')\n\t\treturn { error: 'invalid_type', key: 'proteins', expected: 'number' };\n\n\tif (typeof raw.carbohydrates !== 'number')\n\t\treturn { error: 'invalid_type', key: 'carbohydrates', expected: 'number' };\n\n\tif (typeof raw.sugar !== 'number')\n\t\treturn { error: 'invalid_type', key: 'sugar', expected: 'number' };\n\n\tif (typeof raw.fiber !== 'number')\n\t\treturn { error: 'invalid_type', key: 'fiber', expected: 'number' };\n\n\tif (typeof raw.fat !== 'number')\n\t\treturn { error: 'invalid_type', key: 'fat', expected: 'number' };\n\n\tif (typeof raw.sodium !== 'number')\n\t\treturn { error: 'invalid_type', key: 'sodium', expected: 'number' };\n\n\tif (typeof raw.healthyScore !== 'number')\n\t\treturn { error: 'invalid_type', key: 'healthyScore', expected: 'number' };\n\n\tif (raw.healthyScore < 0 || raw.healthyScore > 10)\n\t\treturn { error: 'invalid_range', key: 'healthyScore', expected: 'number between 0 and 10' };\n\n\t// If all checks pass, return the parsed and formatted JSON\n\treturn JSON.stringify(raw, null, 2);\n})() \n}}"
},
{
"id": "",
"name": "=aiRunIndex",
"type": "number",
"value": "={{ $node[\"AI Agent\"].runIndex }} "
}
]
}
},
"typeVersion": 3.4
},
{
"id": "",
"name": "格式化模式错误提示",
"type": "n8n-nodes-base.set",
"position": [
920,
1020
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "",
"name": "schemaErrorPrompt",
"type": "string",
"value": "=If you're seeing this message, it means your previous response did not follow the required output schema defined in your prompt:\n\n{\n \"type\": \"object\",\n \"properties\": {\n \"alimentName\": {\n \"type\": \"string\",\n \"description\": \"The name of the food item, in English\"\n },\n \"averageCalories\": {\n \"type\": \"number\",\n \"description\": \"Average calories per 100g or standard portion (kcal)\"\n },\n \"proteins\": {\n \"type\": \"number\",\n \"description\": \"Amount of protein per 100g or portion (grams)\"\n },\n \"carbohydrates\": {\n \"type\": \"number\",\n \"description\": \"Total amount of carbohydrates per 100g or portion (grams), including fiber and sugars\"\n },\n \"sugar\": {\n \"type\": \"number\",\n \"description\": \"Amount of total sugars (subset of carbohydrates) per 100g or portion (grams)\"\n },\n \"fiber\": {\n \"type\": \"number\",\n \"description\": \"Amount of dietary fiber (subset of carbohydrates) per 100g or portion (grams)\"\n },\n \"fat\": {\n \"type\": \"number\",\n \"description\": \"Amount of fat per 100g or portion (grams)\"\n },\n \"sodium\": {\n \"type\": \"number\",\n \"description\": \"Amount of sodium per 100g or portion (milligrams)\"\n },\n \"healthyScore\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 10,\n \"description\": \"A healthiness score from 0 (very unhealthy) to 10 (very healthy), based on nutritional guidelines\"\n }\n },\n \"required\": [\n \"alimentName\",\n \"averageCalories\",\n \"proteins\",\n \"carbohydrates\",\n \"sugar\",\n \"fiber\",\n \"fat\",\n \"sodium\",\n \"healthyScore\"\n ]\n}\n\n\nPlease revise your output to strictly match this structure.\n\nFor reference, the last user message was:\n{{ $('When chat message received').item.json.chatInput }}\n\nAnd your response was:\n{{ $('AI Agent').item.json.output }}\n\nThis does not conform to the expected schema. Please correct your output accordingly."
},
{
"id": "",
"name": "sessionId",
"type": "string",
"value": "={{ $('When chat message received').item.json.sessionId }}"
},
{
"id": "",
"name": "chatInput",
"type": "string",
"value": "={{ $('When chat message received').item.json.chatInput }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "",
"name": "有效模式输出",
"type": "n8n-nodes-base.set",
"position": [
1460,
760
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "",
"name": "nutritionalValues",
"type": "object",
"value": "={{ $json.output }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
600,
-260
],
"parameters": {
"color": 7,
"width": 520,
"height": 1140,
"content": "## Switch"
},
"typeVersion": 1
},
{
"id": "",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
-160
],
"parameters": {
"color": 7,
"width": 500,
"height": 1040,
"content": "## AI Agent"
},
"typeVersion": 1
},
{
"id": "",
"name": "便签 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
60,
-160
],
"parameters": {
"color": 7,
"width": 500,
"height": 1040,
"content": "## 验证输出 + 设置 `aiRunIndex`"
},
"typeVersion": 1
},
{
"id": "",
"name": "便签 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1160,
360
],
"parameters": {
"color": 7,
"width": 700,
"height": 520,
"content": "## 有效模式输出"
},
"typeVersion": 1
},
{
"id": "",
"name": "便签 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1160,
940
],
"parameters": {
"color": 7,
"width": 700,
"height": 600,
"content": "## 输出处理(有效与无效模式)"
},
"typeVersion": 1
},
{
"id": "",
"name": "设置 schemaValidationError 和 lastAgentOutput",
"type": "n8n-nodes-base.set",
"position": [
1280,
1020
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "",
"name": "schemaValidationError",
"type": "string",
"value": "={{ $('Validate Output + Set `aiRunIndex`').item.json.output }}"
},
{
"id": "",
"name": "lastAgentOutput",
"type": "string",
"value": "={{ $('AI Agent').item.json.output }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "",
"name": "设置聊天输出",
"type": "n8n-nodes-base.set",
"position": [
1640,
1020
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "",
"name": "output",
"type": "string",
"value": "=This output was sent because a schema validation error occurred:\n\n{{ $json.schemaValidationError }}\n\nHowever, here is the last AI agent response:\n\n{{ $json.lastAgentOutput }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "",
"name": "便签 5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1580,
-60
],
"parameters": {
"color": 5,
"width": 720,
"height": 940,
"content": "## 无需结构化输出解析器即可从 AI Agent 获得可靠的结构化输出 - 使用 OpenAI 和 Switch 节点"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"callerPolicy": "",
"executionOrder": "v1",
"executionTimeout": 60
},
"versionId": "",
"connections": {
"Switch": {
"main": [
[
{
"node": "Format Schema Error Prompt",
"type": "main",
"index": 0
}
],
[
{
"node": "Valid Schema Output",
"type": "main",
"index": 0
}
],
[
{
"node": "Set schemaValidationError & lastAgentOutput",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Validate Output + Set `aiRunIndex`",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Format Schema Error Prompt": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Validate Output + Set `aiRunIndex`": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Set schemaValidationError & lastAgentOutput": {
"main": [
[
{
"node": "Set chat Output",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 工程, 人工智能
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用OpenAI和Google表格轻松比较LLMs
使用Google表格并排比较不同LLM的响应
Set
Split Out
Aggregate
+9
21 节点Dataki
工程
AI智能助手:与Supabase存储和Google Drive文件对话
AI智能助手:与Supabase存储和Google Drive文件对话
If
Set
Wait
+20
62 节点Mark Shcherbakov
工程
AI智能助手与Airtable对话及数据分析
AI智能助手与Airtable对话及数据分析
If
Set
Merge
+12
41 节点Mark Shcherbakov
工程
数据分析师 Agent v3
用于电子表格的AI数据分析助手,基于NocoDB平台
Set
Noco Db Tool
Http Request
+5
10 节点Derek Cheung
工程
AI Agent:使用 OpenAI 的 Google 日历助手
AI 智能助手:基于 OpenAI 的 Google 日历助手
Agent
Google Calendar Tool
Chat Trigger
+3
13 节点Dataki
人工智能
支持文本、语音、图像和PDF的AI驱动WhatsApp聊天机器人(RAG)
支持文本、语音、图像和PDF的AI驱动WhatsApp聊天机器人(RAG)
Set
Code
Switch
+15
35 节点NovaNode
工程
工作流信息
难度等级
高级
节点数量16
分类2
节点类型7
作者
Dataki
@datakiI am passionate about transforming complex processes into seamless automations with n8n. My expertise spans across creating ETL pipelines, sales automations, and data & AI-driven workflows. As an avid problem solver, I thrive on optimizing workflows to drive efficiency and innovation.
外部链接
在 n8n.io 查看 →
分享此工作流