-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Python: Add sequential planner to python (#1916)
### 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. --> fixes #1915 ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows SK Contribution Guidelines (https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) - [ ] The code follows the .NET coding conventions (https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions) verified with `dotnet format` - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄 --------- Co-authored-by: Abby Harrison <abby.harrison@microsoft.com> Co-authored-by: Abby Harrison <54643756+awharrison-28@users.noreply.github.com> Co-authored-by: Shawn Callegari <36091529+shawncal@users.noreply.github.com>
- Loading branch information
1 parent
e687301
commit 484b39d
Showing
23 changed files
with
1,829 additions
and
25 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
47 changes: 47 additions & 0 deletions
47
python/samples/kernel-syntax-examples/sequential_planner.py
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,47 @@ | ||
# Copyright (c) Microsoft. All rights reserved. | ||
|
||
import semantic_kernel as sk | ||
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion | ||
from semantic_kernel.core_skills import FileIOSkill, MathSkill, TextSkill, TimeSkill | ||
from semantic_kernel.planning import SequentialPlanner | ||
|
||
|
||
async def main(): | ||
kernel = sk.Kernel() | ||
api_key, org_id = sk.openai_settings_from_dot_env() | ||
|
||
kernel.add_chat_service( | ||
"gpt-3.5", OpenAIChatCompletion("gpt-3.5-turbo", api_key, org_id) | ||
) | ||
kernel.import_skill(MathSkill(), "math") | ||
kernel.import_skill(FileIOSkill(), "fileIO") | ||
kernel.import_skill(TimeSkill(), "time") | ||
kernel.import_skill(TextSkill(), "text") | ||
|
||
# create an instance of sequential planner. | ||
planner = SequentialPlanner(kernel) | ||
|
||
# the ask for which the sequential planner is going to find a relevant function. | ||
ask = "What day of the week is today, all uppercase?" | ||
|
||
# ask the sequential planner to identify a suitable function from the list of functions available. | ||
plan = await planner.create_plan_async(goal=ask) | ||
|
||
# ask the sequential planner to execute the identified function. | ||
result = await plan.invoke_async() | ||
|
||
for step in plan._steps: | ||
print(step.description, ":", step._state.__dict__) | ||
|
||
print("Expected Answer:") | ||
print(result) | ||
""" | ||
Output: | ||
1100 | ||
""" | ||
|
||
|
||
if __name__ == "__main__": | ||
import asyncio | ||
|
||
asyncio.run(main()) |
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
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
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 |
---|---|---|
@@ -1,7 +1,9 @@ | ||
from semantic_kernel.planning.basic_planner import BasicPlanner | ||
from semantic_kernel.planning.plan import Plan | ||
from semantic_kernel.planning.sequential_planner import SequentialPlanner | ||
|
||
__all__ = [ | ||
"SequentialPlanner", | ||
"BasicPlanner", | ||
"Plan", | ||
] |
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
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,46 @@ | ||
# Copyright (c) Microsoft. All rights reserved. | ||
|
||
from enum import Enum | ||
from typing import Optional | ||
|
||
|
||
class PlanningException(Exception): | ||
class ErrorCodes(Enum): | ||
# Unknown error. | ||
UnknownError = -1 | ||
# Invalid goal. | ||
InvalidGoal = 0 | ||
# Invalid plan. | ||
InvalidPlan = 1 | ||
# Invalid configuration. | ||
InvalidConfiguration = 2 | ||
# Create plan error. | ||
CreatePlanError = 3 | ||
|
||
# The error code. | ||
_error_code: ErrorCodes | ||
|
||
def __init__( | ||
self, | ||
error_code: ErrorCodes, | ||
message: str, | ||
inner_exception: Optional[Exception] = None, | ||
) -> None: | ||
"""Initializes a new instance of the PlanningError class. | ||
Arguments: | ||
error_code {ErrorCodes} -- The error code. | ||
message {str} -- The error message. | ||
inner_exception {Exception} -- The inner exception. | ||
""" | ||
super().__init__(error_code, message, inner_exception) | ||
self._error_code = error_code | ||
|
||
@property | ||
def error_code(self) -> ErrorCodes: | ||
"""Gets the error code. | ||
Returns: | ||
ErrorCodes -- The error code. | ||
""" | ||
return self._error_code |
27 changes: 27 additions & 0 deletions
27
python/semantic_kernel/planning/sequential_planner/Skills/SequentialPlanning/config.json
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,27 @@ | ||
{ | ||
"schema": 1, | ||
"description": "Given a request or command or goal generate a step by step plan to fulfill the request using functions. This ability is also known as decision making and function flow", | ||
"type": "completion", | ||
"completion": { | ||
"max_tokens": 1024, | ||
"temperature": 0, | ||
"top_p": 0, | ||
"presence_penalty": 0, | ||
"frequency_penalty": 0, | ||
"stop_sequences": ["<!-- END -->"] | ||
}, | ||
"input": { | ||
"parameters": [ | ||
{ | ||
"name": "input", | ||
"description": "The question to answer", | ||
"defaultValue": "" | ||
}, | ||
{ | ||
"name": "available_functions", | ||
"description": "The list of the agent's available_functions", | ||
"defaultValue": "" | ||
} | ||
] | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
python/semantic_kernel/planning/sequential_planner/Skills/SequentialPlanning/skprompt.txt
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,55 @@ | ||
Create an XML plan step by step, to satisfy the goal given, with the available functions. | ||
|
||
[AVAILABLE FUNCTIONS] | ||
|
||
{{$available_functions}} | ||
|
||
[END AVAILABLE FUNCTIONS] | ||
|
||
To create a plan, follow these steps: | ||
0. The plan should be as short as possible. | ||
1. From a <goal> create a <plan> as a series of <functions>. | ||
2. A plan has 'INPUT' available in context variables by default. | ||
3. Before using any function in a plan, check that it is present in the [AVAILABLE FUNCTIONS] list. If it is not, do not use it. | ||
4. Only use functions that are required for the given goal. | ||
5. Append an "END" XML comment at the end of the plan after the final closing </plan> tag. | ||
6. Always output valid XML that can be parsed by an XML parser. | ||
7. If a plan cannot be created with the [AVAILABLE FUNCTIONS], return <plan />. | ||
|
||
All plans take the form of: | ||
<plan> | ||
<!-- ... reason for taking step ... --> | ||
<function.{FullyQualifiedFunctionName} ... /> | ||
<!-- ... reason for taking step ... --> | ||
<function.{FullyQualifiedFunctionName} ... /> | ||
<!-- ... reason for taking step ... --> | ||
<function.{FullyQualifiedFunctionName} ... /> | ||
(... etc ...) | ||
</plan> | ||
<!-- END --> | ||
|
||
To call a function, follow these steps: | ||
1. A function has one or more named parameters and a single 'output' which are all strings. Parameter values should be xml escaped. | ||
2. To save an 'output' from a <function>, to pass into a future <function>, use <function.{FullyQualifiedFunctionName} ... setContextVariable="<UNIQUE_VARIABLE_KEY>"/> | ||
3. To save an 'output' from a <function>, to return as part of a plan result, use <function.{FullyQualifiedFunctionName} ... appendToResult="RESULT__<UNIQUE_RESULT_KEY>"/> | ||
4. Use a '$' to reference a context variable in a parameter, e.g. when `INPUT='world'` the parameter 'Hello $INPUT' will evaluate to `Hello world`. | ||
5. Functions do not have access to the context variables of other functions. Do not attempt to use context variables as arrays or objects. Instead, use available functions to extract specific elements or properties from context variables. | ||
|
||
DO NOT DO THIS, THE PARAMETER VALUE IS NOT XML ESCAPED: | ||
<function.Name4 input="$SOME_PREVIOUS_OUTPUT" parameter_name="some value with a <!-- comment in it-->"/> | ||
|
||
DO NOT DO THIS, THE PARAMETER VALUE IS ATTEMPTING TO USE A CONTEXT VARIABLE AS AN ARRAY/OBJECT: | ||
<function.CallFunction input="$OTHER_OUTPUT[1]"/> | ||
|
||
Here is a valid example of how to call a function "_Function_.Name" with a single input and save its output: | ||
<function._Function_.Name input="this is my input" setContextVariable="SOME_KEY"/> | ||
|
||
Here is a valid example of how to call a function "FunctionName2" with a single input and return its output as part of the plan result: | ||
<function.FunctionName2 input="Hello $INPUT" appendToResult="RESULT__FINAL_ANSWER"/> | ||
|
||
Here is a valid example of how to call a function "Name3" with multiple inputs: | ||
<function.Name3 input="$SOME_PREVIOUS_OUTPUT" parameter_name="some value with a <!-- comment in it-->"/> | ||
|
||
Begin! | ||
|
||
<goal>{{$input}}</goal> |
7 changes: 7 additions & 0 deletions
7
python/semantic_kernel/planning/sequential_planner/__init__.py
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,7 @@ | ||
from semantic_kernel.planning.sequential_planner.sequential_planner import ( | ||
SequentialPlanner, | ||
) | ||
|
||
__all__ = [ | ||
"SequentialPlanner", | ||
] |
Oops, something went wrong.