Convertir PDF de plan de entrenamiento a plan de entrenamiento para la app Hevy con IA de Gemini

Avanzado

Este es unPersonal Productivity, AI Summarizationflujo de automatización del dominio deautomatización que contiene 16 nodos.Utiliza principalmente nodos como Set, Aggregate, FormTrigger, HttpRequest, ExtractFromFile. Usar IA Gemini para convertir archivos PDF de planes de entrenamiento a planes de entrenamiento de la aplicación Hevy

Requisitos previos
  • Pueden requerirse credenciales de autenticación para la API de destino
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "meta": {
    "instanceId": "42450f423595f391b7c323eb4191c0bc81df9f6de5483a12f34f76cb4146556c",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "9378321b-87f0-479f-8846-9e40a41c91ca",
      "name": "Al enviar el formulario",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1240,
        -140
      ],
      "webhookId": "833ba56e-1dcb-45f7-9702-57800ff9095c",
      "parameters": {
        "options": {},
        "formTitle": "Upload Training Plan",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "data",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".jpg, .png, .pdf, .jpeg"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "634600e6-0b0b-4051-ade7-e0b9f1e353ac",
      "name": "Analizador de salida estructurada",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        228,
        80
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"routine\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"title\": {\n          \"type\": \"string\",\n          \"description\": \"The title of the routine\"\n        },\n        \"folder_id\": {\n          \"type\": \"number\",\n          \"nullable\": true,\n          \"default\": 1352963,\n          \"description\": \"The folder id the routine should be added to. Pass null to insert the routine into default 'My Routines' folder\"\n        },\n        \"notes\": {\n          \"type\": \"string\",\n          \"description\": \"Additional notes for the routine\"\n        },\n        \"exercises\": {\n          \"type\": \"array\",\n          \"description\": \"List of exercises in the routine\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"exercise_template_id\": {\n                \"type\": \"string\",\n                \"description\": \"The ID of the exercise template\"\n              },\n              \"superset_id\": {\n                \"type\": \"integer\",\n                \"nullable\": true,\n                \"description\": \"The ID of the superset\"\n              },\n              \"rest_seconds\": {\n                \"type\": \"integer\",\n                \"nullable\": true,\n                \"description\": \"The rest time in seconds (Pause). Never negative.\"\n              },\n              \"notes\": {\n                \"type\": \"string\",\n                \"nullable\": true,\n                \"description\": \"Additional notes for the exercise\"\n              },\n              \"sets\": {\n                \"type\": \"array\",\n                \"description\": \"Sets for the exercise\",\n                \"items\": {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"type\": {\n                      \"type\": \"string\",\n                      \"enum\": [\"warmup\", \"normal\", \"failure\", \"dropset\"],\n                      \"description\": \"The type of the set\"\n                    },\n                    \"weight_kg\": {\n                      \"type\": \"number\",\n                      \"nullable\": true,\n                      \"description\": \"The weight in kilograms\"\n                    },\n                    \"reps\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The number of repetitions (wdhl.). Never negative.\"\n                    },\n                    \"distance_meters\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The distance in meters\"\n                    },\n                    \"duration_seconds\": {\n                      \"type\": \"integer\",\n                      \"nullable\": true,\n                      \"description\": \"The duration in seconds\"\n                    },\n                    \"custom_metric\": {\n                      \"type\": \"number\",\n                      \"nullable\": true,\n                      \"description\": \"A custom metric for the set. Currently used for steps and floors\"\n                    }\n                  }\n                }\n              }\n            },\n            \"required\": [\"exercise_template_id\", \"sets\"]\n          }\n        }\n      },\n      \"required\": [\"title\", \"exercises\"]\n    }\n  },\n  \"required\": [\"routine\"]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "9cf95512-03fc-44ce-8a4c-bdf828927ac2",
      "name": "google/gemini-2.5-flash",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        60,
        80
      ],
      "parameters": {
        "model": "google/gemini-2.5-flash",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "aCsTDT5LGS5D8Ndl",
          "name": "OpenRouter account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d13c6c4d-c938-4617-a679-5e4cd356168e",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1740,
        -200
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 280,
        "content": "## Scan Any Workout Plan into the Hevy App with AI\n\nThis workflow extracts a workout plan from a PDF, uses AI to match the exercises to those available in the Hevy app, and automatically creates the routine for you.\nSetup:\n\nConfigure the trigger.\nAdd your OpenRouter & Hevy credentials.\nActivate and test!"
      },
      "typeVersion": 1
    },
    {
      "id": "d7a3ba9a-d86d-42bf-a6f9-5f30e699398a",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1100,
        -360
      ],
      "parameters": {
        "width": 260,
        "height": 180,
        "content": "This node converts the incoming PDF file into a Base64 text string. This format is required to send the file content to the AI model in the next step."
      },
      "typeVersion": 1
    },
    {
      "id": "5b42918d-1446-4b91-b867-b9b0f771bfb7",
      "name": "Nota adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -800,
        -360
      ],
      "parameters": {
        "width": 300,
        "height": 180,
        "content": "This node sends the PDF content to an AI model to perform OCR and extract all the text from the document.\nRequires: OpenRouter.ai API credentials."
      },
      "typeVersion": 1
    },
    {
      "id": "a137506d-75c3-45e6-8c78-8f6e0104914f",
      "name": "Nota adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -440,
        -360
      ],
      "parameters": {
        "width": 300,
        "height": 180,
        "content": "These nodes fetch all available exercises from your Hevy account and combine them into a single list. This list provides the context for the AI to know which exercises are valid.\nRequires: https://api.hevyapp.com/docs/ credentials."
      },
      "typeVersion": 1
    },
    {
      "id": "c8ae0644-c339-4929-990c-ca99ab0247b1",
      "name": "Nota adhesiva4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        40,
        -420
      ],
      "parameters": {
        "width": 340,
        "height": 240,
        "content": "This is the core of the workflow.\nIt uses Google's Gemini model to:\n\nRead the messy text from the PDF.\nCompare the exercises mentioned against the official Hevy exercise list.\nCreate a clean, structured JSON output ready for the Hevy API.\nThe prompt and the Schema in the Structured Output Parser are critical here."
      },
      "typeVersion": 1
    },
    {
      "id": "88dbdb21-34e3-4faf-a226-2b3633b1dc4c",
      "name": "Nota adhesiva8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        -340
      ],
      "parameters": {
        "content": "This final node takes the structured data from the AI and makes a POST request to the Hevy API, creating the complete workout routine in your account."
      },
      "typeVersion": 1
    },
    {
      "id": "0002347a-a9e3-43a3-be10-1773e3efd6cf",
      "name": "Convertir PDF a Base64",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1020,
        -140
      ],
      "parameters": {
        "options": {},
        "operation": "binaryToPropery"
      },
      "typeVersion": 1
    },
    {
      "id": "fcce2688-1ecc-4337-9737-3b92764ce718",
      "name": "Extraer texto del PDF mediante IA",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -800,
        -140
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"google/gemini-2.5-flash\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": [\n        {\n          \"type\": \"text\",\n          \"text\": \"Please perform OCR on this document and provide the full extracted content in your response\"\n        },\n        {\n          \"type\": \"image_url\",\n          \"image_url\": {\n            \"url\": \"data:image/jpeg;base64,{{ $json.data }}\"\n          }\n        }\n      ]\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "hPXTjlgijwj0mJav",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c",
      "name": "Obtener lista de ejercicios de Hevy",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -580,
        -140
      ],
      "parameters": {
        "url": "https://api.hevyapp.com/v1/exercise_templates",
        "options": {
          "pagination": {
            "pagination": {
              "parameters": {
                "parameters": [
                  {
                    "name": "page",
                    "value": "={{ $pageCount + 1 }}"
                  }
                ]
              },
              "maxRequests": 10,
              "requestInterval": 100,
              "limitPagesFetched": true,
              "paginationCompleteWhen": "receiveSpecificStatusCodes",
              "statusCodesWhenComplete": "404"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "pageSize",
              "value": "100"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "wmbngFqWDYUxVqMb",
          "name": "Hevy Auth"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "20ccb4bb-b0bd-4567-bb26-1015b3fa0105",
      "name": "Formatear nombres de ejercicios",
      "type": "n8n-nodes-base.set",
      "position": [
        -360,
        -140
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "85dd9d76-d527-43ce-bd36-955bb2a3b3f6",
              "name": "exercise_templates",
              "type": "array",
              "value": "={{ $json.exercise_templates }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "16434525-113f-4f93-b6df-05a096658087",
      "name": "Combinar lista de ejercicios",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -140,
        -140
      ],
      "parameters": {
        "options": {
          "mergeLists": true
        },
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "exercise_templates"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "291e75d6-a372-4a15-ad66-92043cfc107b",
      "name": "Emparejar ejercicios y estructurar rutina",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        80,
        -140
      ],
      "parameters": {
        "text": "=# GOAL\nYour task is to analyze the provided OCR data of a workout routine, interpret its contents, and convert it into a structured JSON object. You must strictly adhere to the provided JSON schema.\n\n# CONTEXT\n- The OCR data is imperfect and may contain typos or formatting quirks.\n- You will be given a list of available exercises from an application database (`Base Exercise Data`).\n\n# INPUT DATA\n1.  **OCR Data:**\n    ```\n    {{ $('Extract Text from PDF via AI').item.json.choices[0].message.content }}\n    ```\n2.  **Base Exercise Data:**\n    ```json\n    {{ $json.exercise_templates.toJsonString() }}\n    ```\n\n# EXTRACTION RULES & SPECIFICS\nThis section contains specific instructions to guide the extraction process.\n\n- **Exercise Matching:** For each exercise name found in the OCR data, you MUST find the most semantically similar exercise in the `Base Exercise Data`. Use its `id` for the `exercise_template_id` in the final JSON. Do not invent new IDs.\n- **Default Folder:** If no folder is specified, use the default `folder_id` of `1352963`.\n- **Interpreting Sets:** A line like \"3x10 @ 50kg\" means 3 sets of 10 repetitions with 50 kilograms.\n- **Rest Times:** Look for terms like \"Pause,\" \"Rest,\" or time values (e.g., \"90s,\" \"1 min\") between exercises to determine the `rest_seconds`.\n- **Supersets:** If exercises are grouped with labels like \"A1, A2\" or listed together without a rest period, they are a superset. Assign them the same, incrementing `superset_id` (e.g., the first superset pair gets `superset_id: 1`, the next pair gets `superset_id: 2`).\n- **Tempo Information (optional):** Look for a 3 or 4-digit number (e.g., `4010`, `31X0`, `311`), often labeled \"Tempo\". If found for an exercise, capture this and include it in that exercise's `notes` field (e.g., `notes: \"Tempo: 4010\"`).\n\n\n\n# OUTPUT INSTRUCTIONS\n- Produce ONLY the final JSON object.\n- Do not include any explanatory text, markdown formatting, or apologies in your response.\n- The output must be a single, valid JSON object conforming to the schema.\n",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "7d710a1d-7e86-4da1-bda1-741d8008cb02",
      "name": "Crear rutina en Hevy",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        456,
        -140
      ],
      "parameters": {
        "url": "https://api.hevyapp.com/v1/routines",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.output.toJsonString() }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "wmbngFqWDYUxVqMb",
          "name": "Hevy Auth"
        }
      },
      "typeVersion": 4.2
    }
  ],
  "pinData": {},
  "connections": {
    "9378321b-87f0-479f-8846-9e40a41c91ca": {
      "main": [
        [
          {
            "node": "0002347a-a9e3-43a3-be10-1773e3efd6cf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "16434525-113f-4f93-b6df-05a096658087": {
      "main": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0002347a-a9e3-43a3-be10-1773e3efd6cf": {
      "main": [
        [
          {
            "node": "fcce2688-1ecc-4337-9737-3b92764ce718",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "20ccb4bb-b0bd-4567-bb26-1015b3fa0105": {
      "main": [
        [
          {
            "node": "16434525-113f-4f93-b6df-05a096658087",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9cf95512-03fc-44ce-8a4c-bdf828927ac2": {
      "ai_languageModel": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "634600e6-0b0b-4051-ade7-e0b9f1e353ac": {
      "ai_outputParser": [
        [
          {
            "node": "291e75d6-a372-4a15-ad66-92043cfc107b",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c": {
      "main": [
        [
          {
            "node": "20ccb4bb-b0bd-4567-bb26-1015b3fa0105",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fcce2688-1ecc-4337-9737-3b92764ce718": {
      "main": [
        [
          {
            "node": "51ad34e9-0aaa-4ebe-adfa-6fd263cba56c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "291e75d6-a372-4a15-ad66-92043cfc107b": {
      "main": [
        [
          {
            "node": "7d710a1d-7e86-4da1-bda1-741d8008cb02",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Productividad personal, Resumen de IA

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Flujos de trabajo relacionados recomendados

Monitor de problemas de la comunidad con OpenRouter AI, rastreo de Reddit y foros
Monitoreo de problemas en comunidades de Reddit y foros usando OpenRouter AI, NocoDB y scraping
Set
Code
Html
+
Set
Code
Html
29 NodosJulian Kaiser
Investigación de mercado
Generación de un boletín semanal de acciones por los derechos animales a partir de proyectos de ley de la Cámara de Representantes de EE. UU. usando Gemini IA
Generar un boletín semanal de acciones por los derechos animales usando Gemini AI basado en proyectos de ley de la Cámara de Representantes de EE. UU.
If
Set
Html
+
If
Set
Html
26 NodosOpen Paws
Redes sociales
Automatización de búsqueda de empleos y personalización de currículum con Mistral AI, LinkedIn y Google Sheets
Automatización de búsqueda de empleos y personalización de CVs con Mistral AI, LinkedIn y Google Sheets
Set
Code
Html
+
Set
Code
Html
46 NodosJordan Hoyle
Productividad personal
Generador de video automatizado
Generar videos de IA a partir de un guion con DeepSeek, TTS y Together.ai
Set
Code
Wait
+
Set
Code
Wait
81 NodosLakindu Siriwardana
Creación de contenido
Extracción de datos de Twitter - Creador de n8n
Generación automática de resúmenes de inteligencia de Twitter y envío a grupos de WhatsApp con Gemini 2.5 Pro
Set
Code
Wait
+
Set
Code
Wait
39 NodosDaniel Lianes
Resumen de IA
Análisis inteligente diario de grupos de WhatsApp: Análisis con GPT-4.1 y transcripción de mensajes de voz
Análisis inteligente diario de grupos de WhatsApp: análisis con GPT-4.1 y transcripción de mensajes de voz
If
Set
Code
+
If
Set
Code
52 NodosDaniel Lianes
Varios
Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos16
Categoría2
Tipos de nodos9
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Julian Kaiser

Julian Kaiser

@jksr

Full Stack Developer turned AI & Automation Engineer, implementing intelligent solutions with custom code, LLMs & n8n. Use my link to book a free 30-minute call to discuss your AI challenges and see if my services might be a good fit for your needs.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34