Back to blog
    n8n IA local: reemplaza OpenAI con tu propio modelo ajustado
    n8nopenaifine-tuninglocal-aitutorialsegment:builder

    n8n IA local: reemplaza OpenAI con tu propio modelo ajustado

    Guía paso a paso para reemplazar las llamadas a la API de OpenAI en tus flujos de n8n con un modelo ajustado ejecutándose localmente. Reduce costos a cero sin sacrificar calidad.

    EErtas Team·

    Tus flujos de trabajo de n8n funcionan genial. Has construido automatizaciones que clasifican emails, extraen datos de facturas, puntúan leads y redactan mensajes de seguimiento — todo impulsado por nodos de OpenAI que entregan resultados de calidad de forma confiable.

    Pero cada uno de esos nodos de IA es un costo recurrente. Cada ejecución quema tokens. Cada token aparece en tu factura mensual. Y a medida que tus automatizaciones escalan — más flujos, más clientes, más volumen — esa factura crece en paralelo.

    ¿Y si pudieras ejecutar la misma calidad de IA, localmente, gratis por ejecución?

    Eso es lo que este tutorial te guía paso a paso. Al final, tendrás un modelo ajustado ejecutándose en Ollama, conectado a tus flujos de n8n, produciendo las mismas salidas de calidad que OpenAI — a cero costo por ejecución.

    No se requiere experiencia en ML. Sin scripting en Python. Solo los pasos específicos para pasar de "pagando a OpenAI por token" a "ejecutando tu propio modelo localmente."

    Lo que estamos construyendo

    Aquí está el estado final:

    ┌──────────────────────────────────────────┐
    │              n8n Workflow                  │
    │                                           │
    │  Trigger → Process → [AI Node] → Action   │
    │                        │                  │
    │                        ▼                  │
    │              HTTP Request Node            │
    │         POST localhost:11434/api/chat     │
    └──────────────────┬───────────────────────┘
                       │
                       ▼
    ┌──────────────────────────────────────────┐
    │            Ollama Server                  │
    │                                           │
    │  ┌─────────────────────────────────────┐ │
    │  │  Your Fine-Tuned Model (GGUF)       │ │
    │  │  Trained on YOUR workflow data      │ │
    │  │  Runs on CPU — no GPU needed        │ │
    │  └─────────────────────────────────────┘ │
    └──────────────────────────────────────────┘
    

    Tu flujo de n8n se activa exactamente como antes. En lugar de que el nodo OpenAI envíe una solicitud a api.openai.com (y cueste tokens), un nodo HTTP Request envía el mismo prompt a Ollama ejecutándose en tu máquina local o VPS. Ollama ejecuta tu modelo ajustado y devuelve el resultado. Mismo formato. Misma calidad. Cero costo de API.

    La idea clave: tu modelo ajustado está entrenado con los pares exactos de entrada/salida de tus flujos existentes de OpenAI. No necesita saber todo lo que GPT-4 sabe. Solo necesita replicar el comportamiento específico del que dependen tus flujos.

    Prerrequisitos

    Antes de empezar, asegúrate de tener:

    • Una instancia de n8n en funcionamiento — autoalojada o n8n cloud. Este tutorial asume que tienes flujos existentes con nodos de OpenAI.
    • Ollama instalado — en tu servidor de n8n, un VPS cercano o tu máquina local. Instalación: curl -fsSL https://ollama.com/install.sh | sh
    • Una cuenta de Ertas — para ajustar tu modelo sin código. Regístrate en ertas.io ($14.50/mes).
    • Historial de ejecuciones del flujo — al menos 200 ejecuciones exitosas del flujo que quieres convertir. Más es mejor.

    Requisitos de hardware para Ollama:

    ConfiguraciónEspecificacionesCosto mensual
    Mismo servidor que n8n4+ vCPU, 16GB+ RAMYa estás pagando por él
    VPS separado4 vCPU, 16GB RAM~$30/mes
    Máquina localCualquier laptop moderno con 16GB RAM$0

    Un modelo de 7B parámetros con cuantización Q4 usa aproximadamente 4-5GB de RAM. Si tu servidor de n8n tiene 16GB+ de RAM, puedes ejecutar Ollama junto con n8n en la misma máquina sin problemas.

    Paso 1: exporta tus datos de entrenamiento de OpenAI

    Tus flujos existentes han estado generando datos de entrenamiento cada vez que se ejecutan. Cada ejecución contiene la entrada que se envió a OpenAI y la salida que regresó. Eso es exactamente lo que necesitamos para ajustar un modelo.

    Identifica el flujo objetivo

    Elige el flujo que quieres convertir primero. El candidato ideal es:

    • Alto volumen — se ejecuta más de 50 veces por día (mayores ahorros de costos)
    • Tarea específica — clasificación, extracción o generación con plantilla (más fácil de ajustar)
    • Calidad consistente — las salidas de OpenAI son confiablemente buenas (datos de entrenamiento limpios)

    Extrae pares de entrada/salida

    Método 1: extracción manual desde la UI de n8n

    1. Abre el flujo objetivo en n8n
    2. Haz clic en "Executions" en la barra lateral
    3. Filtra por estado "Success"
    4. Haz clic en cada ejecución y encuentra el nodo OpenAI
    5. Registra la entrada (el array de mensajes enviado a OpenAI) y la salida (el contenido de la respuesta)
    6. Formatea como JSONL:
    {"input": "Classify this email: Hi, I'd like to cancel my subscription...", "output": "cancellation"}
    {"input": "Classify this email: When will my order arrive?", "output": "shipping_inquiry"}
    {"input": "Classify this email: The product broke after 2 days...", "output": "defect_report"}
    

    Esto funciona para recopilar 50-100 ejemplos pero se vuelve tedioso para datasets más grandes.

    Método 2: extracción automatizada vía API de n8n

    Crea un flujo de n8n separado que extraiga datos de ejecución programáticamente:

    1. Agrega un nodo HTTP Request que llame a la API de n8n:

      • URL: http://localhost:5678/api/v1/executions?workflowId=YOUR_WORKFLOW_ID&status=success&limit=500
      • Agrega tu clave API de n8n en los headers
    2. Agrega un nodo Code para extraer y formatear los datos del nodo de IA:

    const executions = $input.all();
    const trainingData = [];
    
    for (const exec of executions) {
      const nodes = exec.json.data?.resultData?.runData;
      if (nodes && nodes['OpenAI']) {
        const openaiNode = nodes['OpenAI'][0];
        const input = openaiNode.data?.main?.[0]?.[0]?.json?.messages;
        const output = openaiNode.data?.main?.[0]?.[0]?.json?.choices?.[0]?.message?.content;
    
        if (input && output) {
          const userMessage = input.find(m => m.role === 'user')?.content || '';
          trainingData.push({
            input: userMessage,
            output: output
          });
        }
      }
    }
    
    return [{ json: { trainingData, count: trainingData.length } }];
    
    1. Agrega un nodo Write File para guardar la salida como archivo JSONL.

    Método 3: recopilación de datos prospectiva

    Si aún no tienes suficiente historial de ejecuciones, agrega un paso de registro a tu flujo actual. Inserta un nodo Code después de tu nodo OpenAI que agregue cada par de entrada/salida a un archivo o base de datos. Ejecútalo por 1-2 semanas hasta tener más de 300 ejemplos.

    ¿Cuántos datos necesitas?

    Tipo de tareaMínimoPunto óptimoRendimientos decrecientes
    Clasificación binaria (sí/no)100 pares250 pares500+ pares
    Clasificación multiclase200 pares500 pares1,000+ pares
    Extracción de datos (estructurada)200 pares500 pares1,000+ pares
    Generación de texto corto300 pares800 pares2,000+ pares
    Resumen300 pares1,000 pares3,000+ pares

    Apunta a la columna del "punto óptimo". Obtendrás buenos resultados en el mínimo, pero el punto óptimo te da un modelo que maneja mejor los casos extremos.

    Limpia tus datos

    Antes de subir, haz una revisión rápida de calidad:

    • Elimina salidas fallidas. Si OpenAI devolvió un error o una respuesta sin sentido, descarta ese par.
    • Elimina duplicados. Los pares duplicados exactos de entrada/salida no ayudan. Conserva una copia.
    • Verifica consistencia. Si entradas similares produjeron salidas muy diferentes, investiga. Tu modelo aprenderá el promedio — datos de entrenamiento inconsistentes producen salidas inconsistentes.
    • Estandariza formato. Asegúrate de que todas tus salidas sigan el mismo formato (por ejemplo, todas las etiquetas de clasificación en minúsculas, todas las salidas JSON usen el mismo esquema).

    Paso 2: ajusta tu modelo con Ertas

    Ahora tienes un dataset limpio. Es hora de convertirlo en un modelo.

    Sube tus datos

    1. Inicia sesión en Ertas Studio en app.ertas.io
    2. Crea un nuevo proyecto (nómbralo como tu flujo, por ejemplo "Email Classifier" o "Invoice Extractor")
    3. Haz clic en "Upload Dataset" y arrastra tu archivo JSONL
    4. Ertas valida el archivo y te muestra una vista previa — verifica que algunos ejemplos se vean correctos

    Selecciona tu modelo base

    Para tareas de automatización en n8n, estas son las opciones recomendadas:

    Modelo baseMejor paraVelocidad de inferenciaCalidad
    Qwen 2.5 7BClasificación, extracción, salida estructuradaRápidoExcelente
    Llama 3.3 8BGeneración, resumen, salidas más largasRápidoExcelente
    Mistral 7BAutomatización de alto rendimiento, salidas cortasMás rápidoMuy bueno

    Nuestra recomendación para la mayoría de los flujos de n8n: Qwen 2.5 7B. Maneja tareas estructuradas excepcionalmente bien y produce salidas limpias y consistentes — exactamente lo que los flujos de automatización necesitan.

    Configura el entrenamiento

    Ertas auto-configura los parámetros de entrenamiento basándose en tu dataset:

    • Rango LoRA: Seleccionado automáticamente según la complejidad de la tarea (típicamente 16-32 para tareas de automatización)
    • Learning rate: Optimizado para el tamaño de tu dataset
    • Épocas: Usualmente 3-5 para datasets de automatización
    • Split de validación: 10% de tus datos se reserva para evaluación

    Puedes ajustar estos si quieres, pero los valores por defecto están optimizados para casos de uso de automatización y funcionan bien desde el inicio.

    Inicia el entrenamiento

    Haz clic en "Start Training." Dependiendo del tamaño de tu dataset:

    • 200-500 ejemplos: ~15-20 minutos
    • 500-1,000 ejemplos: ~25-35 minutos
    • 1,000+ ejemplos: ~35-50 minutos

    Puedes observar la curva de pérdida de entrenamiento en tiempo real. Para tareas de automatización, típicamente ves que la pérdida cae bruscamente en la primera época y se estabiliza para la época 3.

    Evalúa resultados

    Cuando el entrenamiento se completa, Ertas te muestra:

    • Métricas de precisión: Para tareas de clasificación, obtienes precisión, recall y puntuaciones F1 desglosadas por clase.
    • Comparaciones lado a lado: Las salidas de tu modelo ajustado vs. las salidas originales de GPT-4 para ejemplos de prueba.
    • Predicciones de muestra: Ejecuta cualquier entrada a través del modelo y ve la salida al instante.

    Qué buscar:

    • Precisión de clasificación por encima del 90% (para categorías bien definidas)
    • Completitud de extracción (todos los campos capturados)
    • Calidad de generación (se lee naturalmente, coincide con el formato esperado)

    Si la calidad no está donde la necesitas, las correcciones más comunes son:

    1. Agrega más ejemplos de entrenamiento (especialmente para categorías con bajo rendimiento)
    2. Limpia pares de entrenamiento inconsistentes
    3. Aumenta el rango LoRA (de 16 a 32)

    Paso 3: exporta a GGUF y carga en Ollama

    Exporta desde Ertas

    1. En tu proyecto de Ertas, haz clic en "Export Model"
    2. Selecciona formato GGUF
    3. Elige cuantización Q4_K_M — este es el balance óptimo entre calidad y tamaño de archivo para modelos 7B:
    CuantizaciónTamaño de archivo (7B)CalidadVelocidad
    Q8_0~7.5GBMás altaMás lento
    Q5_K_M~5.5GBMuy altaMedia
    Q4_K_M~4.5GBAltaRápido
    Q3_K_M~3.5GBBuenaMás rápido

    Q4_K_M te da aproximadamente el 99% de la calidad al 60% del tamaño de archivo comparado con Q8. Para tareas de automatización donde las salidas son cortas y estructuradas, la diferencia de calidad es insignificante.

    1. Descarga el archivo GGUF. Se llamará algo como email-classifier-q4km.gguf.

    Carga en Ollama

    Transfiere el archivo GGUF a tu servidor (la máquina ejecutando Ollama):

    scp email-classifier-q4km.gguf user@your-server:/home/user/models/
    

    Crea un Modelfile que le dice a Ollama cómo servir tu modelo:

    FROM /home/user/models/email-classifier-q4km.gguf
    
    PARAMETER temperature 0.1
    PARAMETER num_ctx 4096
    PARAMETER stop "<|im_end|>"
    

    Parámetros clave:

    • temperature 0.1 — Temperatura baja para salidas consistentes y determinísticas. Crítico para tareas de automatización.
    • num_ctx 4096 — Tamaño de la ventana de contexto. Aumenta si tus entradas son más largas.
    • stop token — Depende de tu modelo base. Qwen usa el token im_end, Llama usa el token de fin de secuencia.

    Crea el modelo en Ollama:

    ollama create email-classifier -f Modelfile
    

    Pruébalo:

    ollama run email-classifier "Classify this email: Hi, I need to change my shipping address for order #4521."
    

    Deberías obtener una respuesta como shipping_inquiry — coincidiendo con el formato que tu flujo espera.

    Verifica el endpoint de la API

    Ollama sirve una API REST en el puerto 11434 por defecto. Pruébalo con curl:

    curl http://localhost:11434/api/chat -d '{
      "model": "email-classifier",
      "messages": [
        {
          "role": "system",
          "content": "Classify the following email into one of these categories: cancellation, shipping_inquiry, defect_report, billing_question, general_inquiry"
        },
        {
          "role": "user",
          "content": "Hi, I was charged twice for my last order."
        }
      ],
      "stream": false
    }'
    

    Respuesta esperada:

    {
      "model": "email-classifier",
      "message": {
        "role": "assistant",
        "content": "billing_question"
      }
    }
    

    Si esto funciona, estás listo para conectarlo a n8n.

    Paso 4: crea el nodo de Ollama en n8n

    Ahora el cambio real del flujo. Abre el flujo de n8n que quieres convertir.

    Opción A: reemplaza con nodo HTTP Request (recomendado)

    Esto te da control total sobre la solicitud y funciona con cualquier versión de n8n.

    1. Desactiva el nodo OpenAI (no lo elimines todavía — lo querrás para pruebas de comparación)

    2. Agrega un nodo HTTP Request justo donde estaba el nodo OpenAI

    3. Configura el nodo HTTP Request:

    Método: POST

    URL: http://localhost:11434/api/chat

    (Si Ollama está en un servidor diferente, usa la IP de ese servidor en lugar de localhost)

    Headers:

    • Content-Type: application/json

    Body (JSON):

    {
      "model": "email-classifier",
      "messages": [
        {
          "role": "system",
          "content": "Classify the following email into one of these categories: cancellation, shipping_inquiry, defect_report, billing_question, general_inquiry"
        },
        {
          "role": "user",
          "content": "={{ $json.email_body }}"
        }
      ],
      "stream": false,
      "options": {
        "temperature": 0.1
      }
    }
    

    Reemplaza $json.email_body con cualquier expresión que referencie los datos de entrada del nodo anterior en tu flujo.

    1. Agrega un nodo Code después del HTTP Request para extraer la respuesta:
    const response = $input.first().json;
    const result = response.message?.content?.trim() || response.response?.trim() || '';
    
    return [{
      json: {
        classification: result,
        model: response.model,
        raw_response: response
      }
    }];
    
    1. Conecta la salida del nodo Code a lo que sigue en tu flujo (el mismo nodo al que estaba conectado el nodo OpenAI).

    Opción B: usa el endpoint compatible con OpenAI

    Ollama también sirve una API compatible con OpenAI en /v1/chat/completions. Si tu versión de n8n tiene un nodo OpenAI que te permite cambiar la URL base, puedes:

    1. Abrir la configuración del nodo OpenAI
    2. Cambiar la URL base a http://localhost:11434/v1
    3. Establecer el modelo como email-classifier
    4. Eliminar la clave API (o establecer cualquier valor ficticio — Ollama no necesita una)

    Este enfoque requiere menos cambios en el flujo pero depende de que tu versión de n8n soporte URLs base personalizadas en el nodo OpenAI.

    Opción C: nodo nativo de Ollama

    Las versiones recientes de n8n (1.20+) incluyen integración nativa de Ollama en la sección de nodos de IA. Si está disponible:

    1. Agrega el nodo Ollama Chat Model
    2. Establece la URL base a http://localhost:11434
    3. Selecciona el nombre de tu modelo
    4. Conéctalo a tu flujo

    Esta es la opción más simple pero te da el menor control sobre los parámetros de la solicitud.

    Paso 5: prueba y compara

    Antes de ponerlo en producción, ejecuta una prueba de comparación adecuada.

    Prueba A/B de tu flujo

    1. Mantén tanto el nodo OpenAI como el nodo Ollama en tu flujo
    2. Agrega un nodo Switch antes de ellos que envíe el 50% de las ejecuciones a cada uno
    3. Agrega nodos de registro después de cada uno para capturar las salidas
    4. Ejecuta más de 100 ejecuciones reales a través del split

    Compara salidas

    Después de recopilar datos de comparación, evalúa:

    Para tareas de clasificación:

    MétricaOpenAI (GPT-4)Fine-tuned local
    PrecisiónLínea baseComparar
    Consistencia (misma entrada, misma salida)~95%~99%
    Velocidad2-5 segundos0.3-1 segundo

    Un modelo ajustado es típicamente más consistente que GPT-4 para clasificación porque ha sido entrenado específicamente en tus categorías y no exhibe la variación creativa que los modelos de propósito general tienen.

    Para tareas de extracción:

    MétricaOpenAI (GPT-4)Fine-tuned local
    Completitud de camposLínea baseComparar
    Adherencia al formato (JSON válido, etc.)~92%~97%
    Velocidad3-8 segundos0.5-2 segundos

    Los modelos ajustados tienden a producir formatos de salida más consistentes porque han aprendido tu esquema específico a través del entrenamiento, en lugar de seguir instrucciones de esquema a través de prompting.

    Para tareas de generación:

    MétricaOpenAI (GPT-4)Fine-tuned local
    Calidad (subjetivo)Línea baseComparar
    Consistencia de tonoVariableConsistente
    Velocidad3-10 segundos1-3 segundos

    Las tareas de generación son las más subjetivas. Pasa 20-30 salidas a un revisor humano y puntúalas en una escala de 1-5 por calidad y adecuación.

    Benchmarks de rendimiento

    Aquí hay datos de rendimiento del mundo real para tareas comunes de automatización en n8n ejecutándose en un VPS de $30/mes (4 vCPU, 16GB RAM) con un modelo ajustado Qwen 2.5 7B:

    MétricaAPI OpenAI (GPT-4)Fine-tuned local (7B)
    Tiempo de respuesta (clasificación)1.5-3.0 segundos0.2-0.5 segundos
    Tiempo de respuesta (extracción)2.0-5.0 segundos0.4-1.0 segundos
    Tiempo de respuesta (generación)3.0-8.0 segundos0.8-2.5 segundos
    Rendimiento (solicitudes/segundo)Limitado por nivel de tasa10-20 sol/seg
    Costo por ejecución$0.02-0.10$0.00
    Costo mensual (1K ejec/día)$600-3,000$44.50 fijo
    Costo mensual (10K ejec/día)$6,000-30,000$44.50 fijo
    Dependencia de uptimePágina de estado de OpenAITu servidor
    Los datos salen de tu infraNo

    La ventaja de rendimiento es significativa para flujos por lotes. Si tienes un flujo que procesa 500 emails cada mañana, la versión con OpenAI toma 12-25 minutos (limitada por tasa). La versión local se completa en 25-50 segundos.

    Solución de problemas comunes

    Modelo demasiado lento

    Síntoma: Las respuestas toman más de 5 segundos para tareas simples.

    Soluciones:

    • Revisa el uso de CPU del VPS — si está al 100%, necesitas más vCPUs o una máquina más potente
    • Usa cuantización Q4_K_M en lugar de Q8 — mitad de memoria, 30% más rápido
    • Reduce num_ctx si tus entradas son cortas — una ventana de contexto de 2048 es más rápida que 4096
    • Asegúrate de que no haya otros procesos pesados ejecutándose en el mismo servidor

    Caída de calidad comparada con OpenAI

    Síntoma: Las salidas son notablemente peores de lo que GPT-4 estaba produciendo.

    Soluciones:

    • Más datos de entrenamiento. La corrección más común. Pasa de 200 a más de 500 ejemplos.
    • Datos de entrenamiento más limpios. Elimina cualquier ejemplo donde la salida de OpenAI fue incorrecta o inconsistente.
    • Datos más representativos. Si ciertas categorías o tipos de entrada están subrepresentados, agrega más ejemplos de esos específicamente.
    • Rango LoRA más alto. Si usaste rango 8 o 16, prueba 32. Esto le da al modelo más capacidad para aprender tu tarea.
    • Prueba un modelo base diferente. Si Mistral 7B no da la talla, prueba Qwen 2.5 7B o Llama 3.3 8B. Diferentes modelos base tienen diferentes fortalezas.

    Errores de longitud de contexto

    Síntoma: El modelo devuelve basura o errores en entradas más largas.

    Soluciones:

    • Aumenta num_ctx en tu Modelfile (por ejemplo, de 4096 a 8192)
    • Nota: contexto más grande usa más RAM. Un modelo 7B con contexto de 8K necesita ~6GB de RAM.
    • Si tus entradas regularmente superan los 4K tokens, considera truncar o resumir la entrada antes de enviarla al modelo
    • Para entradas muy largas (más de 8K tokens), considera un enfoque de dos etapas: primero resume, luego clasifica/extrae del resumen

    Ollama no responde

    Síntoma: n8n obtiene errores de conexión rechazada o timeout.

    Soluciones:

    • Verifica que Ollama esté corriendo: systemctl status ollama u ollama list
    • Revisa el puerto: curl http://localhost:11434/api/tags debería devolver una respuesta JSON
    • Si n8n está en una máquina diferente, asegúrate de que Ollama esté enlazado a 0.0.0.0: establece OLLAMA_HOST=0.0.0.0 en la configuración de entorno de Ollama
    • Revisa reglas de firewall: el puerto 11434 debe ser accesible desde la máquina de n8n
    • Revisa RAM: si el servidor se quedó sin memoria, Ollama pudo haber fallado. dmesg | grep -i oom mostrará kills por falta de memoria.

    Formato de salida inconsistente

    Síntoma: El modelo a veces devuelve "billing_question" y a veces "Billing Question" o "The category is billing_question."

    Soluciones:

    • Agrega un paso de post-procesamiento en n8n (nodo Code) que normalice la salida: minúsculas, eliminar espacios en blanco, quitar prefijos
    • Mejora la consistencia de los datos de entrenamiento — asegúrate de que todos tus ejemplos de entrenamiento usen exactamente el mismo formato
    • Baja la temperatura a 0.05 (casi determinístico)
    • Agrega un prompt de sistema que especifique explícitamente el formato de salida

    Puesta en producción

    Una vez que hayas validado la calidad y resuelto cualquier problema:

    1. Elimina el split A/B — enruta el 100% del tráfico al modelo local
    2. Mantén el nodo OpenAI desactivado (no eliminado) como respaldo durante la primera semana
    3. Monitorea por 7 días — revisa las salidas diariamente, compara tasas de error
    4. Después de 7 días: Si todo se ve bien, elimina el nodo OpenAI y remueve la clave API de las credenciales de n8n
    5. Establece un calendario de reentrenamiento — cada 4-8 semanas, exporta nuevos datos de ejecución y reentrena el modelo con el dataset expandido

    Tus flujos de n8n ahora se ejecutan con cero costos de API. Cada ejecución es gratis. Escala al 10x del volumen y tu factura se mantiene exactamente igual: $14.50 por Ertas más $30 por tu VPS.

    Son $44.50/mes por automatización de IA ilimitada. Sin tokens. Sin límites de tasa. Sin facturas sorpresa.


    Ship AI that runs on your users' devices.

    Ertas early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Lectura adicional

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading