Repository navigation
Conditional skills (If / IfElse) feature - #175
Roger Barreto (rogerbarreto) wants to merge 17 commits into
Conversation
…into features/planner-conditionalskill-ifelse
… Conditional Planner example
… Conditional Planner example
| </plan><!-- END --> | ||
|
|
||
| [AVAILABLE FUNCTIONS] | ||
| [EXAMPLE FUNCTIONS] |
There was a problem hiding this comment.
Do you find this improves things to help differentiate the pattern?
There was a problem hiding this comment.
Yes, I was getting very frequently WriterSkill.Summarization instead of the Everything, this was happening with Skills that bumped in the examples given and for some reason the LLM was understanding AVAILABLE examples as indeed available...
There was a problem hiding this comment.
Something for us to consider when we start allowing users to supply their own examples.
There was a problem hiding this comment.
Even changing that to this pattern I see less frequently it using the wrong function, potentially we should use abstract examples that would not conflict with actual skills.
| 7. To save an 'output' from a <function>, to pass into a future <function>, use <function.{FunctionName} ... setContextVariable: ""$<UNIQUE_VARIABLE_KEY>""/> | ||
| 8. To save an 'output' from a <function>, to return as part of a plan result, use <function.{FunctionName} ... appendToResult: ""RESULT__$<UNIQUE_RESULT_KEY>""/> | ||
| 9. Append an ""END"" XML comment at the end of the plan. | ||
| 9. Available conditions: greaterthan, equals, contains, startswith |
There was a problem hiding this comment.
I'd expect more instructions about these reserved words and others.
There was a problem hiding this comment.
This can potentially increase but since we don't have any specific implementation the LLM is currently guessing what to do in the conditions. I'm adding this for the scope of this change but we can limit those later on
There was a problem hiding this comment.
How does it know about 'if' or 'conditiongroup'? Only from examples? That will not work when we allow users to supply their own examples.
| Console.WriteLine("Original plan:"); | ||
| Console.WriteLine(originalPlan.Variables.ToPlan().PlanString); | ||
|
|
||
| await ExecutePlanAsync(kernel, planner, originalPlan, 5); |
There was a problem hiding this comment.
Is 5 the required steps here for completion of the plan? What is the input to the first Summarize? Can you show it with two different inputs to show it goes down each branch?
There was a problem hiding this comment.
The number of steps can be greater, currently the plan will resolve the if (then/else) inner steps and add them as part of the list, so if in the overall branching we end up with more than 5 steps this will abort at the given step. For branching examples I can move this number up a bit.
|
|
||
| if (processFunctions && o2.Name.StartsWith(ConditionIfTag, StringComparison.InvariantCultureIgnoreCase)) | ||
| { | ||
| if (!context.IsFunctionRegistered("Conditional", "If", out var ifCheckFunction)) |
There was a problem hiding this comment.
What if they register with a different name?
| // Load native skill into the kernel skill collection, sharing its functions with prompt templates | ||
| planner = kernel.ImportSkill(new PlannerSkill(kernel), "planning"); | ||
|
|
||
| kernel.ImportSkill(new ConditionalSkill(kernel), "conditional"); |
There was a problem hiding this comment.
I'm wondering if this is how we'll want to do things going forward.
Additionally, I'm still torn on whether we need a special syntax in the prompt for these skills or not -- maybe it could just be like any other. Did you try that?
There was a problem hiding this comment.
PlannerSkill has a dependency on ConditionalSkill but this is not the ideal way moving forward, the PR proved the concept that the IF behavior worked.
Will think more on changes that don't create this problem of skillname referencing/dependency potentially adding ConditionalSkill as a Planner adittional capability instead of a standalone Skill.
Lee Miller (lemillermicrosoft)
left a comment
There was a problem hiding this comment.
Leaving more comments.
| public class ConditionalSkill | ||
| { | ||
| #region Prompts | ||
| internal const string IfStructureCheckPrompt = |
There was a problem hiding this comment.
Maybe out of scope of this PR, but I'm wondering, can we store core skill prompts in separate txt files and read from them? The same applies for Planner and other skills. In this way we can keep our C# classes nice and clean.
There was a problem hiding this comment.
Sure, I think this could be a improvement to tackle
There was a problem hiding this comment.
Right now we are using SemanticFunctionConstants for these definitions.
| maxTokens: 100, | ||
| temperature: 0, | ||
| topP: 0.5 | ||
| ); |
There was a problem hiding this comment.
nit: unnecessary new line here
| using Microsoft.SemanticKernel.SkillDefinition; | ||
|
|
||
| namespace Microsoft.SemanticKernel.CoreSkills; | ||
| public class ConditionalSkill |
There was a problem hiding this comment.
Need an empty line between namespace and class declaration. Also would be nice to add XML comments. Same applies for ConditionException.cs
| foreach (var v in existingVariables) | ||
| { | ||
| // Numeric don't add quotes | ||
| if (Regex.Match(v.Value, "^[0-9.,]+$").Success) |
There was a problem hiding this comment.
nit: a little simplification, feel free to skip
var value = Regex.Match(v.Value, "^[0-9.,]+$").Success ? v.Value : JsonSerializer.Serialize(v.Value);
conditionalVariables.AppendLine($"{v.Key} = {value}");
| [END EXAMPLE FUNCTIONS] | ||
|
|
||
| <goal>Summarize the input, if the input length is greater than 10 then Create an outline for a children's book with 3 chapters about a group of kids in a club and then summarize it otherwise translate to japanese and email it to Martin.</goal> | ||
| <plan> |
There was a problem hiding this comment.
Yowza, this is going to be a token eating machine! We need to drive for simplicity in this format, or it'll burn too many tokens on prompt and response, and the AI is far more likely to get things wrong.
Asks:
at minimum, let's remove . Compound conditions can be constructed by nesting one inside another, or with specialized native skills. This is more complex than required right now.
<if>
<conditiongroup>
<condition variable=""$SUMMARIZED_INPUT"" greaterthan=""10"" />
</conditiongroup>
...becomes...
<if variable=""$SUMMARIZED_INPUT"" greaterthan=""10"">
I also think we can get rid of the <then> tags, as these are token eaters and kind of redundant (the content in the <if...> tags is implicitly then).
As for else, I think this could be another conditional stacked below with the inverse condition. I wonder if the AI would do that on its own:
<if variable=""$SUMMARIZED_INPUT"" greaterthan=""10"">
<do stuff>
</if>
<if variable=""$SUMMARIZED_INPUT"" lessthanequals=""10"">
<do other stuff>
</if>
| 7. To save an 'output' from a <function>, to pass into a future <function>, use <function.{FunctionName} ... setContextVariable: ""$<UNIQUE_VARIABLE_KEY>""/> | ||
| 8. To save an 'output' from a <function>, to return as part of a plan result, use <function.{FunctionName} ... appendToResult: ""RESULT__$<UNIQUE_RESULT_KEY>""/> | ||
| 9. Append an ""END"" XML comment at the end of the plan. | ||
| 9. Available conditions: greaterthan, equals, contains, startswith |
There was a problem hiding this comment.
I think the most important conditions will be "isSet" (i.e. not null or empty), "isUnset".
| <conditiongroup> | ||
| <condition variable=""z"" greaterthan=""10"" /> | ||
| </conditiongroup> | ||
| </not> |
There was a problem hiding this comment.
Yeah, way too complex. These compound conditions would be difficult to maintain. Please cut the conditiongroup for this first version -- keep it simple.
### Motivation and Context <!-- Thank you for your contribution to the copilot-chat repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 3. What problem does it solve? 5. What scenario does it contribute to? 7. If it fixes an open issue, please link to the issue here. --> I would like to provide a production-grade PaaS solution to store the vector database. It provides PostgreSQL database support for memory. We can now use Azure Database for PostgreSQL or CosmosDB for PostgreSQL. Fixes microsoft#166 ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> I added configuration support for PostgreSQL. in the kernel initialization. Furthermore I updated the deployment script to support this configuration. > Note: In the deployment scripts, I've added the SqlAdminPassword parameter, which must be supplied during provisioning. I intentionally named it without the PostgreSQL name, as I also worked on implementing SQL Server Memory store in the SK repository. This parameter could be used by both databases during deployment. ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [Contribution Guidelines](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible > Not found test project on the API part ;( - [x] I didn't break anyone 😄 --------- Co-authored-by: Gil LaHaye <[email protected]>
Motivation and Context
Currently, the core planner doesn’t support conditional behavior.
This design offers an initial “If” statement capability skill that allows planner control flow execution conditioned to check for equals/contains/greaterthan against context variables.
This change will allow Plan to run correctly for prompts like:
Summarize an outline about AI, if the summarization contains any reference to "AGI" then Generate a summary outline for AGI. After that generate a list of synopsis for a novel using the resulting summarization.Description
This change adds a conditional structure to the plan as a way to be able to use a standard conditional structure for branching that can be recursive as follows.
When resolving the conditional group this skill returns the content in Then or Else branches including potential nested ifs.
This structure was build in a way that it can allow future nested complex conditions and checks like:
The nested scenarios above were not yet fully tested and are not officially supported by this PR.
Contribution Checklist
dotnet format