Skip to content

Commit

Permalink
.Net: Adding #each block details + jsonSerializer fix to handle named…
Browse files Browse the repository at this point in the history
… FP literals (#5183)

### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->
Adding #each block details + jsonSerializer fix to handle named FP
literals

Resolves #4838

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [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
- [x] I didn't break anyone 😄
  • Loading branch information
teresaqhoang committed Feb 27, 2024
1 parent 36ce92f commit 90de4f8
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 18 deletions.
37 changes: 22 additions & 15 deletions dotnet/samples/KernelSyntaxExamples/Example65_HandlebarsPlanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,25 @@ private void PrintPlannerDetails(string goal, HandlebarsPlan plan, string result
[InlineData(false)]
public async Task PlanNotPossibleSampleAsync(bool shouldPrintPrompt)
{
WriteSampleHeading("Plan Not Possible");

// Load additional plugins to enable planner but not enough for the given goal.
await RunSampleAsync("Send Mary an email with the list of meetings I have scheduled today.", null, null, shouldPrintPrompt, true, "SummarizePlugin");
/*
[InsufficientFunctionsForGoal] Unable to create plan for goal with available functions.
Goal: Send Mary an email with the list of meetings I have scheduled today.
Available Functions: SummarizePlugin-MakeAbstractReadable, SummarizePlugin-Notegen, SummarizePlugin-Summarize, SummarizePlugin-Topics
Planner output:
As the available helpers do not contain any functionality to send an email or interact with meeting scheduling data, I cannot create a template to achieve the stated goal.
Additional helpers or information may be required.
*/
try
{
WriteSampleHeading("Plan Not Possible");

// Load additional plugins to enable planner but not enough for the given goal.
await RunSampleAsync("Send Mary an email with the list of meetings I have scheduled today.", null, null, shouldPrintPrompt, true, "SummarizePlugin");
/*
[InsufficientFunctionsForGoal] Unable to create plan for goal with available functions.
Goal: Send Mary an email with the list of meetings I have scheduled today.
Available Functions: SummarizePlugin-MakeAbstractReadable, SummarizePlugin-Notegen, SummarizePlugin-Summarize, SummarizePlugin-Topics
Planner output:
As the available helpers do not contain any functionality to send an email or interact with meeting scheduling data, I cannot create a template to achieve the stated goal.
Additional helpers or information may be required.
*/
}
catch (Exception e)
{
WriteLine(e.InnerException?.Message);
}
}

[RetryTheory(typeof(HttpOperationException))]
Expand Down Expand Up @@ -325,11 +332,11 @@ public Task RunPredefinedVariablesSampleAsync(bool shouldPrintPrompt)
return RunSampleAsync("Write a poem about the given person, then translate it into French.", null, initialArguments, shouldPrintPrompt, true, "WriterPlugin", "MiscPlugin");
/*
Original plan:
{{!-- Step 0: Set the given person --}}
{{set "person" "John Doe"}}
{{!-- Step 0: Extract key values --}}
{{set "personName" @root.person.name}}
{{!-- Step 1: Generate a short poem about the person --}}
{{set "poem" (WriterPlugin-ShortPoem input=person)}}
{{set "poem" (WriterPlugin-ShortPoem input=personName)}}
{{!-- Step 2: Translate the poem into French --}}
{{set "translatedPoem" (WriterPlugin-Translate input=poem language="French")}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ namespace Microsoft.SemanticKernel.PromptTemplates.Handlebars.Helpers;
/// </summary>
internal static class KernelSystemHelpers
{
/// <summary>
/// The "NaN", "Infinity", and "-Infinity" String tokens can be read as floating-point constants, and the Single and Double values for these constants will be written as their corresponding JSON string representations.
/// </summary>
private static readonly JsonSerializerOptions s_jsonSerializerOptions = new()
{
NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals
};

/// <summary>
/// Register all (default) or specific categories of system helpers.
/// </summary>
Expand Down Expand Up @@ -91,11 +99,13 @@ internal static class KernelSystemHelpers
var args = ProcessArguments(arguments, variables);
object objectToSerialize = args[0];
return objectToSerialize switch
object v = objectToSerialize switch
{
string stringObject => objectToSerialize,
_ => JsonSerializer.Serialize(objectToSerialize)
_ => JsonSerializer.Serialize(objectToSerialize, s_jsonSerializerOptions)
};
return v;
});

handlebarsInstance.RegisterHelper("concat", (in HelperOptions options, in Context context, in Arguments arguments) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
## Built-in block helpers
- `\{{#if}}\{{/if}}`
- `\{{#unless}}\{{/unless}}`{{#if allowLoops}}
- `\{{#each}}\{{/each}}`{{/if}}
- `\{{#each}}\{{/each}}` - inside this block, you can use:
- `this` to reference the element being iterated over
- `@index` to reference the current index
- `@key` to reference the current key (for object iteration){{/if}}
- `\{{#with}}\{{/with}}`
{{/inline}}

0 comments on commit 90de4f8

Please sign in to comment.