diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 7016e18d98d8..3a3deaaf59fc 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -48,7 +48,7 @@
-
+
@@ -68,10 +68,10 @@
-
-
-
-
+
+
+
+
diff --git a/dotnet/samples/Concepts/ChatCompletion/HybridCompletion_Fallback.cs b/dotnet/samples/Concepts/ChatCompletion/HybridCompletion_Fallback.cs
index cdcd4027b56a..188eee708135 100644
--- a/dotnet/samples/Concepts/ChatCompletion/HybridCompletion_Fallback.cs
+++ b/dotnet/samples/Concepts/ChatCompletion/HybridCompletion_Fallback.cs
@@ -39,9 +39,9 @@ public async Task FallbackToAvailableModelAsync()
// Create a fallback chat client that will fallback to the available chat client when unavailable chat client fails
IChatClient fallbackChatClient = new FallbackChatClient([unavailableChatClient, availableChatClient]);
- ChatOptions chatOptions = new() { Tools = [AIFunctionFactory.Create(GetWeather, new AIFunctionFactoryCreateOptions { Name = "GetWeather" })] };
+ ChatOptions chatOptions = new() { Tools = [AIFunctionFactory.Create(GetWeather)] };
- var result = await fallbackChatClient.CompleteAsync("Do I need an umbrella?", chatOptions);
+ var result = await fallbackChatClient.GetResponseAsync("Do I need an umbrella?", chatOptions);
Output.WriteLine(result);
@@ -64,9 +64,9 @@ public async Task FallbackToAvailableModelStreamingAsync()
// Create a fallback chat client that will fallback to the available chat client when unavailable chat client fails
IChatClient fallbackChatClient = new FallbackChatClient([unavailableChatClient, availableChatClient]);
- ChatOptions chatOptions = new() { Tools = [AIFunctionFactory.Create(GetWeather, new AIFunctionFactoryCreateOptions { Name = "GetWeather" })] };
+ ChatOptions chatOptions = new() { Tools = [AIFunctionFactory.Create(GetWeather)] };
- var result = fallbackChatClient.CompleteStreamingAsync("Do I need an umbrella?", chatOptions);
+ var result = fallbackChatClient.GetStreamingResponseAsync("Do I need an umbrella?", chatOptions);
await foreach (var update in result)
{
@@ -151,7 +151,7 @@ public FallbackChatClient(IList chatClients)
public ChatClientMetadata Metadata => new();
///
- public async Task CompleteAsync(IList chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)
+ public async Task GetResponseAsync(IList chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)
{
for (int i = 0; i < this._chatClients.Count; i++)
{
@@ -159,7 +159,7 @@ public FallbackChatClient(IList chatClients)
try
{
- return await chatClient.CompleteAsync(chatMessages, options, cancellationToken).ConfigureAwait(false);
+ return await chatClient.GetResponseAsync(chatMessages, options, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -177,15 +177,15 @@ public FallbackChatClient(IList chatClients)
}
///
- public async IAsyncEnumerable CompleteStreamingAsync(IList chatMessages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ public async IAsyncEnumerable GetStreamingResponseAsync(IList chatMessages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
for (int i = 0; i < this._chatClients.Count; i++)
{
var chatClient = this._chatClients.ElementAt(i);
- IAsyncEnumerable completionStream = chatClient.CompleteStreamingAsync(chatMessages, options, cancellationToken);
+ IAsyncEnumerable completionStream = chatClient.GetStreamingResponseAsync(chatMessages, options, cancellationToken);
- ConfiguredCancelableAsyncEnumerable.Enumerator enumerator = completionStream.ConfigureAwait(false).GetAsyncEnumerator();
+ ConfiguredCancelableAsyncEnumerable.Enumerator enumerator = completionStream.ConfigureAwait(false).GetAsyncEnumerator();
try
{
diff --git a/dotnet/src/Connectors/Connectors.AzureAIInference.UnitTests/Services/AzureAIInferenceChatCompletionServiceTests.cs b/dotnet/src/Connectors/Connectors.AzureAIInference.UnitTests/Services/AzureAIInferenceChatCompletionServiceTests.cs
index a8447d4838a3..6faef5ab9a11 100644
--- a/dotnet/src/Connectors/Connectors.AzureAIInference.UnitTests/Services/AzureAIInferenceChatCompletionServiceTests.cs
+++ b/dotnet/src/Connectors/Connectors.AzureAIInference.UnitTests/Services/AzureAIInferenceChatCompletionServiceTests.cs
@@ -249,7 +249,7 @@ public async Task GetChatMessageInResponseFormatsAsync(string formatType, string
format = JsonSerializer.Deserialize(formatValue);
break;
case "ChatResponseFormat":
- format = formatValue == "text" ? new ChatCompletionsResponseFormatText() : new ChatCompletionsResponseFormatJSON();
+ format = formatValue == "text" ? new ChatCompletionsResponseFormatText() : new ChatCompletionsResponseFormatJsonObject();
break;
}
diff --git a/dotnet/src/Connectors/Connectors.AzureAIInference/Settings/AzureAIInferencePromptExecutionSettings.cs b/dotnet/src/Connectors/Connectors.AzureAIInference/Settings/AzureAIInferencePromptExecutionSettings.cs
index 3146cb94fb78..c6e9dd5d503e 100644
--- a/dotnet/src/Connectors/Connectors.AzureAIInference/Settings/AzureAIInferencePromptExecutionSettings.cs
+++ b/dotnet/src/Connectors/Connectors.AzureAIInference/Settings/AzureAIInferencePromptExecutionSettings.cs
@@ -136,7 +136,7 @@ public int? MaxTokens
/// Note that to enable JSON mode, some AI models may also require you to instruct the model to produce JSON
/// via a system or user message.
/// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.
- /// The available derived classes include and .
+ /// The available derived classes include and .
///
[JsonPropertyName("response_format")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/AIFunctionKernelFunction.cs b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/AIFunctionKernelFunction.cs
index 2a175afb348d..7ab32b31b869 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/AIFunctionKernelFunction.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/AIFunctionKernelFunction.cs
@@ -2,7 +2,9 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
+using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -12,8 +14,7 @@ namespace Microsoft.SemanticKernel.ChatCompletion;
/// Provides a that wraps an .
///
-/// The implementation should largely be unused, other than for its . The implementation of
-/// only manufactures these to pass along to the underlying
+/// The implementation of only manufactures these to pass along to the underlying
/// with autoInvoke:false, which means the
/// implementation shouldn't be invoking these functions at all. As such, the and
/// methods both unconditionally throw, even though they could be implemented.
@@ -23,28 +24,15 @@ internal sealed class AIFunctionKernelFunction : KernelFunction
private readonly AIFunction _aiFunction;
public AIFunctionKernelFunction(AIFunction aiFunction) :
- base(aiFunction.Metadata.Name,
- aiFunction.Metadata.Description,
- aiFunction.Metadata.Parameters.Select(p => new KernelParameterMetadata(p.Name, AbstractionsJsonContext.Default.Options)
- {
- Description = p.Description,
- DefaultValue = p.DefaultValue,
- IsRequired = p.IsRequired,
- ParameterType = p.ParameterType,
- Schema =
- p.Schema is JsonElement je ? new KernelJsonSchema(je) :
- p.Schema is string s ? new KernelJsonSchema(JsonSerializer.Deserialize(s, AbstractionsJsonContext.Default.JsonElement)) :
- null,
- }).ToList(),
- AbstractionsJsonContext.Default.Options,
+ base(aiFunction.Name,
+ aiFunction.Description,
+ MapParameterMetadata(aiFunction),
+ aiFunction.JsonSerializerOptions,
new KernelReturnParameterMetadata(AbstractionsJsonContext.Default.Options)
{
- Description = aiFunction.Metadata.ReturnParameter.Description,
- ParameterType = aiFunction.Metadata.ReturnParameter.ParameterType,
- Schema =
- aiFunction.Metadata.ReturnParameter.Schema is JsonElement je ? new KernelJsonSchema(je) :
- aiFunction.Metadata.ReturnParameter.Schema is string s ? new KernelJsonSchema(JsonSerializer.Deserialize(s, AbstractionsJsonContext.Default.JsonElement)) :
- null,
+ Description = aiFunction.UnderlyingMethod?.ReturnParameter.GetCustomAttribute()?.Description,
+ ParameterType = aiFunction.UnderlyingMethod?.ReturnParameter.ParameterType,
+ Schema = new KernelJsonSchema(AIJsonUtilities.CreateJsonSchema(aiFunction.UnderlyingMethod?.ReturnParameter.ParameterType)),
})
{
this._aiFunction = aiFunction;
@@ -73,4 +61,30 @@ protected override IAsyncEnumerable InvokeStreamingCoreAsync(K
// This should never be invoked, as instances are always passed with autoInvoke:false.
throw new NotSupportedException();
}
+
+ private static IReadOnlyList MapParameterMetadata(AIFunction aiFunction)
+ {
+ if (!aiFunction.JsonSchema.TryGetProperty("properties", out JsonElement properties))
+ {
+ return Array.Empty();
+ }
+
+ List kernelParams = [];
+ var parameterInfos = aiFunction.UnderlyingMethod?.GetParameters().ToDictionary(p => p.Name!, StringComparer.Ordinal);
+ foreach (var param in properties.EnumerateObject())
+ {
+ ParameterInfo? paramInfo = null;
+ parameterInfos?.TryGetValue(param.Name, out paramInfo);
+ kernelParams.Add(new(param.Name, aiFunction.JsonSerializerOptions)
+ {
+ 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(),
+ ParameterType = paramInfo?.ParameterType,
+ Schema = param.Value.TryGetProperty("schema", out JsonElement schema) ? new KernelJsonSchema(schema) : null,
+ });
+ }
+
+ return kernelParams;
+ }
}
diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatClientChatCompletionService.cs b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatClientChatCompletionService.cs
index 7447b230ec63..419dca381015 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatClientChatCompletionService.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatClientChatCompletionService.cs
@@ -34,12 +34,12 @@ public ChatClientChatCompletionService(IChatClient chatClient, IServiceProvider?
var attrs = new Dictionary();
this.Attributes = new ReadOnlyDictionary(attrs);
- var metadata = chatClient.Metadata;
- if (metadata.ProviderUri is not null)
+ var metadata = chatClient.GetService();
+ if (metadata?.ProviderUri is not null)
{
attrs[AIServiceExtensions.EndpointKey] = metadata.ProviderUri.ToString();
}
- if (metadata.ModelId is not null)
+ if (metadata?.ModelId is not null)
{
attrs[AIServiceExtensions.ModelIdKey] = metadata.ModelId;
}
@@ -57,7 +57,7 @@ public async Task> GetChatMessageContentsAsync
var messageList = ChatCompletionServiceExtensions.ToChatMessageList(chatHistory);
var currentSize = messageList.Count;
- var completion = await this._chatClient.CompleteAsync(
+ var completion = await this._chatClient.GetResponseAsync(
messageList,
ToChatOptions(executionSettings, kernel),
cancellationToken).ConfigureAwait(false);
@@ -76,7 +76,7 @@ public async IAsyncEnumerable GetStreamingChatMessa
{
Verify.NotNull(chatHistory);
- await foreach (var update in this._chatClient.CompleteStreamingAsync(
+ await foreach (var update in this._chatClient.GetStreamingResponseAsync(
ChatCompletionServiceExtensions.ToChatMessageList(chatHistory),
ToChatOptions(executionSettings, kernel),
cancellationToken).ConfigureAwait(false))
@@ -158,13 +158,19 @@ public async IAsyncEnumerable GetStreamingChatMessa
else if (entry.Key.Equals("response_format", StringComparison.OrdinalIgnoreCase) &&
entry.Value is { } responseFormat)
{
- options.ResponseFormat = responseFormat switch
+ if (TryConvert(responseFormat, out string? responseFormatString))
{
- "text" => ChatResponseFormat.Text,
- "json_object" => ChatResponseFormat.Json,
- JsonElement e => ChatResponseFormat.ForJsonSchema(e),
- _ => null,
- };
+ options.ResponseFormat = responseFormatString switch
+ {
+ "text" => ChatResponseFormat.Text,
+ "json_object" => ChatResponseFormat.Json,
+ _ => null,
+ };
+ }
+ else
+ {
+ options.ResponseFormat = responseFormat is JsonElement e ? ChatResponseFormat.ForJsonSchema(e) : null;
+ }
}
else
{
@@ -268,9 +274,9 @@ static bool TryConvert(object? value, [NotNullWhen(true)] out T? result)
}
}
- /// Converts a to a .
+ /// Converts a to a .
/// This conversion should not be necessary once SK eventually adopts the shared content types.
- private static StreamingChatMessageContent ToStreamingChatMessageContent(StreamingChatCompletionUpdate update)
+ private static StreamingChatMessageContent ToStreamingChatMessageContent(ChatResponseUpdate update)
{
StreamingChatMessageContent content = new(
update.Role is not null ? new AuthorRole(update.Role.Value.Value) : null,
diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceChatClient.cs b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceChatClient.cs
index 308dbc64e183..862239ccd505 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceChatClient.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceChatClient.cs
@@ -35,7 +35,7 @@ public ChatCompletionServiceChatClient(IChatCompletionService chatCompletionServ
public ChatClientMetadata Metadata { get; }
///
- public async Task CompleteAsync(IList chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)
+ public async Task GetResponseAsync(IList chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default)
{
Verify.NotNull(chatMessages);
@@ -53,7 +53,7 @@ public ChatCompletionServiceChatClient(IChatCompletionService chatCompletionServ
}
///
- public async IAsyncEnumerable CompleteStreamingAsync(IList chatMessages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ public async IAsyncEnumerable GetStreamingResponseAsync(IList chatMessages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
Verify.NotNull(chatMessages);
@@ -82,6 +82,7 @@ public void Dispose()
serviceKey is not null ? null :
serviceType.IsInstanceOfType(this) ? this :
serviceType.IsInstanceOfType(this._chatCompletionService) ? this._chatCompletionService :
+ serviceType.IsInstanceOfType(this.Metadata) ? this.Metadata :
null;
}
@@ -191,11 +192,11 @@ public void Dispose()
return settings;
}
- /// Converts a to a .
+ /// Converts a to a .
/// This conversion should not be necessary once SK eventually adopts the shared content types.
- private static StreamingChatCompletionUpdate ToStreamingChatCompletionUpdate(StreamingChatMessageContent content)
+ private static ChatResponseUpdate ToStreamingChatCompletionUpdate(StreamingChatMessageContent content)
{
- StreamingChatCompletionUpdate update = new()
+ ChatResponseUpdate update = new()
{
AdditionalProperties = content.Metadata is not null ? new AdditionalPropertiesDictionary(content.Metadata) : null,
AuthorName = content.AuthorName,
diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceExtensions.cs b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceExtensions.cs
index ef8b0b56c7f9..cf5834725700 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceExtensions.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AI/ChatCompletion/ChatCompletionServiceExtensions.cs
@@ -169,15 +169,15 @@ internal static ChatMessage ToChatMessage(ChatMessageContent content)
case Microsoft.SemanticKernel.ImageContent ic:
aiContent =
- ic.DataUri is not null ? new Microsoft.Extensions.AI.ImageContent(ic.DataUri, ic.MimeType) :
- ic.Uri is not null ? new Microsoft.Extensions.AI.ImageContent(ic.Uri, ic.MimeType) :
+ ic.DataUri is not null ? new Microsoft.Extensions.AI.DataContent(ic.DataUri, ic.MimeType ?? "image/*") :
+ ic.Uri is not null ? new Microsoft.Extensions.AI.DataContent(ic.Uri, ic.MimeType ?? "image/*") :
null;
break;
case Microsoft.SemanticKernel.AudioContent ac:
aiContent =
- ac.DataUri is not null ? new Microsoft.Extensions.AI.AudioContent(ac.DataUri, ac.MimeType) :
- ac.Uri is not null ? new Microsoft.Extensions.AI.AudioContent(ac.Uri, ac.MimeType) :
+ ac.DataUri is not null ? new Microsoft.Extensions.AI.DataContent(ac.DataUri, ac.MimeType ?? "audio/*") :
+ ac.Uri is not null ? new Microsoft.Extensions.AI.DataContent(ac.Uri, ac.MimeType ?? "audio/*") :
null;
break;
@@ -193,7 +193,7 @@ internal static ChatMessage ToChatMessage(ChatMessageContent content)
break;
case Microsoft.SemanticKernel.FunctionResultContent frc:
- aiContent = new Microsoft.Extensions.AI.FunctionResultContent(frc.CallId ?? string.Empty, frc.FunctionName ?? string.Empty, frc.Result);
+ aiContent = new Microsoft.Extensions.AI.FunctionResultContent(frc.CallId ?? string.Empty, frc.Result);
break;
}
@@ -211,13 +211,13 @@ internal static ChatMessage ToChatMessage(ChatMessageContent content)
/// Converts a to a .
/// This conversion should not be necessary once SK eventually adopts the shared content types.
- internal static ChatMessageContent ToChatMessageContent(ChatMessage message, Microsoft.Extensions.AI.ChatCompletion? completion = null)
+ internal static ChatMessageContent ToChatMessageContent(ChatMessage message, Microsoft.Extensions.AI.ChatResponse? response = null)
{
ChatMessageContent result = new()
{
- ModelId = completion?.ModelId,
+ ModelId = response?.ModelId,
AuthorName = message.AuthorName,
- InnerContent = completion?.RawRepresentation ?? message.RawRepresentation,
+ InnerContent = response?.RawRepresentation ?? message.RawRepresentation,
Metadata = message.AdditionalProperties,
Role = new AuthorRole(message.Role.Value),
};
@@ -231,20 +231,20 @@ internal static ChatMessageContent ToChatMessageContent(ChatMessage message, Mic
resultContent = new Microsoft.SemanticKernel.TextContent(tc.Text);
break;
- case Microsoft.Extensions.AI.ImageContent ic:
- resultContent = ic.ContainsData ?
- new Microsoft.SemanticKernel.ImageContent(ic.Uri) :
- new Microsoft.SemanticKernel.ImageContent(new Uri(ic.Uri));
+ case Microsoft.Extensions.AI.DataContent dc when dc.MediaTypeStartsWith("image/"):
+ resultContent = dc.Data is not null ?
+ new Microsoft.SemanticKernel.ImageContent(dc.Uri) :
+ new Microsoft.SemanticKernel.ImageContent(new Uri(dc.Uri));
break;
- case Microsoft.Extensions.AI.AudioContent ac:
- resultContent = ac.ContainsData ?
- new Microsoft.SemanticKernel.AudioContent(ac.Uri) :
- new Microsoft.SemanticKernel.AudioContent(new Uri(ac.Uri));
+ case Microsoft.Extensions.AI.DataContent dc when dc.MediaTypeStartsWith("audio/"):
+ resultContent = dc.Data is not null ?
+ new Microsoft.SemanticKernel.AudioContent(dc.Uri) :
+ new Microsoft.SemanticKernel.AudioContent(new Uri(dc.Uri));
break;
case Microsoft.Extensions.AI.DataContent dc:
- resultContent = dc.ContainsData ?
+ resultContent = dc.Data is not null ?
new Microsoft.SemanticKernel.BinaryContent(dc.Uri) :
new Microsoft.SemanticKernel.BinaryContent(new Uri(dc.Uri));
break;
@@ -254,7 +254,7 @@ internal static ChatMessageContent ToChatMessageContent(ChatMessage message, Mic
break;
case Microsoft.Extensions.AI.FunctionResultContent frc:
- resultContent = new Microsoft.SemanticKernel.FunctionResultContent(frc.Name, null, frc.CallId, frc.Result);
+ resultContent = new Microsoft.SemanticKernel.FunctionResultContent(callId: frc.CallId, result: frc.Result);
break;
}
@@ -262,7 +262,7 @@ internal static ChatMessageContent ToChatMessageContent(ChatMessage message, Mic
{
resultContent.Metadata = content.AdditionalProperties;
resultContent.InnerContent = content.RawRepresentation;
- resultContent.ModelId = completion?.ModelId;
+ resultContent.ModelId = response?.ModelId;
result.Items.Add(resultContent);
}
}
diff --git a/dotnet/src/SemanticKernel.Abstractions/AI/Embeddings/EmbeddingGenerationServiceExtensions.cs b/dotnet/src/SemanticKernel.Abstractions/AI/Embeddings/EmbeddingGenerationServiceExtensions.cs
index c060c3f0d523..96f1dd0252dd 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AI/Embeddings/EmbeddingGenerationServiceExtensions.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AI/Embeddings/EmbeddingGenerationServiceExtensions.cs
@@ -132,6 +132,7 @@ public async Task>> GenerateAsync(IEnu
serviceKey is not null ? null :
serviceType.IsInstanceOfType(this) ? this :
serviceType.IsInstanceOfType(this._service) ? this._service :
+ serviceType.IsInstanceOfType(this.Metadata) ? this.Metadata :
null;
}
}
@@ -154,12 +155,12 @@ public EmbeddingGeneratorEmbeddingGenerationService(
var attrs = new Dictionary();
this.Attributes = new ReadOnlyDictionary(attrs);
- var metadata = generator.Metadata;
- if (metadata.ProviderUri is not null)
+ var metadata = (EmbeddingGeneratorMetadata?)generator.GetService(typeof(EmbeddingGeneratorMetadata));
+ if (metadata?.ProviderUri is not null)
{
attrs[AIServiceExtensions.EndpointKey] = metadata.ProviderUri.ToString();
}
- if (metadata.ModelId is not null)
+ if (metadata?.ModelId is not null)
{
attrs[AIServiceExtensions.ModelIdKey] = metadata.ModelId;
}
diff --git a/dotnet/src/SemanticKernel.Abstractions/AbstractionsJsonContext.cs b/dotnet/src/SemanticKernel.Abstractions/AbstractionsJsonContext.cs
index 29caab93da9a..736710ab146c 100644
--- a/dotnet/src/SemanticKernel.Abstractions/AbstractionsJsonContext.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/AbstractionsJsonContext.cs
@@ -6,6 +6,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
+using Microsoft.SemanticKernel.Functions;
namespace Microsoft.SemanticKernel;
@@ -15,6 +16,7 @@ namespace Microsoft.SemanticKernel;
WriteIndented = true)]
[JsonSerializable(typeof(IDictionary))]
[JsonSerializable(typeof(JsonElement))]
+[JsonSerializable(typeof(KernelFunctionSchemaModel))]
[JsonSerializable(typeof(PromptExecutionSettings))]
// types commonly used as values in settings dictionaries
[JsonSerializable(typeof(string))]
diff --git a/dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunction.cs b/dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunction.cs
index cc2d260b48a7..fddac8f48282 100644
--- a/dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunction.cs
+++ b/dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunction.cs
@@ -16,6 +16,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.SemanticKernel.Diagnostics;
+using Microsoft.SemanticKernel.Functions;
namespace Microsoft.SemanticKernel;
@@ -517,6 +518,7 @@ public AIFunction AsAIFunction(Kernel? kernel = null)
/// An wrapper around a .
private sealed class KernelAIFunction : AIFunction
{
+ private static readonly JsonElement s_defaultSchema = JsonDocument.Parse("{}").RootElement;
private readonly KernelFunction _kernelFunction;
private readonly Kernel? _kernel;
@@ -524,37 +526,17 @@ public KernelAIFunction(KernelFunction kernelFunction, Kernel? kernel)
{
this._kernelFunction = kernelFunction;
this._kernel = kernel;
-
- string name = string.IsNullOrWhiteSpace(kernelFunction.PluginName) ?
+ this.Name = string.IsNullOrWhiteSpace(kernelFunction.PluginName) ?
kernelFunction.Name :
$"{kernelFunction.PluginName}-{kernelFunction.Name}";
- this.Metadata = new AIFunctionMetadata(name)
- {
- Description = kernelFunction.Description,
-
- JsonSerializerOptions = kernelFunction.JsonSerializerOptions,
-
- Parameters = kernelFunction.Metadata.Parameters.Select(p => new AIFunctionParameterMetadata(p.Name)
- {
- Description = p.Description,
- ParameterType = p.ParameterType,
- IsRequired = p.IsRequired,
- HasDefaultValue = p.DefaultValue is not null,
- DefaultValue = p.DefaultValue,
- Schema = p.Schema?.RootElement,
- }).ToList(),
-
- ReturnParameter = new AIFunctionReturnParameterMetadata()
- {
- Description = kernelFunction.Metadata.ReturnParameter.Description,
- ParameterType = kernelFunction.Metadata.ReturnParameter.ParameterType,
- Schema = kernelFunction.Metadata.ReturnParameter.Schema?.RootElement,
- },
- };
+ this.JsonSchema = BuildFunctionSchema(kernelFunction);
}
- public override AIFunctionMetadata Metadata { get; }
+ public override string Name { get; }
+ public override JsonElement JsonSchema { get; }
+ public override string Description => this._kernelFunction.Description;
+ public override JsonSerializerOptions JsonSerializerOptions => this._kernelFunction.JsonSerializerOptions ?? base.JsonSerializerOptions;
protected override async Task