Быстрый старт: Поиск векторов

В этом кратком руководстве вы будете использовать клиентскую библиотеку Поиск с использованием ИИ Azure для .NET для создания, загрузки и выполнения запросов к векторному индексу. Клиентская библиотека .NET предоставляет абстракцию по REST API для операций с индексами.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-dotnet-samples/quickstart-vector-search
    
  3. В VectorSearchCreatePopulateIndex/appsettings.json замените значение заполнителя Endpoint на URL-адрес, полученный из метода Get endpoint.

  4. Повторите предыдущий шаг для VectorSearchExamples/appsettings.json.

  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    

Запустите код

  1. Запустите первый проект, чтобы создать и заполнить индекс.

    cd VectorSearchCreatePopulateIndex
    dotnet run
    
  2. В VectorSearchExamples/Program.csполе раскомментируйте методы запроса, которые требуется запустить.

  3. Запустите второй проект, чтобы выполнить эти запросы к индексу.

    cd ..\VectorSearchExamples
    dotnet run
    

Выходные данные

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

Creating or updating index 'hotels-vector-quickstart'...
Index 'hotels-vector-quickstart' updated.

Key: 1, Succeeded: True
Key: 2, Succeeded: True
Key: 3, Succeeded: True
Key: 4, Succeeded: True
Key: 48, Succeeded: True
Key: 49, Succeeded: True
Key: 13, Succeeded: True

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

Single Vector Search Results:
Score: 0.6605852, HotelId: 48, HotelName: Nordick's Valley Motel
Score: 0.6333684, HotelId: 13, HotelName: Luxury Lion Resort
Score: 0.605672, HotelId: 4, HotelName: Sublime Palace Hotel
Score: 0.6026341, HotelId: 49, HotelName: Swirling Currents Hotel
Score: 0.57902366, HotelId: 2, HotelName: Old Century Hotel

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

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

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. Следующий код в VectorSearchCreatePopulateIndex/Program.cs создает схему индекса, включая векторное поле DescriptionVector.

static async Task CreateSearchIndex(string indexName, SearchIndexClient indexClient)
{
    var addressField = new ComplexField("Address");
    addressField.Fields.Add(new SearchableField("StreetAddress") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft });
    addressField.Fields.Add(new SearchableField("City") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("StateProvince") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("PostalCode") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("Country") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });

    var allFields = new List<SearchField>()
    {
        new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFacetable = true, IsFilterable = true },
        new SearchableField("HotelName") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft },
        new SearchableField("Description") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft },
        new VectorSearchField("DescriptionVector", 1536, "my-vector-profile"),
        new SearchableField("Category") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true },
        new SearchableField("Tags", collection: true) { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true },
        new SimpleField("ParkingIncluded", SearchFieldDataType.Boolean) { IsFacetable = true, IsFilterable = true },
        new SimpleField("LastRenovationDate", SearchFieldDataType.DateTimeOffset) { IsSortable = true },
        new SimpleField("Rating", SearchFieldDataType.Double) { IsFacetable = true, IsFilterable = true, IsSortable = true },
        addressField,
        new SimpleField("Location", SearchFieldDataType.GeographyPoint) { IsFilterable = true, IsSortable = true },
    };

    // Create the suggester configuration
    var suggester = new SearchSuggester("sg", new[] { "Address/City", "Address/Country" });

    // Create the semantic search
    var semanticSearch = new SemanticSearch()
    {
        Configurations =
        {
            new SemanticConfiguration(
                name: "semantic-config",
                prioritizedFields: new SemanticPrioritizedFields
                {
                    TitleField = new SemanticField("HotelName"),
                    KeywordsFields = { new SemanticField("Category") },
                    ContentFields = { new SemanticField("Description") }
                })
        }
    };

    // Add vector search configuration
    var vectorSearch = new VectorSearch();
    vectorSearch.Algorithms.Add(new HnswAlgorithmConfiguration(name: "my-hnsw-vector-config-1"));
    vectorSearch.Profiles.Add(new VectorSearchProfile(name: "my-vector-profile", algorithmConfigurationName: "my-hnsw-vector-config-1"));

    var definition = new SearchIndex(indexName)
    {
        Fields = allFields,
        Suggesters = { suggester },
        VectorSearch = vectorSearch,
        SemanticSearch = semanticSearch
    };

    // Create or update the index
    Console.WriteLine($"Creating or updating index '{indexName}'...");
    var result = await indexClient.CreateOrUpdateIndexAsync(definition);
    Console.WriteLine($"Index '{result.Value.Name}' updated.");
    Console.WriteLine();
}

Ключевые моменты:

  • Вы определяете индекс, создав список полей.

  • Этот конкретный индекс поддерживает несколько возможностей поиска:

  • Второй параметр в VectorSearchField указывает, что vectorSearchDimensions, который должен соответствовать выходному размеру вашей модели встраивания. В этом кратком руководстве для сопоставления text-embedding-ada-002 модели используется 1 536 измерений.

  • Конфигурация VectorSearch определяет алгоритм приблизительного ближайшего соседа (ANN). Поддерживаемые алгоритмы включают иерархический навигационируемый малый мир (HNSW) и исчерпывающий K-ближайший сосед (KNN). Дополнительные сведения см. в разделе "Релевантность" в векторном поиске.

Отправка документов в индекс

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

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

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

static async Task UploadDocs(SearchClient searchClient)
{
    var jsonPath = Path.Combine(Directory.GetCurrentDirectory(), "HotelData.json");

    // Read and parse hotel data
    var json = await File.ReadAllTextAsync(jsonPath);
    List<Hotel> hotels = new List<Hotel>();
    try
    {
        using var doc = JsonDocument.Parse(json);
        if (doc.RootElement.ValueKind != JsonValueKind.Array)
        {
            Console.WriteLine("HotelData.json root is not a JSON array.");
        }
        // Deserialize all hotel objects
        hotels = doc.RootElement.EnumerateArray()
            .Select(e => JsonSerializer.Deserialize<Hotel>(e.GetRawText()))
            .Where(h => h != null)
            .ToList();
    }
    catch (JsonException ex)
    {
        Console.WriteLine($"Failed to parse HotelData.json: {ex.Message}");
    }

    try
    {
        // Upload hotel documents to Azure Search
        var result = await searchClient.UploadDocumentsAsync(hotels);
        foreach (var r in result.Value.Results)
        {
            Console.WriteLine($"Key: {r.Key}, Succeeded: {r.Succeeded}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed to upload documents: " + ex);
    }
}

Код взаимодействует с определенным индексом поиска, размещенным в службе Поиск с использованием ИИ Azure, через SearchClient, который является основным объектом, предоставляемым пакетом Azure.Search.Documents. SearchClient предоставляет доступ к операциям индекса, таким как:

  • Прием данных: UploadDocuments(), MergeDocuments()DeleteDocuments()

  • Операции поиска: Search(), Autocomplete()Suggest()

Запрос индекса

Запросы в VectorSearchExamples демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

Этот SearchSingleVector метод демонстрирует базовый сценарий, в котором требуется найти описания документов, которые тесно соответствуют строке векторного запроса. VectorizedQuery настраивает векторный поиск:

  • KNearestNeighborsCount ограничивает количество возвращаемых результатов на основе сходства векторов.
  • Fields задает поле вектора для поиска.
public static async Task SearchSingleVector(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> response = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
        });

    Console.WriteLine($"Single Vector Search Results:");
    await foreach (SearchResult<Hotel> result in response.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}, HotelId: {doc.HotelId}, HotelName: {doc.HotelName}");
    }
    Console.WriteLine();
}

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. Метод SearchSingleVectorWithFilter фильтрует в Tags поле, чтобы отфильтровать все отели, которые не предоставляют бесплатный Wi-Fi.

public static async Task SearchSingleVectorWithFilter(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Filter = "Tags/any(tag: tag eq 'free wifi')",
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" }
        });

    Console.WriteLine($"Single Vector Search With Filter Results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}, HotelId: {doc.HotelId}, HotelName: {doc.HotelName}, Tags: {string.Join(String.Empty, doc.Tags)}");
    }
    Console.WriteLine();
}

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. Метод SingleSearchWithGeoFilter задает географическую точку (Вашингтон округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. По умолчанию фильтры выполняются после векторного поиска.

public static async Task SingleSearchWithGeoFilter(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithGeoFilter = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Filter = "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
            Select = { "HotelId", "HotelName", "Description", "Address", "Category", "Tags" },
            Facets = { "Address/StateProvince" },
        });

    Console.WriteLine($"Vector query with a geo filter:");
    await foreach (SearchResult<Hotel> result in responseWithGeoFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"City/State: {doc.Address.City}/{doc.Address.StateProvince}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine();
    }
    Console.WriteLine();
}

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. Метод SearchHybridVectorAndText выполняет оба типа запросов одновременно, а затем использует взаимное объединение результатов в единый рейтинг. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

public static async Task<SearchResults<Hotel>> SearchHybridVectorAndText(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        "historic hotel walk to restaurants and shopping",
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
            Size = 5,
        });

    Console.WriteLine($"Hybrid search results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine($"Category: {doc.Category}");
        Console.WriteLine($"Tags: {string.Join(String.Empty, doc.Tags)}");
        Console.WriteLine();
    }
    Console.WriteLine();
    return responseWithFilter;
}

Метод SearchHybridVectorAndSemantic демонстрирует семантическое упорядочивание, которое повторно упорядочивает результаты на основе понимания языка.

public static async Task SearchHybridVectorAndSemantic(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        "historic hotel walk to restaurants and shopping",
        new SearchOptions
        {
            IncludeTotalCount = true,
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
            SemanticSearch = new SemanticSearchOptions
            {
                SemanticConfigurationName = "semantic-config"
            },
            QueryType = SearchQueryType.Semantic,
            Size = 5
        });

    Console.WriteLine($"Hybrid search results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine($"Category: {doc.Category}");
        Console.WriteLine();
    }
    Console.WriteLine();
}

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

  • Фактические результаты включают более подробные сведения, включая семантические субтитры и выделения. В этом кратком руководстве изменяются результаты для удобства чтения. Чтобы получить полную структуру ответа, используйте REST для выполнения запроса.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

В этом кратком руководстве вы используете клиентскую библиотеку Поиск с использованием ИИ Azure для Java для создания, загрузки и запроса векторного индекса . Клиентская библиотека Java предоставляет абстракцию над REST API-интерфейсами для операций с индексами.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-java-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-java-samples/quickstart-vector-search
    
  3. В src/main/resources/application.properties замените значение заполнителя azure.search.endpoint на URL-адрес, полученный из метода Get endpoint.

  4. Установите зависимости.

    mvn clean dependency:copy-dependencies
    

    По завершении сборки должна появиться target/dependency папка в каталоге проекта.

  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    

Запустите код

  1. Создайте векторный индекс.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.CreateIndex"
    
  2. Загрузите документы, содержащие предварительно вычисленные эмбеддинги.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.UploadDocuments"
    
  3. Запустите запрос векторного поиска.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingle"
    
  4. (Необязательно) Запустите дополнительные варианты запроса.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingleWithFilter"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingleWithFilterGeo"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchHybrid"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSemanticHybrid"
    

Выходные данные

Вывод CreateIndex.java показывает имя индекса и подтверждение.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using Azure Search index: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

Выходные данные UploadDocuments.java показывают состояние успешности для каждого индексированного документа.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
Waiting for indexing... Current count: 0
All documents indexed successfully.

Выходные данные отображают результаты векторного SearchSingle.java поиска, ранжированные по оценке сходства.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

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

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. Следующий код в CreateIndex.java создает схему индекса, включая векторное поле DescriptionVector.

// Define fields
List<SearchField> fields = Arrays.asList(
    new SearchField("HotelId", SearchFieldDataType.STRING)
        .setKey(true)
        .setFilterable(true),
    new SearchField("HotelName", SearchFieldDataType.STRING)
        .setSortable(true)
        .setSearchable(true),
    new SearchField("Description", SearchFieldDataType.STRING)
        .setSearchable(true),
    new SearchField("DescriptionVector",
        SearchFieldDataType.collection(SearchFieldDataType.SINGLE))
        .setSearchable(true)
        .setVectorSearchDimensions(1536)
        .setVectorSearchProfileName("my-vector-profile"),
    new SearchField("Category", SearchFieldDataType.STRING)
        .setSortable(true)
        .setFilterable(true)
        .setFacetable(true)
        .setSearchable(true),
    new SearchField("Tags", SearchFieldDataType.collection(
        SearchFieldDataType.STRING))
        .setSearchable(true)
        .setFilterable(true)
        .setFacetable(true),
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
);

var searchIndex = new SearchIndex(indexName, fields);

// Define vector search configuration
var hnswParams = new HnswParameters()
    .setM(16)
    .setEfConstruction(200)
    .setEfSearch(128);
var hnsw = new HnswAlgorithmConfiguration("hnsw-vector-config");
hnsw.setParameters(hnswParams);

var vectorProfile = new VectorSearchProfile(
    "my-vector-profile",
    "hnsw-vector-config");
var vectorSearch = new VectorSearch()
    .setAlgorithms(Arrays.asList(hnsw))
    .setProfiles(Arrays.asList(vectorProfile));
searchIndex.setVectorSearch(vectorSearch);

// Define semantic configuration
var prioritizedFields = new SemanticPrioritizedFields()
    .setTitleField(new SemanticField("HotelName"))
    .setContentFields(Arrays.asList(new SemanticField("Description")))
    .setKeywordsFields(Arrays.asList(new SemanticField("Category")));
var semanticConfig = new SemanticConfiguration(
    "semantic-config",
    prioritizedFields);
var semanticSearch = new SemanticSearch()
    .setConfigurations(Arrays.asList(semanticConfig));
searchIndex.setSemanticSearch(semanticSearch);

// Define suggesters
var suggester = new SearchSuggester("sg", Arrays.asList("HotelName"));
searchIndex.setSuggesters(Arrays.asList(suggester));

// Create the search index
SearchIndex result = searchIndexClient.createOrUpdateIndex(searchIndex);

Ключевые моменты:

Отправка документов в индекс

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

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

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

// Documents contain hotel data with 1536-dimension vectors for DescriptionVector
static final List<Map<String, Object>> DOCUMENTS = Arrays.asList(
    new HashMap<>() {{
        put("@search.action", "mergeOrUpload");
        put("HotelId", "1");
        put("HotelName", "Stay-Kay City Hotel");
        put("Description", "This classic hotel is fully-refurbished...");
        put("DescriptionVector", Arrays.asList(/* 1536 float values */));
        put("Category", "Boutique");
        put("Tags", Arrays.asList("view", "air conditioning", "concierge"));
        // Additional fields...
    }}
    // Additional hotel documents
);

// Upload documents to the index
IndexDocumentsResult result = searchClient.uploadDocuments(DOCUMENTS);
for (IndexingResult r : result.getResults()) {
    System.out.println("Key: %s, Succeeded: %s".formatted(r.getKey(), r.isSucceeded()));
}

Код взаимодействует с определенным индексом поиска, размещенным в службе Поиск с использованием ИИ Azure, через SearchClient, который является основным объектом, предоставляемым пакетом azure-search-documents. Элемент SearchClient предоставляет доступ к таким операциям, как:

  • Прием данных: uploadDocuments, mergeDocumentsdeleteDocuments

  • Операции поиска: search, autocompletesuggest

Запрос индекса

Запросы в файлах поиска демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

SearchSingle.java демонстрирует базовый сценарий, в котором требуется найти описания документов, которые тесно соответствуют строке векторного запроса. VectorizedQuery настраивает векторный поиск:

  • setKNearestNeighborsCount() ограничивает количество возвращаемых результатов на основе сходства векторов.
  • setFields() задает поле вектора для поиска.
var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

var searchOptions = new SearchOptions()
    .setTop(7)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search("*", searchOptions, Context.NONE);

for (SearchResult result : results) {
    SearchDocument document = result.getDocument(SearchDocument.class);
    System.out.println("HotelId: %s, HotelName: %s, Score: %s".formatted(
        document.get("HotelId"), document.get("HotelName"), result.getScore()));
}

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. SearchSingleWithFilter.java фильтры в Tags поле для исключения всех отелей, которые не предоставляют бесплатный Wi-Fi.

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

// Add filter for "free wifi" tag
var searchOptions = new SearchOptions()
    .setTop(7)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setFilter("Tags/any(tag: tag eq 'free wifi')")
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search("*", searchOptions, Context.NONE);

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. SearchSingleWithGeoFilter.java указывает географическую точку (Вашингтон, округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. Метод setFilterMode, вызываемый на VectorSearchOptions, определяет, когда выполняется фильтр. В этом случае POST_FILTER выполняет фильтр после векторного поиска.

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Category", "Description",
               "Address/City", "Address/StateProvince")
    .setFacets("Address/StateProvince")
    .setFilter("geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300")
    .setVectorSearchOptions(vectorSearchOptions);

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. SearchHybrid.java выполняет оба типа запросов одновременно, а затем использует Reciprocal Rank Fusion (RRF) для объединения результатов в единую систему ранжирования. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setVectorSearchOptions(vectorSearchOptions);

// Pass both text query and vector search options
var results = searchClient.search(
    "historic hotel walk to restaurants and shopping",
    searchOptions, Context.NONE);

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

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

SemanticSearchOptions semanticSearchOptions = new SemanticSearchOptions()
    .setSemanticConfigurationName("semantic-config");

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Category", "Description")
    .setQueryType(QueryType.SEMANTIC)
    .setSemanticSearchOptions(semanticSearchOptions)
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search(
    "historic hotel walk to restaurants and shopping",
    searchOptions, Context.NONE);

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

  • Фактические результаты включают более подробные сведения, включая семантические субтитры и выделения. В этом кратком руководстве изменяются результаты для удобства чтения. Чтобы получить полную структуру ответа, используйте REST для выполнения запроса.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

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

mvn compile exec:java "-Dexec.mainClass=com.example.search.DeleteIndex"

В этом кратком руководстве вы используете клиентскую библиотеку Поиск с использованием ИИ Azure для JavaScript для создания, загрузки и запроса векторного индекса. Клиентская библиотека JavaScript предоставляет абстракцию по REST API для операций с индексами.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-javascript-samples/quickstart-vector-js
    
  3. В sample.env замените значение заполнителя AZURE_SEARCH_ENDPOINT на URL-адрес, полученный из метода Get endpoint.

  4. Переименуйте sample.env в .env.

    mv sample.env .env
    
  5. Установите зависимости.

    npm install
    

    После завершения установки в каталоге project должна появиться папка node_modules.

  6. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    

Запустите код

  1. Создайте векторный индекс.

    node -r dotenv/config src/createIndex.js
    
  2. Загрузите документы, содержащие предварительно вычисленные эмбеддинги.

    node -r dotenv/config src/uploadDocuments.js
    
  3. Запустите запрос векторного поиска.

    node -r dotenv/config src/searchSingle.js
    
  4. (Необязательно) Запустите дополнительные варианты запроса.

    node -r dotenv/config src/searchSingleWithFilter.js
    node -r dotenv/config src/searchSingleWithFilterGeo.js
    node -r dotenv/config src/searchHybrid.js
    node -r dotenv/config src/searchSemanticHybrid.js
    

Выходные данные

Вывод createIndex.js показывает имя индекса и подтверждение.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using Azure Search index: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

Выходные данные uploadDocuments.js показывают состояние успешности для каждого индексированного документа.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
Waiting for indexing... Current count: 0
All documents indexed successfully.

Выходные данные отображают результаты векторного searchSingle.js поиска, ранжированные по оценке сходства.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

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

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. Следующий код в createIndex.js создает схему индекса, включая векторное поле DescriptionVector.

const searchFields = [
    { name: "HotelId", type: "Edm.String", key: true, sortable: true, filterable: true, facetable: true },
    { name: "HotelName", type: "Edm.String", searchable: true, filterable: true },
    { name: "Description", type: "Edm.String", searchable: true },
    {
        name: "DescriptionVector",
        type: "Collection(Edm.Single)",
        searchable: true,
        vectorSearchDimensions: 1536,
        vectorSearchProfileName: "vector-profile"
    },
    { name: "Category", type: "Edm.String", filterable: true, facetable: true },
    { name: "Tags", type: "Collection(Edm.String)", filterable: true },
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const vectorSearch = {
    profiles: [
        {
            name: "vector-profile",
            algorithmConfigurationName: "vector-search-algorithm"
        }
    ],
    algorithms: [
        {
            name: "vector-search-algorithm",
            kind: "hnsw",
            parameters: { m: 4, efConstruction: 400, efSearch: 1000, metric: "cosine" }
        }
    ]
};

const semanticSearch = {
    configurations: [
        {
            name: "semantic-config",
            prioritizedFields: {
                contentFields: [{ name: "Description" }],
                keywordsFields: [{ name: "Category" }],
                titleField: { name: "HotelName" }
            }
        }
    ]
};

const searchIndex = {
    name: indexName,
    fields: searchFields,
    vectorSearch: vectorSearch,
    semanticSearch: semanticSearch,
    suggesters: [{ name: "sg", searchMode: "analyzingInfixMatching", sourceFields: ["HotelName"] }]
};

const result = await indexClient.createOrUpdateIndex(searchIndex);

Ключевые моменты:

Отправка документов в индекс

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

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

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

const DOCUMENTS = [
    // Array of hotel documents with embedded 1536-dimension vectors
    // Each document contains: HotelId, HotelName, Description, DescriptionVector,
    // Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const searchClient = new SearchClient(searchEndpoint, indexName, credential);

const result = await searchClient.uploadDocuments(DOCUMENTS);
for (const r of result.results) {
    console.log(`Key: ${r.key}, Succeeded: ${r.succeeded}`);
}

Код взаимодействует с определенным индексом поиска, размещенным в службе Поиск с использованием ИИ Azure, через SearchClient, который является основным объектом, предоставляемым пакетом @azure/search-documents. SearchClient предоставляет доступ к операциям индекса, таким как:

  • Прием данных: uploadDocuments, mergeDocumentsdeleteDocuments

  • Операции поиска: search, autocompletesuggest

Запрос индекса

Запросы в файлах поиска демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

searchSingle.js демонстрирует базовый сценарий, в котором требуется найти описания документов, которые тесно соответствуют строке векторного запроса. Объект vectorQuery настраивает векторный поиск:

  • kNearestNeighborsCount ограничивает количество возвращаемых результатов на основе сходства векторов.
  • fields задает поле вектора для поиска.
const vectorQuery = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    includeTotalCount: true,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results = await searchClient.search("*", searchOptions);

for await (const result of results.results) {
    const doc = result.document;
    console.log(`HotelId: ${doc.HotelId}, HotelName: ${doc.HotelName}, Score: ${result.score}`);
}

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. searchSingleWithFilter.js фильтры в Tags поле для исключения всех отелей, которые не предоставляют бесплатный Wi-Fi.

const searchOptions = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    includeTotalCount: true,
    filter: "Tags/any(tag: tag eq 'free wifi')", // Adding filter for "free wifi" tag
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results = await searchClient.search("*", searchOptions);

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. searchSingleWithGeoFilter.js указывает географическую точку (Вашингтон, округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. Свойство filterMode определяет, когда запускается фильтр. В этом случае postFilter выполняет фильтр после векторного поиска.

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"],
    facets: ["Address/StateProvince"],
    filter: "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. searchHybrid.js выполняет оба типа запросов одновременно, а затем использует Reciprocal Rank Fusion (RRF) для объединения результатов в единую систему ранжирования. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

const vectorQuery = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

// Use search text for keyword search (hybrid search = vector + keyword)
const searchText = "historic hotel walk to restaurants and shopping";
const results = await searchClient.search(searchText, searchOptions);

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

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description"],
    queryType: "semantic",
    semanticSearchOptions: {
        configurationName: "semantic-config"
    },
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const searchText = "historic hotel walk to restaurants and shopping";
const results = await searchClient.search(searchText, searchOptions);

for await (const result of results.results) {
    console.log(`Score: ${result.score}, Re-ranker Score: ${result.rerankerScore}`);
}

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

  • Фактические результаты включают более подробные сведения, включая семантические субтитры и выделения. В этом кратком руководстве изменяются результаты для удобства чтения. Чтобы получить полную структуру ответа, используйте REST для выполнения запроса.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

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

node -r dotenv/config src/deleteIndex.js

В данном руководстве быстрого старта используется клиентская библиотека Поиск с использованием ИИ Azure для Python для создания, загрузки и запроса векторного индекса. Клиентская библиотека Python предоставляет абстракцию по REST API для операций с индексами.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-python-samples
    
  2. Перейдите в папку быстрого запуска и откройте ее в Visual Studio Code.

    cd azure-search-python-samples/Quickstart-Vector-Search
    code .
    
  3. В sample.env замените значение заполнителя AZURE_SEARCH_ENDPOINT на URL-адрес, полученный из метода Get endpoint.

  4. Переименуйте sample.env в .env.

    mv sample.env .env
    
  5. Откройте vector-search-quickstart.ipynb.

  6. Нажмите клавиши CTRL+SHIFT+P, выберите записную книжку: выберите ядро записной книжки и следуйте инструкциям по созданию виртуальной среды. Выберите requirements.txt для зависимостей.

    По завершении вы увидите папку .venv в каталоге проекта.

  7. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    

Запустите код

  1. Запустите ячейку Install packages and set variables, чтобы установить необходимые пакеты и загрузить переменные среды.

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

Выходные данные

Каждая ячейка кода выводит выходные данные в записную книжку. В следующем примере приведены выходные данные, в которых показаны результаты поиска векторов Single vector search, ранжированные по оценке сходства.

Total results: 7
- HotelId: 48, HotelName: Nordick's Valley Motel, Category: Boutique
- HotelId: 13, HotelName: Luxury Lion Resort, Category: Luxury
- HotelId: 4, HotelName: Sublime Palace Hotel, Category: Boutique
- HotelId: 49, HotelName: Swirling Currents Hotel, Category: Suite
- HotelId: 2, HotelName: Old Century Hotel, Category: Boutique

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

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

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. Ячейка Create an index в записной книжке создает схему индекса, включая поле DescriptionVectorвектора.

fields = [
    SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True, filterable=True),
    SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
    SearchableField(name="Description", type=SearchFieldDataType.String),
    SearchField(
        name="DescriptionVector",
        type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
        searchable=True,
        vector_search_dimensions=1536,
        vector_search_profile_name="my-vector-profile"
    ),
    SearchableField(name="Category", type=SearchFieldDataType.String, sortable=True, filterable=True, facetable=True),
    SearchField(name="Tags", type=SearchFieldDataType.Collection(SearchFieldDataType.String), searchable=True, filterable=True, facetable=True),
    # Additional fields omitted for brevity
]

Ключевые моменты:

  • Вы определяете индекс, создав список полей. Каждое поле создается с помощью вспомогательного метода, который определяет тип поля и его параметры.

  • Этот конкретный индекс поддерживает несколько возможностей поиска:

  • Свойство vector_search_dimensions должно соответствовать выходному размеру модели внедрения. В этом кратком руководстве для сопоставления text-embedding-ada-002 модели используется 1 536 измерений.

  • Конфигурация VectorSearch определяет алгоритм приблизительного ближайшего соседа (ANN). Поддерживаемые алгоритмы включают иерархический навигационируемый малый мир (HNSW) и исчерпывающий K-ближайший сосед (KNN). Дополнительные сведения см. в разделе "Релевантность" в векторном поиске.

Отправка документов в индекс

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

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

Ячейки Create documents payload и Upload the documents загружают документы в индекс.

documents = [
    # List of hotel documents with embedded 1536-dimension vectors
    # Each document contains: HotelId, HotelName, Description, DescriptionVector,
    # Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
]

search_client = SearchClient(
    endpoint=search_endpoint,
    index_name=index_name,
    credential=credential
)

result = search_client.upload_documents(documents=documents)
for r in result:
    print(f"Key: {r.key}, Succeeded: {r.succeeded}, ErrorMessage: {r.error_message}")

Код взаимодействует с определенным индексом поиска, размещенным в службе Поиск с использованием ИИ Azure, через SearchClient, который является основным объектом, предоставляемым пакетом azure-search-documents. SearchClient предоставляет доступ к операциям индекса, таким как:

  • Прием данных: upload_documents(), merge_documents()delete_documents()

  • Операции поиска: search(), autocomplete()suggest()

Запрос индекса

Запросы в записной книжке демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

Ячейка Single vector search демонстрирует базовый сценарий, в котором необходимо найти описания документов, которые тесно соответствуют строке векторного запроса. VectorizedQuery настраивает векторный поиск:

  • k_nearest_neighbors ограничивает количество возвращаемых результатов на основе сходства векторов.
  • fields задает поле вектора для поиска.
vector_query = VectorizedQuery(
    vector=vector,
    k_nearest_neighbors=5,
    fields="DescriptionVector",
    kind="vector",
    exhaustive=True
)

results = search_client.search(
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=5,
    include_total_count=True
)

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. Ячейки Single vector search with filter фильтруют по полю Tags, чтобы исключить отели, которые не предоставляют бесплатный Wi-Fi.

# vector_query omitted for brevity

results = search_client.search(
    vector_queries=[vector_query],
    filter="Tags/any(tag: tag eq 'free wifi')",
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=7,
    include_total_count=True
)

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. Ячейка Single vector search with geo filter указывает географическую точку (Вашингтон округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. Параметр vector_filter_mode определяет, когда выполняется фильтр. В этом случае postFilter выполняет фильтр после векторного поиска.

# vector_query omitted for brevity

results = search_client.search(
    include_total_count=True,
    top=5,
    select=[
        "HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"
    ],
    facets=["Address/StateProvince"],
    filter="geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vector_filter_mode="postFilter",
    vector_queries=[vector_query]
)

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. Ячейка Hybrid search выполняет оба типа запросов одновременно, а затем использует взаимное объединение результатов в единый рейтинг. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

# vector_query omitted for brevity

results = search_client.search(
    search_text="historic hotel walk to restaurants and shopping",
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=5,
    include_total_count=True
)

Ячейка Semantic hybrid search демонстрирует семантическое ранжирование, которое переставляет результаты на основе языкового понимания.

# vector_query omitted for brevity

results = search_client.search(
    search_text="historic hotel walk to restaurants and shopping",
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Category", "Description"],
    query_type="semantic",
    semantic_configuration_name="my-semantic-config",
    top=5,
    include_total_count=True
)

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

  • Фактические результаты включают более подробные сведения, включая семантические субтитры и выделения. В этом кратком руководстве изменяются результаты для удобства чтения. Чтобы получить полную структуру ответа, используйте REST для выполнения запроса.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

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

В этом кратком руководстве вы используете библиотеку клиента Поиск с использованием ИИ Azure для JavaScript (совместимую с TypeScript) для создания, загрузки и запроса векторного индекса. Клиентская библиотека JavaScript предоставляет абстракцию по REST API для операций с индексами.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-javascript-samples/quickstart-vector-ts
    
  3. В sample.env замените значение заполнителя AZURE_SEARCH_ENDPOINT на URL-адрес, полученный из метода Get endpoint.

  4. Переименуйте sample.env в .env.

    mv sample.env .env
    
  5. Установите зависимости.

    npm install
    

    После завершения установки в каталоге project должна появиться папка node_modules.

  6. Скомпилируйте файлы TypeScript в JavaScript.

    npm run build
    
  7. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    

Запустите код

  1. Создайте векторный индекс.

    node -r dotenv/config dist/createIndex.js
    
  2. Загрузите документы, содержащие предварительно вычисленные эмбеддинги.

    node -r dotenv/config dist/uploadDocuments.js
    
  3. Запустите запрос векторного поиска.

    node -r dotenv/config dist/searchSingle.js
    
  4. (Необязательно) Запустите дополнительные варианты запроса.

    node -r dotenv/config dist/searchSingleWithFilter.js
    node -r dotenv/config dist/searchSingleWithFilterGeo.js
    node -r dotenv/config dist/searchHybrid.js
    node -r dotenv/config dist/searchSemanticHybrid.js
    

    Примечание.

    Эти команды выполняют скомпилированные .js файлы из dist папки. Код TypeScript должен быть транспилирован в JavaScript, прежде чем Node.js его может выполнить, поэтому ранее вы выполнили npm run build.

Выходные данные

Вывод createIndex.ts показывает имя индекса и подтверждение.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using index name: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

Выходные данные uploadDocuments.ts показывают состояние успешности для каждого индексированного документа.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
All documents indexed successfully.

Выходные данные отображают результаты векторного searchSingle.ts поиска, ранжированные по оценке сходства.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

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

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. Следующий код в createIndex.ts создает схему индекса, включая векторное поле DescriptionVector.

const searchFields: SearchField[] = [
    { name: "HotelId", type: "Edm.String", key: true, sortable: true, filterable: true, facetable: true },
    { name: "HotelName", type: "Edm.String", searchable: true, filterable: true },
    { name: "Description", type: "Edm.String", searchable: true },
    {
        name: "DescriptionVector",
        type: "Collection(Edm.Single)",
        searchable: true,
        vectorSearchDimensions: 1536,
        vectorSearchProfileName: "vector-profile"
    },
    { name: "Category", type: "Edm.String", filterable: true, facetable: true },
    { name: "Tags", type: "Collection(Edm.String)", filterable: true },
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const vectorSearch: VectorSearch = {
    profiles: [
        {
            name: "vector-profile",
            algorithmConfigurationName: "vector-search-algorithm"
        }
    ],
    algorithms: [
        {
            name: "vector-search-algorithm",
            kind: "hnsw",
            parameters: { m: 4, efConstruction: 400, efSearch: 1000, metric: "cosine" }
        }
    ]
};

const semanticSearch: SemanticSearch = {
    configurations: [
        {
            name: "semantic-config",
            prioritizedFields: {
                contentFields: [{ name: "Description" }],
                keywordsFields: [{ name: "Category" }],
                titleField: { name: "HotelName" }
            }
        }
    ]
};

const searchIndex: SearchIndex = {
    name: indexName,
    fields: searchFields,
    vectorSearch: vectorSearch,
    semanticSearch: semanticSearch,
    suggesters: [{ name: "sg", searchMode: "analyzingInfixMatching", sourceFields: ["HotelName"] }]
};

const result = await indexClient.createOrUpdateIndex(searchIndex);

Ключевые моменты:

Отправка документов в индекс

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

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

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

const DOCUMENTS = [
    // Array of hotel documents with embedded 1536-dimension vectors
    // Each document contains: HotelId, HotelName, Description, DescriptionVector,
    // Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const searchClient = new SearchClient(searchEndpoint, indexName, credential);

const result = await searchClient.uploadDocuments(DOCUMENTS);
for (const r of result.results) {
    console.log(`Key: ${r.key}, Succeeded: ${r.succeeded}`);
}

Код взаимодействует с определенным индексом поиска, размещенным в службе Поиск с использованием ИИ Azure, через SearchClient, который является основным объектом, предоставляемым пакетом @azure/search-documents. SearchClient предоставляет доступ к операциям индекса, таким как:

  • Прием данных: uploadDocuments, mergeDocumentsdeleteDocuments

  • Операции поиска: search, autocompletesuggest

Запрос индекса

Запросы в файлах поиска демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

searchSingle.ts демонстрирует базовый сценарий, в котором требуется найти описания документов, которые тесно соответствуют строке векторного запроса. Объект VectorQuery настраивает векторный поиск:

  • kNearestNeighborsCount ограничивает количество возвращаемых результатов на основе сходства векторов.
  • fields задает поле вектора для поиска.
const vectorQuery: VectorQuery<HotelDocument> = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions: SearchOptions<HotelDocument> = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    includeTotalCount: true,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results: SearchDocumentsResult<HotelDocument> = await searchClient.search("*", searchOptions);

for await (const result of results.results) {
    const doc = result.document;
    console.log(`HotelId: ${doc.HotelId}, HotelName: ${doc.HotelName}, Score: ${result.score}`);
}

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. searchSingleWithFilter.ts фильтры в Tags поле для исключения всех отелей, которые не предоставляют бесплатный Wi-Fi.

const searchOptions: SearchOptions<HotelDocument> = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    includeTotalCount: true,
    filter: "Tags/any(tag: tag eq 'free wifi')", // Adding filter for "free wifi" tag
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results: SearchDocumentsResult<HotelDocument> = await searchClient.search("*", searchOptions);

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. searchSingleWithGeoFilter.ts указывает географическую точку (Вашингтон, округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. Свойство filterMode определяет, когда запускается фильтр. В этом случае postFilter выполняет фильтр после векторного поиска.

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"] as const,
    facets: ["Address/StateProvince"],
    filter: "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. searchHybrid.ts выполняет оба типа запросов одновременно, а затем использует Reciprocal Rank Fusion (RRF) для объединения результатов в единую систему ранжирования. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

const vectorQuery: VectorQuery<HotelDocument> = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

// Use search text for keyword search (hybrid search = vector + keyword)
const searchText = "historic hotel walk to restaurants and shopping";
const results: SearchDocumentsResult<HotelDocument> = await searchClient.search(searchText, searchOptions);

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

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description"] as const,
    queryType: "semantic" as const,
    semanticSearchOptions: {
        configurationName: "semantic-config"
    },
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const searchText = "historic hotel walk to restaurants and shopping";
const results: SearchDocumentsResult<HotelDocument> = await searchClient.search(searchText, searchOptions);

for await (const result of results.results) {
    console.log(`Score: ${result.score}, Re-ranker Score: ${result.rerankerScore}`);
}

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

  • Фактические результаты включают более подробные сведения, включая семантические субтитры и выделения. В этом кратком руководстве изменяются результаты для удобства чтения. Чтобы получить полную структуру ответа, используйте REST для выполнения запроса.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

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

npm run build && node -r dotenv/config dist/deleteIndex.js

В этом кратком руководстве вы используете REST API Поиск с использованием ИИ Azure для создания, загрузки и запроса векторного индекса.

В Поиск с использованием ИИ Azure векторный индекс содержит схему индекса, которая определяет поля вектора и невектора, конфигурацию векторного поиска для алгоритмов, создающих пространство внедрения, и параметры определений векторных полей, которые вычисляются во время запроса. Индексы— создание или обновление (REST API) создает векторный индекс.

Подсказка

Предварительные условия

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

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Поиск с использованием ИИ Azure. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Поиск с использованием ИИ Azure имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

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

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-rest-samples
    
  2. Перейдите в папку быстрого запуска и откройте ее в Visual Studio Code.

    cd azure-search-rest-samples/Quickstart-vectors
    code .
    
  3. В az-search-quickstart-vectors.rest замените значение заполнителя @baseUrl на URL-адрес, полученный из метода Get endpoint.

  4. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Поиск с использованием ИИ Azure.

    az login
    
  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID создайте маркер доступа.

    az account get-access-token --scope https://search.azure.com/.default --query accessToken -o tsv
    
  6. Замените значение заполнителя @token токеном из предыдущего шага.

Запустите код

  1. В разделе ### List existing indexes by nameвыберите "Отправить запрос" , чтобы проверить подключение.

    Ответ должен отображаться в соседней области. Если у вас уже есть индексы, они будут перечислены. В противном случае список пуст. Если http-код имеет значение 200 OK, вы готовы продолжить работу.

  2. Отправка оставшихся запросов последовательно для создания векторного индекса, отправки документов и выполнения различных типов векторных запросов.

Выходные данные

Каждый запрос запроса возвращает результаты JSON. Следующий пример — это выходные данные ### Run a single vector query запроса, в котором показаны векторные результаты поиска, ранжированные по оценке сходства.

{
  "@odata.count": 5,
  "value": [
    {
      "@search.score": 0.6605852,
      "HotelId": "48",
      "HotelName": "Nordick's Valley Motel",
      "Description": "Only 90 miles (about 2 hours) from the nation's capital and nearby most everything the historic valley has to offer. Hiking? Wine Tasting? Exploring the caverns? It's all nearby and we have specially priced packages to help make our B&B your home base for fun while visiting the valley.",
      "Category": "Boutique",
      "Tags": [
        "continental breakfast",
        "air conditioning",
        "free wifi"
      ]
    },
    {
      "@search.score": 0.6333684,
      "HotelId": "13",
      "HotelName": "Luxury Lion Resort",
      "Description": "Unmatched Luxury. Visit our downtown hotel to indulge in luxury accommodations. Moments from the stadium and transportation hubs, we feature the best in convenience and comfort.",
      "Category": "Luxury",
      "Tags": [
        "bar",
        "concierge",
        "restaurant"
      ]
    },
    {
      "@search.score": 0.605672,
      "HotelId": "4",
      "HotelName": "Sublime Palace Hotel",
      "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
      "Category": "Boutique",
      "Tags": [
        "concierge",
        "view",
        "air conditioning"
      ]
    },
    {
      "@search.score": 0.6026341,
      "HotelId": "49",
      "HotelName": "Swirling Currents Hotel",
      "Description": "Spacious rooms, glamorous suites and residences, rooftop pool, walking access to shopping, dining, entertainment and the city center. Each room comes equipped with a microwave, a coffee maker and a minifridge. In-room entertainment includes complimentary W-Fi and flat-screen TVs.",
      "Category": "Suite",
      "Tags": [
        "air conditioning",
        "laundry service",
        "24-hour front desk service"
      ]
    },
    {
      "@search.score": 0.57902366,
      "HotelId": "2",
      "HotelName": "Old Century Hotel",
      "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
      "Category": "Boutique",
      "Tags": [
        "pool",
        "free wifi",
        "air conditioning",
        "concierge"
      ]
    }
  ]
}

Общие сведения о коде

Примечание.

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

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание векторного индекса
  2. Отправка документов в индекс
  3. Запрос индекса

Создание векторного индекса

Перед добавлением содержимого в Поиск с использованием ИИ Azure необходимо создать индекс, чтобы определить, как хранится и структурировано содержимое. В этом кратком руководстве вызывается индексы (создание) (REST API) для создания векторного индекса с именем hotels-vector-quickstart и его структуры физических данных в вашей службе поиска.

Схема индекса организована вокруг содержимого отеля. Пример данных состоит из векторных и невекторных описаний вымышленных отелей. В следующем фрагменте показана ключевая структура ### Create a new index запроса.

PUT {{baseUrl}}/indexes/hotels-vector-quickstart?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "name": "hotels-vector-quickstart",
    "fields": [
        { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true },
        { "name": "HotelName", "type": "Edm.String", "searchable": true },
        { "name": "Description", "type": "Edm.String", "searchable": true },
        {
            "name": "DescriptionVector",
            "type": "Collection(Edm.Single)",
            "searchable": true,
            "dimensions": 1536,
            "vectorSearchProfile": "my-vector-profile"
        },
        { "name": "Category", "type": "Edm.String", "filterable": true, "facetable": true },
        { "name": "Tags", "type": "Collection(Edm.String)", "filterable": true, "facetable": true }
        // Additional fields omitted for brevity
    ],
    "vectorSearch": {
        "algorithms": [
            { "name": "hnsw-vector-config", "kind": "hnsw" }
        ],
        "profiles": [
            { "name": "my-vector-profile", "algorithm": "hnsw-vector-config" }
        ]
    },
    "semantic": {
        "configurations": [
            {
                "name": "semantic-config",
                "prioritizedFields": {
                    "titleField": { "fieldName": "HotelName" },
                    "prioritizedContentFields": [{ "fieldName": "Description" }]
                }
            }
        ]
    }
}

Ключевые моменты:

Отправка документов в индекс

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

В Поиск с использованием ИИ Azure документы служат как входными данными для индексирования, так и выходных данных для запросов. Для простоты в этом кратком руководстве приведены образцы документов отеля в виде встроенного JSON-кода. Однако в рабочих сценариях содержимое часто извлекается из подключенных источников данных и преобразуется в JSON с помощью индексаторов.

В этом кратком руководстве приводится вызов Документы - Индекс (REST API), чтобы добавить образцы документов для отеля в ваш индекс. В следующем фрагменте показана структура запроса ### Upload 7 documents.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/index?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is ideally located on the main commercial artery of the city...",
            "DescriptionVector": [-0.0347, 0.0289, ... ],  // 1536 floats
            "Category": "Boutique",
            "Tags": ["view", "air conditioning", "concierge"],
            "ParkingIncluded": false,
            "Rating": 3.60,
            "Address": { "City": "New York", "StateProvince": "NY" },
            "Location": { "type": "Point", "coordinates": [-73.975403, 40.760586] }
        }
        // Additional documents omitted for brevity
    ]
}

Ключевые моменты:

  • Каждый документ в массиве value представляет отель и содержит поля, соответствующие схеме индекса. Параметр @search.action задает операцию, выполняемую для каждого документа. В этом кратком руководстве используется инструмент mergeOrUpload, который добавляет документ, если он не существует, или обновляет его, если существует.

  • Документы в данных полезной нагрузки состоят из полей, определенных в схеме индекса.

Запрос индекса

Запросы в примере файла демонстрируют различные шаблоны поиска. Примеры векторных запросов основаны на двух строках:

  • Строка полнотекстового поиска: "historic hotel walk to restaurants and shopping"

  • Строка векторного запроса: "quintessential lodging near running trails, eateries, retail" (векторизованная в математическое представление)

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

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

Запрос ### Run a single vector query демонстрирует базовый сценарий, в котором необходимо найти описания документов, которые тесно соответствуют строке векторного запроса. Массив vectorQueries настраивает векторный поиск:

  • k ограничивает количество возвращаемых результатов на основе сходства векторов.
  • fields задает поле вектора для поиска.
POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Description, Category, Tags",
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector of "quintessential lodging near running trails, eateries, retail"
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Поиск одного вектора с фильтром

В Поиск с использованием ИИ Azure фильтры применяются к полям невектора в индексе. Запрос ### Run a vector query with a filter фильтрует поле Tags , чтобы отфильтровать все отели, которые не предоставляют бесплатный Wi-Fi.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Description, Category, Tags",
    "filter": "Tags/any(tag: tag eq 'free wifi')",
    "vectorFilterMode": "postFilter",
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 7,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Поиск одного вектора с помощью геофильтра

Вы можете указать геопространственную фильтрацию , чтобы ограничить результаты определенной географической областью. Запрос ### Run a vector query with a geo filter указывает географическую точку (Вашингтон округ Колумбия, используя координаты долготы и широты) и возвращает отели в пределах 300 километров. Параметр vectorFilterMode определяет, когда выполняется фильтр. В этом случае postFilter выполняет фильтр после векторного поиска.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Address/City, Address/StateProvince, Description",
    "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    "vectorFilterMode": "postFilter",
    "top": 5,
    "facets": [ "Address/StateProvince"],
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Гибридный поиск объединяет полнотекстовые и векторные запросы в одном запросе. Запрос ### Run a hybrid query выполняет оба типа запросов одновременно, а затем использует взаимное ранжирование Fusion (RRF) для объединения результатов в единый рейтинг. RRF использует инверсию ранжирований результатов из каждого результирующего набора для создания объединенного ранжирования. Обратите внимание, что оценки гибридного поиска равномерно меньше, чем оценки с одним запросом.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "top": 5,
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Запрос ### Run a hybrid query with semantic reranking демонстрирует семантическое ранжирование, которое изменяет порядок результатов на основе понимания языка.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelId, HotelName, Category, Description",
    "queryType": "semantic",
    "semanticConfiguration": "semantic-config",
    "top": 5,
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 7,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Сравните эти результаты с результатами гибридного поиска из предыдущего запроса. Без семантической переоценки, Sublime Palace Hotel занимает первое место, так как Reciprocal Rank Fusion (RRF) объединяет текстовые и векторные оценки, чтобы получить объединенный результат. После семантического ранжирования Swirling Currents Hotel переходит на первое место.

Семантический рангировщик использует модели машинного понимания для оценки того, насколько хорошо каждый результат соответствует намерению запроса. Описание "walking access to shopping, dining, entertainment and the city center" отеля Swirling Currents, которое тесно соответствует поисковому запросу "walk to restaurants and shopping". Это семантическое совпадение для мест для еды и шопинга поблизости поднимает его над Sublime Palace Hotel, который не подчеркивает удобства в шаговой доступности в своем описании.

Ключевые моменты:

  • В гибридном поиске можно интегрировать векторный поиск с полнотекстовый поиск по ключевым словам. Фильтры и семантический ранжирование применяются только к текстовому содержимому, а не к векторам.

Очистите ресурсы

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

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

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

  • Векторный поиск в Поиск с использованием ИИ Azure
  • azure-search-vector-samples GitHub репозиторий