En la era moderna, donde la producción de información y datos es masiva, las aplicaciones de programación están teniendo que desarrollar enfoques cada vez más avanzados para gestionar y buscar datos en la maraña de información. La tarea es aún más desalentadora cuando los datos almacenados están igualmente dispersos y dispares. Uno de estos enfoques se llama LangChain Multi-Query Retriever para RAG.

Este sistema de búsqueda multi-consulta parece ser una forma eficaz de mejorar las búsquedas para los models de lenguaje de gran escala, limitación LLMs por sus siglas en inglés (Large Language Models). Aunque este método es relativamente nuevo, los diseñadores de software ya están explorando las formas en que puede ser aprovechado, evaluado y perfeccionado.

Profundización en la técnica de Multi-Consulta

Una de las formas de mejorar la eficiencia de los sistemas de procesamiento y recuperación de información se llama multi-consulta. Combinada con el uso de models de lenguaje de gran escala (LLM), puede permitir procesos más efectivos de búsqueda de información. Este apartado tiene como objetivo profundizar en la comprensión de esta técnica.

La esencia de la multi-consulta

La multi-consulta se basa en una premisa simple pero poderosa. En lugar de realizar una sola consulta a la base de datos, esta técnica involucra el envío de múltiples consultas. Esto se hace, en su forma más básica, tomando una consulta inicial y pasándola a través de un modelo de lenguaje de gran escala (LLM).

# Inicializamos el LLM
llm = ChatOpenAI(temperature=0)
question = 'Could you tell me about Llama2'

retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectordb.as_retriever(), llm=llm
)

unique_docs = retriever_from_llm.get_relevant_documents(query=question)

El LLM, al emplear tecnología de procesamiento de lenguaje natural de alto nivel y algoritmos complejos, construye múltiples preguntas a partir de la consulta original. Cada una de estas nuevas consultas puede entonces aplicarse a la base de datos, lo que da lugar a múltiples conjuntos de resultados.

En términos del espacio vectorial

Para comprender el valor de la multi-consulta, puede ser útil visualizar el proceso en términos de vectores dentro de un espacio vectorial, que es una representación gráfica comúnmente utilizada en la ciencia de los datos.

En una consulta de búsqueda tradicional, la consulta inicial se convierte en un vector: una entidad matemática codificada que representa la información de la consulta. Este vector se mapea luego en un espacio vectorial. Este esencialmente se convierte en una “ubicación” en un mapa de datos, rodeado de vectores que representan otros elementos de datos relevantes.

query_vector = vector_store.get_vector(query)

La multi-consulta agrega otra dimensión a este proceso. En lugar de generar un solo vector a partir de la consulta inicial, genera varios. Cada uno se mapea entonces en el espacio vectorial.

query_vectors = [vector_store.get_vector(matches) for matches in multiple_queries]

La clave aquí es que, aunque todos los vectores generados a partir de la misma consulta inicial tienen algún grado de similitud, cada uno también tiene su propia varianza única. Esto significa que cada vector puede mapearse a su propio conjunto único de vectores circundantes “relevantes”. Cuando se toman en conjunto, los resultados de todas estas consultas individuales representarán una mayor diversidad de datos en respuesta a una pregunta original.

¿Por qué usar la multi-consulta?

¿Por qué deberíamos complicar el proceso de esta manera? La razón es que un simple vector de consulta, por definición, solo puede representar una interpretación particular de la consulta inicial. Pero en muchos casos, una sola consulta puede tener múltiples interpretaciones válidas, cada una de las cuales podría llevarnos a un conjunto de resultados útilmente diferente. La multi-consulta permite capturar esta variedad de interpretaciones.

Por ejemplo, la consulta "háblame sobre Llama2" podría interpretarse en el contexto de información general sobre el modelo Llama2, su desarrollo, rendimiento, aplicaciones o comparativa con otros modelos. Con la multi-consulta, podríamos generar y realizar consultas siguiendo todas estas interpretaciones, lo que daría lugar a un conjunto de resultados mucho más rico y potencialmente más útil.

En resumen, la multi-consulta representa un paso hacia delante en nuestra capacidad para aprovechar la riqueza y la diversidad de los datos disponibles para nosotros. A medida que nuestra comprensión de esta técnica mejore y se expanda, podremos aplicarla para destacar y extraer cada vez más valor de nuestros vastos almacenes de datos.

Configuración del entorno de LangChain

Comenzamos preparando el entorno de trabajo para la tarea. Aquí, la tarjeta de embarque es la autenticación de la clave de la API de OpenAI. Esta clave será esencial para acceder a las fuentes de datos y los recursos de procesamiento necesarios. Visualiza este paso como si estuvieras obteniendo el pase necesario para desplazarte por el vasto espacio de la información.

openai_api_key = 'set_your_api_key_here'

Preparación del almacenamiento de vectores

Una vez que hemos establecido nuestra clave API, procedemos a establecer un sistema de almacenamiento vectorial. Podría decirse que este almacenamiento vectorial es similar a una base de datos en el sentido de que almacena la información que se procesará. Sin embargo, a diferencia de las bases de datos tradicionales, en lugar de almacenar información en tablas y columnas, la almacena en vectores multidimensionales.

Para este propósito, estamos utilizando Pinecone, una plataforma que permite indexar vectores a gran escala y buscar entre ellos. Ten en cuenta que podrías usar cualquier otra base de datos de vectores, simplemente tendrías que hacer unos pocos ajustes.

Aquí, estamos inicializando y creando nuestro almacenamiento vectorial en Pinecone así:

pinecone.init(api_key=openai_api_key)
pinecone.deinit()

Inicializando el modelo de lenguaje a gran escala (LLM)

Después de tener nuestra base de datos de vectores a punto, avanzamos al siguiente componente clave del proceso: la creación del modelo de lenguaje a gran escala (LLM). Este modelo desempeña un papel crucial en la generación de múltiples consultas a partir de nuestra consulta inicial. En esencia, tomará nuestra pregunta inicial y la traducirá en múltiples preguntas, que luego serán procesadas de forma independiente.

Es interesante destacar que el LLM no se limita a generar consultas, sino que también es el responsable de generar la respuesta final a nuestra consulta después de navegar por todo el proceso de recuperación de información.

Inicializamos nuestro LLM de la siguiente manera:

llm = ChatOpenAI(temperature=0)

Inicializando el recuperador de múltiples consultas

Nuestro almacenamiento vectorial y nuestro LLM están ahora en su lugar, lo que nos permite pasar a la siguiente parte del proceso: la inicialización del recuperador de múltiples consultas. Este es el componente que realmente lleva a cabo las múltiples consultas generadas por el LLM.

retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectordb.as_retriever(), llm=llm
)

Este recuperador requiere como entrada el sistema de almacenamiento vectorial y el LLM. Aquí es donde comenzamos realmente a ver todo trabajando en conjunto. A continuación, le presentamos nuestra consulta inicial al recuperador de múltiples consultas. Dicha consulta inicial es procesada por el LLM que genera múltiples consultas y el recuperador de múltiples consultas procesa cada consulta de forma independiente, devolviendo múltiples vectores.

question = 'Tell me about Llama2'
unique_docs = retriever_from_llm.get_relevant_documents(query=question)

Con esta secuencia de eventos, se lleva a cabo la multi-consulta en LangChain, una serie de procesos interconectados destinados a aprovechar el potencial de los LLMs para obtener información procesable de grandes conjuntos de datos mediante el uso de múltiples vectores de consulta. Este mecanismo innovador abre un camino hacia una búsqueda de información más efectiva y eficiente.

Procesamiento de los resultados de las múltiples consultas

Entrar en detalle en lo que sucede con los resultados de las consultas de LangChain Multi-Query Retriever para RAG puede ser de gran utilidad para entender y optimizar su funcionamiento.

Este apartado se divide en dos secciones claves:

  1. Identificando la relevancia de los documentos devueltos
  2. Optimización del rendimiento de la consulta múltiple

Identificando la relevancia de los documentos devueltos

Una vez que las múltiples consultas son realizadas, los resultados devueltos se presentan en la salida de una forma semi-formateada. Por lo general, se espera que estos documentos contengan información relevante sobre la consulta a la que responden. Sin embargo, no todos los documentos devueltos son útiles para la consulta original.

{
 "documents": [
   {"id": "doc1", "text": "This is the content of document 1 relevant to Llama2." },
   {"id": "doc2", "text": "This is the content of document 2 about LLMs but not about Llama2."},
   {"id": "doc3", "text": "This is the content of document 3 which is not relevant." },
   ...
 ]
}

En general, cuanto mayor sea el número de consultas devueltas, mayor sería la cantidad de documentos devueltos. Pero es importante aclarar que a pesar de que hayan múltiples consultas, el número de registros únicos suele no ser considerablemente mayor que si sólo se hubiera realizado una consulta. Este patrón sugiere que puede existir un solapamiento considerable entre las consultas.

Optimización del rendimiento de la consulta múltiple

Aunque el sistema de consultas múltiples puede ampliar efectivamente el espectro de búsqueda y generar una mayor diversidad de resultados, no está exento de desafíos. Uno de estos desafíos es la necesidad de filtrar la información relevante entre una multitud de documentos devueltos.

Lo que podría considerarse como un factor limitante de este proceso es que, aunque las consultas múltiples puedan devolver una variedad más amplia de documentos, no todos estos documentos serán necesariamente relevantes para la consulta original. Algunos documentos podrían contener información parcialmente relevante pero estar más centrados en otros aspectos no mencionados en la consulta original.

{
 "query":  "Tell me about Llama2",
 "documents": [
   {"id": "doc1", "text": "This is the content of document 1 relevant to Llama2." },
   {"id": "doc2", "text": "This is the content of document 2 about Alpacas."},
   {"id": "doc3", "text": "This is the content of document 3 which is not relevant." },
   ...
 ]
}

Esto puede ser mejorado si se ajustan y personalizan las consultas y sus parámetros con el fin de generar resultados más precisos de acuerdo con la consulta inicial. En términos simples, se podría decir que se trata de afinar la precisión del proceso de retorno de consulta múltiple, que en última instancia, podría mejorar su efectividad y proporcionar una solución de búsqueda de datos más robusta y se podría decir que es la optimización del rendimiento de la consulta múltiple.

Mejoramiento de la multi-consulta con LangChain

El optimizar una consulta múltiple parece ser un arte de equilibrio. Se trata de conseguir la mayor diversidad en las consultas generadas pero también de mantener la relevancia de las mismas para asegurar la calidad de los resultados recuperados. Aquí examinamos detalladamente los distintos aspectos de este proceso, explorando desde la configuración inicial del modelo de lenguaje de gran escala (LLM), la generación de la consulta y su procesamiento, hasta la evaluación de su relevancia.

Generación de una consulta multi-consulta

Voviendo a nuestro código original, una vez que las consultas han sido generadas, es esencial evaluar la relevancia de estas consultas antes de proceder. No todas las consultas generadas pueden ser igualmente útiles o relevantes, y algunas pueden incluso ser redundantes.

Para ilustrar este punto, supongamos que se nos proporciona el siguiente conjunto de consultas por el LLM:

  • ¿Qué información puedes proporcionar sobre Llama2?
  • ¿Podrías proporcionar detalles sobre Llama2?
  • ¿Podrías explicarme más sobre Llama2?

Como puedes ver, aunque estas son técnicamente tres consultas diferentes, todas son muy similares entre sí y probablemente proporcionen resultados muy similares. Este es un ejemplo de donde la diversidad en las consultas puede no ser suficiente.

Modificación de las instrucciones proporcionadas

Vamos a modificar la instrucción proporcionada al LLM para intentar aumentar la variedad de las consultas generadas.

output_parser = LineListOutputParser()

QUERY_PROMPT = PromptTemplate(
    input_variables=["question"],
    template="""Generate 3 different search queries to answer the user question from multiple perspectives around LLMs, Machine learning and related disciplines. Each query must tackle the question from a different viewpoint. We aim to get a variety of relevant search results.
    Provide these alternative questions separated by newlines.
    Original question: {question}""",
)
llm = ChatOpenAI(temperature=0)

# Chain
llm_chain = LLMChain(llm=llm, prompt=QUERY_PROMPT, output_parser=output_parser)

# Other inputs
question = "Could you tell me about Llama2?"

# Run
retriever = MultiQueryRetriever(
    retriever=vectordb.as_retriever(), llm_chain=llm_chain, parser_key="lines"
)  # "lines" is the key (attribute name) of the parsed output

# Results
unique_docs = retriever.get_relevant_documents(
    query=question
)
len(unique_docs)

Aquí hemos hecho un pequeño cambio a nuestra prompt, añadiendo información relevante. Hemos especificado que queremos que las consulta se enfoquen en LLMs, Machine learning y disciplinas relacionadas. Esto proporciona un contexto útil para el generador y puede ayudar a mantener las consultas generadas relevantes a la consulta original.

Esta modificación en las instrucciones ha demostrado tener un impacto significativo en los resultados obtenidos, incrementando la diversidad en las consultas obtenidas y mejorando la calidad en los resultados de la búsqueda. Es evidente, por ende, que el arte de la consulta multi-consulta reside en cómo formulamos estas instrucciones.

Reflexiones finales en el uso de la multi-consulta

La funcionalidad de la multi-consulta en LangChain nos ha proporcionado un panorama interesante en la tarea de mejorar la calidad y diversidad de los datos recuperados. Uno de los aspectos cruciales de este enfoque innovador es la capacidad de ajustar y adaptar la consulta para obtener resultados mucho más variados. Pero, ¿cómo se logra esta maniobrabilidad?

Esto puede hacerse a través de la modificación de las instrucciones que se le dan al modelo de lenguaje de gran escala (LLM). Estas instrucciones actúan como directrices en la generación de las consultas y pueden ser sumamente específicas. En un sentido simple, estas instrucciones ayudan a guiar al LLM para generar consultas que estén más en línea con el objetivo de la consulta original.

prompt = 'Generate 3 different search queries to answer the user question focusing on LLMs, Machine learning and related fields. Each query must tackle the question from a different viewpoint.'

Aquí, la instrucción especifica que se deben generar tres consultas diferentes que tengan el objetivo de responder a la pregunta original desde diferentes ángulos. Este enfoque de personalización es un intento de obtener una mayor diversidad en los resultados y centrar la atención en los LLMs y campos relacionados.

Interpretación errónea y eliminación de ruido

Un problema relevante que surge con esta metodología de consultas diversas es el aumento potencial de los resultados irrelevantes, es decir, el ruido. A medida que la diversidad de las consultas aumenta, existe una mayor posibilidad de que el modelo interprete erróneamente el sentido de la consulta y por tanto incluya en su resultado alguna información no relevante.

Por ejemplo, si introducimos la pregunta "Cuéntame sobre Llama2", el modelo puede interpretar esta consulta de una forma muy literal y generar consultas que se centren en explicaciones detalladas de lo que es Llama2, o puede malinterpretar la consulta y generar preguntas menos pertinentes relacionadas con enfoques completamente diferentes en la misma temática. Aunque estas interpretaciones erróneas pueden aportar una variedad agradable a los resultados, no proporcionan necesariamente la información deseada.

La multi-consulta como una herramienta de un sistema de búsqueda completo

Uno de los aspectos más interesantes de la multi-consulta es su aplicabilidad como una herramienta dentro de un sistema de búsqueda más completo. Aunque la multi-consulta tiene un valor intrínseco al aumentar la diversidad de los resultados de la búsqueda, la verdadera eficiencia puede verse a medida que se integra en un sistema de búsqueda más grande.

La multi-consulta puede proporcionar una serie de resultados potenciales, pero la tarea de restringir estos resultados a los más pertinentes puede requerir la implementación de otros componentes. Por tanto, el verdadero valor de la multi-consulta podría ser su capacidad para proporcionar una base más amplia a los sistemas de búsqueda que luego pueden aplicar otros filtros y técnicas para construir una respuesta más afinada.

En resumen, la estrategia de multi-consulta en LangChain ofrece un interesante avance en el campo de la recuperación de información. La flexibilidad que aporta al poder ajustar y adaptar las consultas es una gran ventaja, pero también es esencial tener en cuenta los desafíos inherentes a este enfoque. La elección de las instrucciones proporcionadas al LLM, la interpretación errónea potencial y la necesidad de implementar la multi-consulta dentro de un sistema más grande son todos aspectos que deben ser considerados en su utilización.

Comparte esta publicación