AI Semantic Ranking

Azure AI Search Semantic Ranking uses Microsoft’s language understanding models to re-rank your search results by meaning, not just keyword matches. ExamineX makes it easy to enable this on your indexes and queries with just a few lines of code.

How it works

  1. Your normal search runs first (BM25 keyword scoring)
  2. The top 50 results are passed to a deep learning model that understands language
  3. Results are re-ranked by semantic relevance — the most meaningful matches float to the top
  4. Optionally, captions (relevant passages) and answers (direct responses to questions) are extracted

This is especially powerful for natural language queries like “hotels within walking distance to live music” where keyword matching alone falls short.

Requirements

Index Configuration

To enable semantic ranking, add one or more AzureSearchSemanticConfiguration entries to your index options. Each configuration is a named set of field-to-role mappings that tells the language model which fields contain your title, content, and keywords.

Single configuration

For most cases, a single configuration is all you need:

services.AddUmbraco(_env, _config)
    .AddBackOffice()
    .AddWebsite()
    .AddComposers()
    .AddExamineXAzureSearch(azureSearch =>
    {
        azureSearch.ConfigureIndex("ExternalIndex", options =>
        {
            options.SemanticConfigurations = new[]
            {
                new AzureSearchSemanticConfiguration
                {
                    TitleField = "nodeName",
                    ContentFields = new[] { "bodyText", "Description" },
                    KeywordsFields = new[] { "nodeTypeAlias" }
                }
            };
        });
    })
    .Build();

Multiple configurations

When your index contains different document shapes (e.g. articles and products), you can define a configuration for each. The first configuration becomes the index default:

options.SemanticConfigurations = new[]
{
    new AzureSearchSemanticConfiguration
    {
        ConfigurationName = "article-config",
        TitleField = "nodeName",
        ContentFields = new[] { "bodyText", "Description" }
    },
    new AzureSearchSemanticConfiguration
    {
        ConfigurationName = "product-config",
        TitleField = "productName",
        ContentFields = new[] { "productDescription" },
        KeywordsFields = new[] { "category", "tags" }
    }
};

At query time, use SemanticSearchQueryOptions.ConfigurationName to select which configuration to use. If not specified, the default (first) configuration is used.

Property Description Default
ConfigurationName Name for this semantic configuration. Required when using multiple configurations. "default"
TitleField The field representing the document title null
ContentFields Fields containing the main content (order matters — most important first) Empty
KeywordsFields Fields containing keywords/tags Empty

Tips:

  • ContentFields are the most important — they should contain your richest, most descriptive text
  • You can specify multiple content and keyword fields, prioritized by array order
  • The TitleField is optional but recommended for best results
  • Field names should match your Examine field definitions — ExamineX handles any necessary name formatting automatically

Querying with Semantic Ranking

Once your index has a semantic configuration, you can enable semantic ranking on any query by passing AzureSearchQueryOptions with SemanticSearchQueryOptions:

The simplest usage — your search text is used for both the initial BM25 keyword search and the semantic re-ranking:

var searcher = index.Searcher;

var results = searcher.Search("hotels near the beach", new AzureSearchQueryOptions(
    new SemanticSearchQueryOptions
    {
        EnableCaptions = true
    }));

Query builder

When using the query builder, your Examine query uses Lucene syntax which isn’t ideal input for the language model. In this case, set SemanticQuery to provide a plain-text natural language version of the query for the semantic model:

var results = searcher.CreateQuery("content")
    .Field("bodyText", "beach hotel")
    .Execute(new AzureSearchQueryOptions(
        new SemanticSearchQueryOptions
        {
            SemanticQuery = "beach hotel with ocean views",
            EnableCaptions = true,
            EnableAnswers = true
        }));

SemanticSearchQueryOptions

Property Description Default
ConfigurationName Which semantic configuration to use. Required when using multiple configurations. If not set, the index default (first) configuration is used. Uses the index default
SemanticQuery An optional plain-text query for the semantic model. When omitted, the search text is used for both the keyword search and semantic re-ranking. Recommended when using the query builder, since Lucene syntax is poor input for language understanding. Uses the search text
EnableCaptions Extract the most relevant passages from each result false
HighlightCaptions Apply emphasis tags to caption highlights true
EnableAnswers Extract direct answers to question-like queries false

Working with Results

Reranker Score

When semantic ranking is active, each result includes a reranker score (0–4 scale) indicating semantic relevance. Results are automatically ordered by this score. The original BM25 score remains available via ISearchResult.Score.

foreach (var result in results)
{
    // Original BM25 score
    var bm25Score = result.Score;

    // Semantic reranker score (0-4, higher = more relevant)
    if (result.Values.ContainsKey(AzureSearchFieldNames.SemanticRerankerScore))
    {
        var rerankerScore = double.Parse(result[AzureSearchFieldNames.SemanticRerankerScore]);
    }
}

Captions

Captions are the most relevant passages extracted from your content fields. They’re available when EnableCaptions = true:

foreach (var result in results)
{
    if (result.Values.ContainsKey(AzureSearchFieldNames.SemanticCaption))
    {
        var caption = result[AzureSearchFieldNames.SemanticCaption];
        var captionHighlighted = result[AzureSearchFieldNames.SemanticCaptionHighlighted];
    }
}

Semantic Answers

Answers are verbatim passages from your index that directly respond to question-like queries. They’re available at the query level (not per-result) when EnableAnswers = true:

var searchResults = (AzureSearchResults)searcher.Search("what lives in total darkness?",
    new AzureSearchQueryOptions(
        new SemanticSearchQueryOptions
        {
            EnableAnswers = true
        }));

if (searchResults.SemanticAnswers != null)
{
    foreach (var answer in searchResults.SemanticAnswers)
    {
        Console.WriteLine($"Answer: {answer.Text}");
        Console.WriteLine($"From document: {answer.Key}");
        Console.WriteLine($"Confidence: {answer.Score}");
    }
}

Note: Answers are not guaranteed — the service only returns them when it finds a high-confidence match.

Field Name Constants

Use the AzureSearchFieldNames constants to access semantic data in results:

Constant Value Description
SemanticRerankerScore __semanticRerankerScore The reranker relevance score (0–4)
SemanticCaption __semanticCaption Plain text caption
SemanticCaptionHighlighted __semanticCaptionHighlighted Caption with emphasis highlights

Limitations

  • Sorting: You cannot combine OrderBy with semantic ranking. Azure AI Search returns an error when both are used. ExamineX validates this early and throws an InvalidOperationException with a clear message.
  • Top 50 only: Semantic ranking reranks the top 50 results from the initial BM25 scoring pass. Results beyond position 50 keep their original BM25 ordering.
  • Free tier limit: The Free tier supports semantic ranking but is limited to 1,000 queries/month. For production workloads, upgrade to a paid tier.
  • Query type: ExamineX uses the SemanticQuery approach which is compatible with all query types (Lucene full syntax included). You do not need to change your existing queries.