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: New result types - FunctionResult and KernelResult #2864

Merged
merged 31 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
efcfdc3
Introduced FunctionResult and KernelResult
dmytrostruk Sep 18, 2023
ba85008
Fixed null warnings
dmytrostruk Sep 18, 2023
1366c4d
Fixed null reference warnings
dmytrostruk Sep 18, 2023
5fdf312
Small improvement
dmytrostruk Sep 18, 2023
e1d9fbb
Added unit tests to verify FunctionResult
dmytrostruk Sep 18, 2023
7de92ac
Added support for IAsyncEnumerable in FunctionResult
dmytrostruk Sep 18, 2023
6b2240f
Added XML documentation
dmytrostruk Sep 18, 2023
efdc7dc
Merge branch 'main' into new-result-types
dmytrostruk Sep 18, 2023
26f5dae
Run dotnet format
dmytrostruk Sep 18, 2023
5000e3f
Merge branch 'main' into new-result-types
dmytrostruk Sep 19, 2023
3ae474a
Addressed PR feedback
dmytrostruk Sep 19, 2023
e88dd5a
Improved KernelResult
dmytrostruk Sep 19, 2023
b35543d
Merge from main branch
dmytrostruk Sep 19, 2023
256fb2d
Merge branch 'main' into new-result-types
dmytrostruk Sep 19, 2023
e06cedb
Merge branch 'main' into new-result-types
dmytrostruk Sep 19, 2023
524d954
Merge from main branch
dmytrostruk Sep 20, 2023
fa39156
Fixes based on PR feedback
dmytrostruk Sep 20, 2023
42e89e2
Merge from main branch
dmytrostruk Sep 21, 2023
26e11b2
Added FunctionName, PluginName and Metadata to FunctionResult
dmytrostruk Sep 21, 2023
53eb4f6
Added unit test for function results
dmytrostruk Sep 21, 2023
be91c3c
Merge branch 'main' into pr/2864
dmytrostruk Sep 21, 2023
07fdbfe
Merge branch 'main' into new-result-types
dmytrostruk Sep 21, 2023
66536c0
Small improvements
dmytrostruk Sep 21, 2023
9535937
Merge branch 'new-result-types' of https://github.com/dmytrostruk/sem…
dmytrostruk Sep 21, 2023
cebec10
Small fix in Plan. Fixed tests.
dmytrostruk Sep 21, 2023
124e68d
Small fixes
dmytrostruk Sep 21, 2023
07e7a3d
Merge branch 'main' into new-result-types
dmytrostruk Sep 21, 2023
ba9144e
Small update in Plan
dmytrostruk Sep 21, 2023
cfa2c25
Added MADR
dmytrostruk Sep 21, 2023
a0c8124
Merge branch 'main' into pr/2864
dmytrostruk Sep 22, 2023
07e792d
Merge branch 'main' into new-result-types
dmytrostruk Sep 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion dotnet/samples/ApplicationInsightsExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static async Task Main()
var result = await kernel.RunAsync(plan);

Console.WriteLine("Result:");
Console.WriteLine(result.Result);
Console.WriteLine(result.GetValue<string>());
}
finally
{
Expand Down
4 changes: 2 additions & 2 deletions dotnet/samples/KernelSyntaxExamples/Example02_Pipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ public static async Task RunAsync()
// Load native skill
var text = kernel.ImportSkill(new TextPlugin());

SKContext result = await kernel.RunAsync(" i n f i n i t e s p a c e ",
KernelResult result = await kernel.RunAsync(" i n f i n i t e s p a c e ",
text["TrimStart"],
text["TrimEnd"],
text["Uppercase"]);

Console.WriteLine(result);
Console.WriteLine(result.GetValue<string>());
}
}
4 changes: 2 additions & 2 deletions dotnet/samples/KernelSyntaxExamples/Example03_Variables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public static async Task RunAsync()
var variables = new ContextVariables("Today is: ");
variables.Set("day", DateTimeOffset.Now.ToString("dddd", CultureInfo.CurrentCulture));

SKContext result = await kernel.RunAsync(variables,
KernelResult result = await kernel.RunAsync(variables,
text["AppendDay"],
text["Uppercase"]);

Console.WriteLine(result);
Console.WriteLine(result.GetValue<string>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,15 @@ private static async Task Example2Async(IKernel kernel)
["externalInformation"] = string.Empty
});

var result = answer.GetValue<string>()!;

// If the answer contains commands, execute them using the prompt renderer.
if (answer.Result.Contains("bing.search", StringComparison.OrdinalIgnoreCase))
if (result.Contains("bing.search", StringComparison.OrdinalIgnoreCase))
{
var promptRenderer = new PromptTemplateEngine();

Console.WriteLine("---- Fetching information from Bing...");
var information = await promptRenderer.RenderAsync(answer.Result, kernel.CreateNewContext());
var information = await promptRenderer.RenderAsync(result, kernel.CreateNewContext());

Console.WriteLine("Information found:");
Console.WriteLine(information);
Expand All @@ -167,7 +169,7 @@ private static async Task Example2Async(IKernel kernel)
}

Console.WriteLine("---- ANSWER:");
Console.WriteLine(answer);
Console.WriteLine(answer.GetValue<string>());

/* OUTPUT:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private static async Task PoetrySamplesAsync()
var result = await kernel.RunAsync(plan);

Console.WriteLine("Result:");
Console.WriteLine(result.Result);
Console.WriteLine(result.GetValue<string>());
}

private static async Task EmailSamplesWithRecallAsync()
Expand Down Expand Up @@ -186,7 +186,7 @@ await foreach (MemoryQueryResult memory in memories)
var result = await kernel.RunAsync(newInput, restoredPlan);

Console.WriteLine("Result:");
Console.WriteLine(result.Result);
Console.WriteLine(result.GetValue<string>());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ private static async Task ConversationSummaryPluginAsync()
IDictionary<string, ISKFunction> conversationSummarySkill =
kernel.ImportSkill(new ConversationSummaryPlugin(kernel));

SKContext summary = await kernel.RunAsync(
KernelResult summary = await kernel.RunAsync(
ChatTranscript,
conversationSummarySkill["SummarizeConversation"]);

Console.WriteLine("Generated Summary:");
Console.WriteLine(summary.Result);
Console.WriteLine(summary.GetValue<string>());
}

private static async Task GetConversationActionItemsAsync()
Expand All @@ -152,12 +152,12 @@ private static async Task GetConversationActionItemsAsync()
IDictionary<string, ISKFunction> conversationSummarySkill =
kernel.ImportSkill(new ConversationSummaryPlugin(kernel));

SKContext summary = await kernel.RunAsync(
KernelResult summary = await kernel.RunAsync(
ChatTranscript,
conversationSummarySkill["GetConversationActionItems"]);

Console.WriteLine("Generated Action Items:");
Console.WriteLine(summary.Result);
Console.WriteLine(summary.GetValue<string>());
}

private static async Task GetConversationTopicsAsync()
Expand All @@ -168,12 +168,12 @@ private static async Task GetConversationTopicsAsync()
IDictionary<string, ISKFunction> conversationSummarySkill =
kernel.ImportSkill(new ConversationSummaryPlugin(kernel));

SKContext summary = await kernel.RunAsync(
KernelResult summary = await kernel.RunAsync(
ChatTranscript,
conversationSummarySkill["GetConversationTopics"]);

Console.WriteLine("Generated Topics:");
Console.WriteLine(summary.Result);
Console.WriteLine(summary.GetValue<string>());
}

private static IKernel InitializeKernel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static async Task<string> ListPullRequestsFromGitHubAsync(BearerAuthentic
var result = await kernel.RunAsync(contextVariables, skill["PullsList"]);

Console.WriteLine("Successful GitHub List Pull Requests skill response.");
var resultJson = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
var resultJson = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.GetValue<string>()!);
var pullRequests = JArray.Parse((string)resultJson!["content"]);

if (pullRequests != null && pullRequests.First != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static async Task RunAsync()
var result = await kernel.RunAsync(contextVariables, jiraSkills["GetIssue"]);

Console.WriteLine("\n\n\n");
var formattedContent = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result.Result), Formatting.Indented);
var formattedContent = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result.GetValue<string>()!), Formatting.Indented);
Console.WriteLine("GetIssue jiraSkills response: \n{0}", formattedContent);
}

Expand All @@ -74,7 +74,7 @@ public static async Task RunAsync()
var result = await kernel.RunAsync(contextVariables, jiraSkills["AddComment"]);

Console.WriteLine("\n\n\n");
var formattedContent = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result.Result), Formatting.Indented);
var formattedContent = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(result.GetValue<string>()!), Formatting.Indented);
Console.WriteLine("AddComment jiraSkills response: \n{0}", formattedContent);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System;
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.Planning;
using Microsoft.SemanticKernel.Planning.Action;
using RepoUtils;
Expand Down Expand Up @@ -43,10 +42,10 @@ public static async Task RunAsync()
var plan = await planner.CreatePlanAsync(goal);

// Execute the full plan (which is a single function)
SKContext result = await plan.InvokeAsync();
var result = await plan.InvokeAsync();

// Show the result, which should match the given goal
Console.WriteLine(result);
Console.WriteLine(result.GetValue<string>());

/* Output:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static async Task RunAsync()
var result = await plan.InvokeAsync(context);

Console.WriteLine("Result:");
Console.WriteLine(result.Result);
Console.WriteLine(result.GetValue<string>());
Console.WriteLine();
}
/* Example Output
Expand Down Expand Up @@ -154,7 +154,7 @@ public async Task<string> RunMarkupAsync(string docString, SKContext context)
Console.WriteLine();

var result = await plan.InvokeAsync();
return result.Result;
return result.GetValue<string>()!;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ public static async Task RunAsync()
var myFunction = kernel.CreateSemanticFunction(FunctionDefinition);

// Using InvokeAsync with 3 results (Currently invoke only supports 1 result, but you can get the other results from the ModelResults)
var textResult = await myFunction.InvokeAsync("Sci-fi",
var functionResult = await myFunction.InvokeAsync("Sci-fi",
settings: new CompleteRequestSettings { ResultsPerPrompt = 3, MaxTokens = 500, Temperature = 1, TopP = 0.5 });
Console.WriteLine(textResult);
Console.WriteLine(textResult.ModelResults.Select(result => result.GetOpenAIChatResult()).AsJson());

Console.WriteLine(functionResult.GetValue<string>());
Console.WriteLine(functionResult.ModelResults.Select(result => result.GetOpenAIChatResult()).AsJson());
Console.WriteLine();

// Using the Kernel RunAsync
textResult = await kernel.RunAsync("sorry I forgot your birthday", myFunction);
Console.WriteLine(textResult);
Console.WriteLine(textResult.ModelResults.LastOrDefault()?.GetOpenAIChatResult()?.Usage.AsJson());
var kernelResult = await kernel.RunAsync("sorry I forgot your birthday", myFunction);
Console.WriteLine(kernelResult.GetValue<string>());
Console.WriteLine(kernelResult.ModelResults.LastOrDefault()?.GetOpenAIChatResult()?.Usage.AsJson());
Console.WriteLine();

// Using Chat Completion directly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ public static async Task GroundednessCheckingSkill()
context.Variables.Set("topic", "people and places");
context.Variables.Set("example_entities", "John, Jane, mother, brother, Paris, Rome");

var extractionResult = (await entityExtraction.InvokeAsync(context)).Result;
var extractionResult = (await entityExtraction.InvokeAsync(context)).GetValue<string>();

Console.WriteLine("======== Extract Entities ========");
Console.WriteLine(extractionResult);

context.Variables.Update(extractionResult);
context.Variables.Set("reference_context", s_groundingText);

var groundingResult = (await reference_check.InvokeAsync(context)).Result;
var groundingResult = (await reference_check.InvokeAsync(context)).GetValue<string>();

Console.WriteLine("======== Reference Check ========");
Console.WriteLine(groundingResult);
Expand All @@ -106,7 +106,7 @@ public static async Task GroundednessCheckingSkill()
var excisionResult = await entity_excision.InvokeAsync(context);

Console.WriteLine("======== Excise Entities ========");
Console.WriteLine(excisionResult.Result);
Console.WriteLine(excisionResult.GetValue<string>());
}

public static async Task PlanningWithGroundedness()
Expand Down Expand Up @@ -142,7 +142,7 @@ public static async Task PlanningWithGroundedness()
Console.WriteLine(plan.ToPlanWithGoalString());

var results = await plan.InvokeAsync(s_groundingText);
Console.WriteLine(results.Result);
Console.WriteLine(results.GetValue<string>());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.Planning;
using Microsoft.SemanticKernel.Plugins.Core;
using Microsoft.SemanticKernel.Plugins.Web;
Expand Down Expand Up @@ -68,7 +67,7 @@ private static void PrintResults()
Console.WriteLine("Mode\tModel\tAnswer\tStepsTaken\tIterations\tTimeTaken");
foreach (var er in ExecutionResults.OrderByDescending(s => s.model).Where(s => s.question == question))
{
Console.WriteLine($"{er.mode}\t{er.model}\t{er.stepsTaken}\t{er.iterations}\t{er.timeTaken}\t{er.answer}");
Console.WriteLine($"{er.mode}\t{er.model}\t{er.timeTaken}\t{er.answer}");
}
}
}
Expand All @@ -79,8 +78,6 @@ private struct ExecutionResult
public string? model;
public string? question;
public string? answer;
public string? stepsTaken;
public string? iterations;
public string? timeTaken;
}

Expand Down Expand Up @@ -147,42 +144,25 @@ private static async Task RunWithQuestion(IKernel kernel, ExecutionResult curren
plannerConfig.MaxTokens = MaxTokens.Value;
}

SKContext result;
sw.Start();

try
{
StepwisePlanner planner = new(kernel: kernel, config: plannerConfig);
var plan = planner.CreatePlan(question);

result = await plan.InvokeAsync(kernel.CreateNewContext());
var planResult = await plan.InvokeAsync(kernel.CreateNewContext());
var result = planResult.GetValue<string>()!;

if (result.Result.Contains("Result not found, review _stepsTaken to see what", StringComparison.OrdinalIgnoreCase))
if (result.Contains("Result not found, review _stepsTaken to see what", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Could not answer question in " + plannerConfig.MaxIterations + " iterations");
currentExecutionResult.answer = "Could not answer question in " + plannerConfig.MaxIterations + " iterations";
}
else
{
Console.WriteLine("Result: " + result.Result);
currentExecutionResult.answer = result.Result;
}

if (result.Variables.TryGetValue("stepCount", out string? stepCount))
{
Console.WriteLine("Steps Taken: " + stepCount);
currentExecutionResult.stepsTaken = stepCount;
}

if (result.Variables.TryGetValue("skillCount", out string? skillCount))
{
Console.WriteLine("Skills Used: " + skillCount);
}

if (result.Variables.TryGetValue("iterations", out string? iterations))
{
Console.WriteLine("Iterations: " + iterations);
currentExecutionResult.iterations = iterations;
Console.WriteLine("Result: " + result);
currentExecutionResult.answer = result;
}
}
#pragma warning disable CA1031
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void MyRemovedPreExecutionHandler(object? sender, FunctionInvokingEventArgs e)

void MyPostExecutionHandler(object? sender, FunctionInvokedEventArgs e)
{
Console.WriteLine($"{e.FunctionView.SkillName}.{e.FunctionView.Name} : Post Execution Handler - Total Tokens: {e.SKContext.ModelResults.First().GetOpenAIChatResult().Usage.TotalTokens}");
Console.WriteLine($"{e.FunctionView.SkillName}.{e.FunctionView.Name} : Post Execution Handler - Total Tokens: {e.ModelResults.First().GetOpenAIChatResult().Usage.TotalTokens}");
}

kernel.FunctionInvoking += MyPreHandler;
Expand Down Expand Up @@ -238,11 +238,11 @@ private static async Task SkippingFunctionsAsync()
Console.WriteLine($"Only not skipped functions will trigger invoked event - Function name: {e.FunctionView.Name}");
};

var context = await kernel.RunAsync(
var result = await kernel.RunAsync(
skipMeFunction,
dontSkipMeFunction);

Console.WriteLine($"Final result: {context.Result}");
Console.WriteLine($"Final result: {result.GetValue<string>()}");
}

private static async Task RepeatFunctionsAsync()
Expand Down
9 changes: 5 additions & 4 deletions dotnet/samples/NCalcPlugins/LanguageCalculatorPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ public LanguageCalculatorPlugin(IKernel kernel)
string input,
SKContext context)
{
SKContext answer;
string answer;

try
{
answer = await this._mathTranslator.InvokeAsync(input).ConfigureAwait(false);
var result = await this._mathTranslator.InvokeAsync(input).ConfigureAwait(false);
answer = result.GetValue<string>() ?? throw new InvalidOperationException("No result from Math Translator function.");
}
catch (Exception ex)
{
Expand All @@ -102,14 +103,14 @@ public LanguageCalculatorPlugin(IKernel kernel)

string pattern = @"```\s*(.*?)\s*```";

Match match = Regex.Match(answer.Result, pattern, RegexOptions.Singleline);
Match match = Regex.Match(answer, pattern, RegexOptions.Singleline);
if (match.Success)
{
var result = EvaluateMathExpression(match);
return result;
}

throw new InvalidOperationException($"Input value [{input}] could not be understood, received following {answer.Result}");
throw new InvalidOperationException($"Input value [{input}] could not be understood, received following {answer}");
}

private static string EvaluateMathExpression(Match match)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private Mock<IKernel> CreateMockKernelAndFunctionFlowWithTestString(string testP
default
)).Callback<SKContext, CompleteRequestSettings, CancellationToken>(
(c, s, ct) => c.Variables.Update("Hello world!")
).Returns(() => Task.FromResult(returnContext));
).Returns(() => Task.FromResult(new FunctionResult(returnContext, testPlanString)));

// Mock Skills
kernel.Setup(x => x.Skills).Returns(skills.Object);
Expand Down Expand Up @@ -214,7 +214,7 @@ private Mock<ISkillCollection> CreateMockSkillCollection()
.Returns<SKContext, CompleteRequestSettings, CancellationToken>((context, settings, CancellationToken) =>
{
context.Variables.Update("MOCK FUNCTION CALLED");
return Task.FromResult(context);
return Task.FromResult(new FunctionResult(context));
});
skills.Setup(x => x.GetFunction(skillName, name))
.Returns(mockFunction.Object);
Expand Down