From 938c6c2484585017a5d8e62ee45e81d2c37f16e8 Mon Sep 17 00:00:00 2001 From: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:48:28 +0000 Subject: [PATCH 1/4] Add unit tests for Text Search AOT enhancements --- .../CustomResultJsonSerializerContext.cs | 16 ++++ .../Plugins/CustomResult.cs | 12 +++ dotnet/src/SemanticKernel.AotTests/Program.cs | 5 + .../SemanticKernel.AotTests.csproj | 1 + .../UnitTests/Search/MockTextSearch.cs | 42 +++++++++ .../Search/TextSearchExtensionsTests.cs | 94 +++++++++++++++++++ .../Search/VectorStoreTextSearchTests.cs | 35 +++++++ .../Data/TextSearch/TextSearchExtensions.cs | 12 +-- 8 files changed, 211 insertions(+), 6 deletions(-) create mode 100644 dotnet/src/SemanticKernel.AotTests/JsonSerializerContexts/CustomResultJsonSerializerContext.cs create mode 100644 dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs create mode 100644 dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockTextSearch.cs create mode 100644 dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs diff --git a/dotnet/src/SemanticKernel.AotTests/JsonSerializerContexts/CustomResultJsonSerializerContext.cs b/dotnet/src/SemanticKernel.AotTests/JsonSerializerContexts/CustomResultJsonSerializerContext.cs new file mode 100644 index 000000000000..c5a0d599864c --- /dev/null +++ b/dotnet/src/SemanticKernel.AotTests/JsonSerializerContexts/CustomResultJsonSerializerContext.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json.Serialization; +using Microsoft.SemanticKernel.Data; +using SemanticKernel.AotTests.Plugins; + +namespace SemanticKernel.AotTests.JsonSerializerContexts; + +[JsonSerializable(typeof(CustomResult))] +[JsonSerializable(typeof(int))] +[JsonSerializable(typeof(KernelSearchResults))] +[JsonSerializable(typeof(KernelSearchResults))] +[JsonSerializable(typeof(KernelSearchResults))] +internal sealed partial class CustomResultJsonSerializerContext : JsonSerializerContext +{ +} diff --git a/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs b/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs new file mode 100644 index 000000000000..4ab3d1045218 --- /dev/null +++ b/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace SemanticKernel.AotTests.Plugins; +internal sealed class CustomResult +{ + public string Value { get; set; } + + public CustomResult(string value) + { + this.Value = value; + } +} diff --git a/dotnet/src/SemanticKernel.AotTests/Program.cs b/dotnet/src/SemanticKernel.AotTests/Program.cs index 49fae7449dd4..a9fa29b9a2a3 100644 --- a/dotnet/src/SemanticKernel.AotTests/Program.cs +++ b/dotnet/src/SemanticKernel.AotTests/Program.cs @@ -59,6 +59,11 @@ private static async Task Main(string[] args) // Tests for text search VectorStoreTextSearchTests.GetTextSearchResultsAsync, + VectorStoreTextSearchTests.AddVectorStoreTextSearch, + + TextSearchExtensionsTests.CreateWithSearch, + TextSearchExtensionsTests.CreateWithGetTextSearchResults, + TextSearchExtensionsTests.CreateWithGetSearchResults, ]; private static async Task RunUnitTestsAsync(IEnumerable> functionsToRun) diff --git a/dotnet/src/SemanticKernel.AotTests/SemanticKernel.AotTests.csproj b/dotnet/src/SemanticKernel.AotTests/SemanticKernel.AotTests.csproj index 6b54614b9ca5..9da3b544ac88 100644 --- a/dotnet/src/SemanticKernel.AotTests/SemanticKernel.AotTests.csproj +++ b/dotnet/src/SemanticKernel.AotTests/SemanticKernel.AotTests.csproj @@ -18,6 +18,7 @@ + diff --git a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockTextSearch.cs b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockTextSearch.cs new file mode 100644 index 000000000000..72aa218239f9 --- /dev/null +++ b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/MockTextSearch.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel.Data; + +namespace SemanticKernel.AotTests.UnitTests.Search; + +internal sealed class MockTextSearch : ITextSearch +{ + private readonly KernelSearchResults? _objectResults; + private readonly KernelSearchResults? _textSearchResults; + private readonly KernelSearchResults? _stringResults; + + public MockTextSearch(KernelSearchResults? objectResults) + { + this._objectResults = objectResults; + } + + public MockTextSearch(KernelSearchResults? textSearchResults) + { + this._textSearchResults = textSearchResults; + } + + public MockTextSearch(KernelSearchResults? stringResults) + { + this._stringResults = stringResults; + } + + public Task> GetSearchResultsAsync(string query, TextSearchOptions? searchOptions = null, CancellationToken cancellationToken = default) + { + return Task.FromResult(this._objectResults!); + } + + public Task> GetTextSearchResultsAsync(string query, TextSearchOptions? searchOptions = null, CancellationToken cancellationToken = default) + { + return Task.FromResult(this._textSearchResults!); + } + + public Task> SearchAsync(string query, TextSearchOptions? searchOptions = null, CancellationToken cancellationToken = default) + { + return Task.FromResult(this._stringResults!); + } +} diff --git a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs new file mode 100644 index 000000000000..603b95a939f5 --- /dev/null +++ b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Text.Json; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.Data; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SemanticKernel.AotTests.JsonSerializerContexts; +using SemanticKernel.AotTests.Plugins; + +namespace SemanticKernel.AotTests.UnitTests.Search; + +internal sealed class TextSearchExtensionsTests +{ + private static readonly JsonSerializerOptions s_jsonSerializerOptions = new() + { + TypeInfoResolverChain = { CustomResultJsonSerializerContext.Default } + }; + + public static async Task CreateWithSearch() + { + // Arrange + var testData = new List { "test-value" }; + KernelSearchResults results = new(testData.ToAsyncEnumerable()); + ITextSearch textSearch = new MockTextSearch(results); + + // Act + var plugin = textSearch.CreateWithSearch("SearchPlugin", s_jsonSerializerOptions); + + // Assert + await AssertSearchFunctionSchemaAndInvocationResult(plugin["Search"], testData[0]); + } + + public static async Task CreateWithGetTextSearchResults() + { + // Arrange + var testData = new List { new("test-value") }; + KernelSearchResults results = new(testData.ToAsyncEnumerable()); + ITextSearch textSearch = new MockTextSearch(results); + + // Act + var plugin = textSearch.CreateWithGetTextSearchResults("SearchPlugin", s_jsonSerializerOptions); + + // Assert + await AssertSearchFunctionSchemaAndInvocationResult(plugin["GetTextSearchResults"], testData[0]); + } + + public static async Task CreateWithGetSearchResults() + { + // Arrange + var testData = new List { new("test-value") }; + KernelSearchResults results = new(testData.ToAsyncEnumerable()); + ITextSearch textSearch = new MockTextSearch(results); + + // Act + var plugin = textSearch.CreateWithGetSearchResults("SearchPlugin", s_jsonSerializerOptions); + + // Assert + await AssertSearchFunctionSchemaAndInvocationResult(plugin["GetSearchResults"], testData[0]); + } + + #region assert + internal static async Task AssertSearchFunctionSchemaAndInvocationResult(KernelFunction function, T expectedResult) + { + // Assert input parameter schema + AssertSearchFunctionMetadata(function.Metadata); + + // Assert the function result + FunctionResult functionResult = await function.InvokeAsync(new(), new() { ["query"] = "Mock Query" }); + + var result = functionResult.GetValue>()!; + Assert.AreEqual(1, result.Count); + Assert.AreEqual(expectedResult, result[0]); + } + + internal static void AssertSearchFunctionMetadata(KernelFunctionMetadata metadata) + { + // Assert input parameter schema + Assert.AreEqual(3, metadata.Parameters.Count); + Assert.AreEqual("{\"description\":\"What to search for\",\"type\":\"string\"}", metadata.Parameters[0].Schema!.ToString()); + Assert.AreEqual("{\"description\":\"Number of results (default value: 2)\",\"type\":\"integer\"}", metadata.Parameters[1].Schema!.ToString()); + Assert.AreEqual("{\"description\":\"Number of results to skip (default value: 0)\",\"type\":\"integer\"}", metadata.Parameters[2].Schema!.ToString()); + + // Assert return type schema + var type = typeof(T).Name; + var expectedSchema = type switch + { + "String" => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"Results\"]}", + "TextSearchResult" => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"Name\":{\"type\":[\"string\",\"null\"]},\"Link\":{\"type\":[\"string\",\"null\"]},\"Value\":{\"type\":\"string\"}},\"required\":[\"Value\"]}}},\"required\":[\"Results\"]}", + _ => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"Name\":{\"type\":[\"string\",\"null\"]},\"Link\":{\"type\":[\"string\",\"null\"]},\"Value\":{\"type\":\"string\"}},\"required\":[\"Value\"]}}},\"required\":[\"Results\"]}", + }; + Assert.AreEqual(expectedSchema, metadata.ReturnParameter.Schema!.ToString()); + } + #endregion +} diff --git a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/VectorStoreTextSearchTests.cs b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/VectorStoreTextSearchTests.cs index 01fb449d455b..eee8ae4db55e 100644 --- a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/VectorStoreTextSearchTests.cs +++ b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/VectorStoreTextSearchTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Data; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -35,6 +37,39 @@ public static async Task GetTextSearchResultsAsync() Assert.AreEqual("test-link", results[0].Link); } + public static async Task AddVectorStoreTextSearch() + { + // Arrange + var testData = new List> + { + new(new DataModel { Key = "test-name", Text = "test-result", Link = "test-link" }, 0.5) + }; + var vectorizableTextSearch = new MockVectorizableTextSearch(testData); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton>(vectorizableTextSearch); + + // Act + serviceCollection.AddVectorStoreTextSearch(); + var textSearch = serviceCollection.BuildServiceProvider().GetService>(); + Assert.IsNotNull(textSearch); + + // Assert + KernelSearchResults searchResults = await textSearch.GetTextSearchResultsAsync("query"); + + List results = []; + + await foreach (TextSearchResult result in searchResults.Results) + { + results.Add(result); + } + + // Assert + Assert.AreEqual(1, results.Count); + Assert.AreEqual("test-name", results[0].Name); + Assert.AreEqual("test-result", results[0].Value); + Assert.AreEqual("test-link", results[0].Link); + } + private sealed class DataModel { [TextSearchResultName] diff --git a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs index 5487ad7fac3f..55e2df49e046 100644 --- a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs +++ b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs @@ -519,9 +519,9 @@ private static KernelFunctionFromMethodOptions DefaultGetSearchResultsMethodOpti private static IEnumerable CreateDefaultKernelParameterMetadata(JsonSerializerOptions jsonSerializerOptions) { return [ - new KernelParameterMetadata("query", jsonSerializerOptions) { Description = "What to search for", IsRequired = true }, - new KernelParameterMetadata("count", jsonSerializerOptions) { Description = "Number of results", IsRequired = false, DefaultValue = 2 }, - new KernelParameterMetadata("skip", jsonSerializerOptions) { Description = "Number of results to skip", IsRequired = false, DefaultValue = 0 }, + new KernelParameterMetadata("query", jsonSerializerOptions) { Description = "What to search for", ParameterType = typeof(string), IsRequired = true }, + new KernelParameterMetadata("count", jsonSerializerOptions) { Description = "Number of results", ParameterType = typeof(int), IsRequired = false, DefaultValue = 2 }, + new KernelParameterMetadata("skip", jsonSerializerOptions) { Description = "Number of results to skip", ParameterType = typeof(int), IsRequired = false, DefaultValue = 0 }, ]; } @@ -530,9 +530,9 @@ private static IEnumerable CreateDefaultKernelParameter private static IEnumerable GetDefaultKernelParameterMetadata() { return s_kernelParameterMetadata ??= [ - new KernelParameterMetadata("query") { Description = "What to search for", IsRequired = true }, - new KernelParameterMetadata("count") { Description = "Number of results", IsRequired = false, DefaultValue = 2 }, - new KernelParameterMetadata("skip") { Description = "Number of results to skip", IsRequired = false, DefaultValue = 0 }, + new KernelParameterMetadata("query") { Description = "What to search for", ParameterType = typeof(string), IsRequired = true }, + new KernelParameterMetadata("count") { Description = "Number of results", ParameterType = typeof(int), IsRequired = false, DefaultValue = 2 }, + new KernelParameterMetadata("skip") { Description = "Number of results to skip", ParameterType = typeof(int), IsRequired = false, DefaultValue = 0 }, ]; } From 866b1769c16c4e6a01e6763d48290c92cfd80618 Mon Sep 17 00:00:00 2001 From: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:22:22 +0000 Subject: [PATCH 2/4] Update dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com> --- .../SemanticKernel.AotTests/Plugins/CustomResult.cs | 1 + .../UnitTests/Search/TextSearchExtensionsTests.cs | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs b/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs index 4ab3d1045218..55685186b1c8 100644 --- a/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs +++ b/dotnet/src/SemanticKernel.AotTests/Plugins/CustomResult.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. namespace SemanticKernel.AotTests.Plugins; + internal sealed class CustomResult { public string Value { get; set; } diff --git a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs index 603b95a939f5..c357b71e3f51 100644 --- a/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs +++ b/dotnet/src/SemanticKernel.AotTests/UnitTests/Search/TextSearchExtensionsTests.cs @@ -83,11 +83,11 @@ internal static void AssertSearchFunctionMetadata(KernelFunctionMetadata meta // Assert return type schema var type = typeof(T).Name; var expectedSchema = type switch - { - "String" => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"Results\"]}", - "TextSearchResult" => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"Name\":{\"type\":[\"string\",\"null\"]},\"Link\":{\"type\":[\"string\",\"null\"]},\"Value\":{\"type\":\"string\"}},\"required\":[\"Value\"]}}},\"required\":[\"Results\"]}", - _ => "{\"type\":\"object\",\"properties\":{\"TotalCount\":{\"type\":[\"integer\",\"null\"],\"default\":null},\"Metadata\":{\"type\":[\"object\",\"null\"],\"default\":null},\"Results\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"Name\":{\"type\":[\"string\",\"null\"]},\"Link\":{\"type\":[\"string\",\"null\"]},\"Value\":{\"type\":\"string\"}},\"required\":[\"Value\"]}}},\"required\":[\"Results\"]}", - }; +{ + "String" => """{"type":"object","properties":{"TotalCount":{"type":["integer","null"],"default":null},"Metadata":{"type":["object","null"],"default":null},"Results":{"type":"array","items":{"type":"string"}}},"required":["Results"]}""", + "TextSearchResult" => """{"type":"object","properties":{"TotalCount":{"type":["integer","null"],"default":null},"Metadata":{"type":["object","null"],"default":null},"Results":{"type":"array","items":{"type":"object","properties":{"Name":{"type":["string","null"]},"Link":{"type":["string","null"]},"Value":{"type":"string"}},"required":["Value"]}}},"required":["Results"]}""", + _ => """{"type":"object","properties":{"TotalCount":{"type":["integer","null"],"default":null},"Metadata":{"type":["object","null"],"default":null},"Results":{"type":"array","items":{"type":"object","properties":{"Name":{"type":["string","null"]},"Link":{"type":["string","null"]},"Value":{"type":"string"}},"required":["Value"]}}},"required":["Results"]}""" +}; Assert.AreEqual(expectedSchema, metadata.ReturnParameter.Schema!.ToString()); } #endregion From e2892142a681f0d285fb765bed6519c676d602fb Mon Sep 17 00:00:00 2001 From: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:41:01 +0000 Subject: [PATCH 3/4] Add count and skip as parameters in TextSearch delegates --- .../Bing_FunctionCallingWithTextSearch.cs | 2 +- .../Data/TextSearch/TextSearchExtensions.cs | 40 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/dotnet/samples/Concepts/Search/Bing_FunctionCallingWithTextSearch.cs b/dotnet/samples/Concepts/Search/Bing_FunctionCallingWithTextSearch.cs index 0c6d84380401..0245eb80757e 100644 --- a/dotnet/samples/Concepts/Search/Bing_FunctionCallingWithTextSearch.cs +++ b/dotnet/samples/Concepts/Search/Bing_FunctionCallingWithTextSearch.cs @@ -36,7 +36,7 @@ public async Task FunctionCallingWithBingTextSearchAsync() // Invoke prompt and use text search plugin to provide grounding information OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions }; KernelArguments arguments = new(settings); - Console.WriteLine(await kernel.InvokePromptAsync("What is the Semantic Kernel?", arguments)); + Console.WriteLine(await kernel.InvokePromptAsync("What is the Semantic Kernel? Search for 5 references.", arguments)); } /// diff --git a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs index 55e2df49e046..807d6ed72229 100644 --- a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs +++ b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs @@ -155,7 +155,7 @@ public static KernelPlugin CreateWithGetSearchResults(this ITextSearch textSearc [RequiresDynamicCode("Uses reflection to handle various aspects of the function creation and invocation, making it incompatible with AOT scenarios.")] public static KernelFunction CreateSearch(this ITextSearch textSearch, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -167,8 +167,8 @@ async Task> SearchAsync(Kernel kernel, KernelFunction functi searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -194,7 +194,7 @@ async Task> SearchAsync(Kernel kernel, KernelFunction functi [Experimental("SKEXP0120")] public static KernelFunction CreateSearch(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -206,8 +206,8 @@ async Task> SearchAsync(Kernel kernel, KernelFunction functi searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -234,7 +234,7 @@ async Task> SearchAsync(Kernel kernel, KernelFunction functi [RequiresDynamicCode("Uses reflection to handle various aspects of the function creation and invocation, making it incompatible with AOT scenarios.")] public static KernelFunction CreateGetTextSearchResults(this ITextSearch textSearch, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -246,8 +246,8 @@ async Task> GetTextSearchResultAsync(Kernel kernel searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -272,7 +272,7 @@ async Task> GetTextSearchResultAsync(Kernel kernel [Experimental("SKEXP0120")] public static KernelFunction CreateGetTextSearchResults(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -284,8 +284,8 @@ async Task> GetTextSearchResultAsync(Kernel kernel searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -311,7 +311,7 @@ async Task> GetTextSearchResultAsync(Kernel kernel [RequiresDynamicCode("Uses reflection to handle various aspects of the function creation and invocation, making it incompatible with AOT scenarios.")] public static KernelFunction CreateGetSearchResults(this ITextSearch textSearch, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -323,8 +323,8 @@ async Task> GetSearchResultAsync(Kernel kernel, KernelFuncti searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -349,7 +349,7 @@ async Task> GetSearchResultAsync(Kernel kernel, KernelFuncti [Experimental("SKEXP0120")] public static KernelFunction CreateGetSearchResults(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null) { - async Task> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken) + async Task> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken, int count = 2, int skip = 0) { arguments.TryGetValue("query", out var query); if (string.IsNullOrEmpty(query?.ToString())) @@ -361,8 +361,8 @@ async Task> GetSearchResultAsync(Kernel kernel, KernelFuncti searchOptions ??= new() { - Top = GetArgumentValue(arguments, parameters, "count", 2), - Skip = GetArgumentValue(arguments, parameters, "skip", 0), + Top = count, + Skip = skip, Filter = CreateBasicFilter(options, arguments) }; @@ -388,7 +388,7 @@ async Task> GetSearchResultAsync(Kernel kernel, KernelFuncti /// List of KernelReturnParameterMetadata. /// Name of the argument. /// Default value of the argument. - private static int GetArgumentValue(KernelArguments arguments, IReadOnlyList parameters, string name, int defaultValue) + /*private static int GetArgumentValue(KernelArguments arguments, IReadOnlyList parameters, string name, int defaultValue) { if (arguments.TryGetValue(name, out var value) && value is int argument) { @@ -402,7 +402,7 @@ private static int GetArgumentValue(KernelArguments arguments, IReadOnlyList /// Create the default for . From 1e2fc9500aa01258608860d1079cf168e1ff8d1f Mon Sep 17 00:00:00 2001 From: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:51:28 +0000 Subject: [PATCH 4/4] Add count and skip as parameters in TextSearch delegates --- .../Data/TextSearch/TextSearchExtensions.cs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs index 807d6ed72229..91c282e9b0ef 100644 --- a/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs +++ b/dotnet/src/SemanticKernel.Core/Data/TextSearch/TextSearchExtensions.cs @@ -380,30 +380,6 @@ async Task> GetSearchResultAsync(Kernel kernel, KernelFuncti #endregion #region private - /// - /// Get the argument value from or users default value from - /// or default to the provided value. - /// - /// KernelArguments instance. - /// List of KernelReturnParameterMetadata. - /// Name of the argument. - /// Default value of the argument. - /*private static int GetArgumentValue(KernelArguments arguments, IReadOnlyList parameters, string name, int defaultValue) - { - if (arguments.TryGetValue(name, out var value) && value is int argument) - { - return argument; - } - - value = parameters.FirstOrDefault(parameter => parameter.Name == name)?.DefaultValue; - if (value is int metadataDefault) - { - return metadataDefault; - } - - return defaultValue; - }*/ - /// /// Create the default for . ///