From 58327fc3b3642cae7f83b8925b08d6f3fb315bdd Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:17:08 +0100 Subject: [PATCH] .Net: Vector Store: Allowing json serializer options to be passed down from vector store options and user agent string. (#8296) ### Motivation and Context See #8086 See #7580 To make it easier for users who are using the default construction for the azure ai search client to also use custom json serializer settings, adding this as an option to the vector store options class and using it when both when constructing the azure ai search client and the collection. Also adding the semantic kernel user agent string to the azure ai search client when constructing it. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone :smile: --- ...zureAISearchServiceCollectionExtensions.cs | 27 +++++++++++++++++-- .../AzureAISearchVectorStore.cs | 10 ++++++- .../AzureAISearchVectorStoreOptions.cs | 10 +++++++ ...earchVectorStoreRecordCollectionOptions.cs | 3 ++- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchServiceCollectionExtensions.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchServiceCollectionExtensions.cs index 7e2de2e8e83e..ba518ddf6724 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchServiceCollectionExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchServiceCollectionExtensions.cs @@ -3,10 +3,13 @@ using System; using Azure; using Azure.Core; +using Azure.Core.Serialization; +using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel.Connectors.AzureAISearch; using Microsoft.SemanticKernel.Data; +using Microsoft.SemanticKernel.Http; namespace Microsoft.SemanticKernel; @@ -59,9 +62,19 @@ public static IServiceCollection AddAzureAISearchVectorStore(this IServiceCollec serviceId, (sp, obj) => { - var searchIndexClient = new SearchIndexClient(endpoint, tokenCredential); var selectedOptions = options ?? sp.GetService(); + // Build options for the Azure AI Search client and construct it. + var searchClientOptions = new SearchClientOptions(); + searchClientOptions.Diagnostics.ApplicationId = HttpHeaderConstant.Values.UserAgent; + if (selectedOptions?.JsonSerializerOptions != null) + { + searchClientOptions.Serializer = new JsonObjectSerializer(selectedOptions.JsonSerializerOptions); + } + + var searchIndexClient = new SearchIndexClient(endpoint, tokenCredential, searchClientOptions); + + // Construct the vector store. return new AzureAISearchVectorStore( searchIndexClient, selectedOptions); @@ -88,9 +101,19 @@ public static IServiceCollection AddAzureAISearchVectorStore(this IServiceCollec serviceId, (sp, obj) => { - var searchIndexClient = new SearchIndexClient(endpoint, credential); var selectedOptions = options ?? sp.GetService(); + // Build options for the Azure AI Search client and construct it. + var searchClientOptions = new SearchClientOptions(); + searchClientOptions.Diagnostics.ApplicationId = HttpHeaderConstant.Values.UserAgent; + if (selectedOptions?.JsonSerializerOptions != null) + { + searchClientOptions.Serializer = new JsonObjectSerializer(selectedOptions.JsonSerializerOptions); + } + + var searchIndexClient = new SearchIndexClient(endpoint, credential, searchClientOptions); + + // Construct the vector store. return new AzureAISearchVectorStore( searchIndexClient, selectedOptions); diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs index 55a71c49dfb8..5a6b7e73b229 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStore.cs @@ -56,7 +56,15 @@ public IVectorStoreRecordCollection GetCollection( return this._options.VectorStoreCollectionFactory.CreateVectorStoreRecordCollection(this._searchIndexClient, name, vectorStoreRecordDefinition); } - var recordCollection = new AzureAISearchVectorStoreRecordCollection(this._searchIndexClient, name, new AzureAISearchVectorStoreRecordCollectionOptions() { VectorStoreRecordDefinition = vectorStoreRecordDefinition }) as IVectorStoreRecordCollection; + var recordCollection = new AzureAISearchVectorStoreRecordCollection( + this._searchIndexClient, + name, + new AzureAISearchVectorStoreRecordCollectionOptions() + { + JsonSerializerOptions = this._options.JsonSerializerOptions, + VectorStoreRecordDefinition = vectorStoreRecordDefinition + }) as IVectorStoreRecordCollection; + return recordCollection!; } diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreOptions.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreOptions.cs index 3c588a90044e..06e099efc4fa 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreOptions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreOptions.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Text.Json; +using Azure.Search.Documents.Indexes; + namespace Microsoft.SemanticKernel.Connectors.AzureAISearch; /// @@ -11,4 +14,11 @@ public sealed class AzureAISearchVectorStoreOptions /// An optional factory to use for constructing instances, if a custom record collection is required. /// public IAzureAISearchVectorStoreRecordCollectionFactory? VectorStoreCollectionFactory { get; init; } + + /// + /// Gets or sets the JSON serializer options to use when converting between the data model and the Azure AI Search record. + /// Note that when using the default mapper and you are constructing your own , you will need + /// to provide the same set of both here and when constructing the . + /// + public JsonSerializerOptions? JsonSerializerOptions { get; init; } = null; } diff --git a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollectionOptions.cs b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollectionOptions.cs index 462dcd5d6e66..62e524a1c7b1 100644 --- a/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollectionOptions.cs +++ b/dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollectionOptions.cs @@ -33,7 +33,8 @@ public sealed class AzureAISearchVectorStoreRecordCollectionOptions /// /// Gets or sets the JSON serializer options to use when converting between the data model and the Azure AI Search record. - /// Note that when using the default mapper, you will need to provide the same set of both here and when constructing the . + /// Note that when using the default mapper and you are constructing your own , you will need + /// to provide the same set of both here and when constructing the . /// public JsonSerializerOptions? JsonSerializerOptions { get; init; } = null; }