diff --git a/src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs b/src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs index 4d16ac6ae6b..f81ee89fb6d 100644 --- a/src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs +++ b/src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs @@ -374,15 +374,14 @@ static bool IsAsyncMethod(MethodInfo method) } } - // There was no argument for the parameter in the dictionary. - // Does it have a default value? - if (parameter.HasDefaultValue) + // If the parameter is required and there's no argument specified for it, throw. + if (!parameter.HasDefaultValue) { - return parameter.DefaultValue; + Throw.ArgumentException(nameof(arguments), $"Missing required parameter '{parameter.Name}' for method '{parameter.Member.Name}'."); } - // Leave it empty. - return null; + // Otherwise, use the optional parameter's default value. + return parameter.DefaultValue; }; } diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs index 198627fb14e..8d069034e15 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs @@ -78,7 +78,7 @@ public async Task SupportsMultipleFunctionCallsPerRequestAsync(bool concurrentIn { Tools = [ - AIFunctionFactory.Create((int i) => "Result 1", "Func1"), + AIFunctionFactory.Create((int? i = 42) => "Result 1", "Func1"), AIFunctionFactory.Create((int i) => $"Result 2: {i}", "Func2"), ] }; diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Functions/AIFunctionFactoryTest.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Functions/AIFunctionFactoryTest.cs index 25f94ac3669..dc104ea6be6 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Functions/AIFunctionFactoryTest.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Functions/AIFunctionFactoryTest.cs @@ -47,6 +47,24 @@ public async Task Parameters_DefaultValuesAreUsedButOverridable_Async() AssertExtensions.EqualFunctionCallResults("hello hello", await func.InvokeAsync([new KeyValuePair("a", "hello")])); } + [Fact] + public async Task Parameters_MissingRequiredParametersFail_Async() + { + AIFunction[] funcs = + [ + AIFunctionFactory.Create((string theParam) => theParam + " " + theParam), + AIFunctionFactory.Create((string? theParam) => theParam + " " + theParam), + AIFunctionFactory.Create((int theParam) => theParam * 2), + AIFunctionFactory.Create((int? theParam) => theParam * 2), + ]; + + foreach (AIFunction f in funcs) + { + Exception e = await Assert.ThrowsAsync(() => f.InvokeAsync()); + Assert.Contains("'theParam'", e.Message); + } + } + [Fact] public async Task Parameters_MappedByType_Async() {