Construyendo aplicaciones personalizadas de preguntas y respuestas utilizando LangChain y la base de datos de vectores de Pinecone

Creando aplicaciones personalizadas de preguntas y respuestas con LangChain y la base de datos de vectores de Pinecone

Introducción

La aparición de grandes modelos de lenguaje es uno de los desarrollos tecnológicos más emocionantes de nuestra época. Ha abierto infinitas posibilidades en inteligencia artificial, ofreciendo soluciones a problemas del mundo real en diversas industrias. Una de las aplicaciones fascinantes de estos modelos es el desarrollo de chatbots o sistemas de pregunta-respuesta personalizados que se basan en fuentes de datos personales u organizacionales. Sin embargo, dado que los modelos de lenguaje se entrenan con datos generales disponibles públicamente, sus respuestas no siempre son específicas o útiles para el usuario final. Podemos utilizar frameworks como LangChain para solucionar este problema y desarrollar chatbots personalizados que proporcionen respuestas específicas basadas en nuestros datos. En este artículo, aprenderemos cómo construir aplicaciones personalizadas de pregunta y respuesta con implementación en Streamlit Cloud.

Objetivos de aprendizaje

Antes de adentrarnos en el artículo, vamos a resumir los principales objetivos de aprendizaje:

  • Aprender todo el flujo de trabajo de pregunta y respuesta personalizada y cuál es el papel de cada componente en el flujo de trabajo
  • Conocer las ventajas de una aplicación de pregunta y respuesta en comparación con el ajuste fino de un modelo de lenguaje personalizado
  • Aprender los conceptos básicos de la base de datos vectorial Pinecone para almacenar y recuperar vectores
  • Construir el pipeline de búsqueda semántica utilizando modelos de lenguaje de OpenAI, LangChain y la base de datos vectorial Pinecone para desarrollar una aplicación en Streamlit.

Este artículo se publicó como parte del Data Science Blogathon.

Visión general de las aplicaciones de pregunta y respuesta

Fuente: ScienceSoft

La pregunta y respuesta o “chat sobre tus datos” es un caso de uso extendido de los modelos de lenguaje y LangChain. LangChain proporciona una serie de componentes para cargar cualquier fuente de datos que puedas encontrar para tu caso de uso. Admite muchas fuentes de datos y transformadores para convertirlos en una serie de cadenas de texto que se almacenan en bases de datos vectoriales. Una vez que los datos se almacenan en una base de datos, se pueden realizar consultas a la base de datos utilizando componentes llamados recuperadores. Además, mediante el uso de modelos de lenguaje, podemos obtener respuestas precisas como chatbots sin tener que revisar toneladas de documentos.

LangChain admite las siguientes fuentes de datos. Como se puede ver en la imagen, permite más de 120 integraciones para conectar cualquier fuente de datos que puedas tener.

Fuente: Documentación de LangChain

Flujo de trabajo de las aplicaciones de pregunta y respuesta

Hemos aprendido sobre las fuentes de datos compatibles con LangChain, lo que nos permite desarrollar un pipeline de pregunta y respuesta utilizando los componentes disponibles en LangChain. A continuación se muestran los componentes utilizados en la carga de documentos, almacenamiento, recuperación y generación de resultados por parte de los modelos de lenguaje.

  1. Cargadores de documentos: Para cargar documentos de usuario con fines de vectorización y almacenamiento
  2. Divisores de texto: Estos son los transformadores de documentos que convierten los documentos en fragmentos de longitud fija para almacenarlos de manera eficiente
  3. Almacenamiento vectorial: Integraciones de bases de datos vectoriales para almacenar vectores de los textos de entrada
  4. Recuperación de documentos: Para recuperar textos basados en las consultas de los usuarios a la base de datos. Utilizan técnicas de búsqueda de similitud para la recuperación
  5. Resultado del modelo: Resultado final del modelo para la consulta del usuario generado a partir de la consulta de entrada y los textos recuperados.

Este es el flujo de trabajo de alto nivel del pipeline de pregunta y respuesta, que puede resolver muchos problemas del mundo real. No me he adentrado en cada componente de LangChain, pero si quieres aprender más al respecto, echa un vistazo a mi artículo anterior publicado en Analytics Vidhya (Enlace: Haz clic aquí)

Q&A app - Un diagrama de flujo de trabajo (Imagen de Autor)

Ventajas de las aplicaciones de preguntas y respuestas personalizadas sobre el ajuste fino de un modelo

  1. Respuestas específicas al contexto
  2. Adaptable a nuevos documentos de entrada
  3. No es necesario ajustar finamente el modelo, lo que ahorra el costo del entrenamiento del modelo
  4. Respuestas más precisas y específicas en lugar de respuestas generales

¿Qué es una base de datos de vectores Pinecone?

Pinecone es una base de datos de vectores popular utilizada en la construcción de aplicaciones impulsadas por LLM. Es versátil y escalable para aplicaciones de IA de alto rendimiento. Es una base de datos de vectores completamente administrada, nativa de la nube y sin problemas de infraestructura para los usuarios.

Las aplicaciones basadas en LLM involucran grandes cantidades de datos no estructurados, que requieren una memoria a largo plazo sofisticada para recuperar información con máxima precisión. Las aplicaciones de IA generativas dependen de la búsqueda semántica en incrustaciones vectoriales para devolver el contexto adecuado según la entrada del usuario.

Pinecone es muy adecuado para tales aplicaciones y está optimizado para almacenar y consultar muchos vectores con baja latencia para construir aplicaciones amigables para el usuario. Aprendamos cómo crear una base de datos de vectores Pinecone para nuestra aplicación de preguntas y respuestas.

# instalar pinecone-client
pip install pinecone-client

# importar pinecone e inicializar con tu clave de API y nombre de entorno
import pinecone
pinecone.init(api_key="TU_CLAVE_DE_API", environment="TU_AMBIENTE")

# crear tu primer índice para empezar a almacenar vectores
pinecone.create_index("primer_indice", dimension=8, metric="coseno")

# Insertar datos de muestra (5 vectores de 8 dimensiones)
index.upsert([
    ("A", [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]),
    ("B", [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]),
    ("C", [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3]),
    ("D", [0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4]),
    ("E", [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
])

# Utilizar el método list_indexes() para obtener una lista de índices disponibles en la base de datos
pinecone.list_indexes()

[Salida]>>> ['primer_indice']

En la demostración anterior, instalamos un cliente de Pinecone para inicializar una base de datos de vectores en nuestro entorno de proyecto. Una vez que se inicializa la base de datos de vectores, podemos crear un índice con la dimensión y la métrica requeridas para insertar incrustaciones vectoriales en la base de datos de vectores. En la siguiente sección, desarrollaremos un pipeline de búsqueda semántica utilizando Pinecone y LangChain para nuestra aplicación.

Construyendo un pipeline de búsqueda semántica utilizando OpenAI y Pinecone

Aprendimos que hay 5 pasos en el flujo de trabajo de la aplicación de preguntas y respuestas. En esta sección, realizaremos los primeros 4 pasos: cargadores de documentos, separadores de texto, almacenamiento de vectores y recuperación de documentos.

Para realizar estos pasos en tu entorno local o en un entorno de bloc de notas basado en la nube como Google Colab, debes instalar algunas bibliotecas y crear una cuenta en OpenAI y Pinecone para obtener sus claves de API, respectivamente. Comencemos con la configuración del entorno:

Instalando las bibliotecas necesarias

# instalar langchain y openai con otras dependencias
!pip install --upgrade langchain openai -q
!pip install pillow==6.2.2
!pip install unstructured -q
!pip install unstructured[local-inference] -q
!pip install detectron2@git+https://github.com/facebookresearch/[email protected] /
                                            #egg=detectron2 -q
!apt-get install poppler-utils
!pip install pinecone-client -q
!pip install tiktoken -q

# configurar el entorno de OpenAI
import os
os.environ["OPENAI_API_KEY"] = "TU_CLAVE_API"

# importar bibliotecas
import os
import openai
import pinecone
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Pinecone
from langchain.llms import OpenAI
from langchain.chains.question_answering import load_qa_chain

Después de la configuración de instalación, importa todas las bibliotecas mencionadas en el fragmento de código anterior. A continuación, sigue los siguientes pasos:

Cargar los documentos

En este paso, cargaremos los documentos desde el directorio como punto de partida para el pipeline del proyecto de IA. Tenemos 2 documentos en nuestro directorio, que cargaremos en nuestro entorno de proyecto.

# cargar los documentos del directorio de contenido/datos
directorio = '/contenido/datos'

# función load_docs para cargar los documentos usando la función langchain
def load_docs(directorio):
  loader = DirectoryLoader(directorio)
  documentos = loader.load()
  return documentos

documentos = load_docs(directorio)
len(documentos)
[Salida]>>> 5

Dividir los datos de texto

Las incrustaciones de texto y los LLM (lenguaje de modelado de aprendizaje) funcionan mejor si cada documento tiene una longitud fija. Por lo tanto, dividir los textos en fragmentos de igual longitud es necesario para cualquier caso de uso de LLM. Utilizaremos ‘RecursiveCharacterTextSplitter’ para convertir los documentos en el mismo tamaño que los documentos de texto.

# dividir los documentos usando el divisor de texto recursivo
def split_docs(documentos, tamaño_fragmento=200, solapamiento_fragmento=20):
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=tamaño_fragmento, chunk_overlap=solapamiento_fragmento)
  docs = text_splitter.split_documents(documentos)
  return docs

# dividir los documentos
docs = split_docs(documentos)
print(len(docs))
[Salida]>>> 12

Almacenar los datos en un almacenamiento vectorial

Una vez que se dividen los documentos, almacenaremos sus incrustaciones en la base de datos vectorial utilizando las incrustaciones de OpenAI.

# ejemplo de incrustación en una palabra aleatoria
incrustaciones = OpenAIEmbeddings()

# inicializar pinecondb
pinecone.init(
    api_key="TU-CLAVE-API",
    environment="TU-ENTORNO"
)

# definir el nombre del índice
nombre_indice = "proyecto-langchain"

# almacenar los datos y las incrustaciones en el índice de pinecone
índice = Pinecone.from_documents(docs, incrustaciones, index_name=nombre_indice)

Recuperar datos de la base de datos vectorial

En esta etapa, recuperaremos los documentos utilizando una búsqueda semántica en nuestra base de datos vectorial. Tenemos vectores almacenados en un índice llamado “proyecto-langchain” y una vez que realicemos una consulta a este índice, obtendremos los documentos más similares de la base de datos.

# Un ejemplo de consulta a nuestra base de datos
consulta = "¿Cuáles son los diferentes tipos de animales domésticos?"

# realizar una búsqueda de similitud y almacenar los documentos en la variable resultado
resultado = índice.similarity_search(
    consulta,  # nuestra consulta de búsqueda
    k=3  # devolver los 3 documentos más relevantes
)
-
--------------------------------[Salida]--------------------------------------
resultado
[Document(page_content='Pequeños mamíferos como hámsters, cobayas y conejos 
suelen ser elegidos por sus
bajas necesidades de mantenimiento. Las aves ofrecen belleza y canto,
y los reptiles como las tortugas y los lagartos pueden ser mascotas intrigantes.',
metadata={'source': '/contenido/datos/Diferentes Tipos de Animales Domésticos.txt'}),
 Document(page_content='Los animales domésticos vienen en todas las formas y tamaños, 
cada uno adecuado para diferentes estilos de vida y entornos domésticos. Los perros y los gatos 
son los más comunes, conocidos por su compañía y personalidades únicas. Pequeños', 
metadata={'source': '/contenido/datos/Diferentes Tipos de Animales Domésticos.txt'}),
 Document(page_content='mascotas intrigantes. Incluso los peces, con su presencia calmante,
pueden ser mascotas maravillosas.', 
metadata={'source': '/contenido/datos/Diferentes Tipos de Animales Domésticos.txt'})]

Podemos recuperar los documentos basados en una búsqueda de similitud desde el almacenamiento vectorial, como se muestra en el fragmento de código anterior. Si estás buscando aprender más sobre aplicaciones de búsqueda semántica, te recomiendo leer mi artículo anterior sobre este tema (enlace: haz clic aquí)

Aplicación personalizada de preguntas y respuestas con Streamlit

En la etapa final de la aplicación de preguntas y respuestas, integraremos todos los componentes del flujo de trabajo para construir una aplicación de preguntas y respuestas personalizada que permita a los usuarios ingresar diversas fuentes de datos como artículos en línea, PDF, CSV, etc., para chatear con ella, lo que los hace más productivos en sus actividades diarias. Necesitamos crear un repositorio en GitHub y agregar los siguientes archivos.

Estructura del repositorio

Agregar estos archivos del proyecto

  1. main.py — Un archivo python que contiene código front-end de streamlit
  2. qanda.py — Diseño de prompt y función de salida del modelo para devolver una respuesta a la consulta de los usuarios
  3. utils.py — Funciones de utilidad para cargar y dividir documentos de entrada
  4. vector_search.py — Función de almacenamiento de embeddings de texto y vectores
  5. requirements.txt — Dependencias del proyecto para ejecutar la aplicación en la nube pública de streamlit

Estamos admitiendo dos tipos de fuentes de datos en esta demostración del proyecto:

  1. Datos de texto basados en URL web
  2. Archivos PDF en línea

Estos dos tipos contienen una amplia gama de datos de texto y son los más frecuentes en muchos casos de uso. Puedes ver el código python main.py a continuación para comprender la interfaz de usuario de la aplicación.

# importar bibliotecas necesarias
import streamlit as st
import openai
import qanda
from vector_search import *
from utils import *
from io  import StringIO

# ingresar la clave de la API de openai
api_key = st.sidebar.text_input("Ingrese su clave de API de OpenAI:", type='password')
# clave de open ai
openai.api_key = str(api_key)

# encabezado de la aplicación
_ , col2,_ = st.columns([1,7,1])
with col2:
    col2 = st.header("Simplchat: Chatea con tus datos")
    url = False
    query = False
    pdf = False
    data = False
    # seleccionar opción según la necesidad del usuario
    options = st.selectbox("Seleccione el tipo de fuente de datos",
                            options=['URL web','PDF','Fuente de datos existente'])
    # hacer una consulta según las opciones de las fuentes de datos
    if options == 'URL web':
        url = st.text_input("Ingrese la URL de la fuente de datos")
        query = st.text_input("Ingrese su consulta")
        button = st.button("Enviar")
    elif options == 'PDF':
        pdf = st.text_input("Ingrese su enlace PDF aquí") 
        query = st.text_input("Ingrese su consulta")
        button = st.button("Enviar")
    elif options == 'Fuente de datos existente':
        data= True
        query = st.text_input("Ingrese su consulta")
        button = st.button("Enviar") 

# escribir el código para obtener la salida según la consulta y las fuentes de datos dadas
if button and url:
    with st.spinner("Actualizando la base de datos..."):
        corpusData = scrape_text(url)
        encodeaddData(corpusData,url=url,pdf=False)
        st.success("Base de datos actualizada")
    with st.spinner("Encontrando una respuesta..."):
        title, res = find_k_best_match(query,2)
        context = "\n\n".join(res)
        st.expander("Contexto").write(context)
        prompt = qanda.prompt(context,query)
        answer = qanda.get_answer(prompt)
        st.success("Respuesta: "+ answer)

# escribir el código para obtener la salida según la consulta y las fuentes de datos dadas
if button and pdf:
    with st.spinner("Actualizando la base de datos..."):
        corpusData = pdf_text(pdf=pdf)
        encodeaddData(corpusData,pdf=pdf,url=False)
        st.success("Base de datos actualizada")
    with st.spinner("Encontrando una respuesta..."):
        title, res = find_k_best_match(query,2)
        context = "\n\n".join(res)
        st.expander("Contexto").write(context)
        prompt = qanda.prompt(context,query)
        answer = qanda.get_answer(prompt)
        st.success("Respuesta: "+ answer)
        
if button and data:
    with st.spinner("Encontrando una respuesta..."):
        title, res = find_k_best_match(query,2)
        context = "\n\n".join(res)
        st.expander("Contexto").write(context)
        prompt = qanda.prompt(context,query)
        answer = qanda.get_answer(prompt)
        st.success("Respuesta: "+ answer)
        
        
# eliminar los vectores de la base de datos
st.expander("Eliminar los índices de la base de datos")
button1 = st.button("Eliminar los vectores actuales")
if button1 == True:
    index.delete(deleteAll='true')

Para verificar otros archivos de código, visita el repositorio GitHub del proyecto. (Enlace: Haz clic aquí)

Implementación de la aplicación de preguntas y respuestas en Streamlit Cloud

Interfaz de la aplicación

Streamlit ofrece una nube comunitaria para alojar aplicaciones de forma gratuita. Además, Streamlit es fácil de usar debido a sus funciones de canalización de integración continua/distribución continua automatizadas. Para obtener más información sobre Streamlit para construir aplicaciones, visita mi artículo anterior que escribí en Analytics Vidya (Enlace: Haz clic aquí)

Casos de uso de aplicaciones personalizadas de preguntas y respuestas en la industria

Adopta aplicaciones personalizadas de preguntas y respuestas en diversas industrias a medida que surgen nuevos y innovadores casos de uso en este campo. Veamos algunos de estos casos de uso:

Asistencia al servicio al cliente

La revolución del servicio al cliente ha comenzado con el surgimiento de los LLM. Ya sea en la industria del comercio electrónico, de las telecomunicaciones o de las finanzas, los bots de servicio al cliente desarrollados a partir de los documentos de una empresa pueden ayudar a los clientes a tomar decisiones más rápidas y mejor informadas, lo que se traduce en un aumento de los ingresos.

Industria de la salud

La información es crucial para que los pacientes reciban un tratamiento oportuno para ciertas enfermedades. Las empresas de atención médica pueden desarrollar un chatbot interactivo para proporcionar información médica, información sobre medicamentos, explicaciones de síntomas y pautas de tratamiento en lenguaje natural sin necesidad de una persona real.

Los abogados lidian con grandes cantidades de información legal y documentos para resolver casos judiciales. Las aplicaciones personalizadas de LLM desarrolladas utilizando grandes cantidades de datos pueden ayudar a los abogados a ser más eficientes y a resolver casos mucho más rápido.

Industria tecnológica

El caso de uso más revolucionario de las aplicaciones de preguntas y respuestas es la asistencia en programación. Las empresas de tecnología pueden construir aplicaciones de este tipo en su base de código interna para ayudar a los programadores a resolver problemas, comprender la sintaxis del código, depurar errores e implementar funcionalidades específicas.

Gobierno y servicios públicos

Las políticas y programas gubernamentales contienen una gran cantidad de información que puede abrumar a muchas personas. Los ciudadanos pueden obtener información sobre programas y regulaciones gubernamentales mediante el desarrollo de aplicaciones personalizadas para dichos servicios gubernamentales. También puede ayudar a completar formularios y solicitudes gubernamentales correctamente.

Conclusión

En conclusión, hemos explorado las emocionantes posibilidades de construir una aplicación personalizada de preguntas y respuestas utilizando LangChain y la base de datos de vectores de Pinecone. Este blog nos ha llevado a través de los conceptos fundamentales, desde una visión general de la aplicación de preguntas y respuestas hasta la comprensión de las capacidades de la base de datos de vectores de Pinecone. Combinando el poder del pipeline de búsqueda semántica de OpenAI con la indexación y recuperación eficientes de Pinecone, hemos aprovechado el potencial para crear una solución de preguntas y respuestas sólida y precisa con Streamlit. Veamos los puntos clave del artículo:

Puntos clave

  • Los modelos de lenguaje grandes (LLMs) han revolucionado la IA, permitiendo diversas aplicaciones. La personalización de los chatbots con datos personales u organizativos es un enfoque poderoso.
  • Aunque los LLMs generales ofrecen una comprensión amplia del lenguaje, las aplicaciones personalizadas de preguntas y respuestas ofrecen una ventaja distintiva sobre los LLMs personalizados ajustados debido a su flexibilidad y rentabilidad.
  • Al incorporar la base de datos de vectores de Pinecone, los LLMs de OpenAI y LangChain, aprendimos cómo desarrollar un pipeline de búsqueda semántica y desplegarlo en una plataforma basada en la nube como Streamlit.

Preguntas frecuentes

Los medios mostrados en este artículo no son propiedad de Analytics Vidhya y se utilizan a discreción del autor.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Este artículo de IA revela DiffEnc Avanzando en los modelos de difusión para mejorar el rendimiento generativo

Los modelos de difusión son modelos poderosos que se destacan en una amplia gama de tareas de generación, como imágen...

Inteligencia Artificial

Este boletín de inteligencia artificial es todo lo que necesitas #75

Esta semana fue testigo de la conclusión del drama en OpenAI con el regreso de Sam Altman y Greg Brockman a OpenAI y ...

Inteligencia Artificial

ExLlamaV2 La biblioteca más rápida para ejecutar LLMs

ExLlamaV2 es una biblioteca diseñada para exprimir aún más rendimiento de GPTQ. Gracias a nuevos kernels, está optimi...

Inteligencia Artificial

La retroalimentación colaborativa ayuda a entrenar a los robots

Un enfoque de aprendizaje por refuerzo entrena a los robots utilizando retroalimentación proporcionada por usuarios n...