Skip to content

Commit bd066f2

Browse files
author
Eric Camplin
committed
give-your-ai-agent-skills 2-, 3- add python pivots
1 parent c04f7d3 commit bd066f2

File tree

4 files changed

+333
-132
lines changed

4 files changed

+333
-132
lines changed

learn-pr/wwl-azure/give-your-ai-agent-skills/2-understand-native-plugins.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ metadata:
1010
ms.topic: unit
1111
ms.custom:
1212
- N/A
13+
zone_pivot_groups: dev-lang-csharp-python
1314
durationInMinutes: 8
1415
content: |
1516
[!include[](includes/2-understand-native-plugins.md)]

learn-pr/wwl-azure/give-your-ai-agent-skills/3-configure-function-choices.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ metadata:
1010
ms.topic: unit
1111
ms.custom:
1212
- N/A
13+
zone_pivot_groups: dev-lang-csharp-python
1314
durationInMinutes: 8
1415
content: |
1516
[!include[](includes/3-configure-function-choices.md)]

learn-pr/wwl-azure/give-your-ai-agent-skills/includes/2-understand-native-plugins.md

Lines changed: 173 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,128 +2,217 @@ Plugins are a key component of the Semantic Kernel SDK. Plugins allow you to enc
22

33
## Creating a plugin
44

5-
For the Semantic Kernel to correctly route requests to your functions, the plugins you create must include details that describe the function's behavior. The details need to be written in a way that can be understood by the AI. The function's input, output and side effects should be described so that they AI can use the function. To create a plugin function, you add the following attributes to your function: `KernelFunction`, `Description`, and `return` if there's data returned from the function. Here's an example of a task management plugin with a function and its description:
5+
For the Semantic Kernel to correctly route requests to your functions, the plugins you create must include details that describe the function's behavior. The details need to be written in a way that can be understood by the AI. The function's input, output and side effects should be described so that the AI can use the function.
66

7-
```c#
8-
using System.ComponentModel;
9-
using Microsoft.SemanticKernel;
7+
::: zone pivot="csharp"
108

11-
public class TaskManagementPlugin
12-
{
13-
// Mock data for the tasks
14-
private readonly List<TaskModel> tasks = new()
15-
{
16-
new TaskModel { Id = 1, Title = "Design homepage", Description = "Create a modern homepage layout", Status = "In Progress", Priority = "High" },
17-
new TaskModel { Id = 2, Title = "Fix login bug", Description = "Resolve the issue with login sessions timing out", Status = "To Do", Priority = "Critical" },
18-
new TaskModel { Id = 3, Title = "Update documentation", Description = "Improve API reference for developers", Status = "Completed", Priority = "Medium" }
19-
};
9+
To create a plugin function in C#, you add the following attributes to your function: `[KernelFunction]`, `[Description]`, and `[return: Description]` if there's data returned from the function. Here’s a minimal example:
2010

21-
[KernelFunction("complete_task")]
22-
[Description("Updates the status of the specified task to Completed")]
23-
[return: Description("The updated task; will return null if the task does not exist")]
24-
public TaskModel? CompleteTask(int id)
25-
{
26-
var task = tasks.FirstOrDefault(task => task.Id == id);
11+
```csharp
12+
using Microsoft.SemanticKernel;
2713

28-
if (task == null)
14+
public class TaskManagementPlugin
15+
{
16+
[KernelFunction("complete_task")]
17+
[Description("Marks a task as completed by its ID.")]
18+
[return: Description("The updated task, or null if not found.")]
19+
public TaskModel? CompleteTask(int id)
2920
{
30-
return null;
21+
// ...complete the task logic...
3122
}
23+
}
24+
```
3225

33-
task.Status = "Completed";
26+
::: zone-end
3427

35-
return task;
36-
}
37-
}
38-
```
28+
::: zone pivot="python"
29+
30+
To create a plugin function in Python, you use the `@kernel_function` decorator with a description parameter. The return type is specified in the function signature (for example, `-> dict | None`). Here’s a minimal example:
31+
32+
```python
33+
from semantic_kernel import kernel_function, KernelPlugin
34+
35+
class TaskManagementPlugin(KernelPlugin):
36+
@kernel_function(name="complete_task", description="Marks a task as completed by its ID.")
37+
def complete_task(self, id: int) -> dict | None:
38+
# ...complete the task logic...
39+
pass
40+
```
41+
42+
::: zone-end
43+
44+
> [!INOTE]
45+
>
46+
> ::: zone pivot="csharp"
47+
>
48+
> In C#, plugin functions use attributes such as `[KernelFunction]` and `[Description]` to provide metadata for the Semantic Kernel. Chat history is managed using the `ChatHistory` class and its methods, such as `AddUserMessage`.
49+
>
50+
> ::: zone-end
51+
>
52+
> ::: zone pivot="python"
53+
>
54+
> In Python, plugin functions use decorators such as `@kernel_function` to provide metadata for the Semantic Kernel. Chat history is typically represented as a list of dictionaries, each with a `role` and `content` key.
55+
>
56+
> ::: zone-end
57+
58+
In this example, only the essentials are shown: the function signature, attributes, and a placeholder for your logic.
3959

40-
In this example, there's a simple `CompleteTask` function that marks a task as complete. To call your function, you need to add the plugin to the kernel using `Plugins.AddFromType`. This will give the kernel access to the plugin's functions. Afterwards you can invoke a function using the `InvokeAsync` method.
60+
To call your function, register the plugin and invoke the function as shown below:
4161

42-
```c#
43-
var builder = new KernelBuilder();
44-
Kernel kernel = builder.Build();
62+
::: zone pivot="csharp"
4563

46-
// Add the plugin to the kernel
47-
kernel.Plugins.AddFromType<TaskManagementPlugin>("TaskManagement");
64+
```csharp
65+
var kernel = new KernelBuilder().Build();
66+
kernel.Plugins.AddFromType<TaskManagementPlugin>("TaskManagement");
4867

49-
// Invoke the function
50-
var arguments = new KernelArguments { ["id"] = id };
51-
var updatedTask = await kernel.InvokeAsync("TaskManagement", "complete_task", arguments);
52-
```
68+
var arguments = new KernelArguments { ["id"] = 1 };
69+
var updatedTask = await kernel.InvokeAsync("TaskManagement", "complete_task", arguments);
70+
```
5371

54-
Using plugin functions allows your agent to perform tasks beyond the capabilities of a typical LLM, such as managing data, interacting with external systems, or handling specific business logic. The modularity of plugins make it easy to add new functionality to your agent without modifying core logic. This approach keeps your code organized, reusable, and easier to maintain.
72+
::: zone-end
73+
74+
::: zone pivot="python"
75+
76+
```python
77+
from semantic_kernel import Kernel
78+
79+
kernel = Kernel()
80+
kernel.add_plugin(TaskManagementPlugin(), "TaskManagement")
81+
82+
arguments = {"id": 1}
83+
updated_task = await kernel.invoke("TaskManagement.complete_task", arguments)
84+
```
85+
86+
::: zone-end
87+
88+
Using plugin functions allows your agent to perform tasks beyond the capabilities of a typical LLM, such as managing data, interacting with external systems, or handling specific business logic. The modularity of plugins makes it easy to add new functionality to your agent without modifying core logic. This approach keeps your code organized, reusable, and easier to maintain.
5589

5690
## Invoke functions automatically
5791

5892
The Semantic Kernel SDK enables the LLM to automatically invoke your plugin functions. Automatically invoking functions allows your application to respond more intelligently to user input. Instead of requiring explicit commands to trigger specific actions, the AI can determine the appropriate function to call based on the user's request. This enhances the user experience by making interactions more natural and reducing the need for precise instructions.
5993

60-
To enable functions to be invoked automatically, you must set the `FunctionChoiceBehavior` property of the `OpenAIPromptExecutionSettings` object to `Auto()`. Afterwards, user prompts will be able to trigger your plugin functions.
94+
To enable functions to be invoked automatically:
95+
96+
::: zone pivot="csharp"
97+
98+
Set the `FunctionChoiceBehavior` property of the `OpenAIPromptExecutionSettings` object to `Auto()`. Afterwards, user prompts will be able to trigger your plugin functions.
99+
100+
::: zone-end
101+
102+
::: zone pivot="python"
103+
104+
Set `function_call="auto"` in the `OpenAIChatCompletionSettings` object. This allows user prompts to automatically trigger your plugin functions based on the LLM's understanding of the user's intent.
105+
106+
::: zone-end
61107

62108
Suppose the `TaskManagementPlugin` contains a `GetCriticalTasks` function:
63109

64-
```c#
65-
[KernelFunction("get_critical_tasks")]
66-
[Description("Gets a list of all tasks marked as 'Critical' priority")]
67-
[return: Description("A list of critical tasks")]
68-
public List<TaskModel> GetCriticalTasks()
69-
{
70-
// Filter tasks with "Critical" priority
71-
return tasks.Where(task => task.Priority.Equals("Critical", StringComparison.OrdinalIgnoreCase)).ToList();
72-
}
73-
```
110+
::: zone pivot="csharp"
111+
112+
```csharp
113+
[KernelFunction("get_critical_tasks")]
114+
[Description("Gets a list of all tasks marked as 'Critical' priority.")]
115+
[return: Description("A list of critical tasks.")]
116+
public List<TaskModel> GetCriticalTasks()
117+
{
118+
// ...return critical tasks...
119+
}
120+
```
121+
122+
::: zone-end
123+
124+
::: zone pivot="python"
125+
126+
```python
127+
from semantic_kernel import kernel_function, KernelPlugin
128+
129+
class TaskManagementPlugin(KernelPlugin):
130+
@kernel_function(name="get_critical_tasks", description="Gets a list of all tasks marked as 'Critical' priority.")
131+
def get_critical_tasks(self) -> list:
132+
# ...return critical tasks...
133+
pass
134+
```
135+
136+
::: zone-end
74137

75138
The user could trigger this function with a prompt to the LLM. For example:
76139

77-
```c#
78-
// Build the kernel
79-
Kernel kernel = builder.Build();
80-
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
140+
::: zone pivot="csharp"
141+
142+
```csharp
143+
var kernel = new KernelBuilder().Build();
144+
kernel.Plugins.AddFromType<TaskManagementPlugin>("TaskManagement");
145+
146+
OpenAIPromptExecutionSettings settings = new()
147+
{
148+
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
149+
};
81150

82-
// Add the plugin
83-
kernel.Plugins.AddFromType<TaskManagementPlugin>("TaskManagement");
151+
var history = new ChatHistory();
152+
history.AddUserMessage("What are all of the critical tasks?");
153+
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
84154

85-
// Enable planning
86-
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
87-
{
88-
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
89-
};
155+
var result = await chatCompletionService.GetChatMessageContentAsync(
156+
history,
157+
executionSettings: settings,
158+
kernel: kernel);
90159

91-
// Create a history store the conversation
92-
var history = new ChatHistory();
93-
history.AddUserMessage("What are all of the critical tasks?");
160+
Console.WriteLine("Assistant: " + result);
161+
```
94162

95-
// Get the response from the AI
96-
var result = await chatCompletionService.GetChatMessageContentAsync(
97-
history,
98-
executionSettings: openAIPromptExecutionSettings,
99-
kernel: kernel);
163+
::: zone-end
100164

101-
// Print the results
102-
Console.WriteLine("Assistant: " + result);
103-
```
165+
::: zone pivot="python"
104166

105-
The output of this code would be similar to the following text:
167+
```python
168+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletionSettings
106169

107-
```output
108-
Assistant: The only critical task is "Fix login bug". The task is currently in the "To Do" status and its description is "Resolve the issue with login sessions timing out".
109-
```
170+
settings = OpenAIChatCompletionSettings(function_call="auto")
110171

111-
Notice that the results of the function are passed to the LLM and a generated response is returned. Automatic function invocation makes your application smarter and more user-friendly. This feature can enhance the overall usability and adaptability of your solution.
172+
history = [{"role": "user", "content": "What are all of the critical tasks?"}]
173+
chat_completion_service = kernel.get_service("chat_completion")
174+
175+
result = await chat_completion_service.get_chat_message_content(
176+
history=history,
177+
execution_settings=settings,
178+
kernel=kernel
179+
)
180+
181+
print("Assistant:", result)
182+
```
183+
184+
::: zone-end
185+
186+
The output of this code would be similar to:
187+
188+
```console
189+
Assistant: The only critical task is "Fix login bug". The task is currently in the "To Do" status and its description is "Resolve the issue with login sessions timing out".
190+
```
191+
192+
Notice that the results of the function are passed to the LLM and a generated response is returned. Automatic function invocation makes your application smarter and more user-friendly.
112193

113194
## Make plugins AI-friendly
114195

115196
To enhance the LLM's ability to understand and utilize your plugin functions, consider the following guidelines:
116197

117-
- **Use descriptive and concise function names**
118-
119-
Names that clearly convey the function's purpose will help the model understand when to call the function. Avoid using abbreviations or acronyms to shorten function names. The DescriptionAttribute increases token consumption, so use it to provide context and instructions when necessary.
198+
- **Use descriptive and concise function names**
199+
200+
::: zone pivot="csharp"
201+
202+
Names that clearly convey the function's purpose will help the model understand when to call the function. Avoid abbreviations or acronyms. Use the `Description` attribute to provide context and instructions when necessary.
203+
204+
::: zone-end
205+
206+
::: zone pivot="python"
207+
208+
Names that clearly convey the function's purpose will help the model understand when to call the function. Avoid abbreviations or acronyms. Use the `description` parameter in the `@kernel_function` decorator to provide context and instructions when necessary.
120209

121-
- **Minimize function parameters**
122-
123-
Limit the number of function parameters and use primitive types whenever possible. This approach reduces token consumption and simplifies the function signature, making it easier for the LLM to match function parameters effectively.
210+
::: zone-end
124211

125-
- **Name function parameters clearly**
212+
- **Minimize function parameters**
213+
Limit the number of function parameters and use primitive types whenever possible. This reduces token consumption and simplifies the function signature.
126214

127-
Use descriptive parameter names that clarify their purpose. The parameter names help the LLM assign accurate values, so avoid using abbreviations or acronyms to shorten parameter names.
215+
- **Name function parameters clearly**
216+
Use descriptive parameter names that clarify their purpose. Avoid abbreviations or acronyms.
128217

129-
Plugins in the Semantic Kernel SDK make it easy to extend your AI application's capabilities. They allow your functions to interact seamlessly with the LLM, whether invoked manually or automatically, creating smarter and more user-friendly experiences. By following best practices for naming and structuring plugins, you ensure the AI can effectively use your functions, keeping your code organized and adaptable to future needs.
218+
Plugins in the Semantic Kernel SDK make it easy to extend your AI application's capabilities. They allow your functions to interact seamlessly with the LLM, whether invoked manually or automatically, creating smarter and more user-friendly experiences. By following best practices for naming and structuring plugins, you ensure the AI can effectively use your functions, keeping your code organized and adaptable to future needs.

0 commit comments

Comments
 (0)