Skip to content

Commit 3bad767

Browse files
author
Eric Camplin
committed
4-filter-invoked-functions.md python pivot
1 parent cdc5a40 commit 3bad767

File tree

1 file changed

+132
-31
lines changed

1 file changed

+132
-31
lines changed

learn-pr/wwl-azure/combine-prompts-functions/includes/3-filter-invoked-functions.md

Lines changed: 132 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,67 +14,153 @@ This filter runs every time a function is executed, whether it originates from a
1414

1515
Here's an example of a function invocation filter that logs the invoked plugin function:
1616

17-
```c#
18-
public sealed class LoggingFilter(ILogger logger) : IFunctionInvocationFilter
19-
{
20-
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
17+
::: zone pivot="csharp"
18+
19+
```c#
20+
public sealed class LoggingFilter(ILogger logger) : IFunctionInvocationFilter
2121
{
22-
logger.LogInformation("Invoking: {PluginName}.{FunctionName}", context.Function.PluginName, context.Function.Name);
22+
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
23+
{
24+
logger.LogInformation("Invoking: {PluginName}.{FunctionName}", context.Function.PluginName, context.Function.Name);
2325

24-
await next(context);
26+
await next(context);
2527

26-
logger.LogInformation("Executed: {PluginName}.{FunctionName}", context.Function.PluginName, context.Function.Name);
28+
logger.LogInformation("Executed: {PluginName}.{FunctionName}", context.Function.PluginName, context.Function.Name);
29+
}
2730
}
28-
}
29-
```
31+
```
32+
33+
::: zone-end
34+
35+
::: zone pivot="python"
36+
37+
````python
38+
# Python example: Function invocation filter using a decorator
39+
40+
from semantic_kernel.functions.kernel_function_decorator import kernel_function
41+
42+
def logging_filter(func):
43+
def wrapper(*args, **kwargs):
44+
print(f"Invoking: {func.__qualname__}")
45+
result = func(*args, **kwargs)
46+
print(f"Executed: {func.__qualname__}")
47+
return result
48+
return wrapper
49+
50+
class WeatherForecastUtils:
51+
@kernel_function(name="GetWeatherForCity", description="Gets the weather for a given city.")
52+
@logging_filter
53+
def get_weather_for_city(self, city: str) -> str:
54+
return "Sunny"
55+
````
56+
57+
::: zone-end
3058

3159
### Prompt Render Filter
3260

3361
Triggered during prompt rendering, this filter provides control over how prompts are formatted and submitted to AI. It's ideal for tasks like modifying prompts for sensitive information (e.g., PII redaction) or enabling semantic caching.
3462

3563
Here's an example of a prompt render filter:
3664

37-
```c#
38-
public class SafePromptFilter : IPromptRenderFilter
39-
{
40-
public async Task OnPromptRenderAsync(PromptRenderContext context, Func<PromptRenderContext, Task> next)
65+
::: zone pivot="csharp"
66+
67+
```c#
68+
public class SafePromptFilter : IPromptRenderFilter
4169
{
42-
await next(context);
70+
public async Task OnPromptRenderAsync(PromptRenderContext context, Func<PromptRenderContext, Task> next)
71+
{
72+
await next(context);
4373

44-
// Modify prompt before submission
45-
context.RenderedPrompt = "Safe and sanitized prompt.";
74+
// Modify prompt before submission
75+
context.RenderedPrompt = "Safe and sanitized prompt.";
76+
}
4677
}
47-
}
48-
```
78+
```
79+
80+
::: zone-end
81+
82+
::: zone pivot="python"
83+
84+
````python
85+
# Python example: Prompt render filter using a decorator
86+
87+
def safe_prompt_filter(render_func):
88+
def wrapper(*args, **kwargs):
89+
prompt = render_func(*args, **kwargs)
90+
# Modify prompt before submission
91+
return "Safe and sanitized prompt."
92+
return wrapper
93+
94+
@safe_prompt_filter
95+
def render_prompt(user_input):
96+
return f"User prompt: {user_input}"
97+
98+
# Example usage
99+
print(render_prompt("Sensitive information here"))
100+
````
101+
102+
::: zone-end
49103

50104
### Auto Function Invocation Filter
51105

52106
This filter is invoked only during the automatic function calling process. It can adjust or even terminate workflows based on intermediate results.
53107

54108
Here's an example of a function invocation filter that terminates the function calling process:
55109

56-
```c#
57-
public sealed class EarlyTerminationFilter : IAutoFunctionInvocationFilter
58-
{
59-
public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
60-
{
61-
await next(context);
110+
::: zone pivot="csharp"
62111

63-
var result = context.Result.GetValue<string>();
64-
if (result == "desired result")
112+
```c#
113+
public sealed class EarlyTerminationFilter : IAutoFunctionInvocationFilter
114+
{
115+
public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
65116
{
66-
context.Terminate = true;
117+
await next(context);
118+
119+
var result = context.Result.GetValue<string>();
120+
if (result == "desired result")
121+
{
122+
context.Terminate = true;
123+
}
67124
}
68125
}
69-
}
70-
```
126+
```
127+
128+
::: zone-end
129+
130+
::: zone pivot="python"
131+
132+
````python
133+
# Python example: Auto function invocation filter using a decorator
134+
135+
def early_termination_filter(func):
136+
def wrapper(*args, **kwargs):
137+
result = func(*args, **kwargs)
138+
# Simulate checking the result and terminating if needed
139+
if result == "desired result":
140+
print("Terminating workflow early.")
141+
return result
142+
return result
143+
return wrapper
144+
145+
@early_termination_filter
146+
def auto_function():
147+
# Simulate function logic
148+
return "desired result"
149+
150+
# Example usage
151+
auto_function()
152+
````
153+
154+
::: zone-end
71155

72156
### Integrate function filters
73157

158+
::: zone pivot="csharp"
159+
74160
To integrate any of the function filters, you can use the following methods:
75161

76162
- **Dependency Injection**:
77-
163+
78164
Add the function to the KernelBuilder services:
79165

80166
```c#
@@ -89,6 +175,21 @@ To integrate any of the function filters, you can use the following methods:
89175
kernel.FunctionInvocationFilters.Add(new LoggingFilter(logger));
90176
```
91177

178+
::: zone-end
179+
180+
::: zone pivot="python"
181+
182+
To integrate filters in Python, apply decorators to your plugin methods or prompt rendering functions as shown above.
183+
Register your plugin class with the kernel as usual:
184+
185+
```
186+
kernel.add_plugin(WeatherForecastUtils(), "WeatherForecastUtils")
187+
```
188+
189+
The decorated methods will have the filter logic applied automatically.
190+
191+
::: zone-end
192+
92193
Always invoke the `next` delegate in your function filter to allow subsequent filters or the primary operation to execute. Skipping this step blocks the operation.
93194

94-
By integrating these filters thoughtfully, you can enhance both the functionality and security of your Semantic Kernel implementations, aligning with best practices for responsible AI development.
195+
By integrating prompt render filters, you make your Semantic Kernel solutions safer and more reliable. Prompt filters let you sanitize prompts before they reach the AI. Auto-invocation filters let you control function execution, enabling early termination or custom logic based on results.

0 commit comments

Comments
 (0)