Generación aumentada de recuperación (RAG) en Azure AI Search

La generación aumentada de recuperación (RAG) es una arquitectura que aumenta las funcionalidades de un modelo de lenguaje grande (LLM) como ChatGPT al agregar un sistema de recuperación de información que proporciona datos de base de datos. Agregar un sistema de recuperación de información proporciona control sobre los datos de base de datos usados por un LLM cuando formula una respuesta. En el caso de una solución empresarial, la arquitectura RAG significa que puede restringir IA generativa al contenido empresarial procedente de documentos vectorizados e imágenes, y otros formatos de datos si ha insertado modelos para ese contenido.

La decisión sobre qué sistema de recuperación de información usar es fundamental porque determina las entradas al LLM. El sistema de recuperación de información debe proporcionar:

  • Estrategias de indexación que se cargan y actualizan a gran escala, para todo el contenido, con la frecuencia necesaria.

  • Funcionalidades de consulta y ajuste de relevancia. El sistema debe devolver los resultados pertinentes, en los formatos de forma abreviada necesarios para cumplir los requisitos de longitud del token de las entradas LLM.

  • Seguridad, alcance global y confiabilidad para los datos y las operaciones.

  • Integración con modelos de inserción para la indexación y modelos de chat o de reconocimiento del lenguaje para la recuperación.

Azure AI Search es una solución probada para la recuperación de información en una arquitectura RAG. Proporciona funcionalidades de indexación y consulta, con la infraestructura y la seguridad de la nube de Azure. A través del código y otros componentes, puede diseñar una solución RAG completa que incluya todos los elementos para la inteligencia artificial generativa sobre su contenido propietario.

Nota:

¿No está familiarizado con los conceptos Copilot y RAG? Vea el vídeo sobre la búsqueda de vectores y el estado de la recuperación de última generación para aplicaciones de IA generativas.

Microsoft tiene varias implementaciones integradas para usar Azure AI Search en una solución RAG.

Los enfoques mantenidos facilitan la puesta en marcha, pero para disponer de más control sobre la arquitectura, necesita una solución personalizada. Estas plantillas crean soluciones globales en:

En el resto de este artículo se explora cómo encaja Azure AI Search en una solución RAG personalizada.

Un resumen general del patrón tiene este aspecto:

  • Comience con una pregunta o solicitud de usuario (solicitud).
  • Envíelo a Azure AI Search para encontrar información relevante.
  • Envíe los resultados de la búsqueda mejor clasificados al LLM.
  • Use la comprensión del lenguaje natural y las funcionalidades de razonamiento del LLM para generar una respuesta a la pregunta inicial.

Azure AI Search proporciona entradas a la pregunta del LLM, pero no entrena el modelo. En la arquitectura RAG, no hay ningún entrenamiento adicional. LLM se entrena previamente mediante datos públicos, pero genera respuestas aumentadas por información del recuperador.

Los patrones RAG que incluyen Azure AI Search tienen los elementos indicados en la ilustración siguiente.

Diagrama de arquitectura de recuperación de información con búsqueda y ChatGPT.

  • Experiencia de usuario de la aplicación (aplicación web) para la experiencia del usuario
  • Servidor de aplicaciones u orquestador (capa de integración y coordinación)
  • Azure AI Search (sistema de recuperación de información)
  • Azure OpenAI (LLM para inteligencia artificial generativa)

La aplicación web proporciona la experiencia del usuario, lo que proporciona la presentación, el contexto y la interacción del usuario. Las preguntas o solicitudes de un usuario empiezan aquí. Las entradas pasan por la capa de integración, en primer lugar a la recuperación de información para obtener los resultados de la búsqueda, pero también van al LLM para establecer el contexto y la intención.

El servidor de aplicaciones o orquestador es el código de integración que coordina las entregas entre la recuperación de información y el LLM. Una opción es usar LangChain para coordinar el flujo de trabajo. LangChain se integra con Azure AI Search, lo que facilita la inclusión de Azure AI Search como un recuperador en el flujo de trabajo. El Kernel semántico es otra opción.

El sistema de recuperación de información proporciona el índice, la lógica de consulta y la carga útil (respuesta de consulta). El índice de búsqueda puede contener vectores o contenido no vectorial. Aunque la mayoría de las muestras y demos incluyen campos vectoriales, no es un requisito. La consulta se ejecuta mediante el motor de búsqueda existente en Azure AI Search, que puede controlar las consultas de palabra clave (o término) y vectores. El índice se crea de antemano, en función de un esquema que defina y se cargue con el contenido que se origina a partir de archivos, bases de datos o almacenamiento.

El LLM recibe la pregunta original, además de los resultados de Azure AI Search. El LLM analiza los resultados y formula una respuesta. Si el LLM es ChatGPT, la interacción del usuario podría ser una conversación de ida y vuelta. Si usa Davinci, es posible que la pregunta sea una respuesta totalmente compuesta. Una solución de Azure probablemente use Azure OpenAI, pero no hay ninguna dependencia difícil en este servicio específico.

Azure AI Search no proporciona integración nativa de LLM para la conservación de chat o flujos de avisos, por lo que debe escribir código que controle la orquestación y el estado. Puede revisar el origen de la demo (Azure-Samples/azure-search-openai-demo) para ver un plano técnico de lo que implica una solución completa. También se recomienda Azure AI Studio o Azure OpenAI Studio para crear soluciones de Azure AI Search basadas en RAG que se integren con LLM.

En Búsqueda de Azure AI, todo el contenido que se puede buscar se almacena en un índice de búsqueda hospedado en el servicio de búsqueda. Un índice de búsqueda está diseñado para consultas rápidas con tiempos de respuesta de milisegundos, por lo que sus estructuras de datos internas existen para admitir ese objetivo. Para ello, un índice de búsqueda almacena contenido indexado y no archivos de contenido completos como archivos PDF o imágenes completos. Internamente, las estructuras de datos incluyen índices invertidos de texto tokenizado, índices vectoriales para inserciones y texto no modificado para los casos en los que se requiere coincidencia textual (por ejemplo, en filtros, búsqueda aproximada, consultas de expresiones regulares).

Al configurar los datos de la solución RAG, se usan las características que crean y cargan un índice en Azure AI Search. Un índice incluye campos que duplican o representan el contenido de origen. Un campo de índice puede ser transferencia simple (un título o una descripción en un documento de origen se convierte en un título o una descripción en un índice de búsqueda), o un campo podría contener la salida de un proceso externo, como la vectorización o el procesamiento de aptitudes que genera una representación o descripción de texto de una imagen.

Como probablemente sepa qué tipo de contenido desea buscar, considere las características de indexación aplicables a cada tipo de contenido:

Content type Indexado como Características
text tokens, texto sin modificar Los indexadores pueden extraer texto sin formato de otros recursos de Azure, como Azure Storage y Cosmos DB. También puede insertar cualquier contenido JSON en un índice. Para modificar el texto en curso, use analizadores y normalizadores para agregar procesamiento léxico durante la indexación. Los mapas de sinónimos son útiles si falta la terminología de documentos de origen que se pueden usar en una consulta.
text vectores 1 El texto se puede fragmentar y vectorizar externamente y, a continuación, indexar como campos vectoriales en el índice.
image tokens, texto no modificado 2 Las aptitudes para OCR y análisis de imágenes pueden procesar imágenes para el reconocimiento de texto o las características de imagen. La información de imagen se convierte en texto que se puede buscar y se agrega al índice. Las aptitudes tienen un requisito de indexador.
image vectores 1 Las imágenes se pueden vectorizar externamente para una representación matemática del contenido de la imagen y, a continuación, indexar como campos vectoriales en el índice. Puede usar un modelo de código abierto como OpenAI CLIP para vectorizar texto e imágenes en el mismo espacio de inserción.

1 La funcionalidad disponible con carácter general de compatibilidad con vectores requiere que llame a otras bibliotecas o modelos para fragmentar y vectorizar datos. Sin embargo, la vectorización integrada (versión preliminar) inserta estos pasos. Para examinar ejemplos de código en los que se muestran ambos enfoques, consulte repositorio azure-search-vectors.

2Las aptitudes son compatibilidad integrada con el enriquecimiento con IA. En el caso de OCR e Image Analysis, la canalización de indexación realiza una llamada interna a las API de Azure AI Vision. Estas aptitudes pasan una imagen extraída a Azure AI para su procesamiento y reciben la salida como texto indexado por Azure AI Search.

Los vectores proporcionan el mejor alojamiento para contenido disimilar (varios formatos de archivo y lenguajes) porque el contenido se expresa universalmente en representaciones matemáticas. Los vectores también admiten la búsqueda de similitud: coincidencias en las coordenadas que son más similares a la consulta vectorial. En comparación con la búsqueda de palabras clave (o búsqueda de términos) que coincide con los términos tokenizados, la búsqueda de similitud es más matizada. Es una mejor opción si hay requisitos de ambigüedad o interpretación en el contenido o en las consultas.

Una vez que los datos están en un índice de búsqueda, se usan las funcionalidades de consulta de Azure AI Search para recuperar el contenido.

En un patrón no RAG, las consultas realizan un recorrido de ida y vuelta desde un cliente de búsqueda. La consulta se envía, se ejecuta en un motor de búsqueda y la respuesta se devuelve a la aplicación cliente. La respuesta, o los resultados de la búsqueda, constan exclusivamente del contenido textual que se encuentra en el índice.

En un patrón RAG, las consultas y respuestas se coordinan entre el motor de búsqueda y el LLM. La pregunta o consulta de un usuario se reenvía tanto al motor de búsqueda como al LLM como mensaje. Los resultados de búsqueda vuelven del motor de búsqueda y se redirigen a un LLM. La respuesta que lo devuelve al usuario es la inteligencia artificial generativa, ya sea una suma o una respuesta del LLM.

No hay ningún tipo de consulta en Azure AI Search, ni siquiera semántica ni búsqueda vectorial, que compone respuestas nuevas. Solo el LLM proporciona inteligencia artificial generativa. Estas son las funcionalidades de Azure AI Search que se usan para formular consultas:

Característica de consulta Fin Por qué usarla
Uso de la sintaxis completa de Lucene Ejecución de consultas sobre texto y contenido numérico no vectorial La búsqueda de texto completo es mejor para coincidencias exactas, en lugar de coincidencias similares. Las consultas de búsqueda de texto completo se clasifican mediante el algoritmo BM25 y admiten el ajuste de relevancia a través de perfiles de puntuación. También admite filtros y facetas.
Filtros y facetas Solo se aplica a campos de texto o numéricos (no vectores). Reduce el área expuesta de búsqueda en función de los criterios de inclusión o exclusión. Agrega precisión a las consultas.
Clasificación semántica Vuelva a clasificar un conjunto de resultados BM25 mediante modelos semánticos. Genera subtítulos y respuestas de forma corta que son útiles como entradas del LLM. Más fácil que los perfiles de puntuación, y en función del contenido, una técnica más confiable para el ajuste de relevancia.
Vector de búsqueda Ejecución de consultas sobre campos vectoriales para la búsqueda de similitud, donde la cadena de consulta es uno o varios vectores. Los vectores pueden representar todos los tipos de contenido, en cualquier lenguaje.
Búsqueda híbrida Combina cualquiera o todas las técnicas de consulta anteriores. Las consultas vectoriales y no vectoriales se ejecutan en paralelo y se devuelven en un conjunto de resultados unificado. Las mejoras más significativas en precisión y recuperación se realizan mediante consultas híbridas.

Estructuración de la respuesta de la consulta

La respuesta de una consulta proporciona la entrada al LLM, por lo que la calidad de los resultados de búsqueda es fundamental para el éxito. Los resultados son un conjunto de filas tabulares. La composición o estructura de los resultados depende de:

  • Campos que determinan qué partes del índice se incluyen en la respuesta.
  • Filas que representan una coincidencia del índice.

Los campos aparecen en los resultados de búsqueda cuando el atributo es "recuperable". Una definición de campo en el esquema de índice tiene atributos y aquellos determinan si se usa un campo en una respuesta. Solo se devuelven campos "recuperables" en los resultados de la consulta de texto completo o vector. De forma predeterminada, se devuelven todos los campos "recuperables", pero puede usar la opción "select" para especificar un subconjunto. Además de "recuperable", no hay restricciones en el campo. Los campos pueden tener cualquier longitud o tipo. Con respecto a la longitud, no hay ningún límite máximo de longitud de campo en Azure AI Search, pero hay límites en el tamaño de una solicitud de API.

Las filas son coincidencias con la consulta, clasificadas por relevancia, similitud o ambos. De forma predeterminada, los resultados se limitan en las 50 coincidencias principales para la búsqueda de texto completo o las coincidencias k-nearest-neighbor para el vector de búsqueda. Puede cambiar los valores predeterminados para aumentar o disminuir el límite hasta el máximo de 1000 documentos. También puede utilizar los parámetros de paginación top y skip para recuperar los resultados como una serie de resultados paginados.

Clasificación por relevancia

Cuando se trabaja con procesos complejos, una gran cantidad de datos y expectativas de respuestas en milisegundos, es fundamental que cada paso añada valor y mejore la calidad del resultado final. En el lado de la recuperación de información, el ajuste de relevancia es una actividad que mejora la calidad de los resultados enviados al LLM. Solo los documentos coincidentes más relevantes o más similares deben incluirse en los resultados.

La relevancia se aplica a la búsqueda de palabras clave (no vectoriales) y a las consultas híbridas (sobre los campos no vectoriales). En Azure AI Search, no hay ninguna optimización de relevancia para las consultas de búsqueda de similitud y vectores. La clasificación BM25 es el algoritmo de clasificación para la búsqueda de texto completo.

El ajuste de relevancia se admite a través de características que mejoran la clasificación BM25. Estos enfoques incluyen:

  • Perfiles de puntuación que aumentan la puntuación de búsqueda si se encuentran coincidencias en un campo de búsqueda específico o en otros criterios.
  • Clasificación semántica que vuelve a clasificar un conjunto de resultados de BM25, usando modelos semánticos de Bing para reordenar los resultados para obtener un ajuste semántico mejor a la consulta original.

En comparación y pruebas comparativas, las consultas híbridas con campos de texto y vector, complementadas con la clasificación semántica sobre los resultados clasificados por BM25, generan los resultados más relevantes.

Código de ejemplo de una consulta de Azure AI Search para escenarios RAG

El código siguiente se copia del archivo retrievethenread.py de un sitio de demo. Genera content para el LLM a partir de resultados de búsqueda de consultas híbridas. Puede escribir una consulta más sencilla, pero este ejemplo es inclusivo del vector de búsqueda y de búsqueda de palabras clave con la revisión ortográfica y el cambio semántico. En la demo, esta consulta se usa para obtener contenido inicial.

# Use semantic ranker if requested and if retrieval mode is text or hybrid (vectors + text)
if overrides.get("semantic_ranker") and has_text:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  query_type=QueryType.SEMANTIC,
                                  query_language="en-us",
                                  query_speller="lexicon",
                                  semantic_configuration_name="default",
                                  top=top,
                                  query_caption="extractive|highlight-false" if use_semantic_captions else None,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
else:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  top=top,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
if use_semantic_captions:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(" . ".join([c.text for c in doc['@search.captions']])) async for doc in r]
else:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(doc[self.content_field]) async for doc in r]
content = "\n".join(results)

Código de integración y LLM

Una solución RAG que incluya Azure AI Search requiere otros componentes y código para crear una solución completa. Mientras que las secciones anteriores trataron la recuperación de información a través de Azure AI Search y qué características se usan para crear y consultar contenido que se puede buscar, en esta sección se presenta la integración y la interacción de LLM.

Los cuadernos de los repositorios de demo son un buen punto de partida porque muestran patrones para pasar los resultados de búsqueda a un LLM. La mayoría del código de una solución RAG consta de llamadas al LLM, por lo que debe desarrollar una comprensión de cómo funcionan esas API, que está fuera del ámbito de este artículo.

El siguiente bloque de celdas del cuaderno chat-read-retrieve-read.ipynb muestra las llamadas de búsqueda en el contexto de una sesión de chat:

# Execute this cell multiple times updating user_input to accumulate chat history
user_input = "Does my plan cover annual eye exams?"

# Exclude category, to simulate scenarios where there's a set of docs you can't see
exclude_category = None

if len(history) > 0:
    completion = openai.Completion.create(
        engine=AZURE_OPENAI_GPT_DEPLOYMENT,
        prompt=summary_prompt_template.format(summary="\n".join(history), question=user_input),
        temperature=0.7,
        max_tokens=32,
        stop=["\n"])
    search = completion.choices[0].text
else:
    search = user_input

# Alternatively simply use search_client.search(q, top=3) if not using semantic ranking
print("Searching:", search)
print("-------------------")
filter = "category ne '{}'".format(exclude_category.replace("'", "''")) if exclude_category else None
r = search_client.search(search, 
                         filter=filter,
                         query_type=QueryType.SEMANTIC, 
                         query_language="en-us", 
                         query_speller="lexicon", 
                         semantic_configuration_name="default", 
                         top=3)
results = [doc[KB_FIELDS_SOURCEPAGE] + ": " + doc[KB_FIELDS_CONTENT].replace("\n", "").replace("\r", "") for doc in r]
content = "\n".join(results)

prompt = prompt_prefix.format(sources=content) + prompt_history + user_input + turn_suffix

completion = openai.Completion.create(
    engine=AZURE_OPENAI_CHATGPT_DEPLOYMENT, 
    prompt=prompt, 
    temperature=0.7, 
    max_tokens=1024,
    stop=["<|im_end|>", "<|im_start|>"])

prompt_history += user_input + turn_suffix + completion.choices[0].text + "\n<|im_end|>" + turn_prefix
history.append("user: " + user_input)
history.append("assistant: " + completion.choices[0].text)

print("\n-------------------\n".join(history))
print("\n-------------------\nPrompt:\n" + prompt)

Instrucciones para empezar

  • Revise los conceptos y estrategias de indexación para determinar cómo desea ingerir y actualizar datos. Decida si va a usar el vector de búsqueda, la búsqueda de palabras clave o la búsqueda híbrida. El tipo de contenido que necesita buscar y el tipo de consultas que desea ejecutar determina el diseño del índice.

  • Revise la creación de consultas para obtener más información sobre la sintaxis y los requisitos de las solicitudes de búsqueda.

Nota:

Algunas características de Azure AI Search están diseñadas para la interacción humana y no son útiles en un patrón RAG. En concreto, puede omitir autocompletar y las sugerencias. Otras características como facetas y “orderby” podrían ser útiles, pero sería poco común en un escenario RAG.

Consulte también