Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.Net: Use explicit arguments in TextSearch delegates to ensure type conversion #10151

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<IEnumerable<string>> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<string>> 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()))
Expand All @@ -167,8 +167,8 @@ async Task<IEnumerable<string>> 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)
};

Expand All @@ -194,7 +194,7 @@ async Task<IEnumerable<string>> SearchAsync(Kernel kernel, KernelFunction functi
[Experimental("SKEXP0120")]
public static KernelFunction CreateSearch(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null)
{
async Task<IEnumerable<string>> SearchAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<string>> 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()))
Expand All @@ -206,8 +206,8 @@ async Task<IEnumerable<string>> 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)
};

Expand All @@ -234,7 +234,7 @@ async Task<IEnumerable<string>> 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<IEnumerable<TextSearchResult>> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<TextSearchResult>> 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()))
Expand All @@ -246,8 +246,8 @@ async Task<IEnumerable<TextSearchResult>> 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)
};

Expand All @@ -272,7 +272,7 @@ async Task<IEnumerable<TextSearchResult>> GetTextSearchResultAsync(Kernel kernel
[Experimental("SKEXP0120")]
public static KernelFunction CreateGetTextSearchResults(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null)
{
async Task<IEnumerable<TextSearchResult>> GetTextSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<TextSearchResult>> 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()))
Expand All @@ -284,8 +284,8 @@ async Task<IEnumerable<TextSearchResult>> 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)
};

Expand All @@ -311,7 +311,7 @@ async Task<IEnumerable<TextSearchResult>> 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<IEnumerable<object>> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<object>> 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()))
Expand All @@ -323,8 +323,8 @@ async Task<IEnumerable<object>> 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)
};

Expand All @@ -349,7 +349,7 @@ async Task<IEnumerable<object>> GetSearchResultAsync(Kernel kernel, KernelFuncti
[Experimental("SKEXP0120")]
public static KernelFunction CreateGetSearchResults(this ITextSearch textSearch, JsonSerializerOptions jsonSerializerOptions, KernelFunctionFromMethodOptions? options = null, TextSearchOptions? searchOptions = null)
{
async Task<IEnumerable<object>> GetSearchResultAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
async Task<IEnumerable<object>> 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()))
Expand All @@ -361,8 +361,8 @@ async Task<IEnumerable<object>> 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)
};

Expand All @@ -380,30 +380,6 @@ async Task<IEnumerable<object>> GetSearchResultAsync(Kernel kernel, KernelFuncti
#endregion

#region private
/// <summary>
/// Get the argument value from <see cref="KernelArguments"/> or users default value from
/// <see cref="KernelReturnParameterMetadata"/> or default to the provided value.
/// </summary>
/// <param name="arguments">KernelArguments instance.</param>
/// <param name="parameters">List of KernelReturnParameterMetadata.</param>
/// <param name="name">Name of the argument.</param>
/// <param name="defaultValue">Default value of the argument.</param>
private static int GetArgumentValue(KernelArguments arguments, IReadOnlyList<KernelParameterMetadata> 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;
}

/// <summary>
/// Create the default <see cref="KernelFunctionFromMethodOptions"/> for <see cref="ITextSearch.SearchAsync(string, TextSearchOptions?, CancellationToken)"/>.
/// </summary>
Expand Down
Loading