Google Driveから医療レポートを取得し、AIによる健康アドバイスを生成

上級

これは自動化ワークフローで、21個のノードを含みます。主にIf, Code, MistralAi, GoogleDrive, GoogleSheetsなどのノードを使用。 Mistral AI と GPT-4 を使って医療レポートを抽出して AI ヘルスアドバイスを生成

前提条件
  • Google Drive API認証情報
  • Google Sheets API認証情報
  • OpenAI API Key

カテゴリー

-
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
  "id": "tUEm5XYFpv149YVQ",
  "name": "Extract Medical reports from Google Drive with AI health advice",
  "tags": [],
  "nodes": [
    {
      "id": "a6a3e84a-be97-4579-ae73-8e3f1f26f4cf",
      "name": "ファイルをダウンロード",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1024,
        464
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "typeVersion": 3
    },
    {
      "id": "057e8d68-e51d-45fb-96c3-6aa45e2a2690",
      "name": "ページのMarkdownを結合",
      "type": "n8n-nodes-base.code",
      "position": [
        1840,
        304
      ],
      "parameters": {
        "jsCode": "// Merge markdown from all pages (works for any number of pages)\nconst pages = $json.pages;\nlet combinedMarkdown = \"\";\n\nfor (let i = 0; i < pages.length; i++) {\n  if (pages[i]?.markdown) {\n    combinedMarkdown += pages[i].markdown + \"\\n\";\n  }\n}\n\nreturn [{ json: { combined_markdown: combinedMarkdown } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d6af767c-c86e-4778-b604-122b48e91231",
      "name": "AI出力を1行ごとに解析",
      "type": "n8n-nodes-base.code",
      "position": [
        2192,
        288
      ],
      "parameters": {
        "jsCode": "const input = $input.first();\nlet data = input.json.message.content || input.json.content || input.json;\n\n// Remove markdown ``` or ```\nif (typeof data === 'string') {\n  data = data.replace(/```+[\\w]*\\s*/g, '').trim();\n}\n\n// Parse JSON\ntry {\n  data = JSON.parse(data);\n} catch (err) {\n  return [{\n    json: {\n      error: \"Failed to parse JSON\",\n      message: err.message,\n      raw: typeof data === 'string' ? data.substring(0, 500) : ''\n    }\n  }];\n}\n\n// Validate array\nif (!Array.isArray(data)) {\n  return [{\n    json: {\n      error: \"Parsed data is not an array\",\n      data\n    }\n  }];\n}\n\n// Map each array entry into a separate n8n item\nreturn data.map(item => {\n  // Clean reference interval: keep only numbers, hyphens, dots, spaces\n  let ref = item.reference_range || 'N/A';\n  if (ref && ref !== 'N/A') {\n    ref = ref.replace(/[^0-9.\\- ]/g, '').replace(/\\s*-\\s*/g, ' - ').replace(/\\s+/g, ' ').trim();\n  }\n  return {\n    json: {\n      'Diagnostic Centre': item.diagnostic_centre || 'N/A',\n      'Name': item.patient_name || 'N/A',\n      'Age': item.age || 'N/A',\n      'Gender': item.gender || 'N/A',\n      'Registered on': item.registration_date || 'N/A',\n      'Sample Type': item.sample_type || 'N/A',\n      'Test Name': item.test_name || 'N/A',\n      'Result': item.result_value !== undefined ? String(item.result_value) : 'N/A',\n      'Unit': item.unit || 'N/A',\n      'Biological reference Interval': ref\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "280f592d-9b76-4653-8a5c-2292004bda36",
      "name": "基準範囲外検出&アドバイス項目",
      "type": "n8n-nodes-base.code",
      "position": [
        2416,
        288
      ],
      "parameters": {
        "jsCode": "function isOutOfRange(result, ref) {\n  if (!result || !ref) return false;\n  // strip units, trim spaces\n  let val = parseFloat((result + '').replace(/[^0-9.\\-]/g, ''));\n  let match = ref.match(/^\\s*(\\d+\\.?\\d*)\\s*-\\s*(\\d+\\.?\\d*)/); // \"0.3-1.2\" etc.\n  if (match) {\n    let low = parseFloat(match[1]);\n    let high = parseFloat(match[2]);\n    return (val < low || val > high);\n  }\n  if (ref.match(/^<\\s*(\\d+)/)) {\n    let high = parseFloat(ref.match(/^<\\s*(\\d+)/)[1]);\n    return (val >= high);\n  }\n  if (ref.match(/^>\\s*(\\d+)/)) {\n    let low = parseFloat(ref.match(/^>\\s*(\\d+)/)[1]);\n    return (val <= low);\n  }\n  return false; // fallback\n}\n\nlet outOfRangeItems = [];\nfor (let item of items) {\n  item.json['Dietary advice'] = '';\n  item.json['Lifestyle advice'] = '';\n  item.json['Exercise advice'] = '';\n  if (isOutOfRange(item.json['Result'], item.json['Biological reference Interval'])) {\n    outOfRangeItems.push(item);\n  }\n}\nreturn outOfRangeItems; // This will go to the AI node for advice\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3e152598-d727-482a-99ca-a38d658dee9c",
      "name": "AI応答を統合",
      "type": "n8n-nodes-base.code",
      "position": [
        2768,
        288
      ],
      "parameters": {
        "jsCode": "// Merge AI Response Back - SIMPLE VERSION\n// Assumes AI responses are in the same order as out-of-range items\n\nconsole.log('=== SIMPLE MERGE START ===');\n\nconst aiItems = items; // AI advice responses\nconst allRows = $('Out-of-Range Detection & Advice Fields').all();\n\nconsole.log('AI items:', aiItems.length);\nconsole.log('Medical rows:', allRows.length);\n\n// Process each row\nfor (let i = 0; i < allRows.length; i++) {\n  const row = allRows[i];\n  \n  let dietary = '';\n  let lifestyle = '';\n  let exercise = '';\n  \n  // If we have AI advice for this index\n  if (i < aiItems.length) {\n    const ai = aiItems[i];\n    \n    // Get content from various possible locations\n    let content = ai.json.content || ai.json.message?.content || ai.json.text || '';\n    \n    if (content) {\n      try {\n        // Remove code fences\n        content = content.replace(/```(?:json)?\\s*/g, '').replace(/```/g, '').trim();\n        \n        // Parse JSON\n        const obj = JSON.parse(content);\n        \n        dietary = obj[\"Dietary advice\"] || obj[\"dietary_advice\"] || '';\n        lifestyle = obj[\"Lifestyle advice\"] || obj[\"lifestyle_advice\"] || '';\n        exercise = obj[\"Exercise advice\"] || obj[\"exercise_advice\"] || '';\n        \n        console.log(`Row ${i}: Successfully extracted advice`);\n        \n      } catch (err) {\n        console.error(`Row ${i}: Parse error -`, err.message);\n      }\n    }\n  }\n  \n  row.json['Dietary advice'] = dietary;\n  row.json['Lifestyle advice'] = lifestyle;\n  row.json['Exercise advice'] = exercise;\n}\n\nconsole.log('=== SIMPLE MERGE COMPLETE ===');\nreturn allRows;"
      },
      "typeVersion": 2
    },
    {
      "id": "a62dfcf0-a9b0-443d-bf87-51c58e34662b",
      "name": "PDF/JPEGファイルをGoogleドライブにアップロード",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "notes": "Folder ID is referenced from the 'Workflow User Configuration'\nFolder ID is read from workflow variable `GOOGLE_DRIVE_FOLDER_ID` (set via Workflow → Settings → Variables). You can also replace the expression directly in this field.",
      "position": [
        1008,
        176
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": {
            "mode": "list",
            "value": "1mPJiZ...<your-folder-id-here>"
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "31350988-e198-493d-83c6-4cb3e6a832f7",
      "name": "画像から抽出",
      "type": "n8n-nodes-base.mistralAi",
      "position": [
        1584,
        368
      ],
      "parameters": {
        "options": {},
        "documentType": "image_url"
      },
      "typeVersion": 1
    },
    {
      "id": "1addfa9f-7104-4da5-a78b-a4dd98e40843",
      "name": "PDFか画像かを確認",
      "type": "n8n-nodes-base.if",
      "position": [
        1296,
        272
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "aad49b11-5871-422b-818f-431e53e9844f",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Upload pdf/jpeg file to Google drive').item.json.mimeType }}",
              "rightValue": "application/pdf"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8fa34cb4-3775-49a7-9276-497c11988a6c",
      "name": "PDFから抽出",
      "type": "n8n-nodes-base.mistralAi",
      "position": [
        1584,
        176
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "39376374-069f-4566-b06d-683154afe334",
      "name": "医療データ抽出(AI)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1952,
        64
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "=You are an expert medical data extraction assistant specializing in diagnostic reports. Your role is to accurately identify and extract EVERY measurable test result (including all sub-parameters of multi-test panels like LFT, Haemogram, Lipid Profile, etc.) in a granular and structured fashion, for each page of the provided document.\nReturn only pure, valid JSON and ensure your output is reliable for direct ingestion by downstream data pipelines.\n"
            },
            {
              "role": "user",
              "content": "=Extract ALL individual test results (including every sub-parameter of multi-panel tests such as Liver Function Test, Haemogram, etc.) from the ENTIRE provided document. \n\nOutput instructions:\n- For EACH test or parameter, create a JSON object with these fields: \n  - diagnostic_centre: Name of the diagnostic center\n  - patient_name: Full patient name\n  - age: age of the patient in Years\n  - gender: gender of the patient\n  - registration_date: Registration date (DD-MMM-YYYY)\n  - sample_type: Type of sample (e.g., Serum, Plasma, Urine)\n  - test_name: Name of the specific test/parameter (e.g., 'Total Bilirubin', 'SGPT', 'Hemoglobin', etc.)\n  - result_value: Result value (only the numeric or string value, no additional text)\n  - unit: Unit of measurement, if present (e.g., mg/dL, g/L, etc.)\n  - reference_range: Normal reference range, if present\n\n- Return ONLY a valid JSON array of all detected test results/parameters. \n- Do not include any markdown, formatting, or code blocks—just the raw JSON array.\n- If a field is missing for a parameter, output an empty string (\"\").\n\nExample:\n[\n  {\n    \"diagnostic_centre\": \"VIJAYA DIAGNOSTIC CENTRE\",\n    \"patient_name\": \"Mr.XYZ\",\n    \"age\": \"58 Years\",\n    \"gender\": \"Male\",\n    \"registration_date\": \"26-Jan-2024\",\n    \"sample_type\": \"Fluoride Plasma\",\n    \"test_name\": \"Post Lunch Glucose\",\n    \"result_value\": \"236\",\n    \"unit\": \"mg/dL\",\n    \"reference_range\": \"100-140\"\n  },\n  {\n    \"diagnostic_centre\": \"VIJAYA DIAGNOSTIC CENTRE\",\n    \"patient_name\": \"Mr.XYZ\",\n    \"age\": \"58 Years\",\n    \"gender\": \"Male\",\n    \"registration_date\": \"26-Jan-2024\",\n    \"sample_type\": \"Serum\",\n    \"test_name\": \"Total Bilirubin\",\n    \"result_value\": \"0.8\",\n    \"unit\": \"mg/dL\",\n    \"reference_range\": \"0.3-1.2\"\n  }\n]\n\nReference {{ $json.combined_markdown }} to provide the full multi-page text as input.\n\n\nExtract every possible test entry into a single JSON array, without markdown, code fences, or comments. Every result/parameter from every page must be present as a separate object.\n"
            }
          ]
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "395f545b-2c39-4fe5-824c-56196d5c5b19",
      "name": "一般的健康アドバイス(AI)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2528,
        80
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a physician-reviewed expert assistant specializing in actionable, personalized wellness guidance based on lab test results."
            },
            {
              "content": "=For this out-of-range medical lab result:\n\nPatient: {{ $json.Name }}\nAge :{{ $json.Age }}\nGender:{{ $json.Gender }}\nTest Name: {{ $json['Test Name'] }}\nResult: {{ $json.Result }} {{ $json.Unit }}\nReference Range: {{ $json['Biological reference Interval'] }}\n\nPlease provide:\n- A two-sentence dietary/nutritional advice\n- A two-sentence lifestyle change suggestion\n- A two-sentence exercise recommendation\n\nReturn your answer ONLY as the following JSON object:\n{\n  \"Dietary advice\": \"...\",\n  \"Lifestyle advice\": \"...\",\n  \"Exercise advice\": \"...\"\n}\nDo not add any additional commentary."
            }
          ]
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "2e4e4a02-0492-4a27-bcd5-d22090a7e210",
      "name": "付箋",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        -80
      ],
      "parameters": {
        "color": 3,
        "width": 288,
        "height": 448,
        "content": "## Google Drive Trigger\n\n## Upload file (Pdf/Image)\n\nMonitors a specific Google Drive folder for newly uploaded medical reports (PDF/image files). Triggers the workflow when a new file is detected (checks every minute)."
      },
      "typeVersion": 1
    },
    {
      "id": "7077505f-39be-426e-bb8c-f39235900794",
      "name": "付箋1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        384
      ],
      "parameters": {
        "color": 3,
        "height": 448,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Download File\n\nDownloads the detected medical report file from Google Drive for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "713f9373-6461-4a1d-838a-e94b90e72e97",
      "name": "付箋2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        48
      ],
      "parameters": {
        "color": 5,
        "width": 256,
        "height": 544,
        "content": "## Check if PDF/Image\n\nDetermines whether the uploaded file is a PDF or an image, routing to the appropriate extraction node."
      },
      "typeVersion": 1
    },
    {
      "id": "79fb1da0-1c7a-4e9e-8588-a606227b02b7",
      "name": "付箋3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        -80
      ],
      "parameters": {
        "color": 6,
        "width": 288,
        "height": 896,
        "content": "## Extract from PDF\n\nUses Mistral AI to extract text and structure from PDF medical reports using OCR capabilities.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Extract from Image\n\nUses Mistral AI to extract text from image-based medical reports (JPG, PNG, etc.) using vision capabilities."
      },
      "typeVersion": 1
    },
    {
      "id": "c53123e0-f5a3-4e8e-af19-0838a3393c0a",
      "name": "付箋6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1792,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 896,
        "content": "## Extract Medical Data (AI)\n\nUses GPT-4 to intelligently extract structured data from the medical report: patient details, test names, results, units, and reference ranges. Outputs pure JSON.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Combine page Markdown\n Merges markdown text from all pages of multi-page reports into a single combined text for unified processing.\n\n\n\n## Parse AI output to one-per-row\n Transforms the AI-generated JSON array into individual n8n items  (one per test result), cleans reference intervals, and standardizes field names for Google Sheets compatibility.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "83ee4286-c175-45a0-86b4-e8b997c72f6a",
      "name": "基準範囲外結果を保存",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3024,
        288
      ],
      "parameters": {
        "sheet": {
          "mode": "name",
          "value": {
            "mode": "name",
            "value": "Out of Range Values"
          }
        },
        "columns": {
          "value": {
            "Age": "={{ $json.Age }}",
            "Name": "={{ $json.Name }}",
            "Unit": "={{ $json.Unit }}",
            "Gender": "={{ $json.Gender }}",
            "Result": "={{ $json.Result }}",
            "Test Name": "={{ $json['Test Name'] }}",
            "Sample Type": "={{ $json['Sample Type'] }}",
            "Dietary advice": "={{ $json['Dietary advice'] }}",
            "Registered \non": "={{ $json['Registered on'] }}",
            "Exercise advice": "={{ $json['Exercise advice'] }}",
            "Lifestyle advice": "={{ $json['Lifestyle advice'] }}",
            "Diagnostic Centre": "={{ $json['Diagnostic Centre'] }}",
            "Biological \nreference Interval": "={{ $json['Biological reference Interval'] }}"
          },
          "schema": [
            {
              "id": "Diagnostic Centre",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Diagnostic Centre",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Age",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Age",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Gender",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Gender",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Registered \non",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Registered \non",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sample Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sample Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Test Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Test Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Result",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Unit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Biological \nreference Interval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Biological \nreference Interval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Dietary advice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Dietary advice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Lifestyle advice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Lifestyle advice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Exercise advice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Exercise advice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": ""
      },
      "typeVersion": 4.7
    },
    {
      "id": "50454400-4968-4e6e-adb5-4afe3cea01ec",
      "name": "付箋10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2368,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 896,
        "content": "## Generate Health Advice (AI) \n\nUses GPT-4 to generate personalized dietary, lifestyle, and exercise recommendations for each out-of-range test result, considering patient age and gender.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Out-of-Range Detection & Advice Fields\nAnalyzes each test result against its reference range. Identifies abnormal values and routes them for personalized health advice generation.\n\n\n\n\n                                                                                                                                                                                                     \n## Merge AI Response Back\nCombines the AI-generated health advice with the corresponding medical test data, preparing complete records for final storage.\n\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "edbfa3ba-e4de-41d0-8e73-3026a882033f",
      "name": "付箋5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        -80
      ],
      "parameters": {
        "color": 2,
        "width": 288,
        "height": 928,
        "content": "\n\n\n## Save Out-of-Range Results\n\nSaves abnormal test results along with personalized health advice to the \"Out of Range Values\" sheet in Google Sheets for priority review.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n ## Save All Test Results\n\nSaves every extracted test result to the \"All Values\" sheet in Google Sheets for comprehensive record-keeping.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "49a1f385-e91e-4047-808d-5b9134050339",
      "name": "全検査結果を保存",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3040,
        512
      ],
      "parameters": {
        "sheet": {
          "mode": "name",
          "value": {
            "mode": "name",
            "value": "All Values"
          }
        },
        "columns": {
          "value": {
            "Age": "={{ $json.Age }}",
            "Name": "={{ $json.Name }}",
            "Unit": "={{ $json.Unit }}",
            "Result": "={{ $json.Result }}",
            "Test Name": "={{ $json['Test Name'] }}",
            "Sample Type": "={{ $json['Sample Type'] }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Age",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Age",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sample Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sample Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Test Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Test Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Result",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Unit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Biological \nreference Interval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Biological \nreference Interval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": ""
      },
      "typeVersion": 4.7
    },
    {
      "id": "e7472172-098d-4a68-811b-89c593545003",
      "name": "付箋4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -80
      ],
      "parameters": {
        "width": 640,
        "height": 912,
        "content": "## Try It Out!\n\nUse n8n to extract medical test data from diagnostic reports uploaded to Google Drive, automatically detect abnormal values, and generate personalized health advice.\n\n### How it works\n\n1. Upload a medical report (PDF or image) to a monitored Google Drive folder\n2. Mistral AI extracts text using OCR while preserving document structure\n3. GPT-4 parses the extracted text into structured JSON (patient info, test names, results, units, reference ranges)\n4. All test results are saved to the \"All Values\" sheet in Google Sheets\n5. JavaScript code compares each result against its reference range to detect abnormalities\n6. For out-of-range values, GPT-4 generates personalized dietary, lifestyle, and exercise advice based on patient age and gender\n7. Abnormal results with recommendations are saved to the \"Out of Range Values\" sheet\n\n### How to use\n\n1. Set up Google Drive folder monitoring and Google Sheets with two tabs: \"All Values\" and \"Out of Range Values\"\n2. Configure API credentials for Google Drive, Mistral AI, and OpenAI (GPT-4)\n3. Upload medical reports to your monitored folder\n4. Review extracted data and personalized health advice in Google Sheets\n\n### Requirements\n\n* Google Drive and Sheets with OAuth2 authentication\n* Mistral AI API key for OCR\n* OpenAI API key (GPT-4 access required) for intelligent extraction and advice generation\n\n### Need Help?\n\n* See the detailed setup guide for step-by-step credential configuration\n* Join the n8n community forum for support"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "a6a3e84a-be97-4579-ae73-8e3f1f26f4cf": {
      "main": [
        [
          {
            "node": "1addfa9f-7104-4da5-a78b-a4dd98e40843",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8fa34cb4-3775-49a7-9276-497c11988a6c": {
      "main": [
        [
          {
            "node": "057e8d68-e51d-45fb-96c3-6aa45e2a2690",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "31350988-e198-493d-83c6-4cb3e6a832f7": {
      "main": [
        [
          {
            "node": "057e8d68-e51d-45fb-96c3-6aa45e2a2690",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1addfa9f-7104-4da5-a78b-a4dd98e40843": {
      "main": [
        [
          {
            "node": "8fa34cb4-3775-49a7-9276-497c11988a6c",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "31350988-e198-493d-83c6-4cb3e6a832f7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "057e8d68-e51d-45fb-96c3-6aa45e2a2690": {
      "main": [
        [
          {
            "node": "39376374-069f-4566-b06d-683154afe334",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3e152598-d727-482a-99ca-a38d658dee9c": {
      "main": [
        [
          {
            "node": "83ee4286-c175-45a0-86b4-e8b997c72f6a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "39376374-069f-4566-b06d-683154afe334": {
      "main": [
        [
          {
            "node": "d6af767c-c86e-4778-b604-122b48e91231",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "395f545b-2c39-4fe5-824c-56196d5c5b19": {
      "main": [
        [
          {
            "node": "3e152598-d727-482a-99ca-a38d658dee9c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d6af767c-c86e-4778-b604-122b48e91231": {
      "main": [
        [
          {
            "node": "280f592d-9b76-4653-8a5c-2292004bda36",
            "type": "main",
            "index": 0
          },
          {
            "node": "49a1f385-e91e-4047-808d-5b9134050339",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a62dfcf0-a9b0-443d-bf87-51c58e34662b": {
      "main": [
        [
          {
            "node": "a6a3e84a-be97-4579-ae73-8e3f1f26f4cf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "280f592d-9b76-4653-8a5c-2292004bda36": {
      "main": [
        [
          {
            "node": "395f545b-2c39-4fe5-824c-56196d5c5b19",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
よくある質問

このワークフローの使い方は?

上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。

このワークフローはどんな場面に適していますか?

上級

有料ですか?

このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。

ワークフロー情報
難易度
上級
ノード数21
カテゴリー-
ノードタイプ8
難易度説明

上級者向け、16ノード以上の複雑なワークフロー

作成者
Sridevi Edupuganti

Sridevi Edupuganti

@edupuganti

I help customers experience 10x faster ROI through AI Automation. AI Generalist | Pursuing Generative AI & ML(IIT-G) | Google Certified Prompt Engineer | Ex-VP | Ex-Microsoft | ISB Certified CTO & AI Leader | Azure & AI Strategist | 5X Azure | n8n level2 | Wellness Advocate & Cult Ninja

外部リンク
n8n.ioで表示

このワークフローを共有

カテゴリー

カテゴリー: 34