8
n8n 한국어amn8n.com

태국어를 지원하는 OCR 명함 읽기 레이아웃

고급

이것은AI Summarization, Multimodal AI분야의자동화 워크플로우로, 28개의 노드를 포함합니다.주로 Set, Gmail, EditImage, FormTrigger, GoogleSheets 등의 노드를 사용하며. 태국어 OCR를 사용하여 명함을 디지털화하고 Google Sheets나 CRM에 저장

사전 요구사항
  • Google 계정 및 Gmail API 인증 정보
  • Google Sheets API 인증 정보
  • OpenAI API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "yzYmkHXckHPtae5x",
  "meta": {
    "instanceId": "ad308e106dee10af1f4894a48cfebd5708187ea753f37a1ba1315e7270c95d76",
    "templateId": "4300",
    "templateCredsSetupCompleted": true
  },
  "name": "Template_OCR Business Card Reader with Thai Support – Enrich & Save Contacts to CRM Spreadsheet",
  "tags": [],
  "nodes": [
    {
      "id": "e0db3554-f691-4650-a4d6-6116976dfad9",
      "name": "메모",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -800
      ],
      "parameters": {
        "color": 4,
        "width": 2840,
        "height": 808,
        "content": "## Version 1: Without Search API\n\n1. Trigger – Upload a business card image.\n\n2. Typhoon OCR – Extracts text from the card. Edit Image node prior to this node is needed.\n\n3. Typhoon LLM (Parser) – Converts the raw text into a structured contact fields in JSON format.\n\n4. Typhoon LLM (Enricher) – Adds extra fields such as job type, job level, and sector.\n\n✨ Adjust the prompt here to match your business needs.\n\n5. Typhoon LLM (Email Draft) – Generates a short greeting email (in case needed)\n\n6. Google Sheets – Saves the structured contact information.\n\n7. Optional Email Step – If you’d like to send the greeting email:\n- Connect the Text to JSON and Gmail nodes.\n- Leave them disconnected if you don’t need this feature.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0057ad5a-e36a-41a3-9bcc-ed0cf1062dd9",
      "name": "Typhoon OCR",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        864,
        -128
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "typhoon-ocr-preview-techsauce-workshop"
        },
        "options": {
          "temperature": 0.1
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "nsDA5kGPLZ6DcBko",
          "name": "Orn's Typhoon account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5eafbe54-990d-492b-9fe3-7aa107ed9bc4",
      "name": "Typhoon 2.1 Gemma1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1264,
        -128
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "typhoon-v2.1-12b-instruct-techsauce-workshop"
        },
        "options": {
          "temperature": 0.4
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "SalMhDvrXYFs2i7y",
          "name": "opentyphoon account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "fc973c4a-e1b9-42d7-8e9b-bd87bd69f76f",
      "name": "OCR 에이전트",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        768,
        -352
      ],
      "parameters": {
        "text": "=Below is an image of a document page, along with its dimensions and possibly some raw textual content previously extracted from it. Note that the text extraction may be incomplete or partially missing. Carefully consider both the layout and any available text to reconstruct the document accurately.\nYour task is to return the markdown representation of this document, presenting tables in HTML format as they naturally appear.\nIf the document contains images or figures, analyze them and include the tag <figure>IMAGE_ANALYSIS</figure> in the appropriate location.\nYour final output must be in JSON format with a single key `natural_text` containing the response.\nRAW_TEXT_START\nPage dimensions: {{ $json.size.width }}.0x{{ $json.size.height }}.0\n[Image 0x0 to {{ $json.size.width }}x{{ $json.size.height }}]\nRAW_TEXT_END",
        "options": {
          "passthroughBinaryImages": true
        },
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "0d7d718e-89d1-4a15-82f4-e558cf9288de",
      "name": "Contact Info Parser",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1168,
        -352
      ],
      "parameters": {
        "text": "=Extract the following information from the provided text and format as JSON:\n\n**Text to process:**\n{{ $json.output }}\n\n**Required JSON fields:**\n- `first_name_en` - First name in English if exists\n- `first_name_th` - First name in Thai if exists\n- `last_name_en` - Last name in English if exists \n- `last_name_th` - Last name in Thai if exists\n- `nick_name_en` - Nick name in English if exists\n- `nick_name_th` - Nick name in Thai if exists\n- `job_title_en` - Job title in English if exists\n- `job_title_th` - Job title in Thai if exists\n- `organization_en` - Organization name in English if exists\n- `organization_th` - Organization name in Thai if exists\n- `email` - Email address\n- `phone` - Phone number\n- `website` - Website URL\n\n**Instructions:**\n- Return only valid JSON without code fences, markdown, or explanatory text\n- Use `null` as the value for missing information\n- Do not copy `first_name_en` OR `last_name_en` to `first_name_th` OR `last_name_th` name, and vice versa\n- If there is a name in parentheses and it is before last name or after last name, you can assume that it is the nick name. Strip out the parenthesis before parsing as nick_name\n- Preserve original formatting for names and titles\n- If there is a country code for phone number, make sure to remove the plus (+) sign and put the code in parentheses. For example, if the phone number contains +66 you will parse it as (66)\n- Remove spaces between numbers in phone number\n- Ensure all field names match exactly as specified above\n\n**Expected output format:**\n```json\n{\n  \"first_name_en\": \"value\",\n  \"first_name_th\": \"value\",\n  \"last_name_en\": \"value\",\n  \"last_name_th\": \"value\",\n  \"nick_name_en\": \"value\",\n  \"nick_name_th\": \"value\",\n  \"job_title_en\": \"value\", \n  \"job_title_th\": \"value\",\n  \"organization_en\": \"value\",\n  \"organization_th\": \"value\",\n  \"email\": \"value\",\n  \"phone\": \"value\",\n  \"website\": \"value\"\n}\n```",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are a smart assistant that extracts contact information from messy text (e.g. OCR results from a business card).  \n\nInstructions: \n- The input text may include either or both English and Thai. Carefully identify the language (Thai or English) for each piece of information.\n - If both English and Thai versions appear, fill both fields.\n- If not, fill in only the relevant language fields and use 'null' for missing information\n- Only capitalize the first letter of `first_name_en` and `last_name_en` and `nick_name_en`\n - Put the text in the correct language field. For example, if the name is in Thai, fill first_name_th / last_name_th / nick_name_th, and vice versa\n- For website, if not explicitly given, just imply it from an email domain. However, you should do so only if the email domain appears to be a company domain, not a free domain like gmail, outlook, etc. Otherwise, just leave it blank."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "a6887325-f2c0-4a22-b736-60cc5025b4a8",
      "name": "Contact Info Enricher",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1568,
        -352
      ],
      "parameters": {
        "text": "=Given this original JSON {{ $json.text }}, your task is to classify and return the following additional fields in JSON:\n\n1. job_type\nPossible values: Technical, Business, Both\n\n2. job_level\nPossible values: Junior, Senior, Manager/Director, Executive\n\n3. sector\nPossible values:\n- Consulting / System Integrator\n- Academic\n- Startup\n- Enterprise\n- Government\n\nReturn only the JSON object. Do not include any code fences or markdown.\n",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are an assistant that classifies business contacts into marketing categories. Instructions: - Use job title, organization name, email domain, and website to make the best classification. - Carefully infer the likely job_type from job title. E.g., technical roles like engineer, developer = Technical; sales or marketing = Business; roles blending both = Both - Infer job_level from job title: Junior, Senior, Manager/Director, Executive. - Infer sector from organization name or email domain: Academic for universities or schools; Government for ministries or departments; Startup for small tech companies; Enterprise for large companies; Consulting/System Integrator for consultancies. - If you cannot confidently assign a field, leave it as an empty string."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "846ba69b-80bc-4a9d-af57-173da37ac92c",
      "name": "Add Contact to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2624,
        -352
      ],
      "parameters": {
        "columns": {
          "value": {
            "text": "={{ $('On form submission').item.json['Message (Optional)'] }}",
            "email": "={{ $json.contact_obj.email }}",
            "phone": "={{ $json.contact_obj.phone }}",
            "sector": "={{ $json.contact_obj.sector }}",
            "website": "={{ $json.contact_obj.website }}",
            "job_type": "={{ $json.contact_obj.job_type }}",
            "job_level": "={{ $json.contact_obj.job_level }}",
            "job_title_en": "={{ $json.contact_obj.job_title_en }}",
            "job_title_th": "={{ $json.contact_obj.job_title_th }}",
            "last_name_en": "={{ $json.contact_obj.last_name_en }}",
            "last_name_th": "={{ $json.contact_obj.last_name_th }}",
            "nick_name_en": "={{ $json.contact_obj.nick_name_en }}",
            "nick_name_th": "={{ $json.contact_obj.nick_name_th }}",
            "first_name_en": "={{ $json.contact_obj.first_name_en }}",
            "first_name_th": "={{ $json.contact_obj.first_name_th }}",
            "organization_en": "={{ $json.contact_obj.organization_en }}",
            "organization_th": "={{ $json.contact_obj.organization_th }}"
          },
          "schema": [
            {
              "id": "first_name_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "first_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_name_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "first_name_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "first_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_name_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nick_name_en",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "nick_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nick_name_th",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "nick_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_title_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job_title_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_title_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job_title_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "job_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_level",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "job_level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organization_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organization_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organization_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organization_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sector",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "sector",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "website",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "website",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "text",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI/edit#gid=0",
          "cachedResultName": "Workshop Template"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI/edit?usp=drivesdk",
          "cachedResultName": "BizCard Contacts"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "oTvdvBcVJxGfaKoq",
          "name": "Google Sheets - Oravee SCB 10X"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "67ef3890-7b46-446c-81e7-5e0db4627e01",
      "name": "Greeting 이메일 Composer1",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2048,
        -352
      ],
      "parameters": {
        "text": "=Write a short, friendly greeting email to the person whose name card was collected at an event or a workshop (Techsauce Global Summit 2025) and format the email into a JSON object with two fields:\\n\n- \\\"subject\\\": the email subject\\n   \n- \\\"body\\\": the message content\\n\\n\nYou have access to structured data from a name card,{{ $('Text to JSON') .item.json.contact_obj.toJsonString() }}, including the recipient’s first name (which you can use to greet them). Other details may be available but are not guaranteed.\nYou also have access to the name card’s owner message that is left when they gave us the name card. {{ $('On form submission').item.json['Message (Optional)'] }}. The email contain should acknowledge the message received and respond with helpful information.\nDo not include markdown, explanations, or code blocks. Your email MUST BE IN ENGLISH.\nAt the end of the email content, also add that this email sender is not an official email and is used for the automation workflow demo purpose only. If the recipient want to contact Typhoon team formally, please send an email or reply back to \"contact@opentyphoon.ai\"",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are a warm, helpful, and professional marketing/community representative from Typhoon. Your task is to write a personalized greeting email based on given information in the user prompt.   Instructions:  1. If `first_name` is available, greet the recipient using it. If not, use a general greeting.\\n  2. Acknowledge the recent contact (e.g. we received your name card)\\n  3. Acknowledge the contact’s message or questions if provided in the prompt (optional)\\n   4. Invite follow-up or continued conversation\\n  5. Keep it short, clear, and friendly. Do not assume things you don’t know for sure and add too much personalization based on all the fields you’re givena\\n 6. Email content must be complete. Do not add boilerplate or incomplete content pieces. 7. Return only a valid JSON object with \\\"headline\\\" and \\\"body\\\". "
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "e3f1f80e-382c-4c63-979e-eb3fd94db039",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3456,
        80
      ],
      "webhookId": "198ebc0a-e32a-4b7a-ac3d-ad0809d4af79",
      "parameters": {
        "sendTo": "={{ $('Text to JSON').item.json.contact_obj.email }}",
        "message": "={{ $json.contact_obj.body }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $json.contact_obj.subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "jjWIZ1r4G9jmW2iN",
          "name": "Gmail account 2"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "bf27f2e5-b4a4-48e6-8011-d74727e58937",
      "name": "이미지 편집",
      "type": "n8n-nodes-base.editImage",
      "position": [
        544,
        -352
      ],
      "parameters": {
        "operation": "information",
        "dataPropertyName": "={{ $json.parents[0] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "756142bb-26de-4db5-809c-fb98e6a5dbc2",
      "name": "Text to JSON 2",
      "type": "n8n-nodes-base.set",
      "position": [
        2384,
        -352
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d07ce0e8-330a-49fc-b5a3-20decd56c00d",
              "name": "contact_obj",
              "type": "object",
              "value": "={{ $json.text.replaceAll(\"```json\", \"\").replaceAll(\"```\", \"\").trim().parseJson() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ba6190d3-ff24-4d62-8a64-18239fe210d2",
      "name": "On form submission1",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        288,
        480
      ],
      "webhookId": "3b703ab4-d61d-4d3f-acea-b040850f15f7",
      "parameters": {
        "options": {},
        "formTitle": "Name card collector",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "nameCard",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".jpg, .png, .jpeg"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Message (Optional)"
            }
          ]
        },
        "formDescription": "Upload your name card and message (optional) here. We will get back to you soon."
      },
      "typeVersion": 2.2
    },
    {
      "id": "c82c8637-d392-4739-a236-15b13f31316f",
      "name": "Typhoon OCR1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        832,
        704
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "typhoon-ocr-preview"
        },
        "options": {
          "temperature": 0.1
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "nsDA5kGPLZ6DcBko",
          "name": "Orn's Typhoon account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "29a46645-4fb0-4db2-a7c8-e0de640c7c86",
      "name": "Typhoon 2.1 Gemma2",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1232,
        704
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "typhoon-v2.1-12b-instruct"
        },
        "options": {
          "temperature": 0.4
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "SalMhDvrXYFs2i7y",
          "name": "opentyphoon account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "02449c4d-b30b-4599-8ac1-32c3af6c52d0",
      "name": "OCR 에이전트1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        736,
        480
      ],
      "parameters": {
        "text": "=Below is an image of a document page, along with its dimensions and possibly some raw textual content previously extracted from it. Note that the text extraction may be incomplete or partially missing. Carefully consider both the layout and any available text to reconstruct the document accurately.\nYour task is to return the markdown representation of this document, presenting tables in HTML format as they naturally appear.\nIf the document contains images or figures, analyze them and include the tag <figure>IMAGE_ANALYSIS</figure> in the appropriate location.\nYour final output must be in JSON format with a single key `natural_text` containing the response.\nRAW_TEXT_START\nPage dimensions: {{ $json.size.width }}.0x{{ $json.size.height }}.0\n[Image 0x0 to {{ $json.size.width }}x{{ $json.size.height }}]\nRAW_TEXT_END",
        "options": {
          "passthroughBinaryImages": true
        },
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "3a8ae88a-de0f-4e9b-9fca-80895bb0eb75",
      "name": "Contact Info Parser1",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1136,
        480
      ],
      "parameters": {
        "text": "=Extract the following information from the provided text and format as JSON:\n\n**Text to process:**\n{{ $json.output }}\n\n**Required JSON fields:**\n- `first_name_en` - First name in English if exists\n- `first_name_th` - First name in Thai if exists\n- `last_name_en` - Last name in English if exists \n- `last_name_th` - Last name in Thai if exists\n- `nick_name_en` - Nick name in English if exists\n- `nick_name_th` - Nick name in Thai if exists\n- `job_title_en` - Job title in English if exists\n- `job_title_th` - Job title in Thai if exists\n- `organization_en` - Organization name in English if exists\n- `organization_th` - Organization name in Thai if exists\n- `email` - Email address\n- `phone` - Phone number\n- `website` - Website URL\n\n**Instructions:**\n- Return only valid JSON without code fences, markdown, or explanatory text\n- Use `null` as the value for missing information\n- Do not copy `first_name_en` OR `last_name_en` to `first_name_th` OR `last_name_th` name, and vice versa\n- If there is a name in parentheses and it is before last name or after last name, you can assume that it is the nick name. Strip out the parenthesis before parsing as nick_name\n- Preserve original formatting for names and titles\n- If there is a country code for phone number, make sure to remove the plus (+) sign and put the code in parentheses. For example, if the phone number contains +66 you will parse it as (66)\n- Remove spaces between numbers in phone number\n- Ensure all field names match exactly as specified above\n\n**Expected output format:**\n```json\n{\n  \"first_name_en\": \"value\",\n  \"first_name_th\": \"value\",\n  \"last_name_en\": \"value\",\n  \"last_name_th\": \"value\",\n  \"nick_name_en\": \"value\",\n  \"nick_name_th\": \"value\",\n  \"job_title_en\": \"value\", \n  \"job_title_th\": \"value\",\n  \"organization_en\": \"value\",\n  \"organization_th\": \"value\",\n  \"email\": \"value\",\n  \"phone\": \"value\",\n  \"website\": \"value\"\n}\n```",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are a smart assistant that extracts contact information from messy text (e.g. OCR results from a business card).  \n\nInstructions: \n- The input text may include either or both English and Thai. Carefully identify the language (Thai or English) for each piece of information.\n - If both English and Thai versions appear, fill both fields.\n- If not, fill in only the relevant language fields and use 'null' for missing information\n- Only capitalize the first letter of `first_name_en` and `last_name_en` and `nick_name_en`\n - Put the text in the correct language field. For example, if the name is in Thai, fill first_name_th / last_name_th / nick_name_th, and vice versa\n- For website, if not explicitly given, just imply it from an email domain. However, you should do so only if the email domain appears to be a company domain, not a free domain like gmail, outlook, etc. Otherwise, just leave it blank."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "4d0c2e41-1f82-4ba5-a7e9-2e37f7536a40",
      "name": "Greeting 이메일 Composer",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2176,
        480
      ],
      "parameters": {
        "text": "=Write a short, friendly greeting email to the person whose name card was collected at an event or a workshop (Techsauce Global Summit 2025) and format the email into a JSON object with two fields:\\n\n- \\\"subject\\\": the email subject\\n   \n- \\\"body\\\": the message content\\n\\n\nYou have access to structured data from a name card,{{ $('Text to JSON2') .item.json.contact_obj.toJsonString() }}, including the recipient’s first name (which you can use to greet them). Other details may be available but are not guaranteed.\nYou also have access to the name card’s owner message that is left when they gave us the name card, {{ $('On form submission1').item.json['Message (Optional)'] }}. The email contain should acknowledge the message received and respond with helpful information.\nDo not include markdown, explanations, or code blocks. Your email MUST BE IN ENGLISH.\nAt the end of the email content, also add that this email sender is not an official email and is used for the automation workflow demo purpose only. If the recipient want to contact Typhoon team formally, please send an email or reply back to \"contact@opentyphoon.ai\"",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are a warm, helpful, and professional marketing/community representative from Typhoon. Your task is to write a personalized greeting email based on given information in the user prompt.   Instructions:  1. If `first_name` is available, greet the recipient using it. If not, use a general greeting.\\n  2. Acknowledge the recent contact (e.g. we received your name card)\\n  3. Acknowledge the contact’s message or questions if provided in the prompt (optional)\\n   4. Invite follow-up or continued conversation\\n  5. Keep it short, clear, and friendly. Do not assume things you don’t know for sure and add too much personalization based on all the fields you’re givena\\n 6. Email content must be complete. Do not add boilerplate or incomplete content pieces. 7. Return only a valid JSON object with \\\"headline\\\" and \\\"body\\\". "
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "129e4a62-233c-4916-b05b-9a50fd91605d",
      "name": "이미지 편집1",
      "type": "n8n-nodes-base.editImage",
      "position": [
        512,
        480
      ],
      "parameters": {
        "operation": "information",
        "dataPropertyName": "nameCard"
      },
      "typeVersion": 1
    },
    {
      "id": "8681cc2e-c443-478a-9cf5-85e036c36fb2",
      "name": "Text to JSON",
      "type": "n8n-nodes-base.set",
      "position": [
        2576,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d07ce0e8-330a-49fc-b5a3-20decd56c00d",
              "name": "contact_obj",
              "type": "object",
              "value": "={{ $json.text.replaceAll(\"```json\", \"\").replaceAll(\"```\", \"\").trim().parseJson() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f73d3276-dba0-44da-be86-98adb5238e4f",
      "name": "메모1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        48
      ],
      "parameters": {
        "color": 5,
        "width": 2824,
        "height": 840,
        "content": "## Version 2: With Search API\n\n1. Trigger: Form submission with name card\n\n2. Typhoon OCR extracts text. Edit Image node prior to this node is needed.\n\n3. Typhoon LLM converts the raw text into a structured contact fields in JSON format.\n\n4. Search API (via SerpAPI) enriches with profile/company info\n\n✨ Adjust the prompt here to match your business needs.\n\n5. Typhoon LLM (Email Draft) – Generates a short greeting email (in case needed)\n\n6. Google Sheets – Saves the structured contact information.\n\n7. Optional Email Step – If you’d like to send the greeting email:\n- Connect the Text to JSON and Gmail nodes.\n- Leave them disconnected if you don’t need this feature."
      },
      "typeVersion": 1
    },
    {
      "id": "6f7bac8e-9a60-4865-af09-dc9b16f20ac0",
      "name": "Search 에이전트",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1536,
        480
      ],
      "parameters": {
        "text": "=Given this original JSON {{ $json.text }}, your task is to classify and return the following additional fields in JSON:\n\n1. job_type\nPossible values: Technical, Business, Both\n\n2. job_level\nPossible values: Junior, Senior, Manager/Director, Executive\n\n3. sector\nPossible values:\n- Consulting / System Integrator\n- Academic\n- Startup\n- Enterprise\n- Government\n\n4. profile summary\nwhich is a short description about this person as you search their name on the internet\n\nYou will retrieve all relevant information from the Internet to get as most completed information as possible.\n\nReturn only the JSON object. Do not include any code fences or markdown.",
        "options": {},
        "promptType": "define"
      },
      "notesInFlow": false,
      "retryOnFail": false,
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "23231cbf-c8fe-47b2-8994-0d70e5a2dc45",
      "name": "Add Contact to Google Sheet1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2832,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "email": "={{ $('Text to JSON2').item.json.contact_obj.email }}",
            "phone": "={{ $('Text to JSON2').item.json.contact_obj.phone }}",
            "sector": "={{ $('Text to JSON2').item.json.contact_obj.sector }}",
            "message": "={{ $('On form submission1').item.json['Message (Optional)'] }}",
            "website": "={{ $('Text to JSON2').item.json.contact_obj.website }}",
            "job_type": "={{ $('Text to JSON2').item.json.contact_obj.job_type }}",
            "job_level": "={{ $('Text to JSON2').item.json.contact_obj.job_level }}",
            "job_title_en": "={{ $('Text to JSON2').item.json.contact_obj.job_title_en }}",
            "job_title_th": "={{ $('Text to JSON2').item.json.contact_obj.job_title_th }}",
            "last_name_en": "={{ $('Text to JSON2').item.json.contact_obj.last_name_en }}",
            "last_name_th": "={{ $('Text to JSON2').item.json.contact_obj.last_name_th }}",
            "nick_name_en": "={{ $('Text to JSON2').item.json.contact_obj.nick_name_en }}",
            "nick_name_th": "={{ $('Text to JSON2').item.json.contact_obj.nick_name_th }}",
            "email content": "={{ $json.contact_obj.body }}",
            "email subject": "={{ $json.contact_obj.subject }}",
            "first_name_en": "={{ $('Text to JSON2').item.json.contact_obj.first_name_en }}",
            "first_name_th": "={{ $('Text to JSON2').item.json.contact_obj.first_name_th }}",
            "organization_en": "={{ $('Text to JSON2').item.json.contact_obj.organization_en }}",
            "organization_th": "={{ $('Text to JSON2').item.json.contact_obj.organization_th }}",
            "profile summary": "={{ $('Text to JSON2').item.json.contact_obj.profile_summary }}"
          },
          "schema": [
            {
              "id": "first_name_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "first_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_name_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "first_name_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "first_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_name_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nick_name_en",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "nick_name_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nick_name_th",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "nick_name_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_title_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job_title_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_title_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "job_title_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "job_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "job_level",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "job_level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organization_en",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organization_en",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organization_th",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "organization_th",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sector",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "sector",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "website",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "website",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "profile summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "profile summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "message",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email subject",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email subject",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email content",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email content",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI/edit#gid=0",
          "cachedResultName": "Workshop Template"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UleIustQHKLHjImasGFFt3ZPi26Uv7JEEVJ6a39uMwI/edit?usp=drivesdk",
          "cachedResultName": "BizCard Contacts"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "oTvdvBcVJxGfaKoq",
          "name": "Google Sheets - Oravee SCB 10X"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "d3737de6-7617-4a8a-b2d2-df59f91bc80f",
      "name": "SerpAPI 검색",
      "type": "@n8n/n8n-nodes-langchain.toolSerpApi",
      "position": [
        1696,
        720
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "serpApi": {
          "id": "xSjB5Nw1g3WoVdzg",
          "name": "SerpAPI account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "380daa54-9c54-4fa5-9d5d-18c59feea4bd",
      "name": "Text to JSON2",
      "type": "n8n-nodes-base.set",
      "position": [
        1936,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d07ce0e8-330a-49fc-b5a3-20decd56c00d",
              "name": "contact_obj",
              "type": "object",
              "value": "={{ $('Search Agent').item.json.output.replaceAll(\"```json\", \"\").replaceAll(\"```\", \"\").trim().parseJson() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "852cc251-296e-4308-baf0-a79a7bda1d43",
      "name": "Text to JSON",
      "type": "n8n-nodes-base.set",
      "position": [
        3232,
        80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d07ce0e8-330a-49fc-b5a3-20decd56c00d",
              "name": "contact_obj",
              "type": "object",
              "value": "={{ $json.text.replaceAll(\"```json\", \"\").replaceAll(\"```\", \"\").trim().parseJson() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9a392744-2e06-4aa4-b512-c750fcce476d",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "disabled": true,
      "position": [
        320,
        -352
      ],
      "webhookId": "4541605d-f810-43b6-b4ac-20bae0f866a0",
      "parameters": {
        "options": {},
        "formTitle": "Name card collector",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "nameCard",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".jpg, .png, .jpeg"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Message (Optional)"
            }
          ]
        },
        "formDescription": "Upload your name card and message (optional) here. We will get back to you soon."
      },
      "typeVersion": 2.2
    },
    {
      "id": "09d18c2d-2e76-4f40-b3f0-450b409fd4b6",
      "name": "메모2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -160
      ],
      "parameters": {
        "width": 624,
        "height": 672,
        "content": "\n# OCR Business Card Reader with Thai Support – Enrich & Save Contacts to CRM\n\nThis workflow demonstrates how to use Typhoon OCR + LLM to digitize business cards, enrich the details, and save them directly into Google Sheets (or any CRM). It works with Thai and English name cards and even includes an optional greeting email step.\n\nTwo versions are included:\n\n🟢 Without Search API → Cost-free, Typhoon-only enrichment\n\n🔵 With Search API → Adds Google Search enrichment for richer profiles (may incur cost)\n\nUse cases: Event lead capture, sales enablement, networking database.\n\nPowered by Typhoon → [opentyphoon.ai](https://opentyphoon.ai) (free API available)\n\n👉 For step-by-step Typhoon setup, see the [official documentation](https://opentyphoon.ai/blog/en/n8n-typhoon-integration-guide)"
      },
      "typeVersion": 1
    },
    {
      "id": "a6b92d4b-777c-4710-88d1-d9d046225b41",
      "name": "메모3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3120,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 544,
        "content": "Optional nodes to facilitate sending emails"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {
    "On form submission1": [
      {
        "json": {
          "formMode": "production",
          "nameCard": {
            "size": 4586239,
            "filename": "IMG_7939.JPG",
            "mimetype": "image/jpeg"
          },
          "submittedAt": "2025-08-07T00:37:13.666+07:00",
          "Message (Optional)": ""
        }
      }
    ]
  },
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "2a769238-0ab3-4d65-9562-e42963b9bcb8",
  "connections": {
    "SerpAPI": {
      "ai_tool": [
        [
          {
            "node": "Search Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "OCR Agent": {
      "main": [
        [
          {
            "node": "0d7d718e-89d1-4a15-82f4-e558cf9288de",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Image": {
      "main": [
        [
          {
            "node": "OCR Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OCR Agent1": {
      "main": [
        [
          {
            "node": "3a8ae88a-de0f-4e9b-9fca-80895bb0eb75",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Image1": {
      "main": [
        [
          {
            "node": "OCR Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0057ad5a-e36a-41a3-9bcc-ed0cf1062dd9": {
      "ai_languageModel": [
        [
          {
            "node": "OCR Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Search Agent": {
      "main": [
        [
          {
            "node": "380daa54-9c54-4fa5-9d5d-18c59feea4bd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "852cc251-296e-4308-baf0-a79a7bda1d43": {
      "main": [
        [
          {
            "node": "23231cbf-c8fe-47b2-8994-0d70e5a2dc45",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c82c8637-d392-4739-a236-15b13f31316f": {
      "ai_languageModel": [
        [
          {
            "node": "OCR Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "380daa54-9c54-4fa5-9d5d-18c59feea4bd": {
      "main": [
        [
          {
            "node": "Greeting Email Composer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "756142bb-26de-4db5-809c-fb98e6a5dbc2": {
      "main": [
        [
          {
            "node": "846ba69b-80bc-4a9d-af57-173da37ac92c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9a392744-2e06-4aa4-b512-c750fcce476d": {
      "main": [
        [
          {
            "node": "Edit Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5eafbe54-990d-492b-9fe3-7aa107ed9bc4": {
      "ai_languageModel": [
        [
          {
            "node": "0d7d718e-89d1-4a15-82f4-e558cf9288de",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "a6887325-f2c0-4a22-b736-60cc5025b4a8",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Greeting Email Composer1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "29a46645-4fb0-4db2-a7c8-e0de640c7c86": {
      "ai_languageModel": [
        [
          {
            "node": "3a8ae88a-de0f-4e9b-9fca-80895bb0eb75",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Greeting Email Composer",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Search Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "0d7d718e-89d1-4a15-82f4-e558cf9288de": {
      "main": [
        [
          {
            "node": "a6887325-f2c0-4a22-b736-60cc5025b4a8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ba6190d3-ff24-4d62-8a64-18239fe210d2": {
      "main": [
        [
          {
            "node": "Edit Image1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3a8ae88a-de0f-4e9b-9fca-80895bb0eb75": {
      "main": [
        [
          {
            "node": "Search Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a6887325-f2c0-4a22-b736-60cc5025b4a8": {
      "main": [
        [
          {
            "node": "Greeting Email Composer1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Greeting Email Composer": {
      "main": [
        [
          {
            "node": "852cc251-296e-4308-baf0-a79a7bda1d43",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Greeting Email Composer1": {
      "main": [
        [
          {
            "node": "756142bb-26de-4db5-809c-fb98e6a5dbc2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "846ba69b-80bc-4a9d-af57-173da37ac92c": {
      "main": [
        []
      ]
    },
    "23231cbf-c8fe-47b2-8994-0d70e5a2dc45": {
      "main": [
        []
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - AI 요약, 멀티모달 AI

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수28
카테고리2
노드 유형10
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Typhoon Team

Typhoon Team

@opentyphoon

Typhoon is an advanced research initiative focused on developing open-source large language models (LLMs) specifically optimized for the Thai language. As a hub for cutting-edge AI innovation, Typhoon offers open-source models, datasets, tooling, and research that enable the development of tailored AI solutions for real-world use cases.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34