En este artículo, presentaremos un framework especializado para crear aplicaciones basadas en Modelos de Lenguaje con Largo Memorandos (LLMs). Con el creciente interés en los LLMs en el campo de la Inteligencia Artificial del Lenguaje, es esencial contar con un enfoque efectivo para desarrollar aplicaciones que aprovechen al máximo su potencial. Exploraremos cómo la librería LangChain para Python proporciona una estructura sólida y herramientas prácticas para el desarrollo ágil de aplicaciones con LLMs. Prepárate para descubrir cómo utilizar este framework para impulsar la creación de aplicaciones inteligentes con LLMs.

¿Qué es LangChain?

Efectivamente, el párrafo anterior lo ha escrito GPT utilizando la API de OpenAI, gracias a una aplicación muy sencilla hecha con LangChain. Esta librería no solo nos permite usar el producto de OpenAI de forma sencilla en nuestras aplicaciones, sino otros muchos modelos, incluidos los Open Source de HuggingFace. Y es que una aplicación con un modelo de lenguaje puede englobar muchas cosas más que una sola llamada a una API, es posible que queramos que nuestra aplicación tenga un contexto determinado, o responda de una manera específica y solo cuando tenga respuestas específicas. LangChain nos provee de una capa de abstracción que simplifica el proceso de unir las distintas piezas que juegan alrededor de un modelo de lenguaje.

En este artículo vamos a crear una aplicación en la que vamos a poder hacer preguntas sobre un contexto específico. En nuestro caso, vamos a cargar información desestructurada, almacenarla en una base de datos de vectores y, finalmente, hacer preguntas con ese contexto. Así podemos dar una primera visión de cómo podemos usar LangChain a nuestro favor para integrar una IA de lenguaje natural en nuestro sistema.

Crear la aplicación

Para poder crear paso a paso cada una de las fases y tener nuestra aplicación completa, podemos fijarnos en este diagrama.

Para empezar a meternos en materia lo primero que necesitamos son las dependencias. Nosotros vamos a usar GPT de OpenAI (ya que para usar una instancia de Microsoft tendríamos que utilizar otro módulo distinto) para nuestra aplicación, pero, como hemos dicho anteriormente, podemos usar otros muchos modelos provenientes de otros proveedores como el Hugging Face Hub, Cohere o directamente un punto de API que venga de Amazon API Gateway.

pip install langchain openai

Cargar y almacenar documentos

En este apartado nos vamos a ocupar de las tres primeras cajas del diagrama. De una manera muy sencilla podemos cargar, trocear y almacenar los documentos en forma de embeddings. Aunque LangChain nos proporciona un montón de herramientas para cubrir el mayor número de casos posibles, la realidad es que con muy pocas líneas podemos empezar a trabajar.

Cuando trabajamos con LangChain, nos referimos a los documentos a aquellos datos que van a dar contexto a la aplicación de lenguaje, así que lo primero que tenemos que hacer es cargarlos en memoria. Vamos a cargar una página web y, gracias a la funcionalidad que tiene LangChain sobre BeautifulSoup4, no necesitamos limpiar y recoger el texto a mano. Hemos elegido la web del día recomendada de la Wikipedia y sobre ella vamos a crear nuestro sistema QA.

from langchain.document_loaders import WebBaseLoader

loader = WebBaseLoader("https://es.wikipedia.org/wiki/Empire_State_of_Mind")

Una vez lo tenemos en memoria, utilizamos uno de sus splitters para partir el texto en trozos. Cuando trabajamos con grandes documentos lo más óptimo a la hora de almacenarlos y buscar en ellos es partiéndolos en trozos más pequeños. Idealmente, nos gustaría que todo lo que esté relacionado de forma semántica estuviese en un mismo trozo. Para controlar el tamaño utilizamos el argumento chunk_size. Este es posible que nos separe trozos de texto que podrían tener que ver (por ejemplo una frase que se quede a la mitad) y para ello podemos usar chunk_overlap donde indicamos cuánto trozo de la frase queremos que se repita en la siguiente.

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
all_splits = text_splitter.split_documents(loader.load())

Finalmente, solo nos queda guardar la información codificada en embeddings. En esta aplicación vamos a usar ChromaDB, ya que no es necesario configurarla fuera de nuestra aplicación, pero podríamos usar cualquier otra y si está integrada en la librería nos ahorra bastante trabajo.

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

vectorstore = Chroma.from_documents(documents=all_splits,
embedding=OpenAIEmbeddings())

Aplicación conversacional

Lo que queremos en esta parte es buscar en la base de datos que acabamos de crear la información que necesitamos de forma conversacional. Es decir, por un lado, usaremos un algoritmo de búsqueda en la base de datos y, por otro lado, utilizaremos un LLM (en este caso GPT) para que nos devuelva la información en forma de respuesta.

from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
qa_chain = RetrievalQA.from_chain_type(llm,  retriever=vectorstore.as_retriever())
question = "¿De qué trata la canción?"
qa_chain({"query": question})

A lo que obtendremos la siguiente respuesta:

{'query': '¿De qué trata la canción?', 'result': 'La canción trata sobre la esencia de la ciudad de Nueva York y hace referencias a elementos característicos de la cultura estadounidense, como el equipo de béisbol New York Yankees. También contiene referencias a drogas, lugares de Nueva York y sus residentes famosos.'}

Que es una buena respuesta basada en el artículo.

Antes de seguir, vamos a parar aquí un momento porque es interesante hablar de chains o las cadenas de LangChain. Las cadenas en LangChain están pensadas para poder crear una aplicación coherente que tiene múltiples componentes. Por ejemplo, en nuestro caso, tenemos un LLM, una base de datos de vectores y un prompt. Sin embargo, lo más seguro es que nuestra aplicación sea más compleja, incluyendo componentes de prompt engineering o una combinación de cadenas. Por si quieres más información, mi compañero Tomás Calleja profundiza en este post sobre el uso de cadenas en LangChain para IA generativa.

En nuestro caso utilizamos la cadena como método de RetrievalQA. RetrievalQA nos permite buscar en documentos indexados. Así podemos juntar de forma sencilla las componentes de nuestra aplicación. LangChain también nos permite crear cadenas complejas, o incluso custom, y aplicarlas a las clases de búsqueda y conversación.

Modificando el objetivo de la aplicación con prompts

Podemos modificar a nuestro gusto los prompts para poder darle carácter a la aplicación o incluso modificar su cometido. Para ello, lo que hacemos es crear un prompt que cumpla nuestro objetivo y que se integre fácilmente con las frases de la parte conversacional. A mí que me gustan mucho los emojis, le voy a pedir que conteste poniendo unos cuantos:

from langchain.prompts import PromptTemplate

template = """Responde introduciendo emojis en cada frase y al final con un emoji de un abrazo.
{context}
Question: {question}
Respuesta:"""
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context", "question"],
template=template,)
qa_chain = RetrievalQA.from_chain_type(llm,
retriever=vectorstore.as_retriever(),
chain_type_kwargs={"prompt": QA_CHAIN_PROMPT})
question = "¿De qué trata la canción?"

qa_chain({"query": question})
{'query': '¿De qué trata la canción?', 'result': 'La canción trata sobre la esencia de la ciudad de Nueva York y contiene referencias a elementos característicos de la cultura estadounidense, como el equipo de béisbol New York Yankees. 🎶🗽🎹🎤🌃🏙️🎵

¡Un abrazo! 🤗'}

Como hemos dicho antes, no solo podemos cambiar el carácter, sino el cometido:

template = """Determina si la frase es verdadera o falsa y si es false explica por qué y tu mejor corrección
{context}
Frase: {question}
Respuesta:"""
question = "La canción la canta Beyoncé"

A lo que nos responde:

{'query': 'La canción la canta Beyoncé', 'result': 'La frase es falsa. La canción no es interpretada por Beyoncé, sino por Jay-Z y Alicia Keys.'}

Conclusión

Con esta introducción tenemos las herramientas necesarias para crear aplicaciones con LLMs, además de forma muy sencilla y, en un vistazo a la documentación, y muy completa, ya que se integra bien con otras librerías y con los principales actores en el desarrollo de aplicaciones con modelos de lenguaje.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete