Skip to content

Commit

Permalink
.Net: Removing IsSemantic and IsAsync properties from ISKFunction and…
Browse files Browse the repository at this point in the history
… FunctionView (microsoft#2881)

### Motivation and Context
The Kernel no longer differentiates between Native and Semantic
functions, nor between async and synchronous functions. These are
abstractions that are resolved internally.

### Description
ISKFunction
 - Removing IsSemantic
 - Updating tests and callers

FunctionView
 - Removing IsSemantic
 - Removing IsAsync
 - Updating tests and callers

### Contribution Checklist
- [X] The code builds clean without any errors or warnings
- [X] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [X] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄
   BREAKING CHANGE - due to change in public APIs. Low impact.

---------

Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
  • Loading branch information
2 people authored and SOE-YoungS committed Oct 31, 2023
1 parent 663f2b8 commit 0a0ad99
Show file tree
Hide file tree
Showing 25 changed files with 194 additions and 283 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private Mock<ISkillCollection> CreateMockSkillCollection()
var skills = new Mock<ISkillCollection>();
foreach (var (name, skillName, description, isSemantic) in functions)
{
var functionView = new FunctionView(name, skillName, description, new List<ParameterView>(), isSemantic, true);
var functionView = new FunctionView(name, skillName, description);
var mockFunction = CreateMockFunction(functionView);
functionsView.Add(functionView);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public async Task CanCallGetAvailableFunctionsWithFunctionsAsync()

// Arrange FunctionView
var functionMock = new Mock<ISKFunction>();
var functionView = new FunctionView("functionName", "skillName", "description", new List<ParameterView>(), true, false);
var nativeFunctionView = new FunctionView("nativeFunctionName", "skillName", "description", new List<ParameterView>(), false, false);
var functionView = new FunctionView("functionName", "skillName", "description");
var nativeFunctionView = new FunctionView("nativeFunctionName", "skillName", "description");
var functionsView = new List<FunctionView>() { functionView, nativeFunctionView };

// Arrange Mock Memory and Result
Expand Down Expand Up @@ -133,8 +133,8 @@ public async Task CanCallGetAvailableFunctionsWithFunctionsWithRelevancyAsync()

// Arrange FunctionView
var functionMock = new Mock<ISKFunction>();
var functionView = new FunctionView("functionName", "skillName", "description", new List<ParameterView>(), true, false);
var nativeFunctionView = new FunctionView("nativeFunctionName", "skillName", "description", new List<ParameterView>(), false, false);
var functionView = new FunctionView("functionName", "skillName", "description");
var nativeFunctionView = new FunctionView("nativeFunctionName", "skillName", "description");
var functionsView = new List<FunctionView>() { functionView, nativeFunctionView };

// Arrange Mock Memory and Result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ private static Mock<ISKFunction> CreateMockFunction(FunctionView functionView, s
var functionsView = new List<FunctionView>();
foreach (var (name, skillName, description, isSemantic, resultString) in functions)
{
var functionView = new FunctionView(name, skillName, description, new List<ParameterView>() { new(name: "param", description: "description") }, isSemantic, true);
var functionView = new FunctionView(name, skillName, description)
{
Parameters = new ParameterView[] { new("param", "description") }
};
var mockFunction = CreateMockFunction(functionView);
functionsView.Add(functionView);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task ItCanCreatePlanAsync(string goal)
var skills = new Mock<ISkillCollection>();
foreach (var (name, skillName, description, isSemantic) in input)
{
var functionView = new FunctionView(name, skillName, description, new List<ParameterView>(), isSemantic, true);
var functionView = new FunctionView(name, skillName, description);
var mockFunction = CreateMockFunction(functionView);
functionsView.Add(functionView);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal static class GrpcOperationExtensions
/// <returns>The list of parameters.</returns>
public static IReadOnlyList<ParameterView> GetParameters(this GrpcOperation operation)
{
var parameters = new List<ParameterView>
var parameters = new ParameterView[]
{
// Register the "address" parameter so that it's possible to override it if needed.
new ParameterView(GrpcOperation.AddressArgumentName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,8 @@ async Task<SKContext> ExecuteAsync(SKContext context)
}

var parameters = restOperationParameters
.Select(p => new ParameterView
.Select(p => new ParameterView(p.AlternativeName ?? p.Name)
{
Name = p.AlternativeName ?? p.Name,
Description = $"{p.Description ?? p.Name}{(p.IsRequired ? " (required)" : string.Empty)}",
DefaultValue = p.DefaultValue ?? string.Empty,
Type = string.IsNullOrEmpty(p.Type) ? null : new ParameterViewType(p.Type),
Expand Down
14 changes: 14 additions & 0 deletions dotnet/src/InternalUtilities/src/Diagnostics/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.

using System.ComponentModel;

namespace System.Runtime.CompilerServices;

/// <summary>
/// Reserved to be used by the compiler for tracking metadata.
/// This class should not be used by developers in source code.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal static class IsExternalInit
{
}
2 changes: 1 addition & 1 deletion dotnet/src/InternalUtilities/src/Diagnostics/Verify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ internal static void DirectoryExists(string path)
/// Make sure every function parameter name is unique
/// </summary>
/// <param name="parameters">List of parameters</param>
internal static void ParametersUniqueness(IList<ParameterView> parameters)
internal static void ParametersUniqueness(IReadOnlyList<ParameterView> parameters)
{
int count = parameters.Count;
if (count > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ namespace Microsoft.SemanticKernel.SemanticFunctions;
public interface IPromptTemplate
{
/// <summary>
/// Get the list of parameters required by the template, using configuration and template info.
/// The list of parameters required by the template, using configuration and template info.
/// </summary>
/// <returns>List of parameters</returns>
IList<ParameterView> GetParameters();
IReadOnlyList<ParameterView> Parameters { get; }

/// <summary>
/// Render the template using the information in the context
Expand Down
Original file line number Diff line number Diff line change
@@ -1,79 +1,25 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Microsoft.SemanticKernel.SkillDefinition;

/// <summary>
/// Class used to copy and export data from the skill collection.
/// The data is mutable, but changes do not affect the skill collection.
/// A function view is a read-only representation of a function.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class FunctionView
/// <param name="Name">Name of the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}</param>
/// <param name="SkillName">Name of the skill containing the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}</param>
/// <param name="Description">Function description. The description is used in combination with embeddings when searching relevant functions.</param>
/// <param name="Parameters">Optional list of function parameters</param>
public sealed record FunctionView(
string Name,
string SkillName,
string Description = "",
IReadOnlyList<ParameterView>? Parameters = null)
{
/// <summary>
/// Name of the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}
/// </summary>
public string Name { get; set; } = string.Empty;

/// <summary>
/// Name of the skill containing the function. The name is used by the skill collection and in prompt templates e.g. {{skillName.functionName}}
/// </summary>
public string SkillName { get; set; } = string.Empty;

/// <summary>
/// Function description. The description is used in combination with embeddings when searching relevant functions.
/// </summary>
public string Description { get; set; } = string.Empty;

/// <summary>
/// Whether the delegate points to a semantic function
/// </summary>
public bool IsSemantic { get; set; }

/// <summary>
/// Whether the delegate is an asynchronous function
/// </summary>
public bool IsAsynchronous { get; set; }

/// <summary>
/// List of function parameters
/// </summary>
public IList<ParameterView> Parameters { get; set; } = new List<ParameterView>();

/// <summary>
/// Constructor
/// </summary>
public FunctionView()
{
}

/// <summary>
/// Create a function view.
/// </summary>
/// <param name="name">Function name</param>
/// <param name="skillName">Skill name, e.g. the function namespace</param>
/// <param name="description">Function description</param>
/// <param name="parameters">List of function parameters provided by the skill developer</param>
/// <param name="isSemantic">Whether the function is a semantic one (or native is False)</param>
/// <param name="isAsynchronous">Whether the function is async. Note: all semantic functions are async.</param>
public FunctionView(
string name,
string skillName,
string description,
IList<ParameterView> parameters,
bool isSemantic,
bool isAsynchronous = true)
{
this.Name = name;
this.SkillName = skillName;
this.Description = description;
this.Parameters = parameters;
this.IsSemantic = isSemantic;
this.IsAsynchronous = isAsynchronous;
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay => $"{this.Name} ({this.Description})";
public IReadOnlyList<ParameterView> Parameters { get; init; } = Parameters ?? Array.Empty<ParameterView>();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SemanticKernel.AI;
Expand Down Expand Up @@ -29,13 +30,6 @@ public interface ISKFunction
/// </summary>
string Description { get; }

/// <summary>
/// Whether the function is defined using a prompt template.
/// IMPORTANT: native functions might use semantic functions internally,
/// so when this property is False, executing the function might still involve AI calls.
/// </summary>
bool IsSemantic { get; }

/// <summary>
/// AI service settings
/// </summary>
Expand Down Expand Up @@ -81,4 +75,17 @@ public interface ISKFunction
/// <param name="requestSettings">LLM completion settings</param>
/// <returns>Self instance</returns>
ISKFunction SetAIConfiguration(AIRequestSettings? requestSettings);

#region Obsolete

/// <summary>
/// Whether the function is defined using a prompt template.
/// IMPORTANT: native functions might use semantic functions internally,
/// so when this property is False, executing the function might still involve AI calls.
/// </summary>
[Obsolete("Kernel no longer differentiates between Semantic and Native functions. This will be removed in a future release.")]
[EditorBrowsable(EditorBrowsableState.Never)]
bool IsSemantic { get; }

#endregion
}
Original file line number Diff line number Diff line change
@@ -1,75 +1,16 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics;
using Microsoft.SemanticKernel.Diagnostics;

namespace Microsoft.SemanticKernel.SkillDefinition;

/// <summary>
/// Class used to copy and export data about parameters
/// for planner and related scenarios.
/// Class used to copy and export data about parameters for planner and related scenarios.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class ParameterView
{
private string _name = string.Empty;

/// <summary>
/// Parameter name. Alphanumeric chars + "_" only.
/// </summary>
public string Name
{
get => this._name;
set
{
Verify.ValidFunctionParamName(value);
this._name = value;
}
}

/// <summary>
/// Parameter description.
/// </summary>
public string? Description { get; set; }

/// <summary>
/// Default value when the value is not provided.
/// </summary>
public string? DefaultValue { get; set; }

/// <summary>
/// Parameter type.
/// </summary>
public ParameterViewType? Type { get; set; }

/// <summary>
/// Constructor
/// </summary>
public ParameterView()
{
}

/// <summary>
/// Create a function parameter view, using information provided by the skill developer.
/// </summary>
/// <param name="name">Parameter name. The name must be alphanumeric (underscore is the only special char allowed).</param>
/// <param name="description">Parameter description</param>
/// <param name="defaultValue">Default parameter value, if not provided</param>
/// <param name="type">Parameter type.</param>
public ParameterView(
string name,
string? description = null,
string? defaultValue = null,
ParameterViewType? type = null)
{
this.Name = name;
this.Description = description;
this.DefaultValue = defaultValue;
this.Type = type;
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay => string.IsNullOrEmpty(this.Description)
? this.Name
: $"{this.Name} ({this.Description})";
}
/// <param name="Name">Parameter name. The name must be alphanumeric (underscore is the only special char allowed).</param>
/// <param name="Description">Parameter description</param>
/// <param name="DefaultValue">Default parameter value, if not provided</param>
/// <param name="Type">Parameter type.</param>
public sealed record ParameterView(
string Name,
string? Description = null,
string? DefaultValue = null,
ParameterViewType? Type = null);
Loading

0 comments on commit 0a0ad99

Please sign in to comment.