{
  "nodes": [
    {
      "id": "0b64edf1-57e0-4704-b78c-c8ab2b91f74d",
      "name": "When clicking \u2018Test workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        480,
        300
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a875d1c5-ccfe-4bbf-b429-56a42b0ca778",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1280,
        720
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-1.5-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a5e00543-dbaa-4e62-afb0-825ebefae3f3",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1480,
        720
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"caption_title\": \"\",\n\t\"caption_text\": \"\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "bb9af9c6-6c81-4e92-a29f-18ab3afbe327",
      "name": "Get Info",
      "type": "n8n-nodes-base.editImage",
      "position": [
        1100,
        400
      ],
      "parameters": {
        "operation": "information"
      },
      "typeVersion": 1
    },
    {
      "id": "8a0dbd5d-5886-484a-80a0-486f349a9856",
      "name": "Resize For AI",
      "type": "n8n-nodes-base.editImage",
      "position": [
        1100,
        560
      ],
      "parameters": {
        "width": 512,
        "height": 512,
        "options": {},
        "operation": "resize"
      },
      "typeVersion": 1
    },
    {
      "id": "d29f254a-5fa3-46fa-b153-19dfd8e8c6a7",
      "name": "Calculate Positioning",
      "type": "n8n-nodes-base.code",
      "position": [
        2020,
        720
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const { size, output } = $input.item.json;\n\nconst lineHeight = 35;\nconst fontSize = Math.round(size.height / lineHeight);\nconst maxLineLength = Math.round(size.width/fontSize) * 2;\nconst text = `\"${output.caption_title}\". ${output.caption_text}`;\nconst numLinesOccupied = Math.round(text.length / maxLineLength);\n\nconst verticalPadding = size.height * 0.02;\nconst horizontalPadding = size.width * 0.02;\nconst rectPosX = 0;\nconst rectPosY = size.height - (verticalPadding * 2.5) - (numLinesOccupied * fontSize);\nconst textPosX = horizontalPadding;\nconst textPosY = size.height - (numLinesOccupied * fontSize) - (verticalPadding/2);\n\nreturn {\n  caption: {\n    fontSize,\n    maxLineLength,\n    numLinesOccupied,\n    rectPosX,\n    rectPosY,\n    textPosX,\n    textPosY,\n    verticalPadding,\n    horizontalPadding,\n  }\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "12a7f2d6-8684-48a5-aa41-40a8a4f98c79",
      "name": "Apply Caption to Image",
      "type": "n8n-nodes-base.editImage",
      "position": [
        2380,
        560
      ],
      "parameters": {
        "options": {},
        "operation": "multiStep",
        "operations": {
          "operations": [
            {
              "color": "=#0000008c",
              "operation": "draw",
              "endPositionX": "={{ $json.size.width }}",
              "endPositionY": "={{ $json.size.height }}",
              "startPositionX": "={{ $json.caption.rectPosX }}",
              "startPositionY": "={{ $json.caption.rectPosY }}"
            },
            {
              "font": "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf",
              "text": "=\"{{ $json.output.caption_title }}\". {{ $json.output.caption_text }}",
              "fontSize": "={{ $json.caption.fontSize }}",
              "fontColor": "#FFFFFF",
              "operation": "text",
              "positionX": "={{ $json.caption.textPosX }}",
              "positionY": "={{ $json.caption.textPosY }}",
              "lineLength": "={{ $json.caption.maxLineLength }}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4d569ec8-04c2-4d21-96e1-86543b26892d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -120,
        80
      ],
      "parameters": {
        "width": 423.75,
        "height": 431.76353488372104,
        "content": "## \uc2dc\ub3c4\ud574 \ubcf4\uc138\uc694!\n\n### \uc774 \uc6cc\ud06c\ud50c\ub85c\ub294 \uc774\ubbf8\uc9c0\ub97c \uac00\uc838\uc640 AI\ub97c \uc0ac\uc6a9\ud558\uc5ec \ucea1\uc158\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4. OpenAI \ub178\ub4dc\ub294 \uc624\ub7ab\ub3d9\uc548 \uc774 \uc791\uc5c5\uc744 \ud560 \uc218 \uc788\uc5c8\uc9c0\ub9cc, \uc774 \uc6cc\ud06c\ud50c\ub85c\ub294 Google\uc758 Gemini\uc640 \uac19\uc740 \ub2e4\ub978 \ub2e4\uc911 \ubaa8\ub2ec \ube44\uc804 \ubaa8\ub378\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc77c\ud55c \uac83\uc744 \ub2ec\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubcf4\uc5ec\uc90d\ub2c8\ub2e4.\n\n\ub610\ud55c, Edit Image \ub178\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc0dd\uc131\ub41c \ucea1\uc158\uc744 \uc774\ubbf8\uc9c0\uc5d0 \uc624\ubc84\ub808\uc774\ud560 \uac83\uc785\ub2c8\ub2e4. \uc774\ub294 \ucd9c\ud310\ubb3c\uc5d0 \uc720\uc6a9\ud560 \uc218 \uc788\uac70\ub098 \uc800\uc791\uad8c \ubc0f/\ub610\ub294 \uc6cc\ud130\ub9c8\ud06c\ub97c \uc704\ud574 \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\n### \ub3c4\uc6c0\uc774 \ud544\uc694\ud558\uc2e0\uac00\uc694?\n[Discord](https://discord.com/invite/XPKeKXeB7d)\uc5d0 \uac00\uc785\ud558\uac70\ub098 [Forum](https://community.n8n.io/)\uc5d0\uc11c \ubb3c\uc5b4\ubcf4\uc138\uc694!"
      },
      "typeVersion": 1
    },
    {
      "id": "45d37945-5a7a-42eb-8c8c-5940ea276072",
      "name": "Merge Image & Caption",
      "type": "n8n-nodes-base.merge",
      "position": [
        1620,
        400
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3
    },
    {
      "id": "53a26842-ad56-4c8d-a59d-4f6d3f9e2407",
      "name": "Merge Caption & Positions",
      "type": "n8n-nodes-base.merge",
      "position": [
        2200,
        560
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3
    },
    {
      "id": "b6c28913-b16a-4c59-aa49-47e9bb97f86d",
      "name": "Get Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        680,
        300
      ],
      "parameters": {
        "url": "https://images.pexels.com/photos/1267338/pexels-photo-1267338.jpeg?auto=compress&cs=tinysrgb&w=600",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "6c25054d-8103-4be9-bea7-6c3dd47f49a3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        340,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 586.25,
        "height": 486.25,
        "content": "## 1. \uc774\ubbf8\uc9c0 \uac00\uc838\uc624\uae30\n\n[HTTP \uc694\uccad \ub178\ub4dc\uc5d0 \ub300\ud574 \ub354 \uc77d\uae30](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\n\uc774\ubc88 \ub370\ubaa8\ub97c \uc704\ud574, Pexels.com(\uc778\uae30 \uc788\ub294 \ubb34\ub8cc \uc2a4\ud1a1 \uc0ac\uc9c4 \uc0ac\uc774\ud2b8)\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uac00\uc838\uc624\uae30 \uc704\ud574 HTTP \uc694\uccad \ub178\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub2e4\uc6b4\ub85c\ub4dc\ud558\uaca0\uc2b5\ub2c8\ub2e4.\n\n\uc790\uc2e0\uc758 \uc6cc\ud06c\ud50c\ub85c\uc6b0\uc5d0\uc11c, \uc774\uac83\uc740 \uc6f9\ud6c4\ud06c\uc640 \uac19\uc740 \ub2e4\ub978 \ud2b8\ub9ac\uac70\ub85c \ub300\uccb4\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
      },
      "typeVersion": 1
    },
    {
      "id": "d1b708e2-31c3-4cd1-a353-678bc33d4022",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        140
      ],
      "parameters": {
        "color": 7,
        "width": 888.75,
        "height": 783.75,
        "content": "## 2. \ube44\uc804 \ubaa8\ub378\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucea1\uc158 \uc0dd\uc131\n\n[Basic LLM Chain\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc54c\uc544\ubcf4\uae30](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm)\n\nn8n\uc758 \uae30\ubcf8 LLM \ub178\ub4dc\ub294 \ud638\ud658\ub418\ub294 LLM\uc5d0 \ubcf4\ub0bc \ubc14\uc774\ub108\ub9ac\ub098 \uc774\ubbf8\uc9c0 URL\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\uac8c \ud558\uc5ec \ub2e4\uc911 \ubaa8\ub2ec \uc785\ub825\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4. \uc774\ub294 \uc2dc\uac01\uc801 \ubd84\ub958\ub098 OCR \uc791\uc5c5\uc744 \uc774\uc804\uc5d0 \ub354 \uc804\uc6a9 OCR \ubaa8\ub378\uc5d0 \uc758\uc874\ud558\ub358 \uac83\uacfc \ub2ec\ub9ac \uc774 \uac15\ub825\ud55c \uae30\ub2a5\uc744 \uc27d\uac8c \ud65c\uc6a9\ud560 \uc218 \uc788\uac8c \ud569\ub2c8\ub2e4.\n\n\uc5ec\uae30\uc11c, \uc6b0\ub9ac\ub294 \uc774\ubbf8\uc9c0 \ubc14\uc774\ub108\ub9ac\ub97c \"\uc0ac\uc6a9\uc790 \uba54\uc2dc\uc9c0\" \uc635\uc158\uc73c\ub85c \uac04\ub2e8\ud788 \uc804\ub2ec\ud558\uc5ec LLM\uc5d0\uac8c \uc8fc\uc5b4\uc9c4 \uc8fc\uc81c\uc5d0 \uc801\ud569\ud55c \ucea1\uc158 \uc81c\ubaa9\uacfc \ud14d\uc2a4\ud2b8\ub97c \uc0dd\uc131\ud558\ub3c4\ub85d \uc694\uccad\ud588\uc2b5\ub2c8\ub2e4. \uc0dd\uc131\ub41c \ud6c4, \uc774 \ud14d\uc2a4\ud2b8\ub97c \uc774\ubbf8\uc9c0\uc640 \ud568\uaed8 \uc804\ub2ec\ud558\uc5ec \ub458\uc744 \uacb0\ud569\ud560 \uac83\uc785\ub2c8\ub2e4."
      },
      "typeVersion": 1
    },
    {
      "id": "36a39871-340f-4c44-90e6-74393b9be324",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1880,
        280
      ],
      "parameters": {
        "color": 7,
        "width": 753.75,
        "height": 635,
        "content": "## 3. \uc774\ubbf8\uc9c0\uc5d0 \ucea1\uc158 \uc624\ubc84\ub808\uc774\n\n[Edit Image \ub178\ub4dc\uc5d0 \ub300\ud574 \ub354 \uc54c\uc544\ubcf4\uae30](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.editimage)\n\n\ub9c8\uce68\ub0b4, \uc0dd\uc131\ub41c \ucea1\uc158\uc744 \uc774\ubbf8\uc9c0\uc5d0 \ubc30\uce58\ud558\uae30 \uc704\ud574 \uae30\ubcf8\uc801\uc778 \uacc4\uc0b0\uc744 \uc218\ud589\ud560 \uac83\uc785\ub2c8\ub2e4. n8n\uc758 \uc0ac\uc6a9\uc790 \uce5c\ud654\uc801\uc778 \uc774\ubbf8\uc9c0 \ud3b8\uc9d1 \uae30\ub2a5 \ub355\ubd84\uc5d0, \uc774\ub294 \uc6cc\ud06c\ud50c\ub85c\uc6b0 \ub0b4\uc5d0\uc11c \uc644\uc804\ud788 \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4!\n\nCode \ub178\ub4dc \ub3c4\uad6c\ub294 \uc774\ub7ec\ud55c \uc720\ud615\uc758 \uacc4\uc0b0\uc5d0 \uc774\uc0c1\uc801\uc774\uba70, \uc774 \uc608\uc81c\uc5d0\uc11c \ucea1\uc158\uc744 \uc774\ubbf8\uc9c0\uc758 \ud558\ub2e8\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc624\ubc84\ub808\uc774\ub97c \ub9cc\ub4e4\uae30 \uc704\ud574, Edit Image \ub178\ub4dc\ub294 \uc774\ubbf8\uc9c0\uc5d0 \ud14d\uc2a4\ud2b8\ub97c \uc0bd\uc785\ud560 \uc218 \uc788\uac8c \ud574\uc8fc\uba70, \uc774\ub97c \ud1b5\ud574 \uc0dd\uc131\ub41c \ucea1\uc158\uc744 \ucd94\uac00\ud560 \uac83\uc785\ub2c8\ub2e4."
      },
      "typeVersion": 1
    },
    {
      "id": "d175fe97-064e-41da-95fd-b15668c330c4",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2660,
        280
      ],
      "parameters": {
        "width": 563.75,
        "height": 411.25,
        "content": "\uadf8\ub9bc 1. AI \uc0dd\uc131 \ucea1\uc158\uc744 \uac00\uc9c4 \uc608\uc2dc \uc785\ub825 \uc774\ubbf8\uc9c0"
      },
      "typeVersion": 1
    },
    {
      "id": "23db0c90-45b6-4b85-b017-a52ad5a9ad5b",
      "name": "Image Captioning Agent",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1280,
        560
      ],
      "parameters": {
        "text": "Generate a caption for this image.",
        "messages": {
          "messageValues": [
            {
              "message": "=You role is to provide an appropriate image caption for user provided images.\n\nThe individual components of a caption are as follows: who, when, where, context and miscellaneous. For a really good caption, follow this template: who + when + where + context + miscellaneous\n\nGive the caption a punny title."
            },
            {
              "type": "HumanMessagePromptTemplate",
              "messageType": "imageBinary"
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.4
    }
  ],
  "connections": {
    "Get Info": {
      "main": [
        [
          {
            "node": "Merge Image & Caption",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Image": {
      "main": [
        [
          {
            "node": "Resize For AI",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resize For AI": {
      "main": [
        [
          {
            "node": "Image Captioning Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Positioning": {
      "main": [
        [
          {
            "node": "Merge Caption & Positions",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Image & Caption": {
      "main": [
        [
          {
            "node": "Calculate Positioning",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Caption & Positions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image Captioning Agent": {
      "main": [
        [
          {
            "node": "Merge Image & Caption",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Image Captioning Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Image Captioning Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Merge Caption & Positions": {
      "main": [
        [
          {
            "node": "Apply Caption to Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Test workflow\u2019": {
      "main": [
        [
          {
            "node": "Get Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}