Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ private static IReadOnlyList<KernelParameterMetadata> MapParameterMetadata(AIFun
return Array.Empty<KernelParameterMetadata>();
}

HashSet<string>? requiredParameters = GetRequiredParameterNames(aiFunction.JsonSchema);

List<KernelParameterMetadata> kernelParams = [];
var parameterInfos = aiFunction.UnderlyingMethod?.GetParameters().ToDictionary(p => p.Name!, StringComparer.Ordinal);
foreach (var param in properties.EnumerateObject())
Expand All @@ -76,7 +78,7 @@ private static IReadOnlyList<KernelParameterMetadata> MapParameterMetadata(AIFun
{
Description = param.Value.TryGetProperty("description", out JsonElement description) ? description.GetString() : null,
DefaultValue = param.Value.TryGetProperty("default", out JsonElement defaultValue) ? defaultValue : null,
IsRequired = param.Value.TryGetProperty("required", out JsonElement required) && required.GetBoolean(),
IsRequired = requiredParameters?.Contains(param.Name) ?? false,
ParameterType = paramInfo?.ParameterType,
Schema = param.Value.TryGetProperty("schema", out JsonElement schema)
? new KernelJsonSchema(schema)
Expand All @@ -86,4 +88,25 @@ private static IReadOnlyList<KernelParameterMetadata> MapParameterMetadata(AIFun

return kernelParams;
}

/// <summary>
/// Gets the names of the required parameters from the AI function's JSON schema.
/// </summary>
/// <param name="schema">The JSON schema of the AI function.</param>
/// <returns>The names of the required parameters.</returns>
private static HashSet<string>? GetRequiredParameterNames(JsonElement schema)
{
HashSet<string>? requiredParameterNames = null;

if (schema.TryGetProperty("required", out JsonElement requiredElement) && requiredElement.ValueKind == JsonValueKind.Array)
{
foreach (var node in requiredElement.EnumerateArray())
{
requiredParameterNames ??= [];
requiredParameterNames.Add(node.GetString()!);
}
}

return requiredParameterNames;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Linq;
using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Xunit;

namespace SemanticKernel.UnitTests.AI.ChatCompletion;

public class AIFunctionKernelFunctionTests
{
[Fact]
public void ShouldAssignIsRequiredParameterMetadataPropertyCorrectly()
{
// Arrange and Act
AIFunction aiFunction = AIFunctionFactory.Create((string p1, int? p2 = null) => p1);

AIFunctionKernelFunction sut = new(aiFunction);

// Assert
KernelParameterMetadata? p1Metadata = sut.Metadata.Parameters.FirstOrDefault(p => p.Name == "p1");
Assert.True(p1Metadata?.IsRequired);

KernelParameterMetadata? p2Metadata = sut.Metadata.Parameters.FirstOrDefault(p => p.Name == "p2");
Assert.False(p2Metadata?.IsRequired);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</PackageReference>
<PackageReference Include="Microsoft.ML.Tokenizers" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Microsoft.Extensions.AI" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading