Compartir a través de


Inicio rápido: Búsqueda generativa (RAG) mediante datos de referencia de Azure AI Search

En este inicio rápido envía consultas a un modelo de finalización de chat para una experiencia de búsqueda conversacional sobre el contenido indexado en Búsqueda de Azure AI. Después de configurar los recursos de Azure OpenAI y Azure AI Search en Azure Portal, ejecute código para llamar a las API.

Requisitos previos

Descarga de un archivo

Descargue un Jupyter Notebook de GitHub para enviar las solicitudes de este inicio rápido. Para obtener más información, consulte Descarga de archivos de GitHub.

También puede iniciar un nuevo archivo en el sistema local y crear solicitudes manualmente con las instrucciones de este artículo.

Configurar el acceso

Las solicitudes al punto de conexión de búsqueda deben autenticarse y autorizarse. Puede usar claves de API o roles para esta tarea. Las claves son más fáciles de empezar, pero los roles son más seguros. En este inicio rápido se asumen los roles.

Va a configurar dos clientes, por lo que necesita permisos en ambos recursos.

Búsqueda de Azure AI recibe la solicitud de consulta del sistema local. Asígnese la asignación de roles Lector de datos de índice de búsqueda si el índice de ejemplo de hoteles ya existe. Si no existe, asígnese los roles Colaborador del servicio de búsqueda y Colaborador de datos del índice de búsqueda para poder crear y consultar el índice.

Azure OpenAI recibe la consulta y los resultados de búsqueda del sistema local. Asígnese al rol Usuario de OpenAI de Cognitive Services en Azure OpenAI.

  1. Inicie sesión en Azure Portal.

  2. Configuración de Búsqueda de Azure AI para el acceso basado en roles:

    1. En Azure Portal, busque el servicio de Búsqueda de Azure AI.

    2. En el menú de la izquierda, seleccione Configuración>Claves y, a continuación, seleccione Control de acceso basado en rol o Ambos.

  3. Asignar roles:

    1. En el menú izquierdo, seleccione Control de acceso (IAM).

    2. En Búsqueda de Azure AI, seleccione estos roles para crear, cargar y consultar un índice de búsqueda y, a continuación, asígnelos a la identidad de usuario de Microsoft Entra ID:

      • Colaborador de datos de índice de búsqueda
      • Colaborador del servicio Search
    3. En Azure OpenAI, seleccione Control de acceso (IAM) para asignarse este rol a sí mismo en Azure OpenAI:

      • Usuario de OpenAI de Cognitive Services

Los permisos pueden tardar varios minutos en aplicarse.

Creación de un índice

Un índice de búsqueda proporciona datos de base para el modelo de chat. Se recomienda el índice hotels-sample-index, que se puede crear en minutos y se ejecuta en cualquier nivel de servicio de búsqueda. Este índice se crea mediante datos de ejemplo integrados.

  1. Busque el servicio de búsqueda en Azure Portal.

  2. En la página principal de Información general, seleccione Importar datos para iniciar el asistente.

  3. En la página Conectar a los datos, seleccione Ejemplos en la lista desplegable.

  4. Elija el hotels-sample.

  5. Seleccione Siguiente en las páginas restantes y acepte los valores predeterminados.

  6. Una vez creado el índice, seleccione Administración de búsqueda>Índices en el menú izquierdo para abrir el índice.

  7. Seleccione Editar JSON.

  8. Desplácese hasta el final del índice, donde puede encontrar marcadores de posición para construcciones que se pueden agregar a un índice.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. En una nueva línea después de "normalizadores", pegue la siguiente configuración semántica. En este ejemplo se especifica un "defaultConfiguration", que es importante para la ejecución de este inicio rápido.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Guarde los cambios mediante Guardar.

  11. Ejecute la siguiente consulta en el Explorador de búsqueda para probar su índice: complimentary breakfast.

    La salida debe ser similar al siguiente ejemplo. Los resultados que se devuelven directamente desde el motor de búsqueda constan de campos y sus valores literales, junto con metadatos como una puntuación de búsqueda y una puntuación de clasificación semántica y un título si usa el clasificador semántico. Usamos una instrucción select para devolver solo los campos HotelName, Description y Tags.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Obtener puntos de conexión de servicio

En las secciones restantes, configurará llamadas API a Azure OpenAI y Búsqueda de Azure AI. Obtenga los puntos de conexión de servicio para que pueda proporcionarlos como variables en el código.

  1. Inicie sesión en Azure Portal.

  2. Búsqueda del servicio de búsqueda.

  3. En la página principal de Información general, copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.search.windows.net.

  4. Busque el Azure OpenAI Service.

  5. En la página principal de Información general, seleccione el vínculo para ver los puntos de conexión. Copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.openai.azure.com/.

Creación de un entorno virtual

En este paso, vuelva al sistema local y Visual Studio Code. Se recomienda crear un entorno virtual para poder instalar las dependencias de forma aislada.

  1. En Visual Studio Code, abra la carpeta que contiene Quickstart-RAG.ipynb.

  2. Presione Ctrl-mayús-P para abrir la paleta de comandos, busque "Python: Crear entorno" y, a continuación, seleccione Venv para crear un entorno virtual en el área de trabajo actual.

  3. Seleccione Quickstart-RAG\requirements.txt para las dependencias.

El entorno tarda varios minutos en crearse. Cuando el entorno esté listo, continúe con el paso siguiente.

Inicio de sesión en Azure

Usa Microsoft Entra ID y las asignaciones de roles para la conexión. Asegúrese de que ha iniciado sesión en el mismo inquilino y suscripción que Búsqueda de Azure AI y Azure OpenAI. Puede usar la CLI de Azure en la línea de comandos para mostrar las propiedades actuales, cambiar las propiedades e iniciar sesión. Para obtener más información, consulte Conexión sin claves.

Ejecute cada uno de los siguientes comandos en secuencia.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Ahora debería iniciar sesión en Azure desde el dispositivo local.

Configuración de la consulta y el subproceso de chat

En esta sección se usa Visual Studio Code y Python para llamar a las API de finalización de chat en Azure OpenAI.

  1. Inicie Visual Studio Code y abra el archivo .ipynb o cree un nuevo archivo de Python.

  2. Instale los siguientes paquetes de Python.

    ! pip install azure-search-documents==11.6.0b5 --quiet
    ! pip install azure-identity==1.16.1 --quiet
    ! pip install openai --quiet
    ! pip install aiohttp --quiet
    ! pip install ipykernel --quiet
    
  3. Establezca las siguientes variables, sustituyendo los marcadores de posición por los puntos de conexión recopilados en el paso anterior.

     AZURE_SEARCH_SERVICE: str = "PUT YOUR SEARCH SERVICE ENDPOINT HERE"
     AZURE_OPENAI_ACCOUNT: str = "PUT YOUR AZURE OPENAI ENDPOINT HERE"
     AZURE_DEPLOYMENT_MODEL: str = "gpt-4o"
    
  4. Configure clientes, la indicación, la consulta y la respuesta.

    Para la nube de Azure Government, modifique el punto de conexión de API en el proveedor de tokens a "https://cognitiveservices.azure.us/.default".

    # Set up the query for generating responses
     from azure.identity import DefaultAzureCredential
     from azure.identity import get_bearer_token_provider
     from azure.search.documents import SearchClient
     from openai import AzureOpenAI
    
     credential = DefaultAzureCredential()
     token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")
     openai_client = AzureOpenAI(
         api_version="2024-06-01",
         azure_endpoint=AZURE_OPENAI_ACCOUNT,
         azure_ad_token_provider=token_provider
     )
    
     search_client = SearchClient(
         endpoint=AZURE_SEARCH_SERVICE,
         index_name="hotels-sample-index",
         credential=credential
     )
    
     # This prompt provides instructions to the model
     GROUNDED_PROMPT="""
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
     Query: {query}
     Sources:\n{sources}
     """
    
     # Query is the question being asked. It's sent to the search engine and the chat model
     query="Can you recommend a few hotels with complimentary breakfast?"
    
     # Search results are created by the search client
     # Search results are composed of the top 5 results and the fields selected from the search index
     # Search results include the top 5 matches to your query
     search_results = search_client.search(
         search_text=query,
         top=5,
         select="Description,HotelName,Tags"
     )
     sources_formatted = "\n".join([f'{document["HotelName"]}:{document["Description"]}:{document["Tags"]}' for document in search_results])
    
     # Send the search results and the query to the LLM to generate a response based on the prompt.
     response = openai_client.chat.completions.create(
         messages=[
             {
                 "role": "user",
                 "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
             }
         ],
         model=AZURE_DEPLOYMENT_MODEL
     )
    
     # Here is the response from the chat model.
     print(response.choices[0].message.content)
    

    La salida procede de Azure OpenAI y consta de recomendaciones de varios hoteles. El ejemplo siguiente muestra el aspecto que podría tener la salida:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
     such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
     instant oatmeal, bagels, and muffins
    

    Si recibe un mensaje de error Prohibido, compruebe la configuración de Azure AI Search para asegurarse de que el acceso basado en roles esté habilitado.

    Si recibe un mensaje de error de autorización, espere unos minutos e inténtelo de nuevo. Las asignaciones de roles pueden tardar varios minutos en estar operativas.

    Si recibe un mensaje de error de Recurso no encontrado, compruebe los URI de recursos y asegúrese de que la versión de la API en el modelo de chat sea válida.

    De lo contrario, para experimentar más, cambie la consulta y vuelva a ejecutar el último paso para comprender mejor cómo funciona el modelo con los datos de puesta a tierra.

    También puede modificar la indicación para cambiar el tono o la estructura de la salida.

    También puede probar la consulta sin clasificación semántica estableciendo use_semantic_reranker=False en el paso de parámetros de consulta. La clasificación semántica puede mejorar considerablemente la relevancia de los resultados de la consulta y la capacidad del LLM para devolver información útil. La experimentación puede ayudarle a decidir si supone una diferencia para su contenido.

Envío de una consulta RAG compleja

Azure AI Search admite tipos complejos para estructuras JSON anidadas. En el índice hotels-sample-index, Address es un ejemplo de un tipo complejo, que consta de Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode, y Address.Country. El índice también cuenta con una colección compleja de Rooms para cada hotel.

Si el índice tiene tipos complejos, la consulta puede proporcionar esos campos si convierte primero la salida de los resultados de búsqueda en JSON y, a continuación, pasa el JSON al modelo de chat. En el ejemplo siguiente se agregan tipos complejos a la solicitud. Las instrucciones de formato incluyen una especificación JSON.

import json

# Query is the question being asked. It's sent to the search engine and the LLM.
query="Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people."

# Set up the search results and the chat thread.
# Retrieve the selected fields from the search index related to the question.
selected_fields = ["HotelName","Description","Address","Rooms","Tags"]
search_results = search_client.search(
    search_text=query,
    top=5,
    select=selected_fields,
    query_type="semantic"
)
sources_filtered = [{field: result[field] for field in selected_fields} for result in search_results]
sources_formatted = "\n".join([json.dumps(source) for source in sources_filtered])

response = openai_client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
        }
    ],
    model=AZURE_DEPLOYMENT_MODEL
)

print(response.choices[0].message.content)

La salida procede de Azure OpenAI y agrega contenido de tipos complejos.

Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:

1. **Head Wind Resort**
   - **Description:** The best of old town hospitality combined with views of the river and 
   cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
   and free Wi-Fi throughout the hotel.
   - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
   - **Tags:** Coffee in lobby, free Wi-Fi, view
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

2. **Double Sanctuary Resort**
   - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
   listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
   in room. Offers continental breakfast.
   - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
   - **Tags:** View, pool, restaurant, bar, continental breakfast
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

3. **Swan Bird Lake Inn**
   - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
   Locally made caramel cinnamon rolls are a favorite.
   - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
   - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
   - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99

4. **Gastronomic Landscape Hotel**
   - **Description:** Known for its culinary excellence under the management of William Dough, 
   offers continental breakfast.
   - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
   - **Tags:** Restaurant, bar, continental breakfast
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
...
   - **Tags:** Pool, continental breakfast, free parking
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99

Enjoy your stay! Let me know if you need any more information.

Errores de solución de problemas

Para depurar errores de autenticación, inserte el código siguiente antes del paso que llama al motor de búsqueda y al LLM.

import sys
import logging # Set the logging level for all azure-storage-* libraries
logger = logging.getLogger('azure.identity') 
logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler(stream=sys.stdout)
formatter = logging.Formatter('[%(levelname)s %(name)s] %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

Vuelva a ejecutar el script de consulta. Ahora debería obtener instrucciones INFO y DEBUG en la salida que proporcionan más detalles sobre el problema.

Si ve mensajes de salida relacionados con los errores de adquisición de tokens y ManagedIdentityCredential, puede ser que tenga varios inquilinos y que el inicio de sesión de Azure use un inquilino que no tenga el servicio de búsqueda. Para obtener el identificador de inquilino, busque "propiedades de inquilino" en Azure Portal o ejecute az login tenant list.

Una vez que tenga el id. de inquilino, ejecute az login --tenant <YOUR-TENANT-ID> en un símbolo del sistema y vuelva a ejecutar el script.

Limpieza

Cuando trabaje con su propia suscripción, es una buena idea al final de un proyecto identificar si todavía se necesitan los recursos que ha creado. Los recursos que se dejan en ejecución pueden costarle mucho dinero. Puede eliminar los recursos de forma individual o bien eliminar el grupo de recursos para eliminar todo el conjunto de recursos.

Puede encontrar y administrar recursos en Azure Portal mediante el vínculo Todos los recursos o Grupos de recursos en el panel izquierdo.

Requisitos previos

Configurar el acceso

Las solicitudes al punto de conexión de búsqueda deben autenticarse y autorizarse. Puede usar claves de API o roles para esta tarea. Las claves son más fáciles de empezar, pero los roles son más seguros. En este inicio rápido se asumen los roles.

Va a configurar dos clientes, por lo que necesita permisos en ambos recursos.

Búsqueda de Azure AI recibe la solicitud de consulta del sistema local. Asígnese la asignación de roles Lector de datos de índice de búsqueda si el índice de ejemplo de hoteles ya existe. Si no existe, asígnese los roles Colaborador del servicio de búsqueda y Colaborador de datos del índice de búsqueda para poder crear y consultar el índice.

Azure OpenAI recibe la consulta y los resultados de búsqueda del sistema local. Asígnese al rol Usuario de OpenAI de Cognitive Services en Azure OpenAI.

  1. Inicie sesión en Azure Portal.

  2. Configuración de Búsqueda de Azure AI para el acceso basado en roles:

    1. En Azure Portal, busque el servicio de Búsqueda de Azure AI.

    2. En el menú de la izquierda, seleccione Configuración>Claves y, a continuación, seleccione Control de acceso basado en rol o Ambos.

  3. Asignar roles:

    1. En el menú izquierdo, seleccione Control de acceso (IAM).

    2. En Búsqueda de Azure AI, seleccione estos roles para crear, cargar y consultar un índice de búsqueda y, a continuación, asígnelos a la identidad de usuario de Microsoft Entra ID:

      • Colaborador de datos de índice de búsqueda
      • Colaborador del servicio Search
    3. En Azure OpenAI, seleccione Control de acceso (IAM) para asignarse este rol a sí mismo en Azure OpenAI:

      • Usuario de OpenAI de Cognitive Services

Los permisos pueden tardar varios minutos en aplicarse.

Creación de un índice

Un índice de búsqueda proporciona datos de base para el modelo de chat. Se recomienda el índice hotels-sample-index, que se puede crear en minutos y se ejecuta en cualquier nivel de servicio de búsqueda. Este índice se crea mediante datos de ejemplo integrados.

  1. Busque el servicio de búsqueda en Azure Portal.

  2. En la página principal de Información general, seleccione Importar datos para iniciar el asistente.

  3. En la página Conectar a los datos, seleccione Ejemplos en la lista desplegable.

  4. Elija el hotels-sample.

  5. Seleccione Siguiente en las páginas restantes y acepte los valores predeterminados.

  6. Una vez creado el índice, seleccione Administración de búsqueda>Índices en el menú izquierdo para abrir el índice.

  7. Seleccione Editar JSON.

  8. Desplácese hasta el final del índice, donde puede encontrar marcadores de posición para construcciones que se pueden agregar a un índice.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. En una nueva línea después de "normalizadores", pegue la siguiente configuración semántica. En este ejemplo se especifica un "defaultConfiguration", que es importante para la ejecución de este inicio rápido.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Guarde los cambios mediante Guardar.

  11. Ejecute la siguiente consulta en el Explorador de búsqueda para probar su índice: complimentary breakfast.

    La salida debe ser similar al siguiente ejemplo. Los resultados que se devuelven directamente desde el motor de búsqueda constan de campos y sus valores literales, junto con metadatos como una puntuación de búsqueda y una puntuación de clasificación semántica y un título si usa el clasificador semántico. Usamos una instrucción select para devolver solo los campos HotelName, Description y Tags.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Obtener puntos de conexión de servicio

En las secciones restantes, configurará llamadas API a Azure OpenAI y Búsqueda de Azure AI. Obtenga los puntos de conexión de servicio para que pueda proporcionarlos como variables en el código.

  1. Inicie sesión en Azure Portal.

  2. Búsqueda del servicio de búsqueda.

  3. En la página principal de Información general, copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.search.windows.net.

  4. Busque el Azure OpenAI Service.

  5. En la página principal de Información general, seleccione el vínculo para ver los puntos de conexión. Copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.openai.azure.com/.

Configuración de variables de entorno para el desarrollo local

  1. Cree un archivo .env.

  2. Agregue las siguientes variables de entorno al .env archivo y reemplace los valores por sus propios puntos de conexión de servicio y claves.

    AZURE_SEARCH_ENDPOINT=<YOUR AZURE AI SEARCH ENDPOINT>
    AZURE_SEARCH_INDEX_NAME=hotels-sample-index
    
    AZURE_OPENAI_ENDPOINT=<YOUR AZURE OPENAI ENDPOINT>
    AZURE_OPENAI_VERSION=<YOUR AZURE OPENAI API VERSION>
    AZURE_DEPLOYMENT_MODEL=<YOUR DEPLOYMENT NAME>
    

Configuración del proyecto de Node.JS

Configure el proyecto con Visual Studio Code y TypeScript.

  1. Inicie Visual Studio Code en un nuevo directorio.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Cree un nuevo paquete para los módulos ESM en el directorio del proyecto.

    npm init -y
    npm pkg set type=module
    

    Esto crea un package.json archivo con valores predeterminados.

  3. Instale los siguientes paquetes de npm.

    npm install @azure/identity @azure/search-documents openai dotenv @types/node
    
  4. Cree un src directorio en el directorio del proyecto.

    mkdir src
    
  5. Cree un tsconfig.json archivo en el directorio del proyecto para ESM con el siguiente contenido.

    {
      "compilerOptions": {
        "target": "esnext",
        "module": "NodeNext",
        "moduleResolution": "nodenext",
        "rootDir": "./src",
        "outDir": "./dist/",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "declaration": true,
        "sourceMap": true,
        "resolveJsonModule": true,
        "moduleDetection": "force", // Add this for ESM
        "allowSyntheticDefaultImports": true // Helpful for ESM interop
      },
      "include": [
        "src/**/*.ts"
      ]
    }
    

Inicio de sesión en Azure

Usa Microsoft Entra ID y las asignaciones de roles para la conexión. Asegúrese de que ha iniciado sesión en el mismo inquilino y suscripción que Búsqueda de Azure AI y Azure OpenAI. Puede usar la CLI de Azure en la línea de comandos para mostrar las propiedades actuales, cambiar las propiedades e iniciar sesión. Para obtener más información, consulte Conexión sin claves.

Ejecute cada uno de los siguientes comandos en secuencia.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Ahora debería iniciar sesión en Azure desde el dispositivo local.

Configurar la consulta y el hilo de chat

Cree un script de consulta que use el índice de Azure AI Search y el modelo de chat para generar respuestas basadas en datos de base. Los pasos siguientes le guían a través de la configuración del script de consulta.

  1. Cree un query.ts archivo en el src directorio con el código siguiente.

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient, AzureKeyCredential, SearchDocumentsResult } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients(): { openaiClient: AzureOpenAI, searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>, modelName: string }  {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT!;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME!;
    
        const searchClient = new SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT!;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION!;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL!;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>, query: string): Promise<string> {
        console.log(`Searching for: "${query}"\n`);
        const searchResults: SearchDocumentsResult<{ HotelName: string; Description: string; Tags: string[] | string }> = await searchClient.search(query, {
            top: 5,
            select: ["Description", "HotelName", "Tags"]
        });
    
        const sources: string[] = [];
        for await (const result of searchResults.results) {
            const doc = result.document;
            sources.push(
                `Hotel: ${doc.HotelName}\n` +
                `Description: ${doc.Description}\n` +
                `Tags: ${Array.isArray(doc.Tags) ? doc.Tags.join(', ') : doc.Tags}\n`
            );
        }
        const sourcesFormatted = sources.join("\n---\n");
        return sourcesFormatted;
    }
    async function queryOpenAIForResponse(
        openaiClient: AzureOpenAI, 
        query: string, 
        sourcesFormatted: string, 
        modelName: string
    ): Promise<{ choices: { message: { content: string | null } }[] }> {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main():Promise<void> {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = "Can you recommend a few hotels with complimentary breakfast?";
    
        const sources = await queryAISearchForSources(searchClient, query);
        const response = await queryOpenAIForResponse(openaiClient, query, sources, modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    

    El código anterior hace lo siguiente:

    • Importa las bibliotecas necesarias para Azure AI Search y Azure OpenAI.
    • Usa variables de entorno para configurar los clientes de Azure AI Search y Azure OpenAI.
    • Define una función para obtener los clientes de Búsqueda de Azure AI y Azure OpenAI mediante variables de entorno para la configuración.
    • Define una función para consultar los orígenes de Azure AI Search en función de la consulta de usuario.
    • Define una función para consultar Azure OpenAI para obtener una respuesta basada en la consulta de usuario y los orígenes recuperados de Azure AI Search.
    • La main función organiza el flujo llamando a las funciones de búsqueda y OpenAI y, a continuación, imprime la respuesta.
  2. Compile el código TypeScript en JavaScript.

    tsc
    

    Este comando compila el código TypeScript en el src directorio y genera los archivos JavaScript en el dist directorio.

  3. Ejecute el siguiente comando en un terminal para ejecutar el script de consulta:

    node -r dotenv/config dist/query.js
    

    .env se pasa al entorno de ejecución mediante el -r dotenv/config.

  4. Consulte el resultado que consta de recomendaciones para varios hoteles. El ejemplo siguiente muestra el aspecto que podría tener la salida:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
        such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
        instant oatmeal, bagels, and muffins
    

Solución de problemas

Si recibe un mensaje de error Prohibido, compruebe la configuración de Azure AI Search para asegurarse de que el acceso basado en roles esté habilitado.

Si recibe un mensaje de error de autorización, espere unos minutos e inténtelo de nuevo. Las asignaciones de roles pueden tardar varios minutos en estar operativas.

Si recibe un mensaje de error de Recurso no encontrado, compruebe los URI de recursos y asegúrese de que la versión de la API en el modelo de chat sea válida.

De lo contrario, para experimentar más, cambie la consulta y vuelva a ejecutar el último paso para comprender mejor cómo funciona el modelo con los datos de puesta a tierra.

También puede modificar la indicación para cambiar el tono o la estructura de la salida.

También puede probar la consulta sin clasificación semántica estableciendo use_semantic_reranker=False en el paso de parámetros de consulta. La clasificación semántica puede mejorar considerablemente la relevancia de los resultados de la consulta y la capacidad del LLM para devolver información útil. La experimentación puede ayudarle a decidir si supone una diferencia para su contenido.

Envío de una consulta RAG compleja

Azure AI Search admite tipos complejos para estructuras JSON anidadas. En el índice hotels-sample-index, Address es un ejemplo de un tipo complejo, que consta de Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode, y Address.Country. El índice también cuenta con una colección compleja de Rooms para cada hotel.

Si el índice tiene tipos complejos, cambie el mensaje para incluir instrucciones de formato:

Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
  1. Cree un nuevo archivo queryComplex.ts en el src directorio .

  2. Copie el código siguiente en el archivo:

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient, SearchDocumentsResult } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients(): { openaiClient: AzureOpenAI; searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>; modelName: string }  {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT!;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME!;
        const searchClient = new SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT!;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION!;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL!;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    
    async function queryAISearchForSources(
        searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>,
        query: string
    ): Promise<SearchDocumentsResult<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>> {
        console.log(`Searching for: "${query}"\n`);
    
        const selectedFields: readonly ["HotelName", "Description", "Address", "Rooms", "Tags"] = ["HotelName", "Description", "Address", "Rooms", "Tags"];
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: selectedFields,
            queryType: "semantic",
            semanticSearchOptions: {},
        });
    
        return searchResults;
    }
    async function queryOpenAIForResponse(
        openaiClient: AzureOpenAI, 
        query: string, 
        sourcesFormatted: string, 
        modelName: string
    ): Promise<{ choices: { message: { content: string | null } }[] }> {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main(): Promise<void> {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = `
        Can you recommend a few hotels that offer complimentary breakfast? 
        Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
        `;
    
        const sourcesResult = await queryAISearchForSources(searchClient, query);
        let sourcesFormatted = "";
    
        for await (const result of sourcesResult.results) {
            // Explicitly typing result to ensure compatibility
            sourcesFormatted += JSON.stringify(result.document) + "\n";
        }
    
        const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    
  3. Compile el código TypeScript en JavaScript.

    tsc
    

    Este comando compila el código TypeScript en el src directorio y genera los archivos JavaScript en el dist directorio.

  4. Ejecute el siguiente comando en un terminal para ejecutar el script de consulta:

    node -r dotenv/config dist/queryComplex.js
    

    .env se pasa al entorno de ejecución mediante el -r dotenv/config.

  5. Vea la salida de Azure OpenAI y agrega contenido de tipos complejos.

Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:

1. **Head Wind Resort**
   - **Description:** The best of old town hospitality combined with views of the river and 
   cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
   and free Wi-Fi throughout the hotel.
   - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
   - **Tags:** Coffee in lobby, free Wi-Fi, view
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

2. **Double Sanctuary Resort**
   - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
   listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
   in room. Offers continental breakfast.
   - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
   - **Tags:** View, pool, restaurant, bar, continental breakfast
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

3. **Swan Bird Lake Inn**
   - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
   Locally made caramel cinnamon rolls are a favorite.
   - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
   - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
   - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99

4. **Gastronomic Landscape Hotel**
   - **Description:** Known for its culinary excellence under the management of William Dough, 
   offers continental breakfast.
   - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
   - **Tags:** Restaurant, bar, continental breakfast
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
...
   - **Tags:** Pool, continental breakfast, free parking
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99

Enjoy your stay! Let me know if you need any more information.

Errores de solución de problemas

Para depurar errores del SDK de Azure, establezca la variable AZURE_LOG_LEVEL de entorno en una de las siguientes opciones: verbose, info, warning, error. Esto habilitará el registro detallado para el SDK de Azure, que puede ayudar a identificar problemas con la autenticación, la conectividad de red u otros problemas.

Vuelva a ejecutar el script de consulta. Ahora debería obtener instrucciones informativas de los SDK en la salida que proporcionan más detalles sobre los problemas.

Si ve mensajes de salida relacionados con los errores de adquisición de tokens y ManagedIdentityCredential, puede ser que tenga varios inquilinos y que el inicio de sesión de Azure use un inquilino que no tenga el servicio de búsqueda. Para obtener el identificador de inquilino, busque "propiedades de inquilino" en Azure Portal o ejecute az login tenant list.

Una vez que tenga el id. de inquilino, ejecute az login --tenant <YOUR-TENANT-ID> en un símbolo del sistema y vuelva a ejecutar el script.

Limpieza

Cuando trabaje con su propia suscripción, es una buena idea al final de un proyecto identificar si todavía se necesitan los recursos que ha creado. Los recursos que se dejan en ejecución pueden costarle mucho dinero. Puede eliminar los recursos de forma individual o bien eliminar el grupo de recursos para eliminar todo el conjunto de recursos.

Puede encontrar y administrar recursos en Azure Portal mediante el vínculo Todos los recursos o Grupos de recursos en el panel izquierdo.

Requisitos previos

Configurar el acceso

Las solicitudes al punto de conexión de búsqueda deben autenticarse y autorizarse. Puede usar claves de API o roles para esta tarea. Las claves son más fáciles de empezar, pero los roles son más seguros. En este inicio rápido se asumen los roles.

Va a configurar dos clientes, por lo que necesita permisos en ambos recursos.

Búsqueda de Azure AI recibe la solicitud de consulta del sistema local. Asígnese la asignación de roles Lector de datos de índice de búsqueda si el índice de ejemplo de hoteles ya existe. Si no existe, asígnese los roles Colaborador del servicio de búsqueda y Colaborador de datos del índice de búsqueda para poder crear y consultar el índice.

Azure OpenAI recibe la consulta y los resultados de búsqueda del sistema local. Asígnese al rol Usuario de OpenAI de Cognitive Services en Azure OpenAI.

  1. Inicie sesión en Azure Portal.

  2. Configuración de Búsqueda de Azure AI para el acceso basado en roles:

    1. En Azure Portal, busque el servicio de Búsqueda de Azure AI.

    2. En el menú de la izquierda, seleccione Configuración>Claves y, a continuación, seleccione Control de acceso basado en rol o Ambos.

  3. Asignar roles:

    1. En el menú izquierdo, seleccione Control de acceso (IAM).

    2. En Búsqueda de Azure AI, seleccione estos roles para crear, cargar y consultar un índice de búsqueda y, a continuación, asígnelos a la identidad de usuario de Microsoft Entra ID:

      • Colaborador de datos de índice de búsqueda
      • Colaborador del servicio Search
    3. En Azure OpenAI, seleccione Control de acceso (IAM) para asignarse este rol a sí mismo en Azure OpenAI:

      • Usuario de OpenAI de Cognitive Services

Los permisos pueden tardar varios minutos en aplicarse.

Creación de un índice

Un índice de búsqueda proporciona datos de base para el modelo de chat. Se recomienda el índice hotels-sample-index, que se puede crear en minutos y se ejecuta en cualquier nivel de servicio de búsqueda. Este índice se crea mediante datos de ejemplo integrados.

  1. Busque el servicio de búsqueda en Azure Portal.

  2. En la página principal de Información general, seleccione Importar datos para iniciar el asistente.

  3. En la página Conectar a los datos, seleccione Ejemplos en la lista desplegable.

  4. Elija el hotels-sample.

  5. Seleccione Siguiente en las páginas restantes y acepte los valores predeterminados.

  6. Una vez creado el índice, seleccione Administración de búsqueda>Índices en el menú izquierdo para abrir el índice.

  7. Seleccione Editar JSON.

  8. Desplácese hasta el final del índice, donde puede encontrar marcadores de posición para construcciones que se pueden agregar a un índice.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. En una nueva línea después de "normalizadores", pegue la siguiente configuración semántica. En este ejemplo se especifica un "defaultConfiguration", que es importante para la ejecución de este inicio rápido.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Guarde los cambios mediante Guardar.

  11. Ejecute la siguiente consulta en el Explorador de búsqueda para probar su índice: complimentary breakfast.

    La salida debe ser similar al siguiente ejemplo. Los resultados que se devuelven directamente desde el motor de búsqueda constan de campos y sus valores literales, junto con metadatos como una puntuación de búsqueda y una puntuación de clasificación semántica y un título si usa el clasificador semántico. Usamos una instrucción select para devolver solo los campos HotelName, Description y Tags.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Obtener puntos de conexión de servicio

En las secciones restantes, configurará llamadas API a Azure OpenAI y Búsqueda de Azure AI. Obtenga los puntos de conexión de servicio para que pueda proporcionarlos como variables en el código.

  1. Inicie sesión en Azure Portal.

  2. Búsqueda del servicio de búsqueda.

  3. En la página principal de Información general, copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.search.windows.net.

  4. Busque el Azure OpenAI Service.

  5. En la página principal de Información general, seleccione el vínculo para ver los puntos de conexión. Copie la dirección URL. Un punto de conexión de ejemplo podría ser similar a https://example.openai.azure.com/.

Configuración de variables de entorno para el desarrollo local

  1. Cree un archivo .env.

  2. Agregue las siguientes variables de entorno al .env archivo y reemplace los valores por sus propios puntos de conexión de servicio y claves.

    AZURE_SEARCH_ENDPOINT=<YOUR AZURE AI SEARCH ENDPOINT>
    AZURE_SEARCH_INDEX_NAME=hotels-sample-index
    
    AZURE_OPENAI_ENDPOINT=<YOUR AZURE OPENAI ENDPOINT>
    AZURE_OPENAI_VERSION=<YOUR AZURE OPENAI API VERSION>
    AZURE_DEPLOYMENT_MODEL=<YOUR DEPLOYMENT NAME>
    

Configuración del proyecto de Node.JS

Configure el proyecto con Visual Studio Code y TypeScript.

  1. Inicie Visual Studio Code en un nuevo directorio.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Cree un nuevo paquete para los módulos ESM en el directorio del proyecto.

    npm init -y
    npm pkg set type=module
    

    Esto crea un package.json archivo con valores predeterminados.

  3. Instale los siguientes paquetes de npm.

    npm install @azure/identity @azure/search-documents openai dotenv 
    
  4. Cree un src directorio en el directorio del proyecto.

    mkdir src
    

Inicio de sesión en Azure

Usa Microsoft Entra ID y las asignaciones de roles para la conexión. Asegúrese de que ha iniciado sesión en el mismo inquilino y suscripción que Búsqueda de Azure AI y Azure OpenAI. Puede usar la CLI de Azure en la línea de comandos para mostrar las propiedades actuales, cambiar las propiedades e iniciar sesión. Para obtener más información, consulte Conexión sin claves.

Ejecute cada uno de los siguientes comandos en secuencia.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Ahora debería iniciar sesión en Azure desde el dispositivo local.

Configurar la consulta y el hilo de chat

Cree un script de consulta que use el índice de Azure AI Search y el modelo de chat para generar respuestas basadas en datos de base. Los pasos siguientes le guían a través de la configuración del script de consulta.

  1. Cree un query.js archivo en el src directorio con el código siguiente.

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients() {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
    
        const searchClient = new SearchClient(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(searchClient, query) {
        console.log(`Searching for: "${query}"\n`);
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: ["Description", "HotelName", "Tags"]
        });
    
        const sources = [];
        for await (const result of searchResults.results) {
            const doc = result.document;
            sources.push(
                `Hotel: ${doc.HotelName}\n` +
                `Description: ${doc.Description}\n` +
                `Tags: ${Array.isArray(doc.Tags) ? doc.Tags.join(', ') : doc.Tags}\n`
            );
        }
        const sourcesFormatted = sources.join("\n---\n");
        return sourcesFormatted;
    }
    async function queryOpenAIForResponse(openaiClient, query, sourcesFormatted, modelName) {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main() {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = "Can you recommend a few hotels with complimentary breakfast?";
    
        const sources = await queryAISearchForSources(searchClient, query);
        const response = await queryOpenAIForResponse(openaiClient, query, sources, modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    

    El código anterior hace lo siguiente:

    • Importa las bibliotecas necesarias para Azure AI Search y Azure OpenAI.
    • Usa variables de entorno para configurar los clientes de Azure AI Search y Azure OpenAI.
    • Define una función para obtener los clientes de Búsqueda de Azure AI y Azure OpenAI mediante variables de entorno para la configuración.
    • Define una función para consultar los orígenes de Azure AI Search en función de la consulta de usuario.
    • Define una función para consultar Azure OpenAI para obtener una respuesta basada en la consulta de usuario y los orígenes recuperados de Azure AI Search.
    • La main función organiza el flujo llamando a las funciones de búsqueda y OpenAI y, a continuación, imprime la respuesta.
  2. Ejecute el siguiente comando en un terminal para ejecutar el script de consulta:

    node -r dotenv/config query.js
    

    .env se pasa al entorno de ejecución mediante el -r dotenv/config.

  3. Vea el resultado, que consta de recomendaciones para varios hoteles. El ejemplo siguiente muestra el aspecto que podría tener la salida:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
        such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
        instant oatmeal, bagels, and muffins
    

Solución de problemas

Si recibe un mensaje de error Prohibido, compruebe la configuración de Azure AI Search para asegurarse de que el acceso basado en roles esté habilitado.

Si recibe un mensaje de error de autorización, espere unos minutos e inténtelo de nuevo. Las asignaciones de roles pueden tardar varios minutos en estar operativas.

Si recibe un mensaje de error de Recurso no encontrado, compruebe los URI de recursos y asegúrese de que la versión de la API en el modelo de chat sea válida.

De lo contrario, para experimentar más, cambie la consulta y vuelva a ejecutar el último paso para comprender mejor cómo funciona el modelo con los datos de puesta a tierra.

También puede modificar la indicación para cambiar el tono o la estructura de la salida.

También puede probar la consulta sin clasificación semántica estableciendo use_semantic_reranker=False en el paso de parámetros de consulta. La clasificación semántica puede mejorar considerablemente la relevancia de los resultados de la consulta y la capacidad del LLM para devolver información útil. La experimentación puede ayudarle a decidir si supone una diferencia para su contenido.

Envío de una consulta RAG compleja

Azure AI Search admite tipos complejos para estructuras JSON anidadas. En el índice hotels-sample-index, Address es un ejemplo de un tipo complejo, que consta de Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode, y Address.Country. El índice también cuenta con una colección compleja de Rooms para cada hotel.

Si el índice tiene tipos complejos, cambie el mensaje para incluir instrucciones de formato:

Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
  1. Cree un nuevo archivo queryComplex.js.

  2. Copie el código siguiente en el archivo:

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients() {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
    
        const searchClient = new SearchClient(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(
        searchClient,
        query
    ) {
        console.log(`Searching for: "${query}"\n`);
    
        const selectedFields = ["HotelName", "Description", "Address", "Rooms", "Tags"];
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: selectedFields,
            queryType: "semantic",
            semanticSearchOptions: {},
        });
    
        return searchResults;
    }
    async function queryOpenAIForResponse(
        openaiClient, 
        query, 
        sourcesFormatted, 
        modelName
    ){
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main() {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = `
        Can you recommend a few hotels that offer complimentary breakfast? 
        Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
        `;
    
        const sourcesResult = await queryAISearchForSources(searchClient, query);
        let sourcesFormatted = "";
    
        for await (const result of sourcesResult.results) {
            // Explicitly typing result to ensure compatibility
            sourcesFormatted += JSON.stringify(result.document) + "\n";
        }
    
        const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    
  3. Ejecute el siguiente comando en un terminal para ejecutar el script de consulta:

    node -r dotenv/config queryComplex.js
    

    .env se pasa al entorno de ejecución mediante el -r dotenv/config.

  4. Vea la salida de Azure OpenAI y agrega contenido de tipos complejos.

    Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:
    
    1. **Head Wind Resort**
       - **Description:** The best of old town hospitality combined with views of the river and 
       cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
       and free Wi-Fi throughout the hotel.
       - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
       - **Tags:** Coffee in lobby, free Wi-Fi, view
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    2. **Double Sanctuary Resort**
       - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
       listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
       in room. Offers continental breakfast.
       - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
       - **Tags:** View, pool, restaurant, bar, continental breakfast
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    3. **Swan Bird Lake Inn**
       - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
       Locally made caramel cinnamon rolls are a favorite.
       - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
       - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
       - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99
    
    4. **Gastronomic Landscape Hotel**
       - **Description:** Known for its culinary excellence under the management of William Dough, 
       offers continental breakfast.
       - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
       - **Tags:** Restaurant, bar, continental breakfast
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
    ...
       - **Tags:** Pool, continental breakfast, free parking
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99
    
    Enjoy your stay! Let me know if you need any more information.
    

Errores de solución de problemas

Para depurar errores del SDK de Azure, establezca la variable AZURE_LOG_LEVEL de entorno en una de las siguientes opciones: verbose, info, warning, error. Esto habilitará el registro detallado para el SDK de Azure, que puede ayudar a identificar problemas con la autenticación, la conectividad de red u otros problemas.

Vuelva a ejecutar el script de consulta. Ahora debería obtener instrucciones informativas de los SDK en la salida que proporcionan más detalles sobre los problemas.

Si ve mensajes de salida relacionados con los errores de adquisición de tokens y ManagedIdentityCredential, puede ser que tenga varios inquilinos y que el inicio de sesión de Azure use un inquilino que no tenga el servicio de búsqueda. Para obtener el identificador de inquilino, busque "propiedades de inquilino" en Azure Portal o ejecute az login tenant list.

Una vez que tenga el id. de inquilino, ejecute az login --tenant <YOUR-TENANT-ID> en un símbolo del sistema y vuelva a ejecutar el script.

Limpieza

Cuando trabaje con su propia suscripción, es una buena idea al final de un proyecto identificar si todavía se necesitan los recursos que ha creado. Los recursos que se dejan en ejecución pueden costarle mucho dinero. Puede eliminar los recursos de forma individual o bien eliminar el grupo de recursos para eliminar todo el conjunto de recursos.

Puede encontrar y administrar recursos en Azure Portal mediante el vínculo Todos los recursos o Grupos de recursos en el panel izquierdo.