Skip to content

Commit 17dcd11

Browse files
committed
Add setting to enable SessionId on SearchOptions in AzureAISearchMemory
1 parent b67dfe7 commit 17dcd11

File tree

8 files changed

+66
-36
lines changed

8 files changed

+66
-36
lines changed

applications/tests/Evaluation.Tests/appsettings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@
7070
"APIKey": "",
7171
// Hybrid search is not enabled by default. Note that when using hybrid search
7272
// relevance scores are different, usually lower, than when using just vector search
73-
"UseHybridSearch": false
73+
"UseHybridSearch": false,
74+
// Helps improve relevance score consistency for search services with multiple replicas by
75+
// attempting to route a given request to the same replica for that session. Use this when
76+
// favoring consistent scoring over lower latency.
77+
"UseSessionId": false
7478
},
7579
"OpenAI": {
7680
// Name of the model used to generate text (text completion or chat completion)

examples/002-dotnet-Serverless/appsettings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@
7070
"APIKey": "",
7171
// Hybrid search is not enabled by default. Note that when using hybrid search
7272
// relevance scores are different, usually lower, than when using just vector search
73-
"UseHybridSearch": false
73+
"UseHybridSearch": false,
74+
// Helps improve relevance score consistency for search services with multiple replicas by
75+
// attempting to route a given request to the same replica for that session. Use this when
76+
// favoring consistent scoring over lower latency.
77+
"UseSessionId": false
7478
},
7579
"OpenAI": {
7680
// Name of the model used to generate text (text completion or chat completion)

examples/210-KM-without-builder/appsettings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,11 @@
248248
"APIKey": "",
249249
// Hybrid search is not enabled by default. Note that when using hybrid search
250250
// relevance scores are different, usually lower, than when using just vector search
251-
"UseHybridSearch": false
251+
"UseHybridSearch": false,
252+
// Helps improve relevance score consistency for search services with multiple replicas by
253+
// attempting to route a given request to the same replica for that session. Use this when
254+
// favoring consistent scoring over lower latency.
255+
"UseSessionId": false
252256
},
253257
"AzureAIDocIntel": {
254258
// "APIKey" or "AzureIdentity".

examples/401-evaluation/appsettings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@
7070
"APIKey": "",
7171
// Hybrid search is not enabled by default. Note that when using hybrid search
7272
// relevance scores are different, usually lower, than when using just vector search
73-
"UseHybridSearch": false
73+
"UseHybridSearch": false,
74+
// Helps improve relevance score consistency for search services with multiple replicas by
75+
// attempting to route a given request to the same replica for that session. Use this when
76+
// favoring consistent scoring over lower latency.
77+
"UseSessionId": false
7478
},
7579
"OpenAI": {
7680
// Name of the model used to generate text (text completion or chat completion)

extensions/AzureAISearch/AzureAISearch/AzureAISearchConfig.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ public enum AuthTypes
3131
/// </summary>
3232
public bool UseHybridSearch { get; set; } = false;
3333

34+
/// <summary>
35+
/// Helps improve relevance score consistency for search services with multiple replicas by
36+
/// attempting to route a given request to the same replica for that session. Use this when
37+
/// favoring consistent scoring over lower latency.
38+
/// </summary>
39+
public bool UseSessionId { get; set; } = false;
40+
3441
public void SetCredential(TokenCredential credential)
3542
{
3643
this.Auth = AuthTypes.ManualTokenCredential;

extensions/AzureAISearch/AzureAISearch/AzureAISearchMemory.cs

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public class AzureAISearchMemory : IMemoryDb, IMemoryDbUpsertBatch
3434
private readonly ITextEmbeddingGenerator _embeddingGenerator;
3535
private readonly ILogger<AzureAISearchMemory> _log;
3636
private readonly bool _useHybridSearch;
37+
private readonly bool _useSessionId;
3738

3839
/// <summary>
3940
/// Create a new instance
@@ -49,6 +50,7 @@ public AzureAISearchMemory(
4950
this._embeddingGenerator = embeddingGenerator;
5051
this._log = (loggerFactory ?? DefaultLogger.Factory).CreateLogger<AzureAISearchMemory>();
5152
this._useHybridSearch = config.UseHybridSearch;
53+
this._useSessionId = config.UseSessionId;
5254

5355
if (string.IsNullOrEmpty(config.Endpoint))
5456
{
@@ -190,7 +192,7 @@ await client.IndexDocumentsAsync(
190192
FilterMode = VectorFilterMode.PreFilter
191193
}
192194
};
193-
DefineFieldsToSelect(options, withEmbeddings);
195+
this.ApplyCommonSearchOptions(options, withEmbeddings, filters);
194196

195197
if (limit > 0)
196198
{
@@ -199,15 +201,6 @@ await client.IndexDocumentsAsync(
199201
this._log.LogDebug("KNearestNeighborsCount and max results: {0}", limit);
200202
}
201203

202-
// Remove empty filters
203-
filters = filters?.Where(f => !f.IsEmpty()).ToList();
204-
205-
if (filters is { Count: > 0 })
206-
{
207-
options.Filter = AzureAISearchFiltering.BuildSearchFilter(filters);
208-
this._log.LogDebug("Filtering vectors, condition: {0}", options.Filter);
209-
}
210-
211204
Response<SearchResults<AzureAISearchMemoryRecord>>? searchResult = null;
212205
try
213206
{
@@ -254,33 +247,14 @@ public async IAsyncEnumerable<MemoryRecord> GetListAsync(
254247
var client = this.GetSearchClient(index);
255248

256249
SearchOptions options = new();
257-
DefineFieldsToSelect(options, withEmbeddings);
250+
this.ApplyCommonSearchOptions(options, withEmbeddings, filters);
258251

259252
if (limit > 0)
260253
{
261254
options.Size = limit;
262255
this._log.LogDebug("Max results: {0}", limit);
263256
}
264257

265-
// Remove empty filters
266-
filters = filters?.Where(f => !f.IsEmpty()).ToList();
267-
268-
if (filters is { Count: > 0 })
269-
{
270-
options.Filter = AzureAISearchFiltering.BuildSearchFilter(filters);
271-
this._log.LogDebug("Filtering vectors, condition: {0}", options.Filter);
272-
}
273-
274-
// See: https://learn.microsoft.com/azure/search/search-query-understand-collection-filters
275-
// fieldValue = fieldValue.Replace("'", "''", StringComparison.Ordinal);
276-
// var options = new SearchOptions
277-
// {
278-
// Filter = fieldIsCollection
279-
// ? $"{fieldName}/any(s: s eq '{fieldValue}')"
280-
// : $"{fieldName} eq '{fieldValue}')",
281-
// Size = limit
282-
// };
283-
284258
Response<SearchResults<AzureAISearchMemoryRecord>>? searchResult = null;
285259
try
286260
{
@@ -627,7 +601,10 @@ at Azure.Search.Documents.SearchClient.SearchInternal[T](SearchOptions options,
627601
return indexSchema;
628602
}
629603

630-
private static void DefineFieldsToSelect(SearchOptions options, bool withEmbeddings)
604+
private void ApplyCommonSearchOptions(
605+
SearchOptions options,
606+
bool withEmbeddings,
607+
ICollection<MemoryFilter>? filters = null)
631608
{
632609
options.Select.Add(AzureAISearchMemoryRecord.IdField);
633610
options.Select.Add(AzureAISearchMemoryRecord.TagsField);
@@ -636,6 +613,30 @@ private static void DefineFieldsToSelect(SearchOptions options, bool withEmbeddi
636613
{
637614
options.Select.Add(AzureAISearchMemoryRecord.VectorField);
638615
}
616+
617+
// Remove empty filters
618+
filters = filters?.Where(f => !f.IsEmpty()).ToList();
619+
620+
if (filters is { Count: > 0 })
621+
{
622+
options.Filter = AzureAISearchFiltering.BuildSearchFilter(filters);
623+
this._log.LogDebug("Filtering vectors, condition: {0}", options.Filter);
624+
}
625+
626+
// See: https://learn.microsoft.com/azure/search/search-query-understand-collection-filters
627+
// fieldValue = fieldValue.Replace("'", "''", StringComparison.Ordinal);
628+
// var options = new SearchOptions
629+
// {
630+
// Filter = fieldIsCollection
631+
// ? $"{fieldName}/any(s: s eq '{fieldValue}')"
632+
// : $"{fieldName} eq '{fieldValue}')",
633+
// Size = limit
634+
// };
635+
636+
if (this._useSessionId)
637+
{
638+
options.SessionId = Guid.NewGuid().ToString("N");
639+
}
639640
}
640641

641642
private static double ScoreToCosineSimilarity(double score)

service/tests/Core.FunctionalTests/appsettings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
"Auth": "AzureIdentity",
1313
"Endpoint": "https://<...>",
1414
"APIKey": "",
15-
"UseHybridSearch": false
15+
"UseHybridSearch": false,
16+
// Helps improve relevance score consistency for search services with multiple replicas by
17+
// attempting to route a given request to the same replica for that session. Use this when
18+
// favoring consistent scoring over lower latency.
19+
"UseSessionId": false
1620
},
1721
"LlamaSharp": {
1822
"TextModel": {

tools/InteractiveSetup/Services/AzureAISearch.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public static void Setup(Context ctx, bool force = false)
2222
{ "Auth", "ApiKey" },
2323
{ "APIKey", "" },
2424
{ "UseHybridSearch", false },
25+
{ "UseSessionId", false }
2526
};
2627
}
2728

@@ -45,5 +46,6 @@ public static void Setup(Context ctx, bool force = false)
4546

4647
AppSettings.Change(x => x.Services[ServiceName]["Endpoint"] = SetupUI.AskOpenQuestion("Azure AI Search <endpoint>", config["Endpoint"].ToString()));
4748
AppSettings.Change(x => x.Services[ServiceName]["UseHybridSearch"] = SetupUI.AskBoolean("Use hybrid search (yes/no)?", (bool)config["UseHybridSearch"]));
49+
AppSettings.Change(x => x.Services[ServiceName]["UseSessionId"] = SetupUI.AskBoolean("Use session ID (yes/no)?", (bool)config["UseSessionId"]));
4850
}
4951
}

0 commit comments

Comments
 (0)