Herramientas de usuario

Herramientas del sitio


clase:iabd:pia:proyectos:agentes:paso2

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
clase:iabd:pia:proyectos:agentes:paso2 [2026/02/18 17:30] Lorenzoclase:iabd:pia:proyectos:agentes:paso2 [2026/02/19 17:03] (actual) – [Anexo Técnico: Emulación del Estándar OpenAI Chat Completions] Lorenzo
Línea 3: Línea 3:
 Este ejercicio consiste en crear un flujo de trabajo en n8n que actúe como un puente (proxy) entre un cliente de IA (Open WebUI) y los datos reales de la AEMET, procesados por un modelo local de Ollama. Este ejercicio consiste en crear un flujo de trabajo en n8n que actúe como un puente (proxy) entre un cliente de IA (Open WebUI) y los datos reales de la AEMET, procesados por un modelo local de Ollama.
  
-===== Paso 1: Webhook y Extracción de Datos de AEMET =====+===== Paso 1: Webhook y Extracción de Datos de AEMET (JSON Crudo) =====
  
-El primer objetivo es crear un punto de entrada que, al ser consultado, devuelva el JSON crudo de la estación meteorológica de Valencia.+El primer objetivo es crear un punto de entrada que, al ser consultado, devuelva el JSON técnico de la estación meteorológica de Valencia.
  
-**Configuración:** +**Configuración detallada:** 
-  * **Nodo Webhook:** Configurar en modo ''GET'' con el path ''clima-valencia''. +  * **Nodo Webhook:** * HTTP Method: ''GET'' 
-  * **Nodo HTTP Request (Autenticación):** Realizar una petición a la API de AEMET OpenData usando la API Key en las cabeceras+    * Path: ''clima-valencia'' 
-  * **Nodo HTTP Request (Descarga):** AEMET devuelve una URL temporal en el campo ''datos''Se debe realizar una segunda petición a esa URL dinámica+    * Response Mode: ''When Last Node Finishes'' 
-  * **Respuesta:** El flujo debe devolver el JSON con los datos climáticos (temperatura, humedad, viento).+  * **Nodo HTTP Request (Paso A):** * URL: ''https://opendata.aemet.es/opendata/api/observacion/convencional/datos/estacion/8416Y'' (Estación Valencia Aeropuerto). 
 +    * Header: Añadir llave ''api_key'' con tu token de AEMET OpenData. 
 +  * **Nodo HTTP Request (Paso B):** * AEMET no envía los datos directamente, envía un JSON con una URL en el campo ''datos'' 
 +    * Debes crear un segundo nodo HTTP Request cuya URL sea la expresión: ''{{ $json.datos }}''
 +  * **Resultado esperado:** Al llamar a la URL del Webhook, el navegador debe mostrar el array de datos meteorológicos (temperatura, humedad, etc.).
  
 +===== Paso 2: Integración de IA con Ollama (Procesamiento de Lenguaje) =====
  
 +Añadiremos una capa de inteligencia para que la respuesta no sea un JSON técnico, sino un informe humano.
  
-===== Paso 2Integración de IA con Ollama =====+**Instrucciones:** 
 +  1. Instalar y levantar **Ollama** con el modelo ''llama3'' o ''mistral''
 +  2. En n8n, añadir el nodo **Ollama** (o un AI Agent con el modelo Ollama). 
 +  3. Configurar el **Prompt**: 
 +     > "Actúa como un meteorólogo. Basándote en estos datos: Temperatura {{ $json[0].ta }}°C y Humedad {{ $json[0].hr }}%, genera un breve informe del tiempo en Valencia en español." 
 +  4. Ahora, el flujo debe devolver una cadena de texto amigable.
  
-Una vez tenemos los datos técnicos, añadimos una capa de inteligencia para que la respuesta no sea un JSON frío, sino un texto natural en castellano.+===== Paso 3: Emulación de la API de OpenAI (Modo Proxy) =====
  
-**Pasos:** +Este es el paso crítico. Para que **Open WebUI** reconozca nuestro n8n como si fuera "ChatGPT", debemos disfrazar la respuestaLas aplicaciones de IA no esperan un texto suelto, esperan un objeto JSON específico.
-  * Instalar el nodo **Ollama** en n8n+
-  * Conectar el resultado de AEMET al nodo de Ollama. +
-  * **Prompt Engineering:** Configurar el nodo para que actúe como meteorólogo. Ejemplo: //"Traduce estos datos: Temperatura {{ $json.ta }}°C a una frase amigable"//. +
-  * El flujo ahora devuelve una cadena de texto generada por el modelo local (ej. Llama 3).+
  
-===== Paso 3: Emulación de la API de OpenAI (Proxy) ===== +**Configuración Técnica para el alumno:** 
- +  * **Cambiar Webhook:** El método debe ser obligatoriamente ''POST'' y el path ''v1/chat/completions''
-Para que herramientas externas puedan usar nuestro flujo como si fuera un modelo oficial, debemos "disfrazar" la salida de n8n para que cumpla el estándar de OpenAI. +  * **Nodo Respond to Webhook:** Debes configurar el cuerpo de la respuesta en formato **JSON** con la siguiente estructura exacta:
- +
-**Cambios en el flujo:** +
-  * **Webhook:** Cambiar el método ''POST'' y el path ''v1/chat/completions''+
-  * **Nodo Respond to Webhook:** En lugar de devolver solo el texto, se debe construir un objeto JSON que contenga los campos requeridos''id'', ''object'', ''choices'', ''message'' y ''content''.+
  
 <code json> <code json>
 { {
 +  "id": "chatcmpl-n8n-aemet",
 +  "object": "chat.completion",
 +  "created": {{ Math.floor(Date.now() / 1000) }},
 +  "model": "aemet-valencia-bot",
   "choices": [   "choices": [
     {     {
 +      "index": 0,
       "message": {       "message": {
         "role": "assistant",         "role": "assistant",
-        "content": "Resultado de la IA aquí+        "content": "{{ $node["Ollama"].json.output }}
-      }+      }
 +      "finish_reason": "stop"
     }     }
-  ]+  ]
 +  "usage":
 +    "prompt_tokens": 0, 
 +    "completion_tokens": 0, 
 +    "total_tokens":
 +  }
 } }
 </code> </code>
  
 +**¿Por qué hacemos esto?**
 +  * **id/object/created:** Son campos de control que el estándar de OpenAI exige.
 +  * **choices:** Es una lista porque la API original permite devolver varias respuestas, aunque aquí solo enviamos la nuestra en la posición ''[0]''.
 +  * **content:** Es donde inyectamos el texto que generó Ollama en el paso anterior.
 +
 + 
 ===== Paso 4: Consumo desde Open WebUI ===== ===== Paso 4: Consumo desde Open WebUI =====
  
Línea 54: Línea 74:
   * Añadir la URL de nuestro webhook de n8n (omitiendo el final ''/v1/chat/completions'').   * Añadir la URL de nuestro webhook de n8n (omitiendo el final ''/v1/chat/completions'').
   * Seleccionar el nuevo modelo en el chat y comprobar que, al preguntar cualquier cosa, la IA responde con el clima real de Valencia obtenido de la AEMET.   * Seleccionar el nuevo modelo en el chat y comprobar que, al preguntar cualquier cosa, la IA responde con el clima real de Valencia obtenido de la AEMET.
 +  
 +===== Anexo Técnico: Emulación del Estándar OpenAI Chat Completions =====
 +
 +Para que una interfaz como **Open WebUI** o cualquier cliente compatible pueda consumir nuestro flujo de n8n, el Webhook debe comportarse exactamente como un servidor de OpenAI. Esto implica cumplir con una ruta específica y una estructura de respuesta estricta.
 +
 +==== 1. Configuración del Endpoint (Ruta) ====
 +
 +Open WebUI busca por defecto el recurso en la ruta estándar de la API de Chat. Por lo tanto, el nodo **Webhook** de n8n debe configurarse con:
 +
 +  * **HTTP Method:** ''POST''
 +  * **HTTP Path:** ''v1/chat/completions''
 +  * **Response Mode:** ''When Last Node Finishes'' (Esto es crítico: n8n debe esperar a que Ollama termine para responder al chat).
 +
 +==== 2. La Estructura del JSON de Respuesta ====
 +
 +El cliente de chat espera un objeto JSON complejo. Si n8n responde solo con texto plano, el chat dará un error de "Formato Inválido". El nodo final **Respond to Webhook** debe configurarse para devolver un **JSON** con esta estructura mínima:
 +
 +<code json>
 +{
 +  "id": "chatcmpl-n8n-aemet",
 +  "object": "chat.completion",
 +  "created": {{ Math.floor(Date.now() / 1000) }},
 +  "model": "aemet-valencia-bot",
 +  "choices": [
 +    {
 +      "index": 0,
 +      "message": {
 +        "role": "assistant",
 +        "content": "{{ $node["Ollama"].json.output }}"
 +      },
 +      "finish_reason": "stop"
 +    }
 +  ],
 +  "usage": {
 +    "prompt_tokens": 0,
 +    "completion_tokens": 0,
 +    "total_tokens": 0
 +  }
 +}
 +</code>
 +
 +==== 3. Desglose de Campos Clave ====
 +
 +| Campo | Función |
 +| **id** | Identificador único de la respuesta. Usamos un prefijo estático seguido de un ID aleatorio si se desea. |
 +| **created** | Marca de tiempo en formato Unix (segundos). En n8n usamos la expresión ''Math.floor(Date.now() / 1000)''. |
 +| **model** | Nombre que aparecerá en la interfaz del chat como "modelo activo". |
 +| **choices[0].message.content** | Aquí es donde insertamos la respuesta generada por el nodo de **Ollama**. Es el texto que el usuario leerá en su burbuja de chat. |
 +| **finish_reason** | Indica que la IA ha terminado de hablar. Debe ser ''"stop"'' para que el chat cierre la conexión correctamente. |
 +
 +==== 4. Conexión en el Cliente (Open WebUI) ====
 +
 +En la configuración de conexiones de Open WebUI:
 +  * La **Base URL** debe ser la URL de n8n hasta antes de la versión: Ej. ''https://n8n.tu-centro.es/webhook/''.
 +  * Automáticamente, el cliente añadirá ''v1/chat/completions'' al final de esa URL para realizar la petición POST.
clase/iabd/pia/proyectos/agentes/paso2.1771432243.txt.gz · Última modificación: por Lorenzo