Quickstart: Semantic ranking with .NET or Python

In Azure AI Search, semantic ranking is query-side functionality that uses machine reading comprehension from Microsoft to rescore search results, promoting the most semantically relevant matches to the top of the list. Depending on the content and the query, semantic ranking can significantly improve search relevance, with minimal work for the developer.

This quickstart walks you through the index and query modifications that invoke semantic ranker.

Note

For an Azure AI Search solution example with ChatGPT interaction, see this demo or this accelerator.

Prerequisites

  • An Azure account with an active subscription. You can create an account for free.

  • An Azure AI Search resource, at Basic tier or higher, with semantic ranker enabled.

  • An API key and search service endpoint. Sign in to the Azure portal and find your search service.

    In Overview, copy the URL and save it for a later step. An example endpoint might look like https://mydemo.search.windows.net.

    In Keys, copy and save an admin key for full rights to create and delete objects. There are two interchangeable primary and secondary keys. Choose either one.

    Screenshot showing where to find your search service's HTTP endpoint and access key.

Add semantic ranking

To use semantic ranker, add a semantic configuration to a search index, and add parameters to a query. If you have an existing index, you can make these changes without having to reindex your content because there's no impact on the structure of your searchable content.

  • A semantic configuration sets a priority order for fields that contribute a title, keywords, and content used in semantic reranking. Field prioritization allows for faster processing.

  • Queries that invoke semantic ranker include parameters for query type and whether captions and answers are returned. You can add these parameters to your existing query logic. There's no conflict with other parameters.

Build a console application by using the Azure.Search.Documents client library to add semantic ranking to an existing search index.

Alternatively, you can download the source code to start with a finished project.

Set up your environment

  1. Start Visual Studio and create a new project for a console app.

  2. In Tools > NuGet Package Manager, select Manage NuGet Packages for Solution....

  3. Select Browse.

  4. Search for the Azure.Search.Documents package and select the latest stable version.

  5. Select Install to add the assembly to your project and solution.

Create a search client

  1. In Program.cs, add the following using directives.

    using Azure;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    using Azure.Search.Documents.Models;
    
  2. Create two clients: SearchIndexClient creates the index, and SearchClient loads and queries an existing index.

    Both clients need the service endpoint and an admin API key for authentication with create/delete rights. However, the code builds out the URI for you, so specify only the search service name for the serviceName property. Don't include https:// or .search.windows.net.

     static void Main(string[] args)
     {
         string serviceName = "<YOUR-SEARCH-SERVICE-NAME>";
         string apiKey = "<YOUR-SEARCH-ADMIN-API-KEY>";
         string indexName = "hotels-quickstart";
    
    
         // Create a SearchIndexClient to send create/delete index commands
         Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
         AzureKeyCredential credential = new AzureKeyCredential(apiKey);
         SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
    
         // Create a SearchClient to load and query documents
         SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, credential);
         . . . 
     }
    

Create an index

Create or update an index schema to include a SemanticConfiguration. If you're updating an existing index, this modification doesn't require a reindexing because the structure of your documents is unchanged.

// Create hotels-quickstart index
private static void CreateIndex(string indexName, SearchIndexClient adminClient)
{

    FieldBuilder fieldBuilder = new FieldBuilder();
    var searchFields = fieldBuilder.Build(typeof(Hotel));

    var definition = new SearchIndex(indexName, searchFields);
    var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
    definition.Suggesters.Add(suggester);
    definition.SemanticSearch = new SemanticSearch
    {
        Configurations =
        {
            new SemanticConfiguration("my-semantic-config", new()
            {
                TitleField = new SemanticField("HotelName"),
                ContentFields =
                {
                    new SemanticField("Description"),
                    new SemanticField("Description_fr")
                },
                KeywordsFields =
                {
                    new SemanticField("Tags"),
                    new SemanticField("Category")
                }
            })
        }
    };

    adminClient.CreateOrUpdateIndex(definition);
}

The following code creates the index on your search service:

// Create index
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, adminClient);

SearchClient ingesterClient = adminClient.GetSearchClient(indexName);

Load documents

Azure AI Search searches over content stored in the service. The code for uploading documents is identical to the C# quickstart for full text search so we don't need to duplicate it here. You should have four hotels with names, addresses, and descriptions. Your solution should have types for Hotels and Addresses.

Search an index

Here's a query that invokes semantic ranker, with search options for specifying parameters:

Console.WriteLine("Example of a semantic query.");

options = new SearchOptions()
{
    QueryType = Azure.Search.Documents.Models.SearchQueryType.Semantic,
    SemanticSearch = new()
    {
        SemanticConfigurationName = "my-semantic-config",
        QueryCaption = new(QueryCaptionType.Extractive)
    }
};
options.Select.Add("HotelName");
options.Select.Add("Category");
options.Select.Add("Description");

// response = srchclient.Search<Hotel>("*", options);
response = srchclient.Search<Hotel>("what hotel has a good restaurant on site", options);
WriteDocuments(response);

For comparison, here are results from a query that uses the default BM25 ranking, based on term frequency and proximity. Given the query "what hotel has a good restaurant on site", the BM25 ranking algorithm returns matches in the order shown in this screenshot:

Screenshot showing matches ranked by BM25.

In contrast, when semantic ranking is applied to the same query ("what hotel has a good restaurant on site"), the results are reranked based on semantic relevance to the query. This time, the top result is the hotel with the restaurant, which aligns better to user expectations.

Screenshot showing matches ranked based on semantic ranking.

Run the program

Press F5 to rebuild the app and run the program in its entirety.

Output includes messages from Console.WriteLine, with the addition of query information and results.

Clean up resources

When you're working in your own subscription, it's a good idea at the end of a project to identify whether you still need the resources you created. Resources left running can cost you money. You can delete resources individually or delete the resource group to delete the entire set of resources.

You can find and manage resources in the portal, using the All resources or Resource groups link in the left-navigation pane.

Next steps

In this quickstart, you learned how to invoke semantic ranking on an existing index. We recommend trying semantic ranking on your own indexes as a next step. However, if you want to continue with demos, visit the following link.