La creación de un chatbot para una página web, es una tarea que se suele contratar a un proveedor de servicios, pero en este caso voy a contar como se puede realizar de principio a fin y además con un conjunto de herramientas que son libres y gratuitas.
Creación de un chatbot con modelo opensource
Los bot de charla o bot conversacional (en inglés: chatbot), son aplicaciones software que surgen en los años 60, y que simulan mantener una conversación con una persona al proveer respuestas automáticas, las cuales son previamente establecidas por un conjunto de expertos a entradas realizadas por el usuario. Estos bot, también conocidos como sistemas expertos, utilizan el razonamiento basado en casos (CBR: case base reasoning).
Habitualmente, la conversación se establece mediante texto, aunque también hay modelos que disponen de una interfaz de usuario multimedia que permiten la entrada auditiva. Más recientemente, algunos comienzan a utilizar programas conversores de texto a sonido (CTV), dotando de mayor realismo a la interacción con el usuario y ayudando a reducir el tiempo de respuesta.
Para establecer una conversación, han de utilizarse frases fácilmente comprensibles y que sean coherentes, aunque la mayoría de los bot conversacionales no consiguen comprender del todo. En su lugar, tienen en cuenta las palabras o frases del interlocutor, que les permitirán usar una serie de respuestas preparadas de antemano. Estos son capaces de reconocer la manera en la que una frase está formulada gracias a una serie de patrones comparativos preestablecidos, y de este modo, basándose en las diferentes variables de dicha frase, presentan una respuesta correspondiente. De esta manera, el bot es capaz de seguir una conversación con más o menos lógica, pero sin saber realmente de qué está hablando.
Para tener más información te recomiendo visites el siguiente artículo de wikipedia de donde se ha obtenido este fragmento.
¿Qué es Retrieval-Augmented Generation (RAG)?
Es el aumento de conocimiento que se aplica a un LLM con datos que no ha sido entrenado. Esto permite al sistema de IA generativa proporcionar respuestas contextualmente adecuadas a las consultas, así como basar dichas respuestas en datos extremadamente recientes.
En pocas palabras, la RAG ayuda a los LLM a proporcionar respuestas más idóneas.
Conclusiones clave
- La RAG es una técnica de inteligencia artificial relativamente nueva que mejora la calidad de la IA generativa al permitir a grandes modelos de lenguaje (LLM) aprovechar recursos de datos adicionales sin necesidad de volver a entrenarlos.
- Los modelos RAG crean repositorios de conocimientos basados en los datos de la propia organización. Estos repositorios se pueden actualizar continuamente para ayudar a la IA generativa a brindar respuestas adaptadas al contexto y oportunas.
- Los chatbots y otros sistemas conversacionales que utilizan el procesamiento del lenguaje natural pueden beneficiarse enormemente de la RAG y la IA generativa.
- La implementación de RAG requiere tecnologías como bases de datos vectoriales, que permiten la codificación rápida de nuevos datos y la búsqueda en esos datos para alimentar el LLM.
¿Cómo funciona?
Los datos de esa biblioteca de conocimientos se procesan en representaciones numéricas utilizando un tipo especial de algoritmo llamado modelo de lenguaje embebido y se almacenan en una base de datos vectorial, en la que se puede buscar rápidamente para recuperar la información contextual correcta.
Para tener más información te recomiendo visites el siguiente artículo de Oracle de donde se ha obtenido este fragmento.
Arquitectura
Nosotros vamos a ejecutar nuestro modelo LLM en un servidor local. Además vamos a tener la posibilidad de cambiar de modelo desde una interfaz amigable de administración, que nos permite descargarnos el modelo que deseemos utilizar e incluso poder probarlo con antelación. Por ello, he elegido Ollama que tiene un conjunto de modelos opensource bastante interesante. Vamos a ir viendo paso a paso cómo ir instalando y configurando nuestro software.
Pero antes de nada, vamos a ver una breve descripción de cada uno de los elementos que vamos a instalar:
Ollama
Ollama hace que sea muy fácil ejecutar LLM de código abierto localmente. Puede esperar un rendimiento decente incluso en portátiles pequeños. Ollama es una alternativa a Hugging Face para ejecutar modelos localmente. Las bibliotecas de Hugging Face se ejecutan sobre Tensorflow o Torch. Ollama usa llama.cpp como tiempo de ejecución subyacente. Esto hace que sea muy fácil comenzar con Ollama. Ni siquiera necesitas tener Python instalado.
LangChain
LangChain es un marco de trabajo de código abierto para crear aplicaciones basadas en modelos de lenguaje de gran tamaño (LLM). Los LLM son grandes modelos de aprendizaje profundo entrenados previamente con grandes cantidades de datos que pueden generar respuestas a las consultas de los usuarios, por ejemplo, responder preguntas o crear imágenes a partir de peticiones basadas en texto. LangChain proporciona herramientas y abstracciones para mejorar la personalización, precisión y relevancia de la información que generan los modelos. Por ejemplo, los desarrolladores pueden usar los componentes de LangChain para crear nuevas cadenas de peticiones o personalizar las plantillas existentes. LangChain también incluye componentes que permiten a los LLM acceder a nuevos conjuntos de datos sin necesidad de repetir el entrenamiento.
Para tener más información te recomiendo visites el siguiente artículo de AWS de donde se ha obtenido este fragmento.
ChromaDb
ChromaDB es una base de datos especializada en el almacenamiento y recuperación eficiente de información lingüística, incluyendo datos de texto, anotaciones semánticas y sintácticas. ChromaDB es particularmente útil para el almacenamiento y la gestión de grandes cantidades de datos de lenguaje natural, lo que permite a los desarrolladores aprovechar al máximo los avances en algoritmos de aprendizaje automático y análisis de texto.
Para tener más información te recomiendo visites el siguiente artículo de donde se ha obtenido este fragmento.
API con Flask
Flask es un micro marco de trabajo web de Python que proporciona las herramientas necesarias para crear aplicaciones web de manera rápida y sencilla. Aunque es un micro marco, Flask es altamente modular y permite agregar fácilmente extensiones para agregar funcionalidades adicionales.
Para tener más información te recomiendo visites el siguiente artículo de donde se ha obtenido este fragmento y donde puedes seguir el tutorial detallado de como crear una API con Flask.
El Chatbot web
Me he basado en esta integración de un chatbot web, para utilizar los recursos y adaptarlo a nuestro modelo opensource alojado en Ollama.
El código fuente se encuentra aquí.
Y un explicación detallada de como integrarlo con otras API, se encuentra aquí.
La demostración
A continuación se ha embebido la aplicación realizada. Esta está alojada en un servidor de unas características muy limitadas para la ejecución de desarrollos de inteligencia artificial. Pero como demostración de que es posible, aquí se encuentra en funcionamiento:
El chatbot está alojado en un servidor con pocos recursos.
Por ello tarda bastante en contestar. Es precisamente lo que se busca, demostrar la viabilidad en este tipo de entornos.
Preguntas de ejemplo que puede realizar:
- ¿Qué experiencia tiene Rubén Arcos?
- ¿Cuántos años de experiencia tiene Rubén Arcos?
- ¿Qué lenguajes de programación sabe Rubén Arcos?
Haga clic sobre la burbuja morada, para abrir el Chatbot
El tutorial
Como viene siendo habitual en esta página web, vamos a utilizar un entorno dockerizado que será el encargado de levantar Ollama, el administrador web de Ollama y nuestra aplicación de ChatBot web.
Para ello tenemos los siguiente scripts de docker compose:
Script de ejecución más completo (sin GPU)
version: '3.8'
services:
app:
build: .
container_name: ollama-app
ports:
- 8002:8002
- 5678:5678
volumes:
- ./app:/usr/src/app/
command: python app.py
restart: always
depends_on:
- ollama
- ollama-webui
networks:
- ollama-docker
ollama:
image: ollama/ollama:latest
ports:
- 11434:11434
volumes:
- .:/code
- ./ollama/ollama:/root/.ollama
container_name: ollama
pull_policy: always
tty: true
restart: always
networks:
- ollama-docker
ollama-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: ollama-webui
volumes:
- ./ollama/ollama-webui:/app/backend/data
depends_on:
- ollama
ports:
- 8080:8080
environment:
- '/ollama/api=http://ollama:11434/api'
extra_hosts:
- host.docker.internal:host-gateway
restart: unless-stopped
networks:
- ollama-docker
networks:
ollama-docker:
external: false
El script mínimo (sin GPU)
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
tty: true
restart: unless-stopped
# Expose Ollama API outside the container stack
ports:
- 11434:11434
- 53:53
volumes:
- ollama:/root/.ollama
command: pip install -r requirements.txt
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
volumes:
- open-webui:/app/backend/data
depends_on:
- ollama
ports:
- 8080:8080
environment:
- "OLLAMA_API_BASE_URL=http://ollama:11434/api"
extra_hosts:
- host.docker.internal:host-gateway
restart: unless-stopped
volumes:
ollama: {}
open-webui: {}
El script para utilización de GPU
version: '3.8'
services:
app:
build: .
ports:
- 8000:8000
- 5678:5678
volumes:
- .:/code
command: uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
restart: always
depends_on:
- ollama
- ollama-webui
networks:
- ollama-docker
ollama:
volumes:
- ./ollama/ollama:/root/.ollama
container_name: ollama
pull_policy: always
tty: true
restart: unless-stopped
image: ollama/ollama:latest
ports:
- 11434:11434
networks:
- ollama-docker
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
ollama-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: ollama-webui
volumes:
- ./ollama/ollama-webui:/app/backend/data
depends_on:
- ollama
ports:
- 8080:8080
environment:
- '/ollama/api=http://ollama:11434/api'
extra_hosts:
- host.docker.internal:host-gateway
restart: unless-stopped
networks:
- ollama-docker
networks:
ollama-docker:
external: false
Las rutas de acceso que se establecen son:
- Página web de administración de Ollama: http://localhost:8080
- Motor de Ollana: http://localhost:11434
- Aplicación web: http://localhost:8002
Para tener más información te recomiendo visites el siguiente repositorio de donde se ha obtenido este script y donde hay más ejemplos e información.
La instalación del modelo desde el administrador web de Ollama
Una vez tenemos el docker levantado, tan solo tenemos que entrar a la url http://localhost:8080, descargar e instalar el modelo.
A continuación se muestra un video de cómo se realiza:
En nuestro caso introduciremos el modelo: mistral:instruct
La aplicación en consola (el chatbot)
Luego tenemos la aplicación en consola que consume el modelo LLM, en nuestro ejemplo se ha utilizado Mistral por sus gran rendimiento similar a Llama y por ser opensource. También tenemos la especificación del promt de consulta, con unas instrucciones previas a las consultas. Y el método de entrenamiento RAG.
from langchain_community.vectorstores import Chroma
from langchain_community.chat_models import ChatOllama
from langchain_community.embeddings.fastembed import FastEmbedEmbeddings
from langchain_community.document_loaders import WebBaseLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
import sys
class ChatWebDoc:
vector_store = None
retriever = None
chain = None
def __init__(self):
self.model = ChatOllama(model="mistral:instruct")
#Loading embedding
self.embedding = FastEmbedEmbeddings()
self.text_splitter = CharacterTextSplitter(chunk_size=1024, chunk_overlap=100)
self.prompt = ChatPromptTemplate.from_messages(
[
("system",
"""You are an assistant for question-answering tasks. Use only the following
context to answer the question. If you don't know the answer, just say that you don't know.
CONTEXT:
{context}
"""),
("human", "{input}"),
]
)
def ingest(self, url_list):
#Load web pages
docs = WebBaseLoader(url_list).load()
chunks = self.text_splitter.split_documents(docs)
#Create vector store
vector_store = Chroma.from_documents(documents=chunks,
embedding=self.embedding, persist_directory="./chroma_db")
def load(self):
#Load vector store
vector_store = Chroma(persist_directory="./chroma_db",
embedding_function=self.embedding)
#Create chain
self.retriever = vector_store.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={
"k": 3,
"score_threshold": 0.5,
},
)
document_chain = create_stuff_documents_chain(self.model, self.prompt)
self.chain = create_retrieval_chain(self.retriever, document_chain)
def ask(self, query: str):
if not self.chain:
self.load()
result = self.chain.invoke({"input": query})
print(result["answer"])
for doc in result["context"]:
print("Source: ", doc.metadata["source"])
def build():
w = ChatWebDoc()
w.ingest([
"https://www.webagesolutions.com/courses/WA3446-comprehensive-angular-programming",
"https://www.webagesolutions.com/courses/AZ-1005-configuring-azure-virtual-desktop-for-the-enterprise",
"https://www.webagesolutions.com/courses/AZ-305T00-designing-microsoft-azure-infrastructure-solutions",
])
def chat():
w = ChatWebDoc()
w.load()
while True:
query = input(">>> ")
if len(query) == 0:
continue
if query == "/exit":
break
w.ask(query)
if len(sys.argv) < 2:
chat()
elif sys.argv[1] == "--ingest":
build()
La ejecución del entrenamiento RAG de las web provistas anteriorement en el programa anterior se realiza con el comando:
python rag-test.py --ingest
La interactuación con el model una vez entrenado:
python rag-test.py
Recomiendo ver con mayor detalle esta página web donde se trata esta misma aplicación.
La aplicación web (el Chatbot)
Queda pendiente para una futura actualización del artículo que os muestre como integrar en la aplicación web el motor LLM, interactuar con el, entrenarlo con el método RAG y levantarlo en el servidor web. ¡Hasta pronto! 😉
Fuentes: