Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-user-avatar domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/planetac/public_html/wp-includes/functions.php on line 6114
Construir Chatbot con IA usando Chainlit, OpenAI y Literal AI - Planeta Chatbot

Tabla de contenidos

¿Por qué crear chatbots con IA?

Un chatbot generado con IA cambia la forma en que las empresas interactúan con sus clientes. Pueden realizar tareas repetitivas, como responder a preguntas comunes, ayudar con las reservas y recomendar productos, todo en tiempo real. Funcionan 24 horas al día, 7 días a la semana, ofreciendo una asistencia rápida y personalizada a los clientes y ayudándoles a ahorrar tiempo y dinero.

¿Qué es Chainlit?

Chainlit es una herramienta que facilita la creación de chatbots con IA que pueden mantener conversaciones inteligentes. Está diseñado para trabajar sin problemas con los modelos de IA como GPT de OpenAI, ayudando a crear chatbots que se sienten más naturales y humanos. Aquí están algunas características interesantes de Chainlit:

  • Interfaz fácil: Crea rápidamente interfaces de chat que son simples y fáciles de usar con soporte para extensión.
  • Integraciones: Conéctate directamente a cualquiera de estos frameworks y LLMs para conversaciones inteligentes y potenciadas por IA. (FastAPI, Mistral AI, OpenAI, LangChain, Llama Index, LiteLLM, Haystack, Embedchain, vLLM, LMStudio, HuggingFace).
  • Maneja múltiples entradas: No sólo admite texto, sino también la carga de archivos y otras interacciones del usuario.
  • Seguimiento de conversaciones: Realiza un seguimiento de los chats para que los usuarios puedan continuar donde lo dejaron. Mantenga conversaciones persistentes utilizando LiteralAI, SQLAlchemy o DynamoDB.
  • Gestión de chats: Los usuarios pueden renombrar y gestionar sus hilos de conversación fácilmente.
  • Inicio de sesión de usuario: Admite Google, GitLab, Auth0, Azure Directory y muchos más backends de autenticación para facilitar el acceso.
  • Plataformas: Web App, Copilot, API, React, Teams, Slack, Discord.

Ahora que sabemos por qué la IA Powered chatbots son importantes y qué herramientas tenemos para construirlo. Empecemos a construirlo haciendo un ejemplo de chatbot usando Python, Chainlit, OpenAI y LiteralAI. Llamaremos a este chatbot DineBot ya que intentará ayudar a los restaurantes tomando sus pedidos y tratando con los clientes.

Configurar el entorno Python para el Chatbot

Vamos a crear un directorio para el DineBot.

mkdir dinebot

Asegúrate de que Python está instalado (se recomienda la versión 3.10+). A continuación, crea un entorno virtual para mantener las cosas organizadas en un entorno aislado:

python -m venv .venv

Activar entorno virtual

source .venv/bin/activate

Instala las bibliotecas necesarias para Chainlit, OpenAI y LiteralAI

pip install chainlit openai literalai

El entorno DineBot ya está listo. Empecemos a utilizar chainlit y construyamos una versión básica del chatbot.

Inicializar el proyecto Chatbot con Chainlit

Asegúrate de que estás en el mismo directorio, es decir, dinebot que hemos creado anteriormente y el entorno virtual está activado.

Ahora ejecuta el comando chainlit init en la terminal

chainlit init 

Esto creará los archivos básicos y la estructura para tu chatbot que debe tener este aspecto

Created default config file at dinebot/.chainlit/config.toml
Created default translation directory at dinebot/.chainlit/translations
Created default translation file at dinebot/.chainlit/translations/gu.json
Created default translation file at dinebot/.chainlit/translations/hi.json
Created default translation file at dinebot/.chainlit/translations/ml.json
Created default translation file at dinebot/.chainlit/translations/en-US.json
Created default translation file at dinebot/.chainlit/translations/mr.json
Created default translation file at dinebot/.chainlit/translations/ta.json
Created default translation file at dinebot/.chainlit/translations/te.json
Created default translation file at dinebot/.chainlit/translations/he-IL.json
Created default translation file at dinebot/.chainlit/translations/zh-CN.json
Created default translation file at dinebot/.chainlit/translations/bn.json
Created default translation file at dinebot/.chainlit/translations/kn.json
Config file already exists at dinebot/.chainlit/config.toml

Configurar el Chatbot

Crea un nuevo archivo Python llamado app.py en el directorio del proyecto. Este archivo contendrá la lógica para tomar las consultas de los usuarios y comunicarse con LLM para obtener una respuesta a la consulta.

import chainlit as cl


@cl.on_message
async def main(message: cl.Message):

# Send a response back to the user
user_message = f"Received: {message.content}"
await cl.Message(content=user_message).send()

En primer lugar, importamos el paquete chainlit y definimos una función que gestionará los mensajes entrantes de la interfaz de usuario del chatbot. A continuación, decoramos la función con el decorador @cl.on_message para asegurarnos de que se llama cada vez que un usuario introduce un mensaje.

La función principal será llamada cada vez que un usuario introduzca un mensaje en la interfaz de usuario del chatbot. Puedes poner tu lógica personalizada dentro de la función para procesar la entrada del usuario, como analizar el texto, llamar a una API o calcular un resultado.

La clase Message es responsable de enviar una respuesta al usuario. En este ejemplo, simplemente enviamos un mensaje que contiene la entrada del usuario.

Ejecutar ChatBot

Ejecuta el siguiente comando para iniciar el Chatbot:

chainlit run app.py --watch --port 8000

La bandera –watch le dice a Chainlit que habilite la auto-reloading, para que no tengas que reiniciar el servidor cada vez que hagas cambios en tu aplicación. Su interfaz de chatbot ahora debería ser accesible en http://localhost:8000

Por ahora, este chatbot responderá a todo lo que le envíes, ya que aún no hemos integrado ningún LLM.

Entrenar al chatbot para que actúe como asistente de restaurante

Vamos a hacer que el bot sea un poco más interactivo añadiendo algunas instrucciones de ejemplo que expliquen cómo debería funcionar cuando los usuarios interactúen con el bot.

Crea un nuevo archivo Python llm.py en el directorio raíz del proyecto.

import chainlit as cl
from openai import AsyncOpenAI

system_message = """
You are a restuarants Chatbot.
An automated service to collect orders for restuarants online.
Please process the conversation in this order:
- Take the order.
- Ask if the order will be delivered or picked.
- in case of delivery, ask for the delivery address.
- in case of pickup, give the restaurant address for self pick up.
- Upon collecting order, first summarize the order for customer, confirm order and address if delivery, from the customer.
- Ask for payment whether to be cash on delivery or want to pay via card.
- once confirmed, show the final order with prices, delivery or pickup and payment details.
- Say good bye with a progressional way.

Restaurants and Menu:

## 1. **Din Tai Fung** (Taiwanese)
Known for its meticulous and delicious dumplings, Din Tai Fung offers a variety of Taiwanese dishes.

### Menu:

#### Appetizers
- **Cucumber Salad**: $5.00
- **Seaweed & Beancurd in Vinegar Dressing**: $6.00

#### Rice & Soups
- **Fried Rice with Shrimp & Egg**: $11.00
- **Hot & Sour Soup**: $6.00

---

## 2. **Narisawa** (Japanese - Tokyo)
Michelin-starred Narisawa fuses French techniques with traditional Japanese ingredients, focusing on seasonality and environmental sustainability.

### Menu:
#### Seasonal Starters
- **Japanese Seasonal Vegetables**: $20.00
- **Firefly Squid with Seasonal Ingredients**: $22.00

#### Main Course
- **Charcoal Grilled Wagyu Beef**: $55.00
- **Seasonal Fish**: $40.00

---

## 3. **Gaggan Anand** (Indian - Bangkok)
Gaggan Anand is renowned for his innovative twist on traditional Indian cuisine, often presented in a tasting menu format.

### Menu:
#### Small Bites
- **Yoghurt Explosion**: $6.00
- **Edible Plastic Spicy Salad**: $8.00

#### Tandoor
- **Tandoori Chicken**: $15.00
- **Paneer Tikka**: $12.00

---

"""

client = AsyncOpenAI()

messages = [
{'role': 'system', 'content': system_message},
]

async def take_order(message: cl.Message, model="gpt-4o-mini", temperature=0.5):

messages.append(
{'role': 'user', 'content': message.content}
)

message = cl.Message(content="")

response = await client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
stream=True
)

async for part in response:
if token := part.choices[0].delta.content or "":
await message.stream_token(token)

messages.append(
{'role': 'assistant', 'content': message.content}
)

await message.update()

Primero estamos importando chainlit para interactuar con chainlit y luego importando OpenAI para enviar peticiones API al modelo GPT de OpenAI.

A continuación, estamos añadiendo un mensaje de sistema para el asistente OpenAI GPT proporcionando una lista de restaurantes, su menú y los precios de cada elemento en el menú.

La función take_order aceptará cualquier mensaje que el usuario haya enviado. Añadirá este nuevo mensaje del usuario a la lista de mensajes, incluyendo el mensaje del sistema y cualquier mensaje anterior del usuario.

La razón por la que estamos extendiendo la lista de mensajes es que LLM siempre necesita un contexto para el chat en curso. Así que cada vez que recibimos un nuevo mensaje del usuario, lo añadimos a la lista de mensajes y luego pasamos esa misma lista de mensajes al modelo GPT de OpenAI.
Cualquiera que sea la respuesta que obtengamos del modelo GPT, añadimos el contenido del mensaje al objeto chainlit para que chainlit pueda actualizarlo en la interfaz de usuario.

Ahora sólo tenemos que llamar a la función take_order cuando un usuario envía un mensaje desde la interfaz de usuario. Así que vamos a actualizar nuestro app.py que debería verse así ahora.

import chainlit as cl
from llm import take_order


@cl.on_chat_start
async def on_chat_start():
welcome_message = 'Welcome to DineBot. How can I assist you today regarding placing an order?'
msg = cl.Message(content=welcome_message)
await msg.send()


@cl.on_message
async def main(message: cl.Message):
await take_order(message)

Cuando se carga la aplicación, el chatbot primero saludará al usuario usando la función on_chat_start y luego empezará a tomar pedidos del usuario usando la función main.

Antes de ejecutar nuestro Dinebot, vamos a añadir un archivo .env y añadir los siguientes env vars.

CHAINLIT_PORT=8000
OPENAI_API_KEY="sk-proj-****" # Replace your OpenAI key here

Ahora ejecuta el comando chainlit run y nuestro Dinbot debería estar listo para empezar a recibir órdenes.

chainlit run app.py --watch

Visita Dinebot en http://localhost:8000 e intenta hacer algunos pedidos.

Activar la autenticación

Es necesario habilitar la autenticación para que el historial de chat sea persistente

Las aplicaciones Chainlit son públicas por defecto. Para habilitar la autenticación y hacer tu aplicación privada, es necesario definir una variable de entorno CHAINLIT_AUTH_SECRET. Esta es una cadena secreta que se utiliza para firmar los tokens de autenticación. Puedes cambiarla en cualquier momento, pero cerrará la sesión de todos los usuarios. Puedes generar una fácilmente usando chainlit create-secret y añadirla al archivo .env

CHAINLIT_AUTH_SECRET="7U*qm1dwwDXDv@E*S,o34A9VB/dM4DGw*lm>-tVA7TkAa@bWOCW"

Ahora añade este snippet al archivo app.py para una autenticación básica basada en usuario y contraseña. Si deseas agregar OAuth, por favor echa un vistazo aquí.

@cl.password_auth_callback
def auth_callback(username: str, password: str):

# Fetch the user matching username from your database
# and compare the hashed password with the value stored in the database
if (username, password) == ("admin", "admin"):
return cl.User(
identifier="admin", metadata={"role": "admin", "provider": "credentials"}
)
else:
return None

Ahora, cuando recargues tu chatbot, te redirigirá automáticamente a la página de inicio de sesión. Introduce el nombre de usuario admin y la contraseña admin para iniciar sesión en el chatbot.

Hacer Persistente el Historial de Chat

Si recargas la página, no verás lo que has pedido anteriormente. chainlit no hace persistente el historial de chat, pero le ofrece la opción de hacerlo mediante  Literal AISQLAlchemy o DynamoDB.

Literal AI puede aprovecharse como solución de persistencia de datos, lo que te permite habilitar rápidamente el almacenamiento y análisis de datos para tu aplicación Chainlit sin necesidad de configurar tu propia infraestructura.

Para integrar Literal AI, debes registrarte en Literal AI, crear un nuevo proyecto y obtener una clave API.
Añade tu clave API al archivo .env.

CHAINLIT_PORT=8000
OPENAI_API_KEY="sk-proj-****"
CHAINLIT_AUTH_SECRET="7U*qm1dwwDXDv@E*S,o34A9VB/dM4DGw*lm>-tVA7TkAa@bWOCW"
LITERAL_API_KEY="lsk_****" # Replace your Literal AI key here

Pulsa CTRL + C para detener la aplicación del chatbot y ejecútala.

chainlit run app.py --watch

Ahora prueba diferentes chats pidiendo diferentes tipos de comida en diferentes restaurantes y te darás cuenta de que cada vez que creas un nuevo chat y empiezas a interactuar con el chatbot, ese chat se marca como persistente en la barra lateral izquierda.

Chatbot

Intenta desconectarte y volver a conectarte, y deberías ver todos tus chats anteriores.

Resume chat

Te darás cuenta de que puedes recargar cualquier chat anterior desde la barra lateral izquierda, pero no puedes empezar a interactuar con él reanudando ese chat. La razón es que necesitas habilitar explícitamente la reanudación del chat en el chainlit.

Añade esta función a app.py y ya podremos reanudar el chat.

@cl.on_chat_resume
async def on_chat_resume():
pass

Al recargar el chatbot, deberías ver un botón «Resume chat» en la parte inferior de cada chat.

Al hacer clic en «resumen chat» se habilitará la interacción con este chat.

En GitHub encontrarás todo el código empleado en el artículo.


Si este artículo te ha ayudado:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *