LlamaIndex el marco de trabajo definitivo de LLM para indexación y recuperación

LlamaIndex LLM's ultimate framework for indexing and retrieval.

Una introducción a LlamaIndex

LlamaIndex, anteriormente conocido como GPT Index, es un notable marco de datos diseñado para ayudarte a construir aplicaciones con LLMs proporcionando herramientas esenciales que facilitan la ingestión, estructuración, recuperación e integración de datos con varios marcos de aplicación. Las capacidades ofrecidas por LlamaIndex son numerosas y altamente valiosas:

✅ Ingesta de diferentes fuentes y formatos de datos mediante conectores de datos (Llama Hub). ✅ Habilitar operaciones de documentos como la inserción, eliminación, actualización y actualización del índice de documentos. ✅ Soportar la síntesis sobre datos heterogéneos y múltiples documentos. ✅ Usar “Router” para elegir entre diferentes motores de consulta. ✅ Permitir la incorporación hipotética de documentos para mejorar la calidad de salida. ✅ Ofrecer una amplia gama de integraciones con varios almacenes de vectores, complementos de ChatGPT, herramientas de rastreo y LangChain, entre otros. ✅ Soportar la nueva API de llamada a funciones OpenAI.

Estos son solo algunos ejemplos de las extensas capacidades proporcionadas por LlamaIndex. En esta publicación de blog, exploraremos algunas de las funcionalidades que encuentro excepcionalmente útiles con LlamaIndex.

Conectores de datos (LlamaHub)

Cuando se desarrolla una aplicación LLM, es esencial permitir que LLM interactúe efectivamente con fuentes de datos externas. Cómo ingerir datos es la clave aquí. Llama Hub ofrece una amplia gama de más de 100 fuentes y formatos de datos, lo que permite a LlamaIndex o LangChain ingerir datos de manera consistente.

LlamaHub. Fuente: https://llama-hub-ui.vercel.app/.

De forma predeterminada, puedes pip install llama-hub y usarlo como paquete independiente. También puedes optar por usar nuestro método download_loader para descargar individualmente un cargador de datos para su uso con LlamaIndex.

Aquí hay un ejemplo en el que cargamos un cargador de datos de Wikipedia desde el paquete llama-hub. La sintaxis consistente es muy buena.

from llama_hub.wikipedia.base import WikipediaReaderloader = WikipediaReader()documents = loader.load_data(pages=['Berlin', 'Rome', 'Tokyo', 'Canberra', 'Santiago'])

Comprueba la salida:

Llama Hub también admite documentos multimodales. Por ejemplo, el cargador ImageReader utiliza pytesseract o el modelo transformador Donut para extraer texto de una imagen.

Funcionalidades de consulta básicas

Índice, recuperador y motor de consulta

Índice, recuperador y motor de consulta son tres componentes básicos para hacer preguntas sobre tus datos o documentos:

  • El índice es una estructura de datos que nos permite recuperar información relevante rápidamente para una consulta de usuario a partir de documentos externos. El índice funciona mediante el análisis de los documentos en fragmentos de texto, que se llaman objetos “Nodo”, y luego construyendo un índice a partir de los fragmentos.
  • El recuperador se utiliza para buscar y recuperar información relevante dada una consulta de usuario.
  • El motor de consulta se construye sobre el índice y el recuperador, proporcionando una interfaz genérica para hacer preguntas sobre tus datos.

Aquí está la forma más sencilla de hacer preguntas sobre tu documento. Primero creas un índice a partir del documento y luego usas un motor de consulta como interfaz para tu pregunta:

from llama_index import VectorStoreIndexindex = VectorStoreIndex.from_documents(docs)query_engine = index.as_query_engine()response = query_engine.query("¿Quién es Paul Graham?")

Existen varios tipos de índices, métodos de recuperador y motores de consulta que puedes leer en la documentación de LlamaIndex. En el resto de este artículo, me gustaría cubrir algunas de las características geniales que encuentro útiles a continuación.

Manejar actualizaciones de documentos

A menudo, una vez que creamos un índice para nuestro documento, puede haber una necesidad de actualizar periódicamente el documento. Este proceso puede ser costoso si tuviéramos que recrear las incrustaciones para todo el documento nuevamente. La estructura de índice de LlamaIndex ofrece una solución al permitir operaciones de inserción, eliminación, actualización y actualización eficientes. Por ejemplo, se puede insertar un nuevo documento como nodos adicionales (fragmentos de texto) sin necesidad de recrear nodos de documentos anteriores:

# Fuente: https://gpt-index.readthedocs.io/en/latest/how_to/index/document_management.htmlfrom llama_index import ListIndex, Documentindex = ListIndex([])text_chunks = ['text_chunk_1', 'text_chunk_2', 'text_chunk_3']doc_chunks = []for i, text in enumerate(text_chunks):    doc = Document(text, doc_id=f"doc_id_{i}")    doc_chunks.append(doc)# insertfor doc_chunk in doc_chunks:    index.insert(doc_chunk)

Consulta de múltiples documentos

Con LlamaIndex, es fácil consultar múltiples documentos. Esta funcionalidad se habilita a través de la clase `SubQuestionQueryEngine`. Cuando se le proporciona una consulta, el motor de consulta genera un “plan de consulta” que consiste en subconsultas contra subdocumentos, que luego se sintetizan para proporcionar la respuesta final.

# Fuente: https://gpt-index.readthedocs.io/en/latest/examples/usecases/10q_sub_question.html# Cargar datamarch_2022 = SimpleDirectoryReader(input_files=["../data/10q/uber_10q_march_2022.pdf"]).load_data()june_2022 = SimpleDirectoryReader(input_files=["../data/10q/uber_10q_june_2022.pdf"]).load_data()sept_2022 = SimpleDirectoryReader(input_files=["../data/10q/uber_10q_sept_2022.pdf"]).load_data()# Construir índicesmarch_index = VectorStoreIndex.from_documents(march_2022)june_index = VectorStoreIndex.from_documents(june_2022)sept_index = VectorStoreIndex.from_documents(sept_2022)# Construir motores de consulta (query engines)march_engine = march_index.as_query_engine(similarity_top_k=3)june_engine = june_index.as_query_engine(similarity_top_k=3)sept_engine = sept_index.as_query_engine(similarity_top_k=3)query_engine_tools = [    QueryEngineTool(        query_engine=sept_engine,         metadata=ToolMetadata(name='sept_22', description='Proporciona información sobre los estados financieros trimestrales de Uber que finalizan en septiembre de 2022')    ),    QueryEngineTool(        query_engine=june_engine,         metadata=ToolMetadata(name='june_22', description='Proporciona información sobre los estados financieros trimestrales de Uber que finalizan en junio de 2022')    ),    QueryEngineTool(        query_engine=march_engine,         metadata=ToolMetadata(name='march_22', description='Proporciona información sobre los estados financieros trimestrales de Uber que finalizan en marzo de 2022')    ),]# Ejecutar consultas s_engine = SubQuestionQueryEngine.from_defaults(query_engine_tools=query_engine_tools)Run queriesresponse = s_engine.query('Analice el crecimiento de los ingresos de Uber en los dos últimos trimestres presentados')

Como se puede ver a continuación, LlamaIndex descompuso una consulta compleja en 2 subconsultas y pudo comparar la información de varios documentos para obtener la respuesta final.

Usar el “Router” para seleccionar entre diferentes motores de consulta

Imagínese que está construyendo un bot para recuperar información tanto de Notion como de Slack, ¿cómo sabe el modelo de lenguaje qué herramienta usar para buscar información? LlamaIndex es como un ayudante inteligente que puede encontrar cosas para usted, incluso si están en lugares diferentes. Específicamente, el “Router” de LlamaIndex es una abstracción muy simple que permite “elegir” entre diferentes motores de consulta.

En este ejemplo, tenemos dos índices de documentos de Notion y Slack, y creamos dos motores de consulta para cada uno de ellos. Después de eso, juntamos todas las herramientas y creamos una herramienta superpuesta llamada RouterQueryEngine, que selecciona qué herramienta usar en función de la descripción que dimos a las herramientas individuales. De esta manera, cuando hacemos una pregunta sobre Notion, el router buscará automáticamente información de los documentos de Notion.

# Fuente: https://gpt-index.readthedocs.io/en/latest/use_cases/queries.html#routing-over-heterogeneous-datafrom llama_index import TreeIndex, VectorStoreIndexfrom llama_index.tools import QueryEngineTool# definir sub-índicesindex1 = VectorStoreIndex.from_documents(notion_docs)index2 = VectorStoreIndex.from_documents(slack_docs)# definir motores de consulta y herramientastool1 = QueryEngineTool.from_defaults(query_engine=index1.as_query_engine(),description="Usar este motor de consulta para hacer...",)tool2 = QueryEngineTool.from_defaults(query_engine=index2.as_query_engine(),description="Usar este motor de consulta para otra cosa...",)from llama_index.query_engine import RouterQueryEnginequery_engine = RouterQueryEngine.from_defaults(query_engine_tools=[tool1, tool2])response = query_engine.query("En Notion, dame un resumen del plan de productos.")

Hay muchos casos de uso emocionantes para esto. Aquí hay un ejemplo completo que utiliza el enrutador para elegir entre SQL y una base de datos vectorial: https://gpt-index.readthedocs.io/en/latest/examples/query_engine/SQLRouterQueryEngine.html .

Incrustaciones hipotéticas de documentos (HyDE)

Típicamente, cuando hacemos una pregunta sobre un documento externo, lo que normalmente hacemos es utilizar incrustaciones de texto para crear representaciones vectoriales tanto para la pregunta como para el documento. Luego utilizamos la búsqueda semántica para encontrar los fragmentos de texto que son más relevantes para la pregunta. Sin embargo, la respuesta a la pregunta puede diferir significativamente de la pregunta en sí. ¿Y si pudiéramos generar respuestas hipotéticas a nuestra pregunta primero y luego encontrar los fragmentos de texto que son más relevantes para la respuesta hipotética? Ahí es donde entran en juego las incrustaciones hipotéticas de documentos (HyDE) y pueden mejorar potencialmente la calidad de salida.

# Fuente: https://gpt-index.readthedocs.io/en/latest/examples/query_transformations/HyDEQueryTransformDemo.html# cargar documentosdocuments = SimpleDirectoryReader('llama_index/examples/paul_graham_essay/data').load_data()index = VectorStoreIndex.from_documents(documents)query_str = "what did paul graham do after going to RISD"#Ahora, utilizamos HyDEQueryTransform para generar un documento hipotético y lo usamos para la búsqueda de incrustaciones.hyde = HyDEQueryTransform(include_original=True)hyde_query_engine = TransformQueryEngine(query_engine, hyde)response = hyde_query_engine.query(query_str)display(Markdown(f"<b>{response}</b>"))#En este ejemplo, HyDE mejora significativamente la calidad de salida, al alucinar con precisión lo que Paul Graham hizo después de RISD (ver abajo), y así mejorar la calidad de incrustación y la salida final.query_bundle = hyde(query_str)hyde_doc = query_bundle.embedding_strs[0]

Soporte para llamadas de función de OpenAI

OpenAI lanzó recientemente la capacidad de llamar funciones para conectar de manera más confiable las capacidades de GPT con herramientas y API externas. Revisa mi video anterior para ver exactamente cómo funciona.

LlamaIndex ha integrado rápidamente esta funcionalidad y agregado un nuevo agente OpenAIAgent. Revisa este notebook para obtener más información.

¿Y si hay demasiadas funciones? ¡Utiliza el RetrieverOpenAIAgent! Revisa este notebook.

Usar LlamaIndex con LangChain

LlmaIndex ofrece una amplia gama de integraciones con varias tiendas de vectores, complementos de ChatGPT, herramientas de seguimiento y LangChain.

Fuente: https://imgflip.com/memegenerator .

¿Cómo es diferente LIamaIndex de LangChain?

Si has utilizado LangChain, es posible que te preguntes cómo es LlamaIndex diferente de LangChain. Si no estás familiarizado con LangChain, revisa mi blog post y video anterior. Encontrarás similitudes sorprendentes entre LIamaIndex y LangChain en sus funcionalidades, incluyendo la indexación, la búsqueda semántica, la recuperación y las bases de datos vectoriales. Ambos sobresalen en tareas como responder preguntas, resumir documentos y construir chatbots.

Sin embargo, cada uno tiene sus áreas únicas de enfoque. LangChain, con su extensa lista de características, abarca un campo más amplio, concentrándose en el uso de cadenas y agentes para conectarse con APIs externas. Por otro lado, LlamaIndex tiene un enfoque más estrecho y destaca en el área de la indexación de datos y la recuperación de documentos.

¿Cómo usar LlamaIndex con LangChain?

Curiosamente, LIamaIndex y LangChain no son mutuamente excluyentes. De hecho, puedes utilizar ambos en tus aplicaciones LLM. Puedes utilizar tanto el cargador de datos como el motor de consulta de LlamaIndex y los agentes de LangChain. Sé que mucha gente realmente utiliza ambas herramientas en sus proyectos.

Aquí tienes un ejemplo donde utilizamos LlamaIndex para mantener el historial de chat al usar un agente de LangChain. Cuando preguntamos “¿cuál es mi nombre?” en la segunda ronda de conversación, el modelo de lenguaje sabe que “Soy Bob” a partir de la primera ronda de conversación:

# fuente: https://github.com/jerryjliu/llama_index/blob/main/examples/langchain_demo/LangchainDemo.ipynb# Usando LlamaIndex como un módulo de memoriafrom langchain import OpenAIfrom langchain.llms import OpenAIChatfrom langchain.agents import initialize_agent

from llama_index import ListIndexfrom llama_index.langchain_helpers.memory_wrapper import GPTIndexChatMemoryindex = ListIndex([])memory = GPTIndexChatMemory(    index=index,     memory_key="chat_history",     query_kwargs={"response_mode": "compact"},    # return_source devuelve nodos de origen en lugar de consultar el índice    return_source=True,    # return_messages devuelve el contexto en formato de mensaje    return_messages=True)llm = OpenAIChat(temperature=0)# llm=OpenAI(temperature=0)agent_executor = initialize_agent([], llm, agent="conversational-react-description", memory=memory)

Conclusión

En resumen, LlamaIndex es una herramienta increíblemente poderosa para mejorar las capacidades de los modelos de lenguaje grande con tus propios datos. Su variedad de conectores de datos, interfaces avanzadas de consulta y flexibilidad de integración lo convierten en un componente vital en el desarrollo de aplicaciones con LLMs.

Reconocimientos

¡Gracias Jerry Liu por los consejos y comentarios!

Foto de Danielle Barnes en Unsplash

Por Sophia Yang el 19 de junio de 2023

Sophia Yang es una científica de datos senior. Conéctate conmigo en LinkedIn, Twitter y YouTube y únete al DS/ML Book Club ❤️

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

Cómo crear un plan de estudio autodidacta de ciencia de datos de 1 año utilizando la estacionalidad de tu cerebro

Enseñarte a ti mismo ciencia de datos puede parecer algo inalcanzable cuando todo lo que recibes en las redes sociale...

Inteligencia Artificial

La influencia oculta de la contaminación de datos en los grandes modelos de lenguaje

Veea los riesgos de la contaminación de datos en los Modelos de Lenguaje Extensos (LLMs). Estrategias para la detecci...

Inteligencia Artificial

AI Sesgo Desafíos y Soluciones

¿De dónde proviene el sesgo en la inteligencia artificial? Una vez que lo encontramos, ¿cómo podemos reducirlo o elim...

Inteligencia Artificial

xAI de Elon Musk entrenado con el Feed de Twitter

Elon Musk, el visionario detrás de empresas como Tesla y SpaceX, ha vuelto a centrar su atención en el campo de la in...