0
# Filters and Middleware
1
2
Extensible filter system for intercepting and modifying function invocation, prompt rendering, and auto-function invocation. Enables custom middleware, logging, validation, and transformation logic.
3
4
## Capabilities
5
6
### Filter Context Types
7
8
Context objects for different types of filter operations.
9
10
```python { .api }
11
class FunctionInvocationContext:
12
"""
13
Context for function invocation filters.
14
"""
15
16
def __init__(
17
self,
18
function: KernelFunction,
19
kernel: Kernel,
20
arguments: KernelArguments
21
):
22
"""
23
Initialize function invocation context.
24
25
Parameters:
26
- function: The function being invoked
27
- kernel: Kernel instance
28
- arguments: Function arguments
29
"""
30
31
@property
32
def function(self) -> KernelFunction:
33
"""Get the function being invoked."""
34
35
@property
36
def kernel(self) -> Kernel:
37
"""Get the kernel instance."""
38
39
@property
40
def arguments(self) -> KernelArguments:
41
"""Get the function arguments."""
42
43
@property
44
def result(self) -> FunctionResult | None:
45
"""Get the function result (available in post-invocation filters)."""
46
47
class PromptRenderContext:
48
"""
49
Context for prompt rendering filters.
50
"""
51
52
def __init__(
53
self,
54
function: KernelFunction,
55
kernel: Kernel,
56
arguments: KernelArguments
57
):
58
"""
59
Initialize prompt render context.
60
61
Parameters:
62
- function: The function containing the prompt
63
- kernel: Kernel instance
64
- arguments: Arguments for prompt rendering
65
"""
66
67
@property
68
def function(self) -> KernelFunction:
69
"""Get the function containing the prompt."""
70
71
@property
72
def kernel(self) -> Kernel:
73
"""Get the kernel instance."""
74
75
@property
76
def arguments(self) -> KernelArguments:
77
"""Get the prompt arguments."""
78
79
@property
80
def rendered_prompt(self) -> str | None:
81
"""Get the rendered prompt (available in post-render filters)."""
82
83
class AutoFunctionInvocationContext:
84
"""
85
Context for auto function invocation filters.
86
"""
87
88
def __init__(
89
self,
90
function: KernelFunction,
91
kernel: Kernel,
92
arguments: KernelArguments
93
):
94
"""
95
Initialize auto function invocation context.
96
97
Parameters:
98
- function: The function being auto-invoked
99
- kernel: Kernel instance
100
- arguments: Function arguments
101
"""
102
103
@property
104
def function(self) -> KernelFunction:
105
"""Get the function being auto-invoked."""
106
107
@property
108
def kernel(self) -> Kernel:
109
"""Get the kernel instance."""
110
111
@property
112
def arguments(self) -> KernelArguments:
113
"""Get the function arguments."""
114
115
@property
116
def chat_history(self) -> ChatHistory | None:
117
"""Get the chat history (if applicable)."""
118
119
class FilterTypes:
120
"""
121
Enumeration of filter types.
122
"""
123
FUNCTION_INVOCATION: str = "function_invocation"
124
PROMPT_RENDERING: str = "prompt_rendering"
125
AUTO_FUNCTION_INVOCATION: str = "auto_function_invocation"
126
```
127
128
### Filter Integration with Kernel
129
130
The Kernel class includes filter management capabilities through extensions.
131
132
```python { .api }
133
# Filter management methods available on Kernel class
134
class Kernel:
135
"""
136
Kernel with filter management capabilities.
137
"""
138
139
def add_function_invocation_filter(self, filter_func) -> None:
140
"""
141
Add a function invocation filter.
142
143
Parameters:
144
- filter_func: Filter function to add
145
"""
146
147
def add_prompt_rendering_filter(self, filter_func) -> None:
148
"""
149
Add a prompt rendering filter.
150
151
Parameters:
152
- filter_func: Filter function to add
153
"""
154
155
def add_auto_function_invocation_filter(self, filter_func) -> None:
156
"""
157
Add an auto function invocation filter.
158
159
Parameters:
160
- filter_func: Filter function to add
161
"""
162
163
@property
164
def function_invocation_filters(self) -> list:
165
"""Get all function invocation filters."""
166
167
@property
168
def prompt_rendering_filters(self) -> list:
169
"""Get all prompt rendering filters."""
170
171
@property
172
def auto_function_invocation_filters(self) -> list:
173
"""Get all auto function invocation filters."""
174
```
175
176
## Usage Examples
177
178
### Function Invocation Filters
179
180
```python
181
from semantic_kernel import Kernel
182
from semantic_kernel.filters import FunctionInvocationContext
183
import logging
184
185
# Create logging filter
186
async def logging_filter(context: FunctionInvocationContext, next_filter):
187
"""Log function invocations."""
188
logging.info(f"Invoking function: {context.function.name}")
189
logging.info(f"Arguments: {context.arguments}")
190
191
# Call next filter in chain
192
await next_filter(context)
193
194
logging.info(f"Function result: {context.result.value}")
195
196
# Add filter to kernel
197
kernel = Kernel()
198
kernel.add_function_invocation_filter(logging_filter)
199
```
200
201
### Prompt Rendering Filters
202
203
```python
204
from semantic_kernel.filters import PromptRenderContext
205
206
async def prompt_validation_filter(context: PromptRenderContext, next_filter):
207
"""Validate rendered prompts."""
208
# Call next filter to get rendered prompt
209
await next_filter(context)
210
211
# Validate rendered prompt
212
if context.rendered_prompt and len(context.rendered_prompt) > 10000:
213
raise ValueError("Rendered prompt exceeds maximum length")
214
215
print(f"Validated prompt for function: {context.function.name}")
216
217
# Add prompt validation filter
218
kernel.add_prompt_rendering_filter(prompt_validation_filter)
219
```
220
221
### Auto Function Invocation Filters
222
223
```python
224
from semantic_kernel.filters import AutoFunctionInvocationContext
225
226
async def function_approval_filter(context: AutoFunctionInvocationContext, next_filter):
227
"""Require approval for sensitive functions."""
228
sensitive_functions = ["delete_file", "send_email", "make_payment"]
229
230
if context.function.name in sensitive_functions:
231
print(f"Function {context.function.name} requires approval.")
232
approval = input("Approve? (y/N): ")
233
if approval.lower() != 'y':
234
print("Function invocation cancelled.")
235
return
236
237
# Proceed with function invocation
238
await next_filter(context)
239
240
# Add approval filter for auto function invocation
241
kernel.add_auto_function_invocation_filter(function_approval_filter)
242
```
243
244
### Custom Error Handling Filter
245
246
```python
247
import traceback
248
249
async def error_handling_filter(context: FunctionInvocationContext, next_filter):
250
"""Handle and log errors during function invocation."""
251
try:
252
await next_filter(context)
253
except Exception as e:
254
logging.error(f"Error in function {context.function.name}: {str(e)}")
255
logging.error(f"Traceback: {traceback.format_exc()}")
256
257
# Optionally modify the result or re-raise
258
context.result = FunctionResult(
259
function=context.function,
260
value=f"Error occurred: {str(e)}"
261
)
262
263
kernel.add_function_invocation_filter(error_handling_filter)
264
```
265
266
### Performance Monitoring Filter
267
268
```python
269
import time
270
271
async def performance_filter(context: FunctionInvocationContext, next_filter):
272
"""Monitor function execution performance."""
273
start_time = time.time()
274
275
await next_filter(context)
276
277
execution_time = time.time() - start_time
278
print(f"Function {context.function.name} executed in {execution_time:.2f} seconds")
279
280
# Add performance metadata to result
281
if context.result and context.result.metadata:
282
context.result.metadata["execution_time"] = execution_time
283
284
kernel.add_function_invocation_filter(performance_filter)
285
```