{
  "id": "t0pM31b82LN8h8EX",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Recipe Generator for Telegram (from Image or Text)",
  "tags": [],
  "nodes": [
    {
      "id": "if_node_001",
      "name": "Check Input Type",
      "type": "n8n-nodes-base.if",
      "position": [
        400,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition_001",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.message.text }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ai_agent_vision_001",
      "name": "AI Vision Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        704,
        -128
      ],
      "parameters": {
        "text": "=Please analyze this food image and identify all visible ingredients. List them clearly.\n\nImage URL: {{ $json.body.events[0].message.id }}",
        "options": {
          "systemMessage": "=You are a food ingredient identification expert. Analyze food images and identify all visible ingredients accurately. Return a structured list of ingredients."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "openai_vision_model_001",
      "name": "OpenAI Vision Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        672,
        16
      ],
      "parameters": {
        "model": "openai/gpt-4-vision-preview",
        "options": {
          "temperature": 0.3
        }
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "output_parser_001",
      "name": "Ingredient Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        896,
        16
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"ingredients\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"description\": \"List of identified ingredients\"\n    }\n  },\n  \"required\": [\"ingredients\"]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "set_ingredients_001",
      "name": "Format Ingredients",
      "type": "n8n-nodes-base.set",
      "position": [
        1088,
        -128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assignment_001",
              "name": "ingredients_text",
              "type": "string",
              "value": "={{ $json.output.ingredients.join(', ') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "set_text_ingredients_001",
      "name": "Get Text Ingredients",
      "type": "n8n-nodes-base.set",
      "position": [
        688,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assignment_002",
              "name": "ingredients_text",
              "type": "string",
              "value": "={{ $json.message.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "recipe_generator_001",
      "name": "Recipe Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1264,
        144
      ],
      "parameters": {
        "text": "=Based on these ingredients: {{ $json.ingredients_text }}\n\nPlease suggest 3 delicious recipes that can be made with these ingredients. Consider both Japanese and international cuisine options. Text is Japanese.",
        "options": {
          "systemMessage": "You are a professional chef and recipe expert. Create detailed, easy-to-follow recipes based on available ingredients. Include both traditional Japanese dishes and international cuisine. Always provide cooking time, difficulty level, and step-by-step instructions."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "openai_recipe_model_001",
      "name": "OpenAI Recipe Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1264,
        320
      ],
      "parameters": {
        "model": "openai/gpt-4o-mini",
        "options": {
          "temperature": 0.7
        }
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "recipe_parser_001",
      "name": "Recipe Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1456,
        320
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"recipes\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"type\": \"string\",\n            \"description\": \"Recipe name\"\n          },\n          \"cuisine\": {\n            \"type\": \"string\",\n            \"description\": \"Cuisine type (e.g., Japanese, Italian)\"\n          },\n          \"difficulty\": {\n            \"type\": \"string\",\n            \"description\": \"Difficulty level (Easy, Medium, Hard)\"\n          },\n          \"cookingTime\": {\n            \"type\": \"string\",\n            \"description\": \"Total cooking time\"\n          },\n          \"servings\": {\n            \"type\": \"number\",\n            \"description\": \"Number of servings\"\n          },\n          \"ingredients\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"string\"\n            },\n            \"description\": \"Full ingredient list with quantities\"\n          },\n          \"instructions\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"string\"\n            },\n            \"description\": \"Step-by-step cooking instructions\"\n          }\n        },\n        \"required\": [\"name\", \"cuisine\", \"difficulty\", \"cookingTime\", \"servings\", \"ingredients\", \"instructions\"]\n      },\n      \"description\": \"Array of recipe suggestions\"\n    }\n  },\n  \"required\": [\"recipes\"]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "format_response_001",
      "name": "Format Response",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "response_004",
              "name": "message",
              "type": "string",
              "value": "={{\n(() => {\n  return $json.output.recipes.map((r, index) => {\n    return (\n      `\ud83d\udcd6 \u30ec\u30b7\u30d4${index + 1}\uff1a${r.name}\\n` +\n      `\ud83c\udf10 \u30b8\u30e3\u30f3\u30eb\uff1a${r.cuisine}\\n` +\n      `\u23f1 \u8abf\u7406\u6642\u9593\uff1a${r.cookingTime}\\n` +\n      `\ud83c\udf9a \u96e3\u6613\u5ea6\uff1a${r.difficulty}\\n` +\n      `\ud83d\udc65 \u76ee\u5b89\u4eba\u6570\uff1a${r.servings}\u4eba\u5206\\n\\n` +\n      `\ud83d\uded2 \u6750\u6599:\\n${r.ingredients.map(i => `- ${i}`).join(\"\\n\")}\\n\\n` +\n      `\ud83d\udc63 \u624b\u9806:\\n${r.instructions.map((step, i) => `${i + 1}. ${step}`).join(\"\\n\")}`\n    );\n  }).join(\"\\n\\n------------------------\\n\\n\");\n})()\n}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "684b387e-b22d-47a2-8db3-5367850fa33d",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        176,
        -16
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {
          "download": true
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "812b9b19-c320-4a6b-a28f-7bf80a7863bd",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1872,
        144
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a9e0f1b2-c3d4-e5f6-a7b8-c9d0e1f2a3b4",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -320
      ],
      "parameters": {
        "color": 6,
        "width": 500,
        "height": 260,
        "content": "### Phase 1: User Input via Telegram\n\n-   **Telegram Trigger**: Starts the workflow when a user sends a message or image.\n\n-   **Check Input Type**: This crucial IF node checks if the message contains text. If not, it assumes an image was sent and routes the flow to the Vision AI path. This allows the workflow to handle both input types."
      },
      "typeVersion": 1
    },
    {
      "id": "b1c2d3e4-f5a6-b7c8-d9e0-f1a2b3c4d5e6",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -448
      ],
      "parameters": {
        "color": 3,
        "width": 500,
        "height": 380,
        "content": "### Phase 2: Ingredient Extraction (Dual Path)\nThis section's goal is to create a standardized list of ingredients for the next phase.\n\n-   **Image Path (Top)**: The `AI Vision Agent` analyzes the photo to identify ingredients. The `Ingredient Parser` then structures this into a clean list, and `Format Ingredients` converts it to a comma-separated string.\n\n-   **Text Path (Bottom)**: The `Get Text Ingredients` node simply takes the user's text directly."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-a7b8-c9d0-e1f2-a3b4c5d6e7f8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        -192
      ],
      "parameters": {
        "color": 5,
        "width": 500,
        "height": 360,
        "content": "### Phase 3: AI Recipe Generation\n\n-   **Recipe Generator**: This is the main creative AI. It takes the standardized ingredient list (from either path) and acts as a professional chef to generate 3 detailed recipes.\n\n-   **Recipe Parser**: This is critical for reliability. It forces the AI's creative output into a structured JSON format (name, difficulty, instructions, etc.). This ensures the data is clean and predictable for the final formatting step."
      },
      "typeVersion": 1
    },
    {
      "id": "d5e6f7a8-b9c0-d1e2-f3a4-b5c6d7e8f9a0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1648,
        -128
      ],
      "parameters": {
        "color": 4,
        "width": 500,
        "height": 280,
        "content": "### Phase 4: Format & Send Response\n\n-   **Format Response**: This node uses a JavaScript expression to transform the structured recipe JSON from the parser into a beautiful, emoji-rich, and easy-to-read message for the user.\n\n-   **Send a text message**: The final, formatted text is sent back to the user on Telegram."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "timezone": "Asia/Tokyo",
    "errorWorkflow": "",
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "versionId": "30c406be-b5d8-4ba8-873f-8ae990fdbcb9",
  "connections": {
    "Recipe Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Recipe Generator",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Vision Agent": {
      "main": [
        [
          {
            "node": "Format Ingredients",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Response": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Input Type": {
      "main": [
        [
          {
            "node": "AI Vision Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Text Ingredients",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recipe Generator": {
      "main": [
        [
          {
            "node": "Format Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Check Input Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ingredient Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Vision Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Format Ingredients": {
      "main": [
        [
          {
            "node": "Recipe Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Recipe Model": {
      "ai_languageModel": [
        [
          {
            "node": "Recipe Generator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Vision Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Vision Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Text Ingredients": {
      "main": [
        [
          {
            "node": "Recipe Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}