Skip to content

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.

  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.

  • Semantic ranking must be enabled on your Azure Search service
  • The Free tier includes semantic ranking with a limit of 1,000 queries/month — suitable for development and testing. For production workloads, a paid tier is recommended. See Azure AI Search pricing for details.
  • ExamineX 6.2.0, 7.1.0, 8.1.0 or 9.1.0 or later in that major, or any 10.x release

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.

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();

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

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

var searcher = index.Searcher;
var results = searcher.Search("hotels near the beach", new AzureSearchQueryOptions(
new SemanticSearchQueryOptions
{
SemanticQuery = "hotels within walking distance to the beach with live music",
EnableCaptions = true
}));
var results = searcher.CreateQuery("content")
.Field("bodyText", "beach hotel")
.Execute(new AzureSearchQueryOptions(
new SemanticSearchQueryOptions
{
ConfigurationName = "my-semantic-config",
SemanticQuery = "beach hotel with ocean views",
EnableCaptions = true,
EnableAnswers = true
}));
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 A plain-text query for the semantic model. Required when using the query builder: the builder’s Lucene query filters the initial results and this text is used to rerank them. If omitted for a query builder query, a warning is logged and semantic ranking is not applied. Optional for simple Search(string) calls. Uses the search text (simple text search only)
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

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 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];
}
}

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
{
SemanticQuery = "what kind of life lives in total darkness",
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.

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
  • 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: Query builder queries are sent with the full Lucene query parser and a SemanticQuery, so your fielded and boolean clauses (e.g. node type or ancestor filters) still filter the results before semantic reranking. Simple Search(string) calls are sent with the semantic query type, which only accepts plain text.