-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
.Net: SK Process - Sample 3 Food related samples (#9087)
### Description Adding more SK Processes samples: - Creating SK Process Event Builder: helps link process events to Steps internal events - Adding samples to showcase: - reuse of steps] - use of steps specific functions - how to make use of step functions that output multiple events - use of cycles: FoodRuined -> must prepare the food from scratch For additional details check the `GettingStartedWithProcesses/README.md` file ### 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
1 parent
68187f3
commit a4ddbaa
Showing
13 changed files
with
872 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
dotnet/samples/GettingStartedWithProcesses/Step03/Models/FoodIngredients.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
namespace Step03.Models; | ||
|
||
/// <summary> | ||
/// Food Ingredients used in steps such GatherIngredientStep, CutFoodStep, FryFoodStep | ||
/// </summary> | ||
public enum FoodIngredients | ||
{ | ||
Pototoes, | ||
Fish, | ||
Buns, | ||
Sauce, | ||
Condiments, | ||
None | ||
} | ||
|
||
/// <summary> | ||
/// Extensions to have access to friendly string names for <see cref="FoodIngredients"/> | ||
/// </summary> | ||
public static class FoodIngredientsExtensions | ||
{ | ||
private static readonly Dictionary<FoodIngredients, string> s_foodIngredientsStrings = new() | ||
{ | ||
{ FoodIngredients.Pototoes, "Potatoes" }, | ||
{ FoodIngredients.Fish, "Fish" }, | ||
{ FoodIngredients.Buns, "Buns" }, | ||
{ FoodIngredients.Sauce, "Sauce" }, | ||
{ FoodIngredients.Condiments, "Condiments" }, | ||
{ FoodIngredients.None, "None" } | ||
}; | ||
|
||
public static string ToFriendlyString(this FoodIngredients ingredient) | ||
{ | ||
return s_foodIngredientsStrings[ingredient]; | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
dotnet/samples/GettingStartedWithProcesses/Step03/Models/FoodOrderItem.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
namespace Step03.Models; | ||
|
||
/// <summary> | ||
/// Food Items that can be prepared by the PrepareSingleFoodItemProcess | ||
/// </summary> | ||
public enum FoodItem | ||
{ | ||
PotatoFries, | ||
FriedFish, | ||
FishSandwich, | ||
FishAndChips | ||
} | ||
|
||
/// <summary> | ||
/// Extensions to have access to friendly string names for <see cref="FoodItem"/> | ||
/// </summary> | ||
public static class FoodItemExtensions | ||
{ | ||
private static readonly Dictionary<FoodItem, string> s_foodItemsStrings = new() | ||
{ | ||
{ FoodItem.PotatoFries, "Potato Fries" }, | ||
{ FoodItem.FriedFish, "Fried Fish" }, | ||
{ FoodItem.FishSandwich, "Fish Sandwich" }, | ||
{ FoodItem.FishAndChips, "Fish & Chips" }, | ||
}; | ||
|
||
public static string ToFriendlyString(this FoodItem item) | ||
{ | ||
return s_foodItemsStrings[item]; | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
dotnet/samples/GettingStartedWithProcesses/Step03/Processes/FishAndChipsProcess.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using System.Text.Json; | ||
using Microsoft.SemanticKernel; | ||
using Step03.Models; | ||
using Step03.Steps; | ||
|
||
namespace Step03.Processes; | ||
|
||
/// <summary> | ||
/// Sample process that showcases how to create a process with a fan in/fan out behavior and use of existing processes as steps.<br/> | ||
/// Visual reference of this process can be found in the <see href="https://github.com/microsoft/semantic-kernel/tree/main/dotnet/samples/GettingStartedWithProcesses/README.md#Fish_And_Chips_Preparation_Process" >diagram</see> | ||
/// </summary> | ||
public static class FishAndChipsProcess | ||
{ | ||
public static class ProcessEvents | ||
{ | ||
public const string PrepareFishAndChips = nameof(PrepareFishAndChips); | ||
public const string FishAndChipsReady = nameof(FishAndChipsReady); | ||
} | ||
|
||
public static ProcessBuilder CreateProcess(string processName = "FishAndChipsProcess") | ||
{ | ||
var processBuilder = new ProcessBuilder(processName); | ||
var makeFriedFishStep = processBuilder.AddStepFromProcess(FriedFishProcess.CreateProcess()); | ||
var makePotatoFriesStep = processBuilder.AddStepFromProcess(PotatoFriesProcess.CreateProcess()); | ||
var addCondimentsStep = processBuilder.AddStepFromType<AddFishAndChipsCondimentsStep>(); | ||
// An additional step that is the only one that emits an public event in a process can be added to maintain event names unique | ||
var externalStep = processBuilder.AddStepFromType<ExternalFishAndChipsStep>(); | ||
|
||
processBuilder | ||
.OnInputEvent(ProcessEvents.PrepareFishAndChips) | ||
.SendEventTo(makeFriedFishStep.WhereInputEventIs(FriedFishProcess.ProcessEvents.PrepareFriedFish)); | ||
|
||
processBuilder | ||
.OnInputEvent(ProcessEvents.PrepareFishAndChips) | ||
.SendEventTo(makePotatoFriesStep.WhereInputEventIs(PotatoFriesProcess.ProcessEvents.PreparePotatoFries)); | ||
|
||
makeFriedFishStep | ||
.OnEvent(FriedFishProcess.ProcessEvents.FriedFishReady) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(addCondimentsStep, parameterName: "fishActions")); | ||
|
||
makePotatoFriesStep | ||
.OnEvent(PotatoFriesProcess.ProcessEvents.PotatoFriesReady) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(addCondimentsStep, parameterName: "potatoActions")); | ||
|
||
addCondimentsStep | ||
.OnEvent(AddFishAndChipsCondimentsStep.OutputEvents.CondimentsAdded) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(externalStep)); | ||
|
||
return processBuilder; | ||
} | ||
|
||
private sealed class AddFishAndChipsCondimentsStep : KernelProcessStep | ||
{ | ||
public static class Functions | ||
{ | ||
public const string AddCondiments = nameof(AddCondiments); | ||
} | ||
|
||
public static class OutputEvents | ||
{ | ||
public const string CondimentsAdded = nameof(CondimentsAdded); | ||
} | ||
|
||
[KernelFunction(Functions.AddCondiments)] | ||
public async Task AddCondimentsAsync(KernelProcessStepContext context, List<string> fishActions, List<string> potatoActions) | ||
{ | ||
Console.WriteLine($"ADD_CONDIMENTS: Added condiments to Fish & Chips - Fish: {JsonSerializer.Serialize(fishActions)}, Potatoes: {JsonSerializer.Serialize(potatoActions)}"); | ||
fishActions.AddRange(potatoActions); | ||
fishActions.Add(FoodIngredients.Condiments.ToFriendlyString()); | ||
await context.EmitEventAsync(new() { Id = OutputEvents.CondimentsAdded, Data = fishActions }); | ||
} | ||
} | ||
|
||
private sealed class ExternalFishAndChipsStep : ExternalStep | ||
{ | ||
public ExternalFishAndChipsStep() : base(ProcessEvents.FishAndChipsReady) { } | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
dotnet/samples/GettingStartedWithProcesses/Step03/Processes/FishSandwichProcess.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using Microsoft.SemanticKernel; | ||
using Step03.Models; | ||
using Step03.Steps; | ||
|
||
namespace Step03.Processes; | ||
|
||
/// <summary> | ||
/// Sample process that showcases how to create a process with sequential steps and use of existing processes as steps.<br/> | ||
/// Visual reference of this process can be found in the <see href="https://github.com/microsoft/semantic-kernel/tree/main/dotnet/samples/GettingStartedWithProcesses/README.md#Fish_Sandwich_Preparation_Process" >diagram</see> | ||
/// </summary> | ||
public static class FishSandwichProcess | ||
{ | ||
public static class ProcessEvents | ||
{ | ||
public const string PrepareFishSandwich = nameof(PrepareFishSandwich); | ||
public const string FishSandwichReady = nameof(FishSandwichReady); | ||
} | ||
|
||
public static ProcessBuilder CreateProcess(string processName = "FishSandwichProcess") | ||
{ | ||
var processBuilder = new ProcessBuilder(processName); | ||
var makeFriedFishStep = processBuilder.AddStepFromProcess(FriedFishProcess.CreateProcess()); | ||
var addBunsStep = processBuilder.AddStepFromType<AddBunsStep>(); | ||
var addSpecialSauceStep = processBuilder.AddStepFromType<AddSpecialSauceStep>(); | ||
// An additional step that is the only one that emits an public event in a process can be added to maintain event names unique | ||
var externalStep = processBuilder.AddStepFromType<ExternalFriedFishStep>(); | ||
|
||
processBuilder | ||
.OnInputEvent(ProcessEvents.PrepareFishSandwich) | ||
.SendEventTo(makeFriedFishStep.WhereInputEventIs(FriedFishProcess.ProcessEvents.PrepareFriedFish)); | ||
|
||
makeFriedFishStep | ||
.OnEvent(FriedFishProcess.ProcessEvents.FriedFishReady) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(addBunsStep)); | ||
|
||
addBunsStep | ||
.OnEvent(AddBunsStep.OutputEvents.BunsAdded) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(addSpecialSauceStep)); | ||
|
||
addSpecialSauceStep | ||
.OnEvent(AddSpecialSauceStep.OutputEvents.SpecialSauceAdded) | ||
.SendEventTo(new ProcessFunctionTargetBuilder(externalStep)); | ||
|
||
return processBuilder; | ||
} | ||
|
||
private sealed class AddBunsStep : KernelProcessStep | ||
{ | ||
public static class Functions | ||
{ | ||
public const string AddBuns = nameof(AddBuns); | ||
} | ||
|
||
public static class OutputEvents | ||
{ | ||
public const string BunsAdded = nameof(BunsAdded); | ||
} | ||
|
||
[KernelFunction(Functions.AddBuns)] | ||
public async Task SliceFoodAsync(KernelProcessStepContext context, List<string> foodActions) | ||
{ | ||
Console.WriteLine($"BUNS_ADDED_STEP: Buns added to ingredient {foodActions.First()}"); | ||
foodActions.Add(FoodIngredients.Buns.ToFriendlyString()); | ||
await context.EmitEventAsync(new() { Id = OutputEvents.BunsAdded, Data = foodActions }); | ||
} | ||
} | ||
|
||
private sealed class AddSpecialSauceStep : KernelProcessStep | ||
{ | ||
public static class Functions | ||
{ | ||
public const string AddSpecialSauce = nameof(AddSpecialSauce); | ||
} | ||
|
||
public static class OutputEvents | ||
{ | ||
public const string SpecialSauceAdded = nameof(SpecialSauceAdded); | ||
} | ||
|
||
[KernelFunction(Functions.AddSpecialSauce)] | ||
public async Task SliceFoodAsync(KernelProcessStepContext context, List<string> foodActions) | ||
{ | ||
Console.WriteLine($"SPECIAL_SAUCE_ADDED: Special sauce added to ingredient {foodActions.First()}"); | ||
foodActions.Add(FoodIngredients.Sauce.ToFriendlyString()); | ||
await context.EmitEventAsync(new() { Id = OutputEvents.SpecialSauceAdded, Data = foodActions, Visibility = KernelProcessEventVisibility.Public }); | ||
} | ||
} | ||
|
||
private sealed class ExternalFriedFishStep : ExternalStep | ||
{ | ||
public ExternalFriedFishStep() : base(ProcessEvents.FishSandwichReady) { } | ||
} | ||
} |
Oops, something went wrong.