¿Cómo integrar OpenAI Service con el flujo de un chatbot?
Integrar un servicio de inteligencia artificial como OpenAI en un chatbot puede ser un proceso desafiante pero gratificante. La posibilidad de mejorar la comunicación automatizada y ofrecer respuestas precisas da un valor añadido enorme a cualquier proyecto. Aquí te mostramos un proceso paso a paso para lograr esta integración usando Assistant State y OpenAI.
¿Cómo inicializar el estado del asistente?
Para comenzar, debes asegurarte de que el servicio OpenAI ya esté conectado y haya un prompt del sistema esperando un mensaje del usuario. La clave inicial es establecer el estado del asistente dentro del constructor de la lógica existente. Este estado, Assistant State, será crucial para saber cuándo pasar al flujo de preguntas y respuestas, permitiendo que la inteligencia artificial responda de manera adecuada.
// Inicialización del estado del asistenteconstructor(){this.assistantState={};}// Definición del estado al recibir mensaje del usuarioelseif(this.assistantState){// Lógica de manejo de estado}
¿Cómo detectar el estado del asistente?
El siguiente paso es modificar el manejo de los mensajes entrantes para que el sistema pueda detectar cuando el estado del asistente está presente. Esto permitirá desviarse al flujo adecuado de procesamiento, utilizando una serie de condicionales para manejar las diferentes lógicas.
// Detectar el estado y redireccionar el flujoelseif(this.assistantState&& messageFrom){awaitthis.handleAssistantFlow(messageFrom, incomingMessage);}
¿Cómo manejar el flujo del asistente?
Para manejar el flujo del asistente, es necesario implementar la lógica que interactúe con el servicio de OpenAI. Esto involucra crear una función llamada handleAssistantFlow y manejar el estado de interacción con el usuario.
// Implementación del flujo del asistenteasynchandleAssistantFlow(user, message){const state =this.assistantState[user.id];let response;if(state.step==='question'){ response =await openAIService.message(user.message);}// Enviando respuesta al usuarioawait whatsappService.sendMessage(user, response);// Lógica para botones de interacciónconst menuMessage ="¿La respuesta fue de ayuda?";const buttons =[{type:'reply',reply:{id:'option1',title:'Sí, gracias.'}},{type:'reply',reply:{id:'option2',title:'Hacer otra pregunta'}},{type:'reply',reply:{id:'option3',title:'Emergencia'}}];await whatsappService.sendInteraction(user, menuMessage, buttons);}
¿Cómo enviar interacciones basadas en botones?
Una característica poderosa es enviar interacciones que no solo se limitan a texto, sino también incluyen opciones de botón. Esta funcionalidad no solo mejora la experiencia del usuario, sino que también permite respuestas rápidas a situaciones de emergencia o seguimiento de preguntas.
// Ejemplo de estructura de botonesconst menuMessage ="¿La respuesta fue de ayuda?";const buttons =[{type:'reply',reply:{id:'option1',title:'Sí, gracias.'}},{type:'reply',reply:{id:'option2',title:'Hacer otra pregunta'}},{type:'reply',reply:{id:'option3',title:'Emergencia'}}];// Envío del menú de botonesawait whatsappService.sendInteraction(user, menuMessage, buttons);
¿Cómo probar y ajustar el flujo?
Una vez que toda la lógica esté en su lugar, es importante validar y probar el flujo completando varias interacciones, evaluando tanto la precisión de las respuestas del GPT como la funcionalidad de los botones de interacción. Invita a los usuarios a probar preguntando: "Mi perro tiene dos días sin querer comer y está vomitando", para recibir respuestas y verificar si las opciones de interacción funcionan correctamente. Sin embargo, recuerda personalizar cualquier mensaje automatizado conforme a la sensibilidad de los usuarios.
Sugerencias y mejoras
Siempre es recomendable recoger retroalimentación y ajustar el flujo según los comentarios de los usuarios. También, considerar envolver toda la lógica en pruebas para garantizar la integridad del sistema. Compartir en comunidad mejora significativamente la experiencia, además de que puedes comentar con otros desarrolladores tus PROM para enriquecer las capacidades y eficacia de las respuestas de GPT en diversos escenarios.
Integración de ChatGPT en Flujo de Mensajería con WhatsApp
La API de WhatsApp para los títulos de los botones de respuesta rápida puede tener un máximo de 20 caracteres en su título. Si pones uno mas totea. si pones 4 botones totea.
El profe llega al limite pero no lo dice, costo un chingo hallar el fallo
EJEMPLO
const buttons =[{type:"reply",reply:{id:"option_4",title:"Si"// Pasa: Este título tiene 2 caracteres, está dentro del límite de 20.}},{type:"reply",reply:{id:"option_5",title:"Tengo duda"// Pasa: Este título tiene 11 caracteres, está dentro del límite de 20.}},{type:"reply",reply:{id:"option_6",title:"Este título es demasiado largo"// No pasa: Tiene 29 caracteres, excede el límite de 20.}},];
Yo me base en la siguiente formula para tener un prompt efectivo [ROL] + [TAREA] + [INSTRUCCIONES] + [EJEMPLO/DATOS] y el resultado al cual llegue fue el siguiente:
"Eres un veterinario experto, tu tarea es responder todas las preguntas de los usuarios de la empresa Medpet, debes ser amable y coordial con los usuarios, en el momento que no tengas una respuesta clara deberas referirlo a un veterinario humano y que se dirija de forma fisica a un centro de atención, tus instrucciones son 1) Si el usuario te pregunta por algun medicamento deberas darle instrucciones especificas. 2) Asesorar a los usuarios con los posibles sintomas u enfermedades que tenga su mascota. 3) Si consideras que los sintomas de la mascota son graves debes indicarle que debe ir de forma inmediata a un centro asistencial Medpet 4) Solo puedes responder en ingles o español dependiendo del idioma en el cual te escriba el usuario, 5) Al inicio siempre pregunta por el nombre del usuario y a partir de alli llamalo por su nombre 6) Cuando el usuario te hable de su mascota, preguntale por su nombre y si te vas a referir a la mascota hazlo por su nombre, los datos de Medpet son los siguientes, es una cadena de centros asistenciales veterinario con muchos años de experiencia y con sedes en toda latinoamerica y dedicada a combinar tecnologia y veterinaria para el bienestar de las mascotas, su telefono de contacto es 477516242117521"
Mi repositorio es el siguiente donde me encuentro trabajando el proyecto:
Recomiendo trabajar con la API de ChatGPT, pero si no quieren o no pueden pagar tokens, también pueden consultar cómo crear un servicio con la API de Gemini de Google.
Pueden probar ambas opciones. Solo deben agregar un nuevo archivo dentro del proyecto con la integración de la API de Gemini de Google.
Es una opción conveniente porque ofrece un millón de tokens gratis, no impone pagos mínimos y, además, su lógica es bastante similar para adaptarla con cada clase.
Si OpenAI es de pago, tipo prepago, te ofrecen $5 de crédito gratis (sin necesidad de cargar una tarjeta) para que puedas experimentar con la API. La verdad es que este crédito es más que suficiente para hacer bastantes pruebas con prompts cortos, que consumen pocos tokens. El cobro se realiza por tokens, y el precio de estos varía según el modelo de GPT que configures. GPT-4 es bastante más caro que GPT-3.5, que es muy bueno para este caso. Yo implementé un chatbot, y la verdad es que funciona muy bien, aunque requiere dedicarle tiempo a elaborar buenos prompts
Pero anteriormente ya había usado los modelos de openAI y no tenía problema al usarlos. Pero actualmente a pesar de que tengo los $18 que se supone que te dan gratis cada mes, no me permite usar la api si no agrego un método de pago y una recarga de mínimo $5.
Si alguien sabe cómo funciona, le agradecería que me informe un poco :c
Yo lo adapte para usar con gemini ya que no pide algun pago para probarlo, cree otro archivo geminiAiService.js
import{GoogleGenAI}from"@google/genai";importconfigfrom"../config/env.js";const prompt ='Eres parte de un servicio de asistencia online y debes de comportarte como un veterinario de un comercio llamado "MedPet". Resuelve las preguntas lo más simple posible, con una explicación posible. Si es una emergencia o debe de llamarnos (MedPet). Debes de responde en texto simple como si fuera un mensaje de un bot conversacional, no saludes, no generas conversación, solo respondes con la pregunta del usuario.';const client =newGoogleGenAI({apiKey: config.GEMINI_API_KEY});constgeminiAiService=async(message)=>{try{const response =await client.models.generateContent({model:"gemini-2.5-flash",config:{systemInstruction: prompt,},contents: message,});return response.text;}catch(error){console.error(error);}};exportdefault geminiAiService;
En lugar de utilizar ChatGPT de OpenAI, utilice Claude de Antrhopic pero con una librería llamada de los creadores de NextJS, que nos ayuda a poder abstraer los modelos de IA que utilicemos o inclusive mezclarlos, les dejo la muestra de mi código.
ai.service.js
import{ createAnthropic }from"@ai-sdk/anthropic";import{ generateText }from"ai";importconfigfrom"../config/env.js";const anthropicClient =createAnthropic({apiKey: config.AI_API_KEY,});constAIService=async(message)=>{try{const{ text }=awaitgenerateText({model:anthropicClient("claude-3-7-sonnet-20250219"),messages:[{role:"system",content:"Comportarte como un veterinario, deberás de resolver las preguntas lo más simple posible. Responde en texto plano, como si fuera una conversación por WhatsApp, no saludes, no generas conversaciones, solo respondes con la pregunta del usuario.",},{role:"user",content: message,},],});return text;}catch(error){console.log("AI ERROR", error);}};exportdefaultAIService;````message.handler.js````js
if(state.step==='question'){ response =awaitAIService(message);}
Les dejo una actualización de la configuración de openAIServices.js para que sea más costo-eficiente:
Aquí tienes una versión optimizada de tu código para GPT-4o Mini, con el objetivo de minimizar los costos sin afectar la calidad de las respuestas. Se han agregado configuraciones adicionales para controlar el consumo de tokens y mejorar la eficiencia.
Se reduce el costo al limitar la cantidad de tokens generados (max_tokens).
Se optimiza la temperatura para un equilibrio entre creatividad y precisión.
Se añade frequency_penalty y presence_penalty para evitar respuestas demasiado largas o repetitivas.
Se asegura que las respuestas sean concisas y útiles.
importOpenAIfrom'openai';// Importar variables de entornoimportconfigfrom'../src/config/env.js';// Crear Cliente para que reciba la API Keyconst client =newOpenAI({apiKey: config.CHATGPT_API_KEY,});// Servicio de respuesta de ChatGPT optimizadoconstOpenAIService=async(message)=>{try{const response =await client.chat.completions.create({model:'gpt-4o-mini',// Modelo más costo-eficientemessages:[{role:'system',content:'Eres un veterinario experto de Medpet, una cadena de centros asistenciales veterinarios en Latinoamérica. Debes responder de forma concisa y clara, sin extenderte innecesariamente. Si un caso es grave, indica al usuario que acuda inmediatamente a un centro Medpet. Responde solo en el idioma en el que te escriban (inglés o español).'},{role:'user',content: message }],temperature:0.5,max_tokens:250,frequency_penalty:0.2,presence_penalty:0.1,});return response.choices[0].message.content;}catch(error){console.error('Error en OpenAIService:', error);return"Lo siento, ocurrió un error procesando tu solicitud.";}};exportdefaultOpenAIService;```importOpenAIfrom'openai';// Importar variables de entornoimportconfigfrom'../src/config/env.js';// Crear Cliente para que reciba la API Keyconst client =newOpenAI({  apiKey: config.CHATGPT\_API\_KEY,});// Servicio de respuesta de ChatGPT optimizadoconstOpenAIService=async(message)=>{ try{ const response =await client.chat.completions.create({  model:'gpt-4o-mini',// Modelo más costo-eficiente  messages: \[ {role:'system',content:'Eres un veterinario experto de Medpet, una cadena de centros asistenciales veterinarios en Latinoamérica. Debes responder de forma concisa y clara, sin extenderte innecesariamente. Si un caso es grave, indica al usuario que acuda inmediatamente a un centro Medpet. Responde solo en el idioma en el que te escriban (inglés o español).'}, {role:'user',content: message } ],  temperature:0.5,// Menos creatividad, respuestas más directas  max\_tokens:250,// Limita la longitud de la respuesta  frequency\_penalty:0.2,// Evita repeticiones innecesarias  presence\_penalty:0.1,// Evita respuestas redundantes }); return response.choices\[0].message.content; }catch(error){ console.error('Error en OpenAIService:', error); return"Lo siento, ocurrió un error procesando tu solicitud."; }};exportdefaultOpenAIService;