Microcurso completo y práctico para desarrollar chatbots inteligentes
Los chatbots son programas que simulan conversaciones con usuarios humanos a través de interfaces de mensajería. En esta lección aprenderás los fundamentos de los chatbots y sus aplicaciones.
Un chatbot es un software diseñado para mantener una conversación con un usuario, interpretar sus mensajes y responder de manera coherente.
Para la mayoría de aplicaciones prácticas, los chatbots híbridos ofrecen el mejor balance entre complejidad y funcionalidad.
Antes de comenzar a desarrollar nuestro chatbot, necesitamos configurar nuestro entorno de desarrollo con las herramientas necesarias.
Vamos a instalar las bibliotecas principales que usaremos:
pip install nltk
pip install numpy
pip install tensorflow
pip install flask
NLTK (Natural Language Toolkit) es una biblioteca fundamental para procesamiento de lenguaje natural:
import nltk
nltk.download('punkt')
nltk.download('wordnet')
nltk.download('omw-1.4')
1. Instala Python en tu sistema si no lo tienes ya instalado
2. Crea un nuevo entorno virtual para el proyecto
3. Instala todas las bibliotecas mencionadas
Comenzaremos creando un chatbot simple basado en reglas que responde a patrones específicos de entrada.
def simple_chatbot(user_input):
user_input = user_input.lower()
if "hola" in user_input:
return "¡Hola! ¿Cómo estás?"
elif "adiós" in user_input or "chao" in user_input:
return "¡Hasta luego! Fue un placer ayudarte."
elif "gracias" in user_input:
return "De nada, estoy aquí para ayudar."
else:
return "No estoy seguro de entender. ¿Puedes reformular tu pregunta?"
Podemos hacer nuestro chatbot más flexible usando expresiones regulares:
import re
def regex_chatbot(user_input):
user_input = user_input.lower()
if re.search(r'\b(hola|buenos días|buenas tardes)\b', user_input):
return "¡Saludos! ¿En qué puedo ayudarte hoy?"
elif re.search(r'\b(adios|chao|hasta luego|nos vemos)\b', user_input):
return "¡Que tengas un buen día!"
elif re.search(r'\b(gracias|muchas gracias|te lo agradezco)\b', user_input):
return "Fue un placer ayudarte. ¡Vuelve pronto!"
else:
return "No estoy seguro de entenderte completamente. ¿Podrías decirlo de otra forma?"
Crea un diccionario de patrones y respuestas para hacer tu código más mantenible y fácil de expandir.
Para crear chatbots más inteligentes, necesitamos incorporar técnicas de Procesamiento de Lenguaje Natural (NLP).
Dividir el texto en palabras o frases significativas:
from nltk.tokenize import word_tokenize, sent_tokenize
text = "Hola, ¿cómo estás? Espero que bien."
print("Tokens de palabras:", word_tokenize(text))
print("Tokens de oraciones:", sent_tokenize(text))
Reducir palabras a su forma base o lema:
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
words = ["corriendo", "corrió", "correremos"]
lemmas = [lemmatizer.lemmatize(word, pos='v') for word in words]
print(lemmas) # ['correr', 'correr', 'correr']
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
nltk.download('stopwords')
stop_words = set(stopwords.words('spanish'))
text = "Este es un ejemplo de cómo eliminar palabras vacías"
words = word_tokenize(text.lower())
filtered_words = [word for word in words if word not in stop_words]
print(filtered_words) # ['ejemplo', 'eliminar', 'palabras', 'vacías']
Crea una función que tome una oración y devuelva una lista de lemas de las palabras significativas (sin stop words).
Vamos a crear un chatbot más avanzado utilizando técnicas de aprendizaje automático y redes neuronales.
Necesitamos un conjunto de datos de intenciones (intents) para entrenar nuestro chatbot:
intents = {
"saludos": {
"patterns": ["hola", "buenos días", "buenas tardes", "hey"],
"responses": ["¡Hola!", "¡Saludos!", "¿Cómo estás?"]
},
"despedidas": {
"patterns": ["adiós", "hasta luego", "nos vemos", "chao"],
"responses": ["¡Hasta pronto!", "Que tengas un buen día", "Adiós"]
},
"agradecimiento": {
"patterns": ["gracias", "muchas gracias", "te lo agradezco"],
"responses": ["De nada", "Fue un placer", "No hay de qué"]
}
}
from nltk.stem import WordNetLemmatizer
import numpy as np
import random
lemmatizer = WordNetLemmatizer()
words = []
classes = []
documents = []
for intent_name, intent_data in intents.items():
for pattern in intent_data['patterns']:
# Tokenizar cada palabra
word_list = word_tokenize(pattern)
words.extend(word_list)
# Agregar documento al corpus
documents.append((word_list, intent_name))
# Agregar a la lista de clases
if intent_name not in classes:
classes.append(intent_name)
# Lematizar y eliminar duplicados
words = [lemmatizer.lemmatize(word.lower()) for word in words if word not in ignore_words]
words = sorted(set(words))
classes = sorted(set(classes))
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.optimizers import SGD
model = Sequential()
model.add(Dense(128, input_shape=(len(train_x[0]),), activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(len(train_y[0]), activation='softmax'))
sgd = SGD(learning_rate=0.01, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
hist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1)
model.save('chatbot_model.h5')
Ahora vamos a crear una interfaz web para nuestro chatbot utilizando Flask.
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
@app.route('/get_response', methods=['POST'])
def get_response():
user_message = request.form['message']
# Aquí iría la lógica para procesar el mensaje y generar una respuesta
response = "Esta es una respuesta de prueba"
return jsonify({'response': response})
if __name__ == '__main__':
app.run(debug=True)
Crea un archivo templates/index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Chatbot con Flask</title>
<style>
.chat-container {
width: 400px;
margin: 0 auto;
border: 1px solid #ccc;
border-radius: 10px;
padding: 20px;
}
.chat-box {
height: 400px;
overflow-y: scroll;
border: 1px solid #eee;
margin-bottom: 10px;
padding: 10px;
}
.user-message {
text-align: right;
margin: 5px;
padding: 5px;
background-color: #e3f2fd;
border-radius: 5px;
}
.bot-message {
text-align: left;
margin: 5px;
padding: 5px;
background-color: #f5f5f5;
border-radius: 5px;
}
input[type="text"] {
width: 75%;
padding: 8px;
}
button {
width: 20%;
padding: 8px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-box" id="chat-box"></div>
<div class="input-area">
<input type="text" id="user-input" placeholder="Escribe tu mensaje...">
<button onclick="sendMessage()">Enviar</button>
</div>
</div>
<script>
function sendMessage() {
const userInput = document.getElementById('user-input');
const message = userInput.value.trim();
if (message) {
// Mostrar mensaje del usuario
displayMessage(message, 'user');
userInput.value = '';
// Obtener respuesta del bot
fetch('/get_response', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `message=${encodeURIComponent(message)}`
})
.then(response => response.json())
.then(data => {
displayMessage(data.response, 'bot');
});
}
}
function displayMessage(message, sender) {
const chatBox = document.getElementById('chat-box');
const messageDiv = document.createElement('div');
messageDiv.className = sender + '-message';
messageDiv.textContent = message;
chatBox.appendChild(messageDiv);
chatBox.scrollTop = chatBox.scrollHeight;
}
// Permitir enviar con Enter
document.getElementById('user-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>
Una vez que tenemos nuestro chatbot funcionando localmente, es hora de desplegarlo para que esté disponible en línea.
Pasos para desplegar nuestra aplicación Flask en Heroku:
# Requisitos previos:
# 1. Tener cuenta en Heroku
# 2. Tener instalado Heroku CLI
# 3. Tener Git instalado
# Crear archivo requirements.txt
pip freeze > requirements.txt
# Crear archivo Procfile (sin extensión)
echo "web: gunicorn app:app" > Procfile
# Inicializar repositorio Git
git init
git add .
git commit -m "Primer commit"
# Conectar con Heroku y desplegar
heroku login
heroku create nombre-de-tu-app
git push heroku master
# Abrir la aplicación
heroku open
Para aplicaciones más complejas, necesitarás:
Para entornos de producción, considera usar Gunicorn o uWSGI como servidor WSGI en lugar del servidor de desarrollo de Flask.
Ahora que tenemos un chatbot funcional, exploremos cómo mejorarlo con características avanzadas.
Podemos hacer que nuestro chatbot interactúe con servicios externos:
import requests
def get_weather(city):
api_key = "tu_api_key"
base_url = "http://api.openweathermap.org/data/2.5/weather?"
complete_url = f"{base_url}appid={api_key}&q={city}&units=metric&lang=es"
response = requests.get(complete_url)
data = response.json()
if data["cod"] != "404":
main = data["main"]
weather = data["weather"][0]
temp = main["temp"]
desc = weather["description"]
return f"El clima en {city}: {desc}, temperatura: {temp}°C"
else:
return "Ciudad no encontrada"
Podemos guardar el historial de conversaciones o preferencias del usuario:
import sqlite3
def setup_database():
conn = sqlite3.connect('chatbot.db')
c = conn.cursor()
# Crear tabla de conversaciones
c.execute('''CREATE TABLE IF NOT EXISTS conversations
(id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
message TEXT,
response TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)''')
conn.commit()
conn.close()
def save_conversation(user_id, message, response):
conn = sqlite3.connect('chatbot.db')
c = conn.cursor()
c.execute("INSERT INTO conversations (user_id, message, response) VALUES (?, ?, ?)",
(user_id, message, response))
conn.commit()
conn.close()
Podemos analizar el estado emocional del usuario para responder de manera más adecuada:
from textblob import TextBlob
from textblob.sentiments import NaiveBayesAnalyzer
def analyze_sentiment(text):
# Usando el analizador de Bayes Naive (más preciso pero más lento)
blob = TextBlob(text, analyzer=NaiveBayesAnalyzer())
if blob.sentiment.p_pos > 0.6:
return "positive"
elif blob.sentiment.p_neg > 0.6:
return "negative"
else:
return "neutral"
# Ejemplo de uso
user_message = "Estoy muy contento con este servicio"
sentiment = analyze_sentiment(user_message)
if sentiment == "positive":
response = "¡Me alegra saber que estás contento! ¿En qué más puedo ayudarte?"
elif sentiment == "negative":
response = "Lamento escuchar eso. ¿Cómo puedo mejorar tu experiencia?"
else:
response = "Gracias por tu mensaje. ¿En qué puedo ayudarte?"
Combina todo lo aprendido para crear un chatbot especializado en un área de tu interés (ej: asistente de cocina, bot de soporte técnico, guía turístico virtual) con: