Поделиться через


Быстрый старт: генеративный поиск (RAG) с использованием опорных данных из поиска Azure AI

В этом кратком руководстве вы отправляете запросы в модель завершения чата для получения опыта поискового взаимодействия по вашим индексированным данным в службе Azure AI Search. После настройки ресурсов Azure OpenAI и Службы поиска ИИ Azure на портале Azure выполните код для вызова API.

Необходимые компоненты

Настройка доступа

Запросы к конечной точке поиска должны проходить проверку подлинности и авторизованы. Для этой задачи можно использовать ключи ИЛИ роли API. Ключи проще начать с, но роли более безопасны. В этом кратком руководстве предполагается, что роли.

Вы настраиваете два клиента, поэтому вам нужны разрешения для обоих ресурсов.

Поиск по искусственному интеллекту Azure получает запрос из локальной системы. Назначьте себе назначение роли читателя данных индекса поиска, если уже существует пример индекса отелей. Если он не существует, назначьте себя участнику службы поиска и роли участника индексов поиска, чтобы создать и запросить индекс.

Azure OpenAI получает запрос и результаты поиска из локальной системы. Назначьте себе роль пользователя OpenAI в Cognitive Services в Azure OpenAI.

  1. Войдите на портал Azure.

  2. Настройка azure AI Search для доступа на основе ролей:

    1. В портал Azure найдите служба ИИ Azure.

    2. В меню слева выберите >, а затем выберите управление доступом на основе ролей или оба.

  3. Назначение ролей:

    1. В меню слева выберите элемент управления доступом (IAM).

    2. В службе "Поиск ИИ Azure" выберите эти роли для создания, загрузки и запроса индекса поиска, а затем назначьте их идентификатору пользователя Microsoft Entra ID:

      • Участник данных индекса поиска
      • Участник службы поиска
    3. В Azure OpenAI выберите элемент управления доступом (IAM), чтобы назначить эту роль себе в Azure OpenAI:

      • Пользователь службы OpenAI в Cognitive Services

Для принятия в силу разрешений может потребоваться несколько минут.

Создание индекса

Индекс поиска предоставляет данные о заземления для модели чата. Мы рекомендуем использовать индекс hotels-sample-index, который можно создать в минутах и запустить на любом уровне служб поиска. Этот индекс создается с помощью встроенных примеров данных.

  1. В портал Azure найдите службу поиска.

  2. На домашней странице обзора выберите "Импорт данных", чтобы запустить мастер.

  3. На странице подключения к данным выберите примеры из раскрывающегося списка.

  4. Выберите пример отелей.

  5. Нажмите кнопку "Далее" на оставшихся страницах, принимая значения по умолчанию.

  6. После создания индекса выберите индексы управления>поиском в меню слева, чтобы открыть индекс.

  7. Выберите "Изменить JSON".

  8. Прокрутите страницу до конца индекса, где можно найти заполнители для конструкций, которые можно добавить в индекс.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. В новой строке после "нормализаторов" вставьте следующую семантику конфигурации. В этом примере указывается , "defaultConfiguration"что важно для выполнения этого краткого руководства.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Сохраните свои изменения.

  11. Выполните следующий запрос в обозревателе поиска, чтобы проверить индекс: complimentary breakfast

    Выходные данные должны выглядеть примерно так, как показано в следующем примере. Результаты, возвращаемые непосредственно из поисковой системы, состоят из полей и их подробных значений, а также метаданных, таких как оценка поиска и семантическая оценка ранжирования и подпись при использовании семантического ранга. Мы использовали инструкцию select, чтобы вернуть только поля HotelName, Description и 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"
          ]
       },
       . . .
    ]}
    

Получение конечных точек службы

В оставшихся разделах вы настроили вызовы API к Azure OpenAI и поиску ИИ Azure. Получите конечные точки службы, чтобы предоставить их в виде переменных в коде.

  1. Войдите на портал Azure.

  2. Найдите службу поиска.

  3. Скопируйте URL-адрес на домашней странице обзора. Пример конечной точки может выглядеть так: https://example.search.windows.net.

  4. Найдите службу Azure OpenAI.

  5. На домашней странице обзора выберите ссылку для просмотра конечных точек. Скопируйте URL-адрес. Пример конечной точки может выглядеть так: https://example.openai.azure.com/.

Вход в Azure

Для подключения используется идентификатор Microsoft Entra и назначения ролей. Убедитесь, что вы вошли в тот же клиент и подписку, что и поиск ИИ Azure и Azure OpenAI. Azure CLI можно использовать в командной строке для отображения текущих свойств, изменения свойств и входа. Дополнительные сведения см. в разделе "Подключение без ключей".

Выполните каждую из следующих команд в последовательности.

az account show

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

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

Теперь вы должны войти в Azure с локального устройства.

Настройка приложения .NET

Чтобы выполнить дальнейшие действия, вы можете клонировать завершенное пример приложения из GitHub или создать приложение самостоятельно.

Клонирования примера приложения

Чтобы получить доступ к завершенному приложению-примеру для этой статьи:

  1. Клонируйте репозиторий azure-search-dotnet-samples из GitHub.

    git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
    
  2. Перейдите в папку quickstart-rag .

  3. Откройте папку quickstart-rag в Visual Studio Code или откройте файл решения с помощью Visual Studio.

Создание примера приложения

Выполните следующие действия, чтобы создать консольное приложение .NET для подключения к модели ИИ.

  1. В пустом каталоге на компьютере используйте команду dotnet new для создания нового консольного приложения:

    dotnet new console -o AISearchRag
    
  2. Измените каталог в папку приложения:

    cd AISearchRag
    
  3. Установите необходимые пакеты:

    dotnet add package Azure.AI.OpenAI
    dotnet add package Azure.Identity
    dotnet add package Azure.Search.Documents
    
  4. Откройте приложение в Visual Studio Code (или выбранный редактор).

    code .
    

Настройка потока запроса и чата

В следующем примере показано, как настроить минимальный сценарий RAG с помощью службы "Поиск ИИ Azure" для предоставления модели OpenAI с контекстными ресурсами для улучшения созданных ответов.

  1. minimal-query В проекте примера репозитория откройте Program.cs файл, чтобы просмотреть первый пример. Если вы создали проект самостоятельно, добавьте следующий код, чтобы подключиться и запросить службы поиска ИИ Azure и Azure OpenAI.

    Замечание

    Обязательно замените местозаполнители для конечной точки и имени модели Azure OpenAI, а также конечной точки Azure AI Search и имени индекса.

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Models;
    using Azure.AI.OpenAI;
    using OpenAI.Chat;
    using System.Text.Json;
    using Microsoft.Extensions.Logging;
    
    // Azure resource endpoints and deployment info
    string azureSearchServiceEndpoint = "azure-ai-search-endpoint";
    string azureOpenAIEndpoint = "azure-ai-openai-endpoint";
    string azureDeploymentModel = "azure-ai-deployment-name";
    string indexName = "hotels-sample-index";
    
    // Set up Azure credentials and clients
    var credential = new DefaultAzureCredential();
    var searchClient = new SearchClient(new Uri(azureSearchServiceEndpoint), indexName, credential);
    var openAIClient = new AzureOpenAIClient(new Uri(azureOpenAIEndpoint), credential);
    
    // Prompt template for grounding the LLM response in search results
    string 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: {0}
        Sources: {1}";
    
    // The user's query
    string query = "Can you recommend a few hotels with complimentary breakfast?";
    
    // Configure search options: top 5 results, select relevant fields
    var options = new SearchOptions { Size = 5 };
    options.Select.Add("Description");
    options.Select.Add("HotelName");
    options.Select.Add("Tags");
    
    // Execute the search
    var searchResults = await searchClient.SearchAsync<SearchDocument>(query, options);
    var sources = new List<string>();
    
    await foreach (var result in searchResults.Value.GetResultsAsync())
    {
        var doc = result.Document;
        // Format each result as: HotelName:Description:Tags
        sources.Add($"{doc["HotelName"]}:{doc["Description"]}:{doc["Tags"]}");
    }
    string sourcesFormatted = string.Join("\n", sources);
    
    // Format the prompt with the query and sources
    string formattedPrompt = string.Format(GROUNDED_PROMPT, query, sourcesFormatted);
    
    // Create a chat client for the specified deployment/model
    ChatClient chatClient = openAIClient.GetChatClient(azureDeploymentModel);
    
    // Send the prompt to the LLM and stream the response
    var chatUpdates = chatClient.CompleteChatStreamingAsync(
        [ new UserChatMessage(formattedPrompt) ]
    );
    
    // Print the streaming response to the console
    await foreach (var chatUpdate in chatUpdates)
    {
        if (chatUpdate.Role.HasValue)
        {
            Console.Write($"{chatUpdate.Role} : ");
        }
        foreach (var contentPart in chatUpdate.ContentUpdate)
        {
            Console.Write(contentPart.Text);
        }
    }
    

    Приведенный выше код выполняет следующее:

    • Ищет индекс поиска Azure для отелей, соответствующих запросу пользователя о бесплатном завтраке, получении имени отеля, описания и тегов.
    • Форматирует результаты поиска в структурированный список, чтобы служить контекстными источниками для модели создания искусственного интеллекта.
    • Создает запрос, который указывает модели Azure OpenAI отвечать только на предоставленные источники.
    • Отправляет запрос в модель ИИ и передает созданный ответ.
    • Выводит ответ ИИ на консоль, отображая как роль, так и содержимое по мере передачи.
  2. Запустите проект, чтобы инициировать базовый сценарий RAG. Выходные данные Azure OpenAI состоят из рекомендаций для нескольких отелей, таких как следующий пример:

    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
    

Чтобы дополнительно поэкспериментировать, измените запрос и выполните последний шаг, чтобы лучше понять, как модель работает с данными о заземления. Вы также можете изменить запрос, чтобы изменить тон или структуру выходных данных.

Устранение неполадок

При тестировании может появиться любая из следующих ошибок:

  • Запрещено. Проверьте конфигурацию поиска ИИ Azure, чтобы убедиться, что доступ на основе ролей включен.
  • Сбой авторизации: подождите несколько минут и повторите попытку. Выполнение назначений ролей может занять несколько минут.
  • Ресурс не найден: проверьте URI ресурсов и убедитесь, что версия API в модели чата действительна.

Отправка сложного запроса RAG

Поиск ИИ Azure поддерживает сложные типы для вложенных структур JSON. В индексе hotels-sample-index Address является примером сложного типа, состоящего из Address.StreetAddress, , Address.City, Address.StateProvinceAddress.PostalCodeи Address.Country. Индекс также имеет сложную коллекцию Rooms для каждого отеля. Если индекс имеет сложные типы, запрос может предоставить эти поля, если сначала преобразовать выходные данные результатов поиска в JSON, а затем передать JSON в модель чата.

  1. В проекте репозитория-образца complex-query откройте файл Program.cs. Если вы создали проект самостоятельно, замените код следующим образом:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Models;
    using Azure.AI.OpenAI;
    using OpenAI.Chat;
    using System.Text.Json;
    using Microsoft.Extensions.Logging;
    
    // Azure resource endpoints and deployment info
    string azureSearchServiceEndpoint = "azure-ai-search-endpoint";
    string azureOpenAIEndpoint = "azure-ai-openai-endpoint";
    string azureDeploymentModel = "azure-ai-deployment-name";
    string indexName = "hotels-sample-index";
    
    // Set up Azure credentials and clients
    var credential = new DefaultAzureCredential();
    var searchClient = new SearchClient(new Uri(azureSearchServiceEndpoint), indexName, credential);
    var openAIClient = new AzureOpenAIClient(new Uri(azureOpenAIEndpoint), credential);
    
    // Prompt template for the OpenAI model
    string groundedPrompt =
        @"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: {0}
        Sources: {1}";
    
    // The user query and fields to select from search
    var 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.";
    var selectedFields = new[] { "HotelName", "Description", "Address", "Rooms", "Tags" };
    
    // Configure search options
    var options = new SearchOptions { Size = 5 };
    foreach (var field in selectedFields)
    {
        options.Select.Add(field);
    }
    
    // Run Azure Cognitive Search
    var searchResults = await searchClient.SearchAsync<SearchDocument>(query, options);
    
    // Filter and format search results
    var sourcesFiltered = new List<Dictionary<string, object>>();
    await foreach (var result in searchResults.Value.GetResultsAsync())
    {
        sourcesFiltered.Add(
            selectedFields
                .Where(f => result.Document.TryGetValue(f, out _))
                .ToDictionary(f => f, f => result.Document[f])
        );
    }
    var sourcesFormatted = string.Join("\n", sourcesFiltered.ConvertAll(source => JsonSerializer.Serialize(source)));
    
    // Format the prompt for OpenAI
    string formattedPrompt = string.Format(groundedPrompt, query, sourcesFormatted);
    
    // Get a chat client for the OpenAI deployment
    ChatClient chatClient = openAIClient.GetChatClient(azureDeploymentModel);
    
    // Send the prompt to Azure OpenAI and stream the response
    var chatUpdates = chatClient.CompleteChatStreamingAsync(
        new[] { new UserChatMessage(formattedPrompt) }
    );
    
    // Output the streamed chat response
    await foreach (var chatUpdate in chatUpdates)
    {
        if (chatUpdate.Role.HasValue)
        {
            Console.Write($"{chatUpdate.Role} : ");
        }
        foreach (var contentPart in chatUpdate.ContentUpdate)
        {
            Console.Write(contentPart.Text);
        }
    }
    
  2. Запустите проект, чтобы инициировать базовый сценарий RAG. Выходные данные Azure OpenAI состоят из рекомендаций для нескольких отелей, таких как следующий пример:

    1. **Double Sanctuary Resort**
       - **Description**: 5-star luxury hotel with the biggest rooms in the city. Recognized as the #1 hotel in the area by Traveler magazine. Features include free WiFi, flexible check-in/out, a fitness center, and in-room espresso.
       - **Address**: 2211 Elliott Ave, Seattle, WA, 98121, USA
       - **Tags**: view, pool, restaurant, bar, continental breakfast
       - **Room Rate for 4 People**: 
         - Suite, 2 Queen Beds: $254.99 per night
    
    2. **Starlight Suites**
       - **Description**: Spacious all-suite hotel with complimentary airport shuttle and WiFi. Facilities include an indoor/outdoor pool, fitness center, and Florida Green certification. Complimentary coffee and HDTV are also available.
       - **Address**: 19575 Biscayne Blvd, Aventura, FL, 33180, USA
       - **Tags**: pool, coffee in lobby, free wifi
       - **Room Rate for 4 People**:
         - Suite, 2 Queen Beds (Cityside): $231.99 per night
         - Deluxe Room, 2 Queen Beds (Waterfront View): $148.99 per night
    
    3. **Good Business Hotel**
       - **Description**: Located one mile from the airport with free WiFi, an outdoor pool, and a complimentary airport shuttle. Close proximity to Lake Lanier and downtown. The business center includes printers, a copy machine, fax, and a work area.
       - **Address**: 4400 Ashford Dunwoody Rd NE, Atlanta, GA, 30346, USA
       - **Tags**: pool, continental breakfast, free parking
       - **Room Rate for 4 People**:
         - Budget Room, 2 Queen Beds (Amenities): $60.99 per night
         - Deluxe Room, 2 Queen Beds (Amenities): $139.99 per night
    

Устранение неполадок

Если вы видите выходные сообщения при отладке, связанные с ManagedIdentityCredential и ошибками приобретения токенов, возможно, у вас несколько арендаторов, и вход в Azure использует арендатора, у которого нет вашей службы поиска. Чтобы получить идентификатор клиента, выполните поиск портал Azure в поле "Свойства клиента" или выполните командуaz login tenant list.

После получения идентификатора клиента запустите az login --tenant <YOUR-TENANT-ID> в командной строке и повторно запустите скрипт.

Вы также можете регистрить ошибки в коде, создав экземпляр ILogger:

using var loggerFactory = LoggerFactory.Create(builder =>
{
   builder.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();

Очистка

Если вы работаете в собственной подписке, в конце проекта следует решить, нужны ли вам созданные ресурсы. Ресурсы, которые продолжат работать, могут быть платными. Вы можете удалить ресурсы по отдельности либо удалить всю группу ресурсов.

Ресурсы и управление ими можно найти в портал Azure с помощью ссылки "Все ресурсы" или "Группы ресурсов" в левой области.

Необходимые компоненты

Настройка доступа

Запросы к конечной точке поиска должны проходить проверку подлинности и авторизованы. Для этой задачи можно использовать ключи ИЛИ роли API. Ключи проще начать с, но роли более безопасны. В этом кратком руководстве предполагается, что роли.

Вы настраиваете два клиента, поэтому вам нужны разрешения для обоих ресурсов.

Поиск по искусственному интеллекту Azure получает запрос из локальной системы. Назначьте себе назначение роли читателя данных индекса поиска, если уже существует пример индекса отелей. Если он не существует, назначьте себя участнику службы поиска и роли участника индексов поиска, чтобы создать и запросить индекс.

Azure OpenAI получает запрос и результаты поиска из локальной системы. Назначьте себе роль пользователя OpenAI в Cognitive Services в Azure OpenAI.

  1. Войдите на портал Azure.

  2. Настройка azure AI Search для доступа на основе ролей:

    1. В портал Azure найдите служба ИИ Azure.

    2. В меню слева выберите >, а затем выберите управление доступом на основе ролей или оба.

  3. Назначение ролей:

    1. В меню слева выберите элемент управления доступом (IAM).

    2. В службе "Поиск ИИ Azure" выберите эти роли для создания, загрузки и запроса индекса поиска, а затем назначьте их идентификатору пользователя Microsoft Entra ID:

      • Участник данных индекса поиска
      • Участник службы поиска
    3. В Azure OpenAI выберите элемент управления доступом (IAM), чтобы назначить эту роль себе в Azure OpenAI:

      • Пользователь службы OpenAI в Cognitive Services

Для принятия в силу разрешений может потребоваться несколько минут.

Создание индекса

Индекс поиска предоставляет данные о заземления для модели чата. Мы рекомендуем использовать индекс hotels-sample-index, который можно создать в минутах и запустить на любом уровне служб поиска. Этот индекс создается с помощью встроенных примеров данных.

  1. В портал Azure найдите службу поиска.

  2. На домашней странице обзора выберите "Импорт данных", чтобы запустить мастер.

  3. На странице подключения к данным выберите примеры из раскрывающегося списка.

  4. Выберите пример отелей.

  5. Нажмите кнопку "Далее" на оставшихся страницах, принимая значения по умолчанию.

  6. После создания индекса выберите индексы управления>поиском в меню слева, чтобы открыть индекс.

  7. Выберите "Изменить JSON".

  8. Прокрутите страницу до конца индекса, где можно найти заполнители для конструкций, которые можно добавить в индекс.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. В новой строке после "нормализаторов" вставьте следующую семантику конфигурации. В этом примере указывается , "defaultConfiguration"что важно для выполнения этого краткого руководства.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Сохраните свои изменения.

  11. Выполните следующий запрос в обозревателе поиска, чтобы проверить индекс: complimentary breakfast

    Выходные данные должны выглядеть примерно так, как показано в следующем примере. Результаты, возвращаемые непосредственно из поисковой системы, состоят из полей и их подробных значений, а также метаданных, таких как оценка поиска и семантическая оценка ранжирования и подпись при использовании семантического ранга. Мы использовали инструкцию select, чтобы вернуть только поля HotelName, Description и 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"
          ]
       },
       . . .
    ]}
    

Получение конечных точек службы

В оставшихся разделах вы настроили вызовы API к Azure OpenAI и поиску ИИ Azure. Получите конечные точки службы, чтобы предоставить их в виде переменных в коде.

  1. Войдите на портал Azure.

  2. Найдите службу поиска.

  3. Скопируйте URL-адрес на домашней странице обзора. Пример конечной точки может выглядеть так: https://example.search.windows.net.

  4. Найдите службу Azure OpenAI.

  5. На домашней странице обзора выберите ссылку для просмотра конечных точек. Скопируйте URL-адрес. Пример конечной точки может выглядеть так: https://example.openai.azure.com/.

Настройка переменных среды для локальной разработки

  1. Создайте файл .env .

  2. Добавьте в файл следующие переменные .env среды, заменив значения собственными конечными точками и ключами службы.

    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>
    

Настройка проекта Node.JS

Настройте проект с помощью Visual Studio Code и TypeScript.

  1. Запустите Visual Studio Code в новом каталоге.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Создайте новый пакет для модулей ESM в каталоге проекта.

    npm init -y
    npm pkg set type=module
    

    При этом создается package.json файл со значениями по умолчанию.

  3. Установите следующие пакеты npm.

    npm install @azure/identity @azure/search-documents openai dotenv 
    
  4. Создайте каталог src внутри вашего проектного каталога.

    mkdir src
    

Вход в Azure

Для подключения используется идентификатор Microsoft Entra и назначения ролей. Убедитесь, что вы вошли в тот же клиент и подписку, что и поиск ИИ Azure и Azure OpenAI. Azure CLI можно использовать в командной строке для отображения текущих свойств, изменения свойств и входа. Дополнительные сведения см. в разделе "Подключение без ключей".

Выполните каждую из следующих команд в последовательности.

az account show

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

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

Теперь вы должны войти в Azure с локального устройства.

Настройка потока запросов и чата

Создайте скрипт запроса, который использует индекс поиска Azure AI и модель чата для генерации ответов, основывающихся на исходных данных. Ниже приведены инструкции по настройке скрипта запроса.

  1. query.js Создайте файл в каталоге src со следующим кодом.

    // 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);
    });
    

    Приведенный выше код выполняет следующие действия:

    • Импортирует необходимые библиотеки для поиска ИИ Azure и Azure OpenAI.
    • Использует переменные среды для настройки клиентов Azure AI Search и Azure OpenAI.
    • Определяет функцию для получения клиентов для Azure AI Search и Azure OpenAI, используя переменные среды для настройки.
    • Определяет функцию для запроса поиска ИИ Azure для источников на основе запроса пользователя.
    • Определяет функцию для получения ответа от Azure OpenAI на основе запроса пользователя и данных, полученных из поиска Azure AI.
    • Функция main управляет потоком путем вызова функций поиска и OpenAI, а затем выводит ответ.
  2. Выполните следующую команду в терминале, чтобы выполнить скрипт запроса:

    node -r dotenv/config query.js
    

    .env передается в среду выполнения с помощью -r dotenv/config.

  3. Просмотрите выходные данные, состоящие из рекомендаций для нескольких отелей. Ниже приведен пример того, как выглядят выходные данные:

    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
    

Устранение неполадок

Если вы получаете сообщение об ошибке "Запрещено" , проверьте конфигурацию поиска ИИ Azure, чтобы убедиться, что доступ на основе ролей включен.

Если вы получите сообщение об ошибке авторизации, подождите несколько минут и повторите попытку. Выполнение назначений ролей может занять несколько минут.

Если вы не нашли сообщение об ошибке ресурса, проверьте URI ресурса и убедитесь, что версия API в модели чата действительна.

В противном случае для дальнейшего эксперимента измените запрос и выполните последний шаг, чтобы лучше понять, как модель работает с данными о заземления.

Вы также можете изменить запрос, чтобы изменить тон или структуру выходных данных.

Вы также можете попробовать запрос без семантического ранжирования, установив на use_semantic_reranker=False шаге параметров запроса. Семантический ранжирование может значительно повысить релевантность результатов запроса и возможность LLM возвращать полезную информацию. Экспериментирование может помочь вам решить, имеет ли это значение для вашего содержимого.

Отправка сложного запроса RAG

Поиск ИИ Azure поддерживает сложные типы для вложенных структур JSON. В индексе hotels-sample-index Address является примером сложного типа, состоящего из Address.StreetAddress, , Address.City, Address.StateProvinceAddress.PostalCodeи Address.Country. Индекс также имеет сложную коллекцию Rooms для каждого отеля.

Если индекс имеет сложные типы, измените запрос на включение инструкций по форматированию:

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. Создайте новый файл queryComplex.js.

  2. Скопируйте следующий код в файл:

    // 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. Выполните следующую команду в терминале, чтобы выполнить скрипт запроса:

    node -r dotenv/config queryComplex.js
    

    .env передается в среду выполнения с помощью -r dotenv/config.

  4. Просмотрите выходные данные из Azure OpenAI, которые добавляют содержимое из сложных типов.

    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.
    

Устранение ошибок

Чтобы выполнить отладку ошибок Azure SDK, задайте для переменной среды AZURE_LOG_LEVEL одно из следующих значений: verbose, info, warning, error. Это позволит включить подробное ведение журнала для пакета SDK Для Azure, что может помочь выявить проблемы с проверкой подлинности, сетевым подключением или другими проблемами.

Повторно запустите скрипт запроса. Теперь вы должны получить информационные инструкции из пакетов SDK в выходных данных, которые содержат дополнительные сведения о любых проблемах.

Если вы видите выходные сообщения, связанные с ошибками получения управляемых данных ManagedIdentityCredential и маркерами, возможно, у вас несколько клиентов, и вход Azure использует клиент, который не имеет службы поиска. Чтобы получить идентификатор клиента, выполните поиск портал Azure в поле "Свойства клиента" или выполните командуaz login tenant list.

После получения идентификатора клиента запустите az login --tenant <YOUR-TENANT-ID> в командной строке и повторно запустите скрипт.

Очистка

Если вы работаете в собственной подписке, в конце проекта следует решить, нужны ли вам созданные ресурсы. Ресурсы, которые продолжат работать, могут быть платными. Вы можете удалить ресурсы по отдельности либо удалить всю группу ресурсов.

Ресурсы и управление ими можно найти в портал Azure с помощью ссылки "Все ресурсы" или "Группы ресурсов" в левой области.

Необходимые компоненты

Загрузить файл

Скачайте записную книжку Jupyter из GitHub, чтобы отправить запросы в этом кратком руководстве. Дополнительные сведения см. в статье "Скачивание файлов с GitHub".

Вы также можете запустить новый файл в локальной системе и вручную создать запросы, выполнив инструкции в этой статье.

Настройка доступа

Запросы к конечной точке поиска должны проходить проверку подлинности и авторизованы. Для этой задачи можно использовать ключи ИЛИ роли API. Ключи проще начать с, но роли более безопасны. В этом кратком руководстве предполагается, что роли.

Вы настраиваете два клиента, поэтому вам нужны разрешения для обоих ресурсов.

Поиск по искусственному интеллекту Azure получает запрос из локальной системы. Назначьте себе назначение роли читателя данных индекса поиска, если уже существует пример индекса отелей. Если он не существует, назначьте себя участнику службы поиска и роли участника индексов поиска, чтобы создать и запросить индекс.

Azure OpenAI получает запрос и результаты поиска из локальной системы. Назначьте себе роль пользователя OpenAI в Cognitive Services в Azure OpenAI.

  1. Войдите на портал Azure.

  2. Настройка azure AI Search для доступа на основе ролей:

    1. В портал Azure найдите служба ИИ Azure.

    2. В меню слева выберите >, а затем выберите управление доступом на основе ролей или оба.

  3. Назначение ролей:

    1. В меню слева выберите элемент управления доступом (IAM).

    2. В службе "Поиск ИИ Azure" выберите эти роли для создания, загрузки и запроса индекса поиска, а затем назначьте их идентификатору пользователя Microsoft Entra ID:

      • Участник данных индекса поиска
      • Участник службы поиска
    3. В Azure OpenAI выберите элемент управления доступом (IAM), чтобы назначить эту роль себе в Azure OpenAI:

      • Пользователь службы OpenAI в Cognitive Services

Для принятия в силу разрешений может потребоваться несколько минут.

Обновление индекса hotels-sample-index

Индекс поиска предоставляет данные о заземления для модели чата. Мы рекомендуем использовать индекс hotels-sample-index, который можно создать в минутах и запустить на любом уровне служб поиска. Этот индекс создается с помощью встроенных примеров данных.

  1. В портал Azure найдите службу поиска.

  2. На домашней странице обзора выберите "Импорт данных", чтобы запустить мастер.

  3. На странице подключения к данным выберите примеры из раскрывающегося списка.

  4. Выберите пример отелей.

  5. Нажмите кнопку "Далее" на оставшихся страницах, принимая значения по умолчанию.

  6. После создания индекса выберите индексы управления>поиском в меню слева, чтобы открыть индекс.

  7. Выберите "Изменить JSON".

  8. Прокрутите страницу до конца индекса, где можно найти заполнители для конструкций, которые можно добавить в индекс.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. В новой строке после "нормализаторов" вставьте следующую семантику конфигурации. В этом примере указывается , "defaultConfiguration"что важно для выполнения этого краткого руководства.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Сохраните свои изменения.

  11. Выполните следующий запрос в обозревателе поиска, чтобы проверить индекс: complimentary breakfast

    Выходные данные должны выглядеть примерно так, как показано в следующем примере. Результаты, возвращаемые непосредственно из поисковой системы, состоят из полей и их подробных значений, а также метаданных, таких как оценка поиска и семантическая оценка ранжирования и подпись при использовании семантического ранга. Мы использовали инструкцию select, чтобы вернуть только поля HotelName, Description и 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"
          ]
       },
       . . .
    ]}
    

Получение конечных точек службы

В оставшихся разделах вы настроили вызовы API к Azure OpenAI и поиску ИИ Azure. Получите конечные точки службы, чтобы предоставить их в виде переменных в коде.

  1. Войдите на портал Azure.

  2. Найдите службу поиска.

  3. Скопируйте URL-адрес на домашней странице обзора. Пример конечной точки может выглядеть так: https://example.search.windows.net.

  4. Найдите службу Azure OpenAI.

  5. На домашней странице обзора выберите ссылку для просмотра конечных точек. Скопируйте URL-адрес. Пример конечной точки может выглядеть так: https://example.openai.azure.com/.

Создание виртуальной среды

На этом шаге переключитесь на локальную систему и Visual Studio Code. Рекомендуется создать виртуальную среду, чтобы можно было установить зависимости в изоляции.

  1. В Visual Studio Code откройте папку, содержащую quickstart-RAG.ipynb.

  2. Нажмите клавиши CTRL-SHIFT-P, чтобы открыть палитру команд, найдите "Python: Создать среду", а затем выберите Venv , чтобы создать виртуальную среду в текущей рабочей области.

  3. Выберите quickstart-RAG\requirements.txt для зависимостей.

Создание среды занимает несколько минут. Когда среда будет готова, перейдите к следующему шагу.

Вход в Azure

Для подключения используется идентификатор Microsoft Entra и назначения ролей. Убедитесь, что вы вошли в тот же клиент и подписку, что и поиск ИИ Azure и Azure OpenAI. Azure CLI можно использовать в командной строке для отображения текущих свойств, изменения свойств и входа. Дополнительные сведения см. в разделе "Подключение без ключей".

Выполните каждую из следующих команд в последовательности.

az account show

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

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

Теперь вы должны войти в Azure с локального устройства.

Настройка потока запроса и чата

В этом разделе используется Visual Studio Code и Python для вызова API завершения чата в Azure OpenAI.

  1. Запустите Visual Studio Code и откройте IPYNB-файл или создайте новый файл Python.

  2. Установите следующие пакеты 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. Задайте следующие переменные, заменив заполнители конечными точками, собранными на предыдущем шаге.

     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. Настройте клиенты, запрос, запрос и ответ.

    Для облака Azure для государственных организаций измените конечную точку API в поставщике "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)
    

    Выходные данные из Azure OpenAI состоят из рекомендаций для нескольких отелей. Ниже приведен пример того, как выглядят выходные данные:

    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
    

    Если вы получаете сообщение об ошибке "Запрещено" , проверьте конфигурацию поиска ИИ Azure, чтобы убедиться, что доступ на основе ролей включен.

    Если вы получите сообщение об ошибке авторизации, подождите несколько минут и повторите попытку. Выполнение назначений ролей может занять несколько минут.

    Если вы не нашли сообщение об ошибке ресурса, проверьте URI ресурса и убедитесь, что версия API в модели чата действительна.

    В противном случае для дальнейшего эксперимента измените запрос и выполните последний шаг, чтобы лучше понять, как модель работает с данными о заземления.

    Вы также можете изменить запрос, чтобы изменить тон или структуру выходных данных.

    Вы также можете попробовать запрос без семантического ранжирования, установив на use_semantic_reranker=False шаге параметров запроса. Семантический ранжирование может значительно повысить релевантность результатов запроса и возможность LLM возвращать полезную информацию. Экспериментирование может помочь вам решить, имеет ли это значение для вашего содержимого.

Отправка сложного запроса RAG

Поиск ИИ Azure поддерживает сложные типы для вложенных структур JSON. В индексе hotels-sample-index Address является примером сложного типа, состоящего из Address.StreetAddress, , Address.City, Address.StateProvinceAddress.PostalCodeи Address.Country. Индекс также имеет сложную коллекцию Rooms для каждого отеля.

Если индекс имеет сложные типы, запрос может предоставить эти поля, если сначала преобразовать выходные данные результатов поиска в JSON, а затем передать JSON в модель чата. В следующем примере в запрос добавляются сложные типы. Инструкции по форматированию включают спецификацию 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)

Выходные данные из Azure OpenAI и добавляют содержимое из сложных типов.

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.

Устранение ошибок

Чтобы выполнить отладку ошибок проверки подлинности, вставьте следующий код перед шагом, который вызывает поисковую систему и 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)

Повторно запустите скрипт запроса. Теперь вы должны получить инструкции INFO и DEBUG в выходных данных, которые содержат дополнительные сведения о проблеме.

Если вы видите выходные сообщения, связанные с ошибками получения управляемых данных ManagedIdentityCredential и маркерами, возможно, у вас несколько клиентов, и вход Azure использует клиент, который не имеет службы поиска. Чтобы получить идентификатор клиента, выполните поиск портал Azure в поле "Свойства клиента" или выполните командуaz login tenant list.

После получения идентификатора клиента запустите az login --tenant <YOUR-TENANT-ID> в командной строке и повторно запустите скрипт.

Очистка

Если вы работаете в собственной подписке, в конце проекта следует решить, нужны ли вам созданные ресурсы. Ресурсы, которые продолжат работать, могут быть платными. Вы можете удалить ресурсы по отдельности либо удалить всю группу ресурсов.

Ресурсы и управление ими можно найти в портал Azure с помощью ссылки "Все ресурсы" или "Группы ресурсов" в левой области.

Необходимые компоненты

Загрузить файл

Скачайте REST-файл из GitHub, чтобы отправить запросы в этом кратком руководстве. Дополнительные сведения см. в статье "Скачивание файлов с GitHub".

Вы также можете запустить новый файл в локальной системе и вручную создать запросы, выполнив инструкции в этой статье.

Настройка доступа

Запросы к конечной точке поиска должны проходить проверку подлинности и авторизованы. Для этой задачи можно использовать ключи API или роли. Ключи проще начать с, но роли более безопасны. В этом кратком руководстве предполагается, что роли.

Вы настраиваете два клиента, поэтому вам нужны разрешения для обоих ресурсов.

Поиск по искусственному интеллекту Azure получает запрос из локальной системы. Назначьте себе назначение роли читателя данных индекса поиска, если уже существует пример индекса отелей. Если он не существует, назначьте себя участнику службы поиска и роли участника индексов поиска, чтобы создать и запросить индекс.

Azure OpenAI получает запрос и результаты поиска из локальной системы. Назначьте себе роль пользователя OpenAI в Cognitive Services в Azure OpenAI.

  1. Войдите на портал Azure.

  2. Настройка azure AI Search для доступа на основе ролей:

    1. В портал Azure найдите служба ИИ Azure.

    2. В меню слева выберите >, а затем выберите управление доступом на основе ролей или оба.

  3. Назначение ролей:

    1. В меню слева выберите элемент управления доступом (IAM).

    2. В службе "Поиск ИИ Azure" выберите эти роли для создания, загрузки и запроса индекса поиска, а затем назначьте их идентификатору пользователя Microsoft Entra ID:

      • Участник данных индекса поиска
      • Участник службы поиска
    3. В Azure OpenAI выберите элемент управления доступом (IAM), чтобы назначить эту роль себе в Azure OpenAI:

      • Пользователь службы OpenAI в Cognitive Services

Для принятия в силу разрешений может потребоваться несколько минут.

Получение конечных точек и токенов службы

В оставшихся разделах вы настроили вызовы API к Azure OpenAI и поиску ИИ Azure. Получите конечные точки и маркеры службы, чтобы предоставить их в виде переменных в коде.

  1. Войдите на портал Azure.

  2. Найдите службу поиска.

  3. Скопируйте URL-адрес на домашней странице обзора. Пример конечной точки может выглядеть так: https://example.search.windows.net.

  4. Найдите службу Azure OpenAI.

  5. На домашней странице обзора выберите ссылку для просмотра конечных точек. Скопируйте URL-адрес. Пример конечной точки может выглядеть так: https://example.openai.azure.com/.

  6. Получите персональные токены доступа из Azure CLI в командной строке. Ниже приведены команды для каждого ресурса:

    • az account get-access-token --resource https://search.azure.com --query "accessToken" -o tsv
    • az account get-access-token --resource https://cognitiveservices.azure.com --query "accessToken" -o tsv

Настройка клиента

В этом кратком руководстве вы используете клиент REST и REST API Azure AI Search для внедрения модели RAG (Получение-Дополнение-Генерация).

Для этого краткого руководства мы рекомендуем использовать Visual Studio Code с расширением для клиента REST.

Подсказка

Исходный код можно скачать, чтобы начать с готового проекта или выполнить следующие действия, чтобы создать собственный.

  1. Запустите Visual Studio Code и откройте файл quickstart-rag.rest или создайте новый файл.

  2. В верхней части задайте переменные среды для службы поиска, авторизации и имени индекса.

    • Для @searchUrl вставьте URL-адрес в поле поиска.
    • Для @aoaiUrl вставьте конечную точку Azure OpenAI.
    • Для @searchAccessToken вставьте маркер доступа, скопированный для https://search.azure.com.
    • Для @aoaiAccessToken вставьте токен доступа, предназначенный для https://cognitiveservices.azure.com.
  3. Чтобы проверить подключение, отправьте первый запрос.

    ### List existing indexes by name (verify the connection)
     GET  {{searchUrl}}/indexes?api-version=2025-05-01-preview&$select=name  HTTP/1.1
     Authorization: Bearer {{personalAccessToken}}
    
  4. Выберите "Отправленный запрос".

    Снимок экрана ссылки отправки запроса клиента REST.

  5. Выходные данные для этого запроса GET должны быть списком индексов. Среди них должен появиться индекс hotels-sample-index .

Настройка потока запроса и чата

В этом разделе используется Visual Studio Code и REST для вызова API завершения чата в Azure OpenAI.

  1. Настройте запрос на фразу "Можно ли рекомендовать несколько отелей с бесплатным завтраком?". Этот запрос использует семантический рейтинг для возврата соответствующих совпадений, даже если подробный текст не является точным. Результаты хранятся в переменной searchRequest для повторного использования в следующем запросе.

    # @name searchRequest
     POST {{searchUrl}}/indexes/{{index-name}}/docs/search?api-version={{api-version}} HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{searchAccessToken}}
    
     {
       "search": "Can you recommend a few hotels with complimentary breakfast?",
       "queryType": "semantic",
       "semanticConfiguration": "semantic-config",
       "select": "Description,HotelName,Tags",
       "top": 5
     }
    
     ### 3 - Use search results in Azure OpenAI call to a chat completion model
     POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{aoaiAccessToken}}
    
     {
       "messages": [
         {
           "role": "system", 
           "content": "You recommend hotels based on activities and amenities. Answer the query using only the search result. Answer in a friendly and concise manner. Answer ONLY with the facts provided. If there isn't enough information below, say you don't know."
         },
         {
           "role": "user",
           "content": "Based on the hotel search results, can you recommend hotels with breakfast? Here are all the hotels I found:\n\nHotel 1: {{searchRequest.response.body.value[0].HotelName}}\nDescription: {{searchRequest.response.body.value[0].Description}}\n\nHotel 2: {{searchRequest.response.body.value[1].HotelName}}\nDescription: {{searchRequest.response.body.value[1].Description}}\n\nHotel 3: {{searchRequest.response.body.value[2].HotelName}}\nDescription: {{searchRequest.response.body.value[2].Description}}\n\nHotel 4: {{searchRequest.response.body.value[3].HotelName}}\nDescription: {{searchRequest.response.body.value[3].Description}}\n\nHotel 5: {{searchRequest.response.body.value[4].HotelName}}\nDescription: {{searchRequest.response.body.value[4].Description}}\n\nPlease recommend which hotels offer breakfast based on their descriptions."
         }
       ],
       "max_tokens": 1000,
       "temperature": 0.7
     }`
    
  2. Отправьте запрос.

  3. Выходные данные должны выглядеть примерно так:

       "value": [
         {
           "@search.score": 3.9269178,
           "@search.rerankerScore": 2.380699872970581,
           "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": 1.5450059,
           "@search.rerankerScore": 2.1258809566497803,
           "HotelName": "Thunderbird Motel",
           "Description": "Book Now & Save. Clean, Comfortable rooms at the lowest price. Enjoy complimentary coffee and tea in common areas.",
           "Tags": [
             "coffee in lobby",
             "free parking",
             "free wifi"
           ]
         },
         {
           "@search.score": 2.2158256,
           "@search.rerankerScore": 2.121671438217163,
           "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.6395861,
           "@search.rerankerScore": 2.116753339767456,
           "HotelName": "Waterfront Scottish Inn",
           "Description": "Newly Redesigned Rooms & airport shuttle. Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
           "Tags": [
             "24-hour front desk service",
             "continental breakfast",
             "free wifi"
           ]
         },
         {
           "@search.score": 4.885111,
           "@search.rerankerScore": 2.0008862018585205,
           "HotelName": "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.",
           "Tags": [
             "view",
             "pool",
             "restaurant",
             "bar",
             "continental breakfast"
           ]
         }
       ]
    
  4. Настройте ход беседы с помощью модели завершения чата. Этот запрос включает подсказку, предоставляющую инструкции по ответу. Значение max_tokens достаточно большое, чтобы разместить результаты поиска из предыдущего запроса.

     POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{aoaiAccessToken}}
    
     {
     "messages": [
     {
       "role": "system", 
       "content": "You  are a friendly assistant that recommends hotels based on activities and amenities. Answer the query using only the search result. Answer in a friendly and concise manner. Answer ONLY with the facts provided. If there isn't enough information below, say you don't know."
         },
     {
       "role": "user",
       "content": "Based on the hotel search results, can you recommend hotels with breakfast? Here are all the hotels I found:\n\nHotel 1: {{searchRequest.response.body.value[0].HotelName}}\nDescription: {{searchRequest.response.body.value[0].Description}}\n\nHotel 2: {{searchRequest.response.body.value[1].HotelName}}\nDescription: {{searchRequest.response.body.value[1].Description}}\n\nHotel 3: {{searchRequest.response.body.value[2].HotelName}}\nDescription: {{searchRequest.response.body.value[2].Description}}\n\nHotel 4: {{searchRequest.response.body.value[3].HotelName}}\nDescription: {{searchRequest.response.body.value[3].Description}}\n\nHotel 5: {{searchRequest.response.body.value[4].HotelName}}\nDescription: {{searchRequest.response.body.value[4].Description}}\n\nPlease recommend which hotels offer breakfast based on their descriptions."
     }
     ],
     "max_tokens": 1000,
     "temperature": 0.7
     }
    
  5. Отправьте запрос.

  6. Выходные данные должны быть сообщением о состоянии успешного выполнения HTTP 200. В выходные данные входит содержимое, которое отвечает на вопрос:

     "message": {
       "annotations": [],
       "content": "I recommend the following hotels that offer breakfast:\n\n1. **Head Wind Resort** - Offers a complimentary continental breakfast in the lobby.\n2. **Swan Bird Lake Inn** - Serves a continental-style breakfast each morning, including a variety of food and drinks. \n\nEnjoy your stay!",
       "refusal": null,
       "role": "assistant"
     }
    

Обратите внимание, что в выводе отсутствуют несколько отелей, которые упоминают завтрак в поле "Теги". Поле "Теги" представляет собой массив, а в том числе это поле разбивает структуру JSON в результатах. Так как в клиенте REST нет возможностей преобразования строк, дополнительный код для ручного преобразования JSON в строку требуется, если массивы должны быть включены. Мы опустим этот шаг для этого быстрого старта.

Очистка

Если вы работаете в собственной подписке, в конце проекта следует решить, нужны ли вам созданные ресурсы. Ресурсы, которые продолжат работать, могут быть платными. Вы можете удалить ресурсы по отдельности либо удалить всю группу ресурсов.

Ресурсы и управление ими можно найти в портал Azure с помощью ссылки "Все ресурсы" или "Группы ресурсов" в левой области.

Необходимые компоненты

Настройка доступа

Запросы к конечной точке поиска должны проходить проверку подлинности и авторизованы. Для этой задачи можно использовать ключи ИЛИ роли API. Ключи проще начать с, но роли более безопасны. В этом кратком руководстве предполагается, что роли.

Вы настраиваете два клиента, поэтому вам нужны разрешения для обоих ресурсов.

Поиск по искусственному интеллекту Azure получает запрос из локальной системы. Назначьте себе назначение роли читателя данных индекса поиска, если уже существует пример индекса отелей. Если он не существует, назначьте себя участнику службы поиска и роли участника индексов поиска, чтобы создать и запросить индекс.

Azure OpenAI получает запрос и результаты поиска из локальной системы. Назначьте себе роль пользователя OpenAI в Cognitive Services в Azure OpenAI.

  1. Войдите на портал Azure.

  2. Настройка azure AI Search для доступа на основе ролей:

    1. В портал Azure найдите служба ИИ Azure.

    2. В меню слева выберите >, а затем выберите управление доступом на основе ролей или оба.

  3. Назначение ролей:

    1. В меню слева выберите элемент управления доступом (IAM).

    2. В службе "Поиск ИИ Azure" выберите эти роли для создания, загрузки и запроса индекса поиска, а затем назначьте их идентификатору пользователя Microsoft Entra ID:

      • Участник данных индекса поиска
      • Участник службы поиска
    3. В Azure OpenAI выберите элемент управления доступом (IAM), чтобы назначить эту роль себе в Azure OpenAI:

      • Пользователь службы OpenAI в Cognitive Services

Для принятия в силу разрешений может потребоваться несколько минут.

Создание индекса

Индекс поиска предоставляет данные о заземления для модели чата. Мы рекомендуем использовать индекс hotels-sample-index, который можно создать в минутах и запустить на любом уровне служб поиска. Этот индекс создается с помощью встроенных примеров данных.

  1. В портал Azure найдите службу поиска.

  2. На домашней странице обзора выберите "Импорт данных", чтобы запустить мастер.

  3. На странице подключения к данным выберите примеры из раскрывающегося списка.

  4. Выберите пример отелей.

  5. Нажмите кнопку "Далее" на оставшихся страницах, принимая значения по умолчанию.

  6. После создания индекса выберите индексы управления>поиском в меню слева, чтобы открыть индекс.

  7. Выберите "Изменить JSON".

  8. Прокрутите страницу до конца индекса, где можно найти заполнители для конструкций, которые можно добавить в индекс.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. В новой строке после "нормализаторов" вставьте следующую семантику конфигурации. В этом примере указывается , "defaultConfiguration"что важно для выполнения этого краткого руководства.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Сохраните свои изменения.

  11. Выполните следующий запрос в обозревателе поиска, чтобы проверить индекс: complimentary breakfast

    Выходные данные должны выглядеть примерно так, как показано в следующем примере. Результаты, возвращаемые непосредственно из поисковой системы, состоят из полей и их подробных значений, а также метаданных, таких как оценка поиска и семантическая оценка ранжирования и подпись при использовании семантического ранга. Мы использовали инструкцию select, чтобы вернуть только поля HotelName, Description и 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"
          ]
       },
       . . .
    ]}
    

Получение конечных точек службы

В оставшихся разделах вы настроили вызовы API к Azure OpenAI и поиску ИИ Azure. Получите конечные точки службы, чтобы предоставить их в виде переменных в коде.

  1. Войдите на портал Azure.

  2. Найдите службу поиска.

  3. Скопируйте URL-адрес на домашней странице обзора. Пример конечной точки может выглядеть так: https://example.search.windows.net.

  4. Найдите службу Azure OpenAI.

  5. На домашней странице обзора выберите ссылку для просмотра конечных точек. Скопируйте URL-адрес. Пример конечной точки может выглядеть так: https://example.openai.azure.com/.

Настройка переменных среды для локальной разработки

  1. Создайте файл .env .

  2. Добавьте в файл следующие переменные .env среды, заменив значения собственными конечными точками и ключами службы.

    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>
    

Настройка проекта Node.JS

Настройте проект с помощью Visual Studio Code и TypeScript.

  1. Запустите Visual Studio Code в новом каталоге.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Создайте новый пакет для модулей ESM в каталоге проекта.

    npm init -y
    npm pkg set type=module
    

    При этом создается package.json файл со значениями по умолчанию.

  3. Установите следующие пакеты npm.

    npm install @azure/identity @azure/search-documents openai dotenv @types/node
    
  4. Создайте каталог src внутри вашего проектного каталога.

    mkdir src
    
  5. tsconfig.json Создайте файл в каталоге проекта для ESM со следующим содержимым.

    {
      "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"
      ]
    }
    

Вход в Azure

Для подключения используется идентификатор Microsoft Entra и назначения ролей. Убедитесь, что вы вошли в тот же клиент и подписку, что и поиск ИИ Azure и Azure OpenAI. Azure CLI можно использовать в командной строке для отображения текущих свойств, изменения свойств и входа. Дополнительные сведения см. в разделе "Подключение без ключей".

Выполните каждую из следующих команд в последовательности.

az account show

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

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

Теперь вы должны войти в Azure с локального устройства.

Настройка потока запросов и чата

Создайте скрипт запроса, который использует индекс поиска Azure AI и модель чата для генерации ответов, основывающихся на исходных данных. Ниже приведены инструкции по настройке скрипта запроса.

  1. query.ts Создайте файл в каталоге src со следующим кодом.

    // 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);
    });
    

    Приведенный выше код выполняет следующие действия:

    • Импортирует необходимые библиотеки для поиска ИИ Azure и Azure OpenAI.
    • Использует переменные среды для настройки клиентов Azure AI Search и Azure OpenAI.
    • Определяет функцию для получения клиентов для Azure AI Search и Azure OpenAI, используя переменные среды для настройки.
    • Определяет функцию для запроса поиска ИИ Azure для источников на основе запроса пользователя.
    • Определяет функцию для получения ответа от Azure OpenAI на основе запроса пользователя и данных, полученных из поиска Azure AI.
    • Функция main управляет потоком путем вызова функций поиска и OpenAI, а затем выводит ответ.
  2. Создайте код TypeScript в JavaScript.

    tsc
    

    Эта команда компилирует код TypeScript в каталоге src и выводит файлы JavaScript в каталоге dist .

  3. Выполните следующую команду в терминале, чтобы выполнить скрипт запроса:

    node -r dotenv/config dist/query.js
    

    .env передается в среду выполнения с помощью -r dotenv/config.

  4. Просмотр результатов включает рекомендации для нескольких отелей. Ниже приведен пример того, как выглядят выходные данные:

    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
    

Устранение неполадок

Если вы получаете сообщение об ошибке "Запрещено" , проверьте конфигурацию поиска ИИ Azure, чтобы убедиться, что доступ на основе ролей включен.

Если вы получите сообщение об ошибке авторизации, подождите несколько минут и повторите попытку. Выполнение назначений ролей может занять несколько минут.

Если вы не нашли сообщение об ошибке ресурса, проверьте URI ресурса и убедитесь, что версия API в модели чата действительна.

В противном случае для дальнейшего эксперимента измените запрос и выполните последний шаг, чтобы лучше понять, как модель работает с данными о заземления.

Вы также можете изменить запрос, чтобы изменить тон или структуру выходных данных.

Вы также можете попробовать запрос без семантического ранжирования, установив на use_semantic_reranker=False шаге параметров запроса. Семантический ранжирование может значительно повысить релевантность результатов запроса и возможность LLM возвращать полезную информацию. Экспериментирование может помочь вам решить, имеет ли это значение для вашего содержимого.

Отправка сложного запроса RAG

Поиск ИИ Azure поддерживает сложные типы для вложенных структур JSON. В индексе hotels-sample-index Address является примером сложного типа, состоящего из Address.StreetAddress, , Address.City, Address.StateProvinceAddress.PostalCodeи Address.Country. Индекс также имеет сложную коллекцию Rooms для каждого отеля.

Если индекс имеет сложные типы, измените запрос на включение инструкций по форматированию:

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. Создайте файл queryComplex.ts в каталоге src .

  2. Скопируйте следующий код в файл:

    // 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. Создайте код TypeScript в JavaScript.

    tsc
    

    Эта команда компилирует код TypeScript в каталоге src и выводит файлы JavaScript в каталоге dist .

  4. Выполните следующую команду в терминале, чтобы выполнить скрипт запроса:

    node -r dotenv/config dist/queryComplex.js
    

    .env передается в среду выполнения с помощью -r dotenv/config.

  5. Просмотрите выходные данные из Azure OpenAI, которые добавляют содержимое из сложных типов.

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.

Устранение ошибок

Чтобы выполнить отладку ошибок Azure SDK, задайте для переменной среды AZURE_LOG_LEVEL одно из следующих значений: verbose, info, warning, error. Это позволит включить подробное ведение журнала для пакета SDK Для Azure, что может помочь выявить проблемы с проверкой подлинности, сетевым подключением или другими проблемами.

Повторно запустите скрипт запроса. Теперь вы должны получить информационные инструкции из пакетов SDK в выходных данных, которые содержат дополнительные сведения о любых проблемах.

Если вы видите выходные сообщения, связанные с ошибками получения управляемых данных ManagedIdentityCredential и маркерами, возможно, у вас несколько клиентов, и вход Azure использует клиент, который не имеет службы поиска. Чтобы получить идентификатор клиента, выполните поиск портал Azure в поле "Свойства клиента" или выполните командуaz login tenant list.

После получения идентификатора клиента запустите az login --tenant <YOUR-TENANT-ID> в командной строке и повторно запустите скрипт.

Очистка

Если вы работаете в собственной подписке, в конце проекта следует решить, нужны ли вам созданные ресурсы. Ресурсы, которые продолжат работать, могут быть платными. Вы можете удалить ресурсы по отдельности либо удалить всю группу ресурсов.

Ресурсы и управление ими можно найти в портал Azure с помощью ссылки "Все ресурсы" или "Группы ресурсов" в левой области.