Agentes Orientados a Documentos Un Viaje con Bases de Datos Vectoriales, LLMs, Langchain, FastAPI y Docker

Agentes Orientados a Documentos con Bases de Datos Vectoriales, LLMs, Langchain, FastAPI y Docker

Aprovechando ChromaDB, Langchain y ChatGPT: Respuestas Mejoradas y Fuentes Citadas de Bases de Datos de Documentos Grandes

Introducción

Los agentes orientados a documentos están empezando a ganar terreno en el panorama empresarial. Las empresas cada vez aprovechan más estas herramientas para capitalizar la documentación interna, mejorando sus procesos empresariales. Un informe reciente de McKinsey [1] destaca esta tendencia, sugiriendo que la IA generativa podría impulsar la economía mundial en $2.6-4.4 billones al año y automatizar hasta el 70% de las actividades laborales actuales. El estudio identifica el servicio al cliente, las ventas y el marketing, y el desarrollo de software como los principales sectores que se verán afectados por la transformación. La mayor parte del cambio proviene del hecho de que la información que impulsa estas áreas dentro de una empresa puede ser más accesible tanto para los empleados como para los clientes a través del uso de soluciones como los agentes orientados a documentos.

Con la tecnología actual, todavía nos enfrentamos a algunos desafíos. Incluso si consideramos los nuevos Modelos de Lenguaje Grande (LLMs, por sus siglas en inglés) con límites de 100k tokens, los modelos aún tienen ventanas de contexto limitadas. Si bien 100k tokens parecen ser un número alto, es un número pequeño cuando consideramos el tamaño de las bases de datos que alimentan, por ejemplo, un departamento de servicio al cliente. Otro problema que a menudo surge son las imprecisiones en las salidas del modelo. En este artículo, proporcionaremos una guía paso a paso para construir un agente orientado a documentos que pueda manejar documentos de cualquier tamaño y ofrecer respuestas verificables.

Utilizamos una base de datos de vectores, ChromaDB, para aumentar las capacidades de longitud del contexto de nuestro modelo y Langchain para facilitar las integraciones entre los diferentes componentes de nuestra arquitectura. Como nuestro LLM, utilizamos ChatGPT de OpenAI. Dado que queremos servir nuestra aplicación, utilizamos FastAPI para crear puntos finales para que los usuarios interactúen con nuestro agente. Por último, nuestra aplicación se encuentra en contenedores utilizando Docker, lo que nos permite implementarla fácilmente en cualquier tipo de entorno.

Figura 1: Los agentes de IA se vuelven más inteligentes todos los días (fuente de la imagen)

Como siempre, el código está disponible en mi Github .

Bases de Datos de Vectores: El Núcleo Esencial de las Aplicaciones de Búsqueda Semántica

Las bases de datos de vectores son esenciales para desbloquear el poder de la IA generativa. Estos tipos de bases de datos están optimizados para manejar incrustaciones de vectores, representaciones de datos que contienen información semántica rica del dato original. A diferencia de las bases de datos basadas en escalares tradicionales, que tienen dificultades con la complejidad de las incrustaciones de vectores, las bases de datos de vectores indexan estas incrustaciones, asociándolas con su contenido de origen y permitiendo características avanzadas como la búsqueda de información semántica y la memoria a largo plazo en aplicaciones de IA.

Las bases de datos de vectores no son lo mismo que los índices de vectores, como la Búsqueda de Similitud de IA de Facebook (FAISS), que ya hemos cubierto en esta serie en un artículo anterior [2]. Permiten la inserción, eliminación y actualización de datos, almacenan metadatos asociados y admiten actualizaciones de datos en tiempo real sin necesidad de reindexación completa, un proceso que consume mucho tiempo y recursos computacionales.

En lugar de coincidencias exactas, las bases de datos de vectores emplean métricas de similitud para encontrar los vectores más cercanos a una consulta. Utilizan algoritmos de búsqueda de vecino más cercano aproximado (ANN, por sus siglas en inglés) para una búsqueda optimizada. Algunos ejemplos de estos algoritmos son: Proyección Aleatoria, Cuantización de Producto o Pequeño Mundo Navegable Jerárquico. Estos algoritmos comprimen el vector original, acelerando el proceso de consulta. Además, medidas de similitud como la similitud del coseno, la distancia euclidiana y el producto punto comparan e identifican los resultados más relevantes para una consulta.

La Figura 2 ilustra de manera sucinta el proceso de búsqueda de similitud en las bases de datos de vectores. Comenzando con la ingestión de documentos sin procesar (i), los datos se dividen en fragmentos manejables (ii) y se convierten en incrustaciones de vectores (iii). Estas incrustaciones se indexan para una recuperación rápida (iv), y se calculan métricas de similitud entre los vectores de los fragmentos y la consulta del usuario (v). El proceso finaliza con la salida de los fragmentos de datos más relevantes (vi), ofreciendo a los usuarios información alineada con su consulta original.

Figura 2: El proceso de búsqueda de similitud: i) ingestión de documentos sin procesar, ii) procesamiento en fragmentos, iii) creación de incrustaciones, iv) indexación, v) cálculo de métricas de similitud y, finalmente, vi) producción de los fragmentos de salida (imagen por el autor)

Construyendo un Agente Orientado a Documentos

Comenzamos cargando todos los modelos y datos necesarios al iniciar el servidor.

Cargamos nuestros datos desde un directorio predefinido y los procesamos en fragmentos manejables. Estos fragmentos están diseñados para tener un tamaño de modo que podamos pasarlos al LLM a medida que obtenemos los resultados del procedimiento de búsqueda de similitud. Este proceso utiliza el DirectoryLoader para cargar los documentos en memoria y el RecursiveCharacterTextSplitter para dividirlos en fragmentos manejables. Divide los documentos a nivel de carácter, con un tamaño de fragmento predeterminado de 1000 caracteres y una superposición de fragmentos de 20 caracteres. La superposición de fragmentos asegura que haya continuidad contextual entre los fragmentos, minimizando el riesgo de perder contexto significativo en los límites de los fragmentos.

def load_docs(directory: str):    """    Carga los documentos del directorio dado.    """    loader = DirectoryLoader(directory)    documents = loader.load()    return documentsdef split_docs(documents, chunk_size=1000, chunk_overlap=20):    """    Divide los documentos en fragmentos.    """    text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)    docs = text_splitter.split_documents(documents)    return docs

Luego, generamos incrustaciones vectoriales a partir de estos fragmentos utilizando el método SentenceTransformerEmbeddings y los indexamos en ChromaDB, nuestra base de datos vectorial. Estas incrustaciones se almacenan en la base de datos y sirven como nuestros datos buscables. La base de datos no vive en la memoria; observe que la estamos persistiendo en disco, lo que reduce nuestra sobrecarga de memoria. A continuación, cargamos el modelo de chat, específicamente el gpt-3.5-turbo de OpenAI, que sirve como nuestro LLM.

@app.on_event("startup")async def startup_event():    """    Carga todos los modelos y datos necesarios una vez que el servidor se inicia.    """    app.directory = '/app/content/'    app.documents = load_docs(app.directory)    app.docs = split_docs(app.documents)    app.embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")    app.persist_directory = "chroma_db"    app.vectordb = Chroma.from_documents(        documents=app.docs,        embedding=app.embeddings,        persist_directory=app.persist_directory    )    app.vectordb.persist()    app.model_name = "gpt-3.5-turbo"    app.llm = ChatOpenAI(model_name=app.model_name)    app.db = Chroma.from_documents(app.docs, app.embeddings)    app.chain = load_qa_chain(app.llm, chain_type="stuff", verbose=True)

Finalmente, el punto final “/query/{question}” recibe consultas de usuarios. Ejecuta una búsqueda de similitud en la base de datos utilizando la pregunta como entrada. Si existen documentos coincidentes, se alimentan al LLM y se genera la respuesta. La respuesta y las fuentes (los documentos originales y su metadatos) se devuelven, asegurando que la información proporcionada sea fácilmente verificable.

@app.get("/query/{question}")async def query_chain(question: str):    """    Realiza consultas al modelo con una pregunta dada y devuelve la respuesta.    """    matching_docs_score = app.db.similarity_search_with_score(question)    if len(matching_docs_score) == 0:        raise HTTPException(status_code=404, detail="No se encontraron documentos coincidentes")    matching_docs = [doc for doc, score in matching_docs_score]    answer = app.chain.run(input_documents=matching_docs, question=question)    # Prepara las fuentes    sources = [{        "contenido": doc.page_content,        "metadatos": doc.metadata,        "puntuación": score    } for doc, score in matching_docs_score]    return {"respuesta": answer, "fuentes": sources}

Containerizamos la aplicación usando Docker, lo que garantiza aislamiento y consistencia del entorno, independientemente de la plataforma de implementación. El siguiente Dockerfile detalla nuestra configuración:

FROM python:3.9-busterWORKDIR /appCOPY . /appRUN pip install - no-cache-dir -r requirements.txtEXPOSE 1010CMD ["uvicorn", "main:app", " - host", "0.0.0.0", " - port", "1010"]

La aplicación se ejecuta en un entorno de Python 3.9 y necesitamos instalar todas las dependencias necesarias desde un archivo requirements.txt:

langchain==0.0.221uvicorn==0.22.0fastapi==0.99.1unstructured==0.7.12sentence-transformers==2.2.2chromadb==0.3.26openai==0.27.8python-dotenv==1.0.0

La aplicación se sirve a través de Uvicorn en el puerto 1010.

Tenga en cuenta que necesitamos configurar nuestras variables de entorno. Nuestra aplicación requiere la OPENAI_API_KEY para el modelo ChatOpenAI. La mejor práctica para información sensible como claves de API es almacenarlas como variables de entorno en lugar de codificarlas directamente en la aplicación. Utilizamos el paquete python-dotenv para cargar las variables de entorno desde un archivo .env en la raíz del proyecto. En un entorno de producción, sería recomendable utilizar un método más seguro, como Docker secrets o un servicio de bóveda segura.

Experimento: Comprender la efectividad de los agentes orientados a documentos

El objetivo principal del experimento fue evaluar la efectividad de nuestro agente orientado a documentos para proporcionar respuestas completas y precisas a las consultas de los usuarios.

Utilizamos una serie de nuestros artículos de VoAGI como base de conocimientos. Estos artículos, que cubren una variedad de temas de IA y aprendizaje automático, se ingieren e indexan en nuestra base de datos de vectores Chroma. Los artículos seleccionados fueron:

  1. “Whisper JAX vs PyTorch: Descubriendo la verdad sobre el rendimiento de ASR en GPU”
  2. “Probando el modelo de Habla Multilingüe Masivamente (MMS) que admite 1162 idiomas”
  3. “Aprovechando el modelo Falcon 40B, el LLM de código abierto más potente”
  4. “El poder de la llamada a funciones de OpenAI en modelos de aprendizaje de lenguaje: una guía completa”

Los artículos se dividieron en fragmentos manejables, se convirtieron en vectores integrados y se indexaron en nuestra base de datos, formando así la base del conocimiento del agente.

La consulta del usuario se ejecutó llamando al punto final de la API de nuestra aplicación, que está implementada usando FastAPI y se implementa a través de Docker. La consulta que usamos para el experimento fue: “¿Qué es Falcon-40b y puedo usarlo para uso comercial?”.

curl --location 'http://0.0.0.0:1010/query/What is Falcon-40b and can I use it for commercial use'

En respuesta a nuestra consulta, el LLM explicó qué es Falcon-40b y confirmó que se puede usar comercialmente. La información fue respaldada por cuatro fragmentos de origen diferentes, todos provenientes del artículo “Aprovechando el modelo Falcon 40B, el LLM de código abierto más potente”. Cada fragmento de origen también se agregó a la respuesta, como vimos anteriormente, para que el usuario pudiera verificar el texto original que respalda la respuesta del LLM. Los fragmentos también se calificaron en función de su relevancia para la consulta, lo que nos brinda una perspectiva adicional sobre la importancia de esa sección para la respuesta general del agente.

{    "answer": "Falcon-40B es un modelo de lenguaje de vanguardia desarrollado por el Technology Innovation Institute (TII). Es un modelo basado en transformadores que funciona bien en diversas tareas de comprensión del lenguaje. La importancia de Falcon-40B radica en que ahora está disponible de forma gratuita para uso comercial e investigativo, tal como anunció el TII. Esto significa que los desarrolladores e investigadores pueden acceder y modificar el modelo según sus necesidades específicas sin pagar regalías. Sin embargo, es importante tener en cuenta que aunque Falcon-40B está disponible para uso comercial, todavía se entrena con datos de la web y puede contener posibles sesgos y estereotipos presentes en línea. Por lo tanto, se deben implementar estrategias de mitigación adecuadas al utilizar Falcon-40B en un entorno de producción.",    "sources": [        {            "content": "Aquí radica la importancia de Falcon-40B. Al final de la semana pasada, el Technology Innovation Institute (TII) anunció que Falcon-40B ahora es gratuito para uso comercial e investigativo, sin pagar regalías. De esta manera, rompe las barreras de los modelos propietarios, brindando a los desarrolladores e investigadores acceso gratuito a un modelo de lenguaje de vanguardia que pueden utilizar y modificar según sus necesidades específicas.\n\nAdemás, el modelo Falcon-40B es ahora el modelo de mejor rendimiento en la tabla de clasificación OpenLLM, superando a modelos como LLaMA, StableLM, RedPajama y MPT. Esta tabla de clasificación tiene como objetivo rastrear, clasificar y evaluar el rendimiento de varios modelos de lenguaje y chatbots, proporcionando una métrica clara e imparcial de sus capacidades. Figura 1: Falcon-40B domina la tabla de clasificación OpenLLM (fuente de la imagen)\n\nComo siempre, el código está disponible en mi Github. ¿Cómo se desarrolló Falcon LLM?",            "metadata": {                "source": "/app/content/Harnessing the Falcon 40B Model, the Most Powerful Open-Source LLM.txt"            },            "score": 1.045290231704712        },        {            "content": "El bloque decodificador en Falcon-40B presenta un diseño paralelo de atención/MLP (Perceptrón Multicapa) con normalización de dos capas. Esta estructura ofrece beneficios en términos de escalabilidad del modelo y velocidad de cálculo. La paralelización de las capas de atención y MLP mejora la capacidad del modelo para procesar grandes cantidades de datos simultáneamente, lo que reduce el tiempo de entrenamiento. Además, la implementación de la normalización de dos capas ayuda a estabilizar el proceso de aprendizaje y mitigar problemas relacionados con el desplazamiento covariable interno, lo que resulta en un modelo más sólido y confiable. Implementación de capacidades de chat con Falcon-40B-Instruct\n\nEstamos utilizando el Falcon-40B-Instruct, que es la nueva variante de Falcon-40B. Básicamente, es el mismo modelo, pero se ajusta fino en una mezcla de Baize. Baize es un modelo de chat de código abierto entrenado con LoRA, una adaptación de rango bajo de grandes modelos de lenguaje. Baize utiliza 100.000 diálogos de ChatGPT conversando consigo mismo y también los datos de Alpaca para mejorar su rendimiento.",            "metadata": {                "source": "/app/content/Harnessing the Falcon 40B Model, the Most Powerful Open-Source LLM.txt"            },            "score": 1.319214940071106        },        {            "content": "Una de las diferencias fundamentales en el desarrollo de Falcon fue la calidad de los datos de entrenamiento. El tamaño de los datos de preentrenamiento para Falcon fue de casi cinco billones de tokens recopilados de rastreos web públicos, artículos de investigación y conversaciones en redes sociales. Dado que los modelos de lenguaje son particularmente sensibles a los datos en los que se entrenan, el equipo construyó un canal de datos personalizado para extraer datos de alta calidad de los datos de preentrenamiento mediante un amplio filtrado y deduplicación.\n\nEl modelo en sí se entrenó durante dos meses utilizando 384 GPUs en AWS. El resultado es un LLM que supera a GPT-3, requiriendo solo el 75% del presupuesto de cómputo de entrenamiento y una quinta parte del cómputo en el momento de la inferencia.",            "metadata": {                "source": "/app/content/Harnessing the Falcon 40B Model, the Most Powerful Open-Source LLM.txt"            },            "score": 1.3254718780517578        },        {            "content": "Falcon-40B se centra en el inglés, pero también incluye capacidades de idioma alemán, español, francés, italiano, portugués, polaco, holandés, rumano, checo y sueco. Tenga en cuenta que, al igual que cualquier modelo entrenado en datos web, existe el riesgo potencial de reflejar los sesgos y estereotipos presentes en línea. Por lo tanto, evalúe adecuadamente estos riesgos e implemente estrategias de mitigación adecuadas al utilizar Falcon-40B en un entorno de producción. Arquitectura y objetivo del modelo\n\nFalcon-40B, como miembro de la familia de modelos basados en transformadores, sigue la tarea de modelado del lenguaje causal, donde el objetivo es predecir el siguiente token en una secuencia de tokens. Su arquitectura se basa fundamentalmente en los principios de diseño de GPT-3 [1], con algunas modificaciones importantes.",            "metadata": {                "source": "/app/content/Harnessing the Falcon 40B Model, the Most Powerful Open-Source LLM.txt"            },            "score": 1.3283030986785889        }    ]}

Conclusiones

En este artículo, hemos construido una solución para superar los desafíos de manejar documentos a gran escala en sistemas de IA, aprovechando bases de datos de vectores y una suite de herramientas de código abierto. Nuestro enfoque utiliza ChromaDB y Langchain con ChatGPT de OpenAI para construir un agente orientado a documentos capaz.

Nuestro enfoque permite que el agente responda consultas complejas buscando y procesando fragmentos de texto de bases de datos a gran escala, en nuestro caso, una serie de artículos de VoAGI sobre diversos temas de IA. Además de las respuestas del agente, también devolvemos los fragmentos de los documentos originales utilizados para respaldar las afirmaciones del LLM y su puntaje en cuanto a similitud con la consulta del usuario. Esta es una característica importante ya que estos agentes a veces pueden proporcionar información incorrecta.

Crónicas de los Modelos de Lenguaje Grandes: Navegando la Frontera del Procesamiento del Lenguaje Natural

Este artículo pertenece a “Crónicas de los Modelos de Lenguaje Grandes: Navegando la Frontera del Procesamiento del Lenguaje Natural”, una nueva serie semanal de artículos que explorará cómo aprovechar el poder de los modelos grandes para diversas tareas de procesamiento del lenguaje natural. Al adentrarnos en estas tecnologías de vanguardia, buscamos capacitar a desarrolladores, investigadores y entusiastas para aprovechar el potencial del PNL y desbloquear nuevas posibilidades.

Artículos publicados hasta ahora:

  1. Resumiendo los últimos lanzamientos de Spotify con ChatGPT
  2. Maestría en búsqueda semántica a gran escala: Indexar millones de documentos con tiempos de inferencia ultrarrápidos utilizando FAISS y Sentence Transformers
  3. Desbloqueando el poder de los datos de audio: Transcripción y diarización avanzadas con Whisper, WhisperX y PyAnnotate
  4. Whisper JAX vs PyTorch: Descubriendo la verdad sobre el rendimiento de ASR en GPUs
  5. Vosk para reconocimiento de voz empresarial eficiente: Una guía de evaluación e implementación
  6. Probando el Modelo de Habla Masivamente Multilingüe (MMS) que admite 1162 idiomas
  7. Aprovechando el Modelo Falcon 40B, el LLM de código abierto más potente
  8. El poder de las llamadas a funciones de OpenAI en modelos de aprendizaje de lenguaje: Una guía completa

Referencias

[1] https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/the-economic-potential-of-generative-ai-the-next-productivity-frontier#introduction

[2] Maestría en búsqueda semántica a gran escala: Indexar millones de documentos con tiempos de inferencia ultrarrápidos utilizando FAISS y Sentence Transformers

Manténgase en contacto: LinkedIn

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

Transforma imágenes de moda en impresionantes videos fotorrealistas con el marco de IA DreamPose

La fotografía de moda es omnipresente en plataformas en línea, incluyendo redes sociales y sitios web de comercio ele...

Inteligencia Artificial

Se analiza el sonido de la tos para identificar la gravedad de los pacientes de COVID-19

Un estudio identificó características tos que pueden ayudar a evaluar la gravedad de la COVID-19 y permitir el monito...

Inteligencia Artificial

Reino Unido afirma que Rusia ha atacado a legisladores y otros con ciberataques durante años

El gobierno dijo que un grupo vinculado al servicio de inteligencia de Rusia llevó a cabo operaciones sostenidas para...

Inteligencia Artificial

El aumento de los costos de los centros de datos vinculados a las demandas de la inteligencia artificial

El uso de energía asociado con la ejecución de cálculos intensivos de IA se está convirtiendo rápidamente en un facto...