Python para PNL: creación de un chatbot basado en reglas

P

Este es el artículo número 12 de mi serie de artículos sobre Python para PNL. En el artículo anterior, expliqué brevemente las diferentes funcionalidades de Python Biblioteca Gensim. Hasta ahora, en esta serie, hemos cubierto casi todas las bibliotecas de PNL más utilizadas, como NLTK, SpaCy, Gensim, StanfordCoreNLP, Pattern, TextBlob, etc.

En este artículo, no vamos a explorar ninguna biblioteca de PNL. Más bien, desarrollaremos un chatbot basado en reglas muy simple capaz de responder las consultas de los usuarios sobre el deporte del tenis. Pero antes de comenzar la codificación real, primero analicemos brevemente qué son los chatbots y cómo se usan.

¿Qué es un chatbot?

Un chatbot es un agente conversacional capaz de responder las consultas de los usuarios en forma de texto, voz o mediante una interfaz gráfica de usuario. En palabras simples, un chatbot es una aplicación de software que puede conversar con un usuario sobre cualquier tema. Los chatbots se pueden clasificar ampliamente en dos tipos: chatbots orientados a tareas y chatbots de uso general.

Los chatbots orientados a tareas están diseñados para realizar tareas específicas. Por ejemplo, un chatbot orientado a tareas puede responder consultas relacionadas con la reserva de trenes, la entrega de pizzas; también puede trabajar como terapeuta médico personal o asistente personal.

Por otro lado, los chatbots de propósito general pueden tener discusiones abiertas con los usuarios.

También hay un tercer tipo de chatbots llamados chatbots híbridos que pueden participar en discusiones abiertas y orientadas a tareas con los usuarios.

Enfoques para el desarrollo de chatbot

Los enfoques de desarrollo de chatbots se dividen en dos categorías: chatbots basados ​​en reglas y chatbots basados ​​en aprendizaje.

Chatbots basados ​​en el aprendizaje

Los chatbots basados ​​en el aprendizaje son el tipo de chatbots que utilizan técnicas de Machine Learning y un conjunto de datos para aprender a generar una respuesta a las consultas de los usuarios. Los chatbots basados ​​en el aprendizaje se pueden dividir en dos categorías: chatbots basados ​​en la recuperación y chatbots generativos.

Los chatbots basados ​​en la recuperación aprenden a seleccionar una determinada respuesta a las consultas de los usuarios. Por otro lado, los chatbots generativos aprenden a generar una respuesta sobre la marcha.

Una de las principales ventajas de los chatbots basados ​​en el aprendizaje es su flexibilidad para responder a una variedad de consultas de los usuarios. Aunque la respuesta no siempre sea correcta, los chatbots basados ​​en el aprendizaje son capaces de responder a cualquier tipo de consulta de los usuarios. Uno de los principales inconvenientes de estos chatbots es que pueden necesitar una gran cantidad de tiempo y datos para entrenarse.

Chatbots basados ​​en reglas

Los chatbots basados ​​en reglas son bastante sencillos en comparación con los chatbots basados ​​en el aprendizaje. Hay un conjunto específico de reglas. Si la consulta del usuario coincide con alguna regla, se genera la respuesta a la consulta; de lo contrario, se notifica al usuario que la respuesta a la consulta del usuario no existe.

Una de las ventajas de los chatbots basados ​​en reglas es que siempre dan resultados precisos. Sin embargo, en el lado negativo, no escalan bien. Para agregar más respuestas, debe definir nuevas reglas.

En la siguiente sección, explicaré cómo crear un chatbot basado en reglas que responderá a las consultas simples de los usuarios sobre el deporte del tenis.

Desarrollo de chatbot basado en reglas con Python

El chatbot que vamos a desarrollar será muy sencillo. Primero necesitamos un corpus que contenga mucha información sobre el deporte del tenis. Desarrollaremos tal corpus raspando el artículo de Wikipedia sobre tenis. A continuación, realizaremos algunos preprocesos en el corpus y luego dividiremos el corpus en oraciones.

Cuando un usuario ingresa una consulta, la consulta se convertirá en forma vectorizada. Todas las oraciones del corpus también se convertirán a sus correspondientes formas vectorizadas. A continuación, la oración con la mayor similitud de coseno con el vector de entrada del usuario se seleccionará como respuesta a la entrada del usuario.

Siga estos pasos para desarrollar el chatbot:

Importación de bibliotecas necesarias

import nltk
import numpy as np
import random
import string

import bs4 as bs
import urllib.request
import re

Estaremos usando el Beautifulsoup4 biblioteca para analizar los datos de Wikipedia. Además, la biblioteca de expresiones regulares de Python, re, se utilizará para algunas tareas de preprocesamiento en el texto.

Creando el Corpus

Como dijimos anteriormente, usaremos el artículo de Wikipedia sobre Tenis para crear nuestro corpus. El siguiente script recupera el artículo de Wikipedia y extrae todos los párrafos del texto del artículo. Finalmente, el texto se convierte a minúsculas para facilitar su procesamiento.

raw_html = urllib.request.urlopen('https://en.wikipedia.org/wiki/Tennis')
raw_html = raw_html.read()

article_html = bs.BeautifulSoup(raw_html, 'lxml')

article_paragraphs = article_html.find_all('p')

article_text=""

for para in article_paragraphs:
    article_text += para.text

article_text = article_text.lower()

Función de ayuda y preprocesamiento de texto

A continuación, necesitamos preprocesar nuestro texto para eliminar todos los caracteres especiales y espacios vacíos de nuestro texto. La siguiente expresión regular hace eso:

article_text = re.sub(r'[[0-9]*]', ' ', article_text)
article_text = re.sub(r's+', ' ', article_text)

Necesitamos dividir nuestro texto en oraciones y palabras, ya que la similitud del coseno de la entrada del usuario se comparará con cada oración. Ejecute el siguiente script:

article_sentences = nltk.sent_tokenize(article_text)
article_words = nltk.word_tokenize(article_text)

Finalmente, necesitamos crear funciones de ayuda que eliminarán la puntuación del texto de entrada del usuario y también lematizarán el texto. La lematización se refiere a reducir una palabra a su forma raíz. Por ejemplo, la lematización de la palabra “comió” devuelve comer, la palabra “arrojar” se convertirá en tirar y la palabra “peor” se reducirá a “malo”.

Ejecute el siguiente código:

wnlemmatizer = nltk.stem.WordNetLemmatizer()

def perform_lemmatization(tokens):
    return [wnlemmatizer.lemmatize(token) for token in tokens]

punctuation_removal = dict((ord(punctuation), None) for punctuation in string.punctuation)

def get_processed_text(document):
    return perform_lemmatization(nltk.word_tokenize(document.lower().translate(punctuation_removal)))

En el script anterior, primero instanciamos el WordNetLemmatizer desde el NTLK biblioteca. A continuación, definimos una función perform_lemmatization, que toma una lista de palabras como entrada y lematiza la correspondiente lista lematizada de palabras. los punctuation_removal list elimina la puntuación del texto pasado. Finalmente, el get_processed_text El método toma una oración como entrada, la tokeniza, la lematiza y luego elimina la puntuación de la oración.

Responder a los saludos

Dado que estamos desarrollando un chatbot basado en reglas, necesitamos manejar diferentes tipos de entradas de usuario de una manera diferente. Por ejemplo, para los saludos definiremos una función dedicada. Para manejar los saludos, crearemos dos listas: greeting_inputs y greeting_outputs. Cuando un usuario ingrese un saludo, intentaremos buscarlo en el greetings_inputs lista, si se encuentra el saludo, elegiremos aleatoriamente una respuesta del greeting_outputs lista.

Mira el siguiente guión:

greeting_inputs = ("hey", "good morning", "good evening", "morning", "evening", "hi", "whatsup")
greeting_responses = ["hey", "hey hows you?", "*nods*", "hello, how you doing", "hello", "Welcome, I am good and you"]

def generate_greeting_response(greeting):
    for token in greeting.split():
        if token.lower() in greeting_inputs:
            return random.choice(greeting_responses)

Aquí el generate_greeting_response() El método básicamente se encarga de validar el mensaje de saludo y generar la respuesta correspondiente.

Responder a las consultas de los usuarios

Como dijimos anteriormente, la respuesta se generará en función de la similitud de coseno de la forma vectorizada de la oración de entrada y las oraciones en los cuerpos. El siguiente script importa el TfidfVectorizer y el cosine_similarity funciones:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

Ahora tenemos todo configurado que necesitamos para generar una respuesta a las consultas de los usuarios relacionadas con el tenis. Crearemos un método que toma la entrada del usuario, encuentra la similitud del coseno de la entrada del usuario y la compara con las oraciones en el corpus.

Mira el siguiente guión:

def generate_response(user_input):
    tennisrobo_response=""
    article_sentences.append(user_input)

    word_vectorizer = TfidfVectorizer(tokenizer=get_processed_text, stop_words="english")
    all_word_vectors = word_vectorizer.fit_transform(article_sentences)
    similar_vector_values = cosine_similarity(all_word_vectors[-1], all_word_vectors)
    similar_sentence_number = similar_vector_values.argsort()[0][-2]

    matched_vector = similar_vector_values.flatten()
    matched_vector.sort()
    vector_matched = matched_vector[-2]

    if vector_matched == 0:
        tennisrobo_response = tennisrobo_response + "I am sorry, I could not understand you"
        return tennisrobo_response
    else:
        tennisrobo_response = tennisrobo_response + article_sentences[similar_sentence_number]
        return tennisrobo_response

Puedes ver que el generate_response() El método acepta un parámetro que es la entrada del usuario. A continuación, definimos una cadena vacía tennisrobo_response. Luego agregamos la entrada del usuario a la lista de oraciones ya existentes. Después de eso en las siguientes líneas:

word_vectorizer = TfidfVectorizer(tokenizer=get_processed_text, stop_words="english")
all_word_vectors = word_vectorizer.fit_transform(article_sentences)

Inicializamos el tfidfvectorizer y luego convierta todas las oraciones en el corpus junto con la oración de entrada en su forma vectorizada correspondiente.

En la siguiente línea:

similar_vector_values = cosine_similarity(all_word_vectors[-1], all_word_vectors)

Usamos el cosine_similarity función para encontrar la similitud de coseno entre el último elemento de la all_word_vectors list (que en realidad es el vector de palabra para la entrada del usuario, ya que se agregó al final) y los vectores de palabra para todas las oraciones en el corpus.

A continuación, en la siguiente línea:

similar_sentence_number = similar_vector_values.argsort()[0][-2]

Ordenamos la lista que contiene las similitudes de coseno de los vectores, el penúltimo elemento de la lista tendrá el coseno más alto (después de la clasificación) con la entrada del usuario. El último elemento es la entrada del usuario en sí, por lo tanto, no lo seleccionamos.

Finalmente, aplanamos la similitud de coseno recuperada y verificamos si la similitud es igual a cero o no. Si la similitud del coseno del vector emparejado es 0, eso significa que nuestra consulta no tuvo respuesta. En ese caso, simplemente imprimiremos que no entendemos la consulta del usuario.

De lo contrario, si la similitud del coseno no es igual a cero, eso significa que encontramos una oración similar a la entrada en nuestro corpus. En ese caso, simplemente pasaremos el índice de la oración coincidente a nuestra lista “article_sentences” que contiene la colección de todas las oraciones.

Charlando con el Chatbot

Como paso final, necesitamos crear una función que nos permita chatear con el chatbot que acabamos de diseñar. Para hacerlo, escribiremos otra función auxiliar que seguirá ejecutándose hasta que el usuario escriba “Bye”.

Mire el siguiente script, el código se ha explicado después de eso:

continue_dialogue = True
print("Hello, I am your friend TennisRobo. You can ask me any question regarding tennis:")
while(continue_dialogue == True):
    human_text = input()
    human_text = human_text.lower()
    if human_text != 'bye':
        if human_text == 'thanks' or human_text == 'thank you very much' or human_text == 'thank you':
            continue_dialogue = False
            print("TennisRobo: Most welcome")
        else:
            if generate_greeting_response(human_text) != None:
                print("TennisRobo: " + generate_greeting_response(human_text))
            else:
                print("TennisRobo: ", end="")
                print(generate_response(human_text))
                article_sentences.remove(human_text)
    else:
        continue_dialogue = False
        print("TennisRobo: Good bye and take care of yourself...")

En el script anterior, primero configuramos la bandera continue_dialogue a la verdad. Después de eso, imprimimos un mensaje de bienvenida al usuario que solicita cualquier entrada. A continuación, inicializamos un ciclo while que se sigue ejecutando hasta que continue_dialogue bandera es verdadera. Dentro del bucle, se recibe la entrada del usuario, que luego se convierte a minúsculas. La entrada del usuario se almacena en el human_text variable. Si el usuario ingresa la palabra “adiós”, el continue_dialogue se establece en falso y se imprime un mensaje de despedida al usuario.

Por otro lado, si el texto de entrada no es igual a “adiós”, se comprueba si la entrada contiene palabras como “gracias”, “gracias”, etc. o no. Si se encuentran estas palabras, se genera una respuesta “Muy bienvenido”. De lo contrario, si la entrada del usuario no es igual a None, la generate_response Se llama al método que obtiene la respuesta del usuario en función de la similitud del coseno como se explica en la última sección.

Una vez que se genera la respuesta, la entrada del usuario se elimina de la colección de oraciones, ya que no queremos que la entrada del usuario sea parte del corpus. El proceso continúa hasta que el usuario escribe “bye”. Puede ver por qué este tipo de chatbot se llama chatbot basado en reglas. Hay muchas reglas a seguir y si queremos agregar más funcionalidades al chatbot, tendremos que agregar más reglas.

La salida del script del chatbot se ve así:

Puedes ver en la imagen de arriba que ingresé la entrada “roger federer” y la respuesta generada es:

however it must be noted that both rod laver and ken rosewall also won major pro slam tournaments on all three surfaces (grass, clay, wood) rosewall in 1963 and laver in 1967. more recently, roger federer is considered by many observers to have the most "complete" game in modern tennis."

Es posible que la respuesta no sea precisa, sin embargo, todavía tiene sentido.

Es importante mencionar que la idea de este artículo no es desarrollar un chatbot perfecto, sino explicar el principio de funcionamiento de los chatbots basados ​​en reglas.

Conclusión

Los chatbots son agentes conversacionales que participan en diferentes tipos de conversaciones con humanos. Los chatbots están encontrando su lugar en diferentes estratos de la vida que van desde el asistente personal hasta los sistemas de reserva de boletos y los terapeutas fisiológicos. Tener un chatbot en lugar de humanos puede ser muy rentable. Sin embargo, desarrollar un chatbot con la misma eficiencia que los humanos puede resultar muy complicado.

En este artículo, mostramos cómo desarrollar un chatbot simple basado en reglas usando similitud de coseno. En el siguiente artículo, exploramos otro campo de procesamiento del lenguaje natural.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad