En los últimos años, los chatbots se han convertido en una herramienta popular para la atención al cliente en línea, ya que pueden proporcionar respuestas rápidas y precisas a las preguntas de los clientes en tiempo real. Sin embargo, a veces estos chatbots no están diseñados para responder preguntas específicas sobre un producto o servicio en particular, lo que puede frustrar a los usuarios.
Y aquí es donde entra en juego la posibilidad de reentrenar un modelo de lenguaje natural como ChatGPT, aunque esta práctica aplica a más tipos de modelos, no solo los de generación de texto. Este proceso es conocido como aprendizaje de transferencia, y el resultado es mejorar su capacidad para responder preguntas sobre un producto o servicio en particular, o dotarlo de un tono de marca en específico.
En esta entrada de blog, exploraremos el proceso de reentrenamiento de ChatGPT para mejorar la atención al cliente en línea. Cubriremos los pasos específicos para preparar los datos de entrenamiento, entrenar y ajustar el modelo, y cómo implementar el chatbot mejorado en la plataforma de atención al cliente. Los ejemplos serán en Python, aunque los conceptos sirven para otros lenguajes.
Tabla de contenidos
- Paso 1: Preparación de los datos
- Paso 2: División del conjunto de datos
- Paso 3: Preprocesamiento de los datos
- Paso 4: Entrenamiento del modelo
- Paso 5: Ajuste fino (fine-tuning)
- Paso 6: Evaluación del modelo
- Paso 7: Implementación del modelo
Paso 1: Preparación de los datos
Trabajar en inglés
A pesar de que las librerías como nltk tienen soporte a español, su performance no es tan buena en estos lenguajes. Con lo que sería ideal traducirlo a inglés antes de trabajar. Acá un ejemplo de cómo se podría hacer:
import nltk nltk.download('punkt') nltk.download('averaged_perceptron_tagger') nltk.download('brown') nltk.download('spanish_grammars') nltk.download('tagsets') from textblob import TextBlob blob = TextBlob("Hola, ¿cómo estás?") translated = blob.translate(to="en")
El conjunto de datos o “dataset” puede estar en un archivo csv o una base de datos. No importa tanto de dónde provenga, sino que se puedan obtener pares de pregunta / respuesta que serán utilizadas en el reentrenamiento, por ejemplo:
Tabla de contenidos
- Paso 1: Preparación de los datos
- Paso 2: División del conjunto de datos
- Paso 3: Preprocesamiento de los datos
- Paso 4: Entrenamiento del modelo
- Paso 5: Ajuste fino (fine-tuning)
- Paso 6: Evaluación del modelo
- Paso 7: Implementación del modelo
¿Qué modelos tienen disponibles?|Tenemos una amplia variedad de modelos, como por ejemplo: Modelo 1, Modelo 2 ¿Dónde puedo conseguir repuestos?|Tenemos sucursales en Localidad 1, Localidad 2 y próximamente en Localidad 3
Acá tengo por línea un par pregunta|respuesta, pero como dije, sirve cualquier formato. También deberíamos tener muchas preguntas respondidas intentando abarcar todas las cuestiones relacionadas con el negocio.
Una vez que contemos con el dataset, hay que pasar por una serie de pasos de preprocesamiento que los veremos en el punto 3, pero antes hay que hacer una tarea intermedia.
Paso 2: División del conjunto de datos
Se debe dividir el conjunto de datos en dos partes: una para el entrenamiento del modelo y otra para su evaluación.
El objetivo de esta división es evaluar el rendimiento del modelo en datos que no ha visto durante el entrenamiento, lo que se conoce como conjunto de datos de prueba. Este paso es fundamental para asegurarse de que el modelo es capaz de generalizar y no sólo ha memorizado los ejemplos de entrenamiento.
La división se realiza típicamente de manera aleatoria, pero respetando una proporción adecuada entre los datos de entrenamiento y prueba. Una proporción comúnmente utilizada es del 80% de los datos para entrenamiento y el 20% para pruebas.
En Python, se puede realizar la división utilizando la librería Scikit-Learn, específicamente su función `train_test_split`. El siguiente código de ejemplo ilustra cómo realizar la división en un conjunto de datos de texto:
from sklearn.model_selection import train_test_split # cargar los datos data = load_data() # dividir los datos en conjuntos de entrenamiento y prueba train_data, test_data = train_test_split(data, test_size=0.2, random_state=42) # entrenar el modelo con los datos de entrenamiento my_model.train(train_data) # evaluar el modelo con los datos de prueba my_model.evaluate(test_data)
Paso 3: Preprocesamiento de los datos
En esta etapa, se debe preprocesar el conjunto de datos que se utilizará para reentrenar ChatGPT. El objetivo es limpiar y formatear los datos para que sean compatibles con el modelo y garantizar que el modelo reciba datos precisos y consistentes.
3.1. Eliminar signos de puntuación
Los signos de puntuación, como comas, puntos y signos de exclamación, no son necesarios para la comprensión del lenguaje natural por parte del modelo y pueden afectar negativamente el rendimiento. Se pueden eliminar utilizando expresiones regulares y la librería re.
import re def remove_punctuation(text): return re.sub(r'[^\w\s]','',text)
Una aclaración importante en este paso es que al remover ciertos signos y/o stop words (palabras irrelevantes como “de”, “el” por ejemplo), dejaremos los datos más “limpios” pero también eventualmente podremos perder información importante para el modelo. Con lo que habrá que evaluar qué estamos descartando en cada caso.
3.2. Corregir errores ortográficos o gramaticales
La corrección de errores ortográficos o gramaticales es importante para que el modelo reciba datos precisos y no se confunda con palabras mal escritas. Se puede utilizar la librería textblob para corregir errores.
from textblob import TextBlob def correct_spelling(text): blob = TextBlob(text) return str(blob.correct())
3.3. Transformar letras mayúsculas en minúsculas
El modelo no distingue entre letras mayúsculas y minúsculas, por lo que es importante transformar todas las letras en minúsculas para asegurarse de que el modelo tenga una entrada consistente.
def to_lowercase(text): return text.lower()
3.4. Tokenización y vectorización
La tokenización es el proceso de dividir un texto en unidades significativas, como palabras o frases llamadas “tokens”. Es un proceso de convertir el texto en vectores numéricos para que el modelo pueda entenderlo, detectar patrones. Se puede utilizar la librería nltk para tokenizar el texto y la librería gensim para vectorizarlo.
from nltk.tokenize import word_tokenize from gensim.corpora.dictionary import Dictionary def tokenize_and_vectorize(text): tokens = [word_tokenize(sent) for sent in text] dictionary = Dictionary(tokens) corpus = [dictionary.doc2bow(token) for token in tokens] return corpus
Paso 4: Entrenamiento del modelo
Durante el entrenamiento, el modelo procesa las preguntas y sus respectivas respuestas, y utiliza algoritmos de aprendizaje automático para ajustar sus parámetros. El objetivo es encontrar la mejor combinación de parámetros que permita al modelo generar respuestas precisas y coherentes a nuevas preguntas.
Es importante tener en cuenta que el entrenamiento del modelo puede llevar mucho tiempo y requerir un gran poder de procesamiento, por eso quizá este paso se pueda realizar en Google Colab por ejemplo y luego descargar el resultado. Además, es posible que sea necesario ajustar varios hiperparámetros, como el tamaño de la red y la tasa de aprendizaje, para lograr los mejores resultados. Es un poco de prueba y error.
Un ejemplo de código en Python para entrenar un modelo de lenguaje natural podría ser:
from transformers import GPT2LMHeadModel, GPT2Tokenizer tokenizer = GPT2Tokenizer.from_pretrained('gpt2') model = GPT2LMHeadModel.from_pretrained('gpt2') # Cargar los datos de entrenamiento train_data = ... # Entrenar el modelo for epoch in range(num_epochs): for batch in train_data: input_ids, attention_mask, labels = batch loss, logits = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels) loss.backward() optimizer.step() optimizer.zero_grad()
Este código utiliza la biblioteca Hugging Face Transformers para cargar un modelo preentrenado (en este caso, el modelo GPT-2) y un tokenizador. A continuación, se carga el conjunto de datos de entrenamiento y se entrena el modelo durante un número determinado de épocas. Durante cada época, se procesa cada lote del conjunto de datos y se ajustan los parámetros del modelo para minimizar la pérdida.
Paso 5: Ajuste fino (fine-tuning)
Una vez que se ha entrenado el modelo con un conjunto de datos inicial, se puede continuar ajustándolo para mejorar su rendimiento y adaptarlo a necesidades específicas.
En el ajuste fino, se toma el modelo pre-entrenado y se lo entrena con nuevos datos de entrenamiento, con el objetivo de adaptarlo a una tarea específica. En lugar de entrenar un modelo desde cero, el ajuste fino aprovecha el conocimiento y habilidades que ya posee el modelo pre-entrenado.
A continuación dejo un ejemplo de código en Python para realizar el ajuste fino de un modelo de lenguaje natural utilizando la biblioteca Hugging Face Transformers:
from transformers import AutoTokenizer, AutoModelForSequenceClassification, TrainingArguments, Trainer # Cargar el modelo pre-entrenado model_name = "bert-base-uncased" model = AutoModelForSequenceClassification.from_pretrained(model_name) # Cargar el tokenizadortokenizer = AutoTokenizer.from_pretrained(model_name) # Definir los nuevos datos de entrenamiento y evaluación train_data = [("Texto de ejemplo 1", 1), ("Texto de ejemplo 2", 0), ("Texto de ejemplo 3", 1)] eval_data = [("Texto de prueba 1", 1), ("Texto de prueba 2", 0), ("Texto de prueba 3", 1)] # Crear un objeto Trainer para el ajuste fino args = TrainingArguments(output_dir='./results', num_train_epochs=1, per_device_train_batch_size=16, per_device_eval_batch_size=64, warmup_steps=500, evaluation_strategy='epoch', logging_dir='./logs') trainer = Trainer(model=model, args=args, train_dataset=train_data, eval_dataset=eval_data) # Ejecutar el ajuste fino trainer.train()
Paso 6: Evaluación del modelo
La evaluación del modelo es un paso crítico en el proceso de transferencia de aprendizaje, ya que permite medir su desempeño y determinar si es necesario continuar ajustándolo o si ya se puede implementar en una aplicación.
Para evaluar el modelo, se utiliza un conjunto de datos de evaluación separado del conjunto de datos de entrenamiento y ajuste fino. Este conjunto de datos debe tener preguntas y respuestas diferentes a las del conjunto de datos de entrenamiento y debe estar diseñado para evaluar el desempeño general del modelo en la tarea que se quiere resolver.
En Python, se puede evaluar un modelo de lenguaje natural utilizando la biblioteca TensorFlow, que ofrece varias métricas para evaluar modelos de NLP. A continuación, se muestra un ejemplo de cómo se puede evaluar un modelo de clasificación de texto utilizando TensorFlow:
import tensorflow as tf from tensorflow.keras.models import load_model from sklearn.metrics import classification_report # Cargar el modelo entrenado model = load_model('modelo_entrenado.h5') # Cargar los datos de evaluación x_test, y_test = load_eval_data('datos_evaluacion.csv') # Realizar las predicciones en los datos de evaluación y_pred = model.predict(x_test) # Convertir las predicciones a etiquetas de clase y_pred = tf.argmax(y_pred, axis=1) # Generar un informe de clasificación para evaluar el modelo print(classification_report(y_test, y_pred))
Paso 7: Implementación del modelo
Finalmente ya estamos en condiciones de probar nuestro modelo. Este paso únicamente requeriría una o varias entradas de blog distintas ya que es muy variado y dependerá de dónde queramos utilizar nuestro modelo. Pero supongamos que será en un chatbot, podríamos crear una aplicación Flask en Python y utilizar la librería Chatterbot:
from chatterbot import ChatBot from chatterbot.trainers import ListTrainer # Crear instancia del chatbot bot = ChatBot('Mi chatbot') # Entrenar al chatbot (código de ejemplo) # En realidad acá irían todos los pasos anteriores trainer = ListTrainer(bot) trainer.train(['Hola', 'Hola, ¿en qué puedo ayudarte?', 'Quiero saber si tienen servicio a domicilio', 'Sí, contamos con servicio a domicilio en toda la ciudad']) # Integrar el chatbot en una aplicación web from flask import Flask, render_template, request app = Flask(__name__) @app.route("/") def home(): return render_template("home.html") @app.route("/get")def get_bot_response(): userText = request.args.get('msg') return str(bot.get_response(userText)) if __name__ == "__main__": app.run()
Espero que sirva de guía para entender los pasos y el proceso, en un futuro haré un video seguramente explicando en concreto todo esto. Si te parece interesante, hacémelo saber en redes.
Saludos!