9、Function Calling过滤器

9、Function Calling过滤器

Function Calling 过滤器

SK 中提供了两个过滤器IFunctionInvocationFilterIAutoFuntionInvocationFilter 来实现错误处理、日志审计、功能增强。

IFunctionInvocationFilter:函数调用过滤器 - 每次调用KernelFunction时都会执行此过滤器。适用于:

  • 权限验证:在函数调用之前验证用户权限,确保只有授权用户才能执行特定操作。
  • 异常处理:捕获和处理函数执行过程中可能出现的异常,例如网络错误或 AI 模型故障。
  • 结果重写:在函数执行前后修改或重写结果,例如缓存结果或应用 AI 负责性原则。
  • 函数重试:在函数失败时自动重试,例如切换到备用 AI 模型。
  • 日志记录:记录函数调用信息,例如函数名称、参数和结果,用于调试和监控。
  • 敏感信息处理:在将提示发送给 AI 之前,识别和脱敏敏感信息,例如个人信息 (PII)。
  • 语义缓存:缓存函数结果,避免重复调用相同的函数,提高效率。
  • 内容安全:过滤或修改不适当的内容,例如色情或暴力内容。
  • 文本摘要和翻译质量检查:在将文本发送给 AI 进行摘要或翻译之前,检查其质量和完整性。

IAutoFuntionInvocationFilter 自动函数调用过滤器——与IFunctionInvocationFilter类似,此过滤器在automatic function calling范围内运行,适用于:

  • 自动函数调用过程中的控制:在自动函数调用过程中,根据特定条件终止或跳过函数调用,例如当获得期望的结果时。
  • 提供额外的上下文信息:访问自动函数调用过程中的上下文信息,例如聊天历史、待执行函数列表和迭代计数器。
  • 动态调整函数调用:根据上下文信息动态调整函数调用策略,例如选择不同的 AI 模型或参数
1
2
//准备工作
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kernel.Plugins.Clear();
kernel.ImportPluginFromFunctions("HelperFunctions",
[
kernel.CreateFunctionFromMethod(() => DateTime.UtcNow.ToString("R"), "GetCurrentDateTimeInUtc", "Retrieves the current date time in UTC."),
kernel.CreateFunctionFromMethod((string cityName, string currentDateTimeInUtc) =>
cityName switch
{
"Boston" => "61 and rainy",
"London" => "55 and cloudy",
"Miami" => "80 and sunny",
"Paris" => "60 and rainy",
"Tokyo" => "50 and sunny",
"Sydney" => "75 and sunny",
"Tel Aviv" => "80 and sunny",
"Beijing" => throw new Exception("Weather data not available for Beijing."),
_ => "31 and snowing",
}, "GetWeatherForCity", "Gets the current weather for the specified city and specified date time."),
]);

异常处理过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private sealed class ExceptionHandleFilter : IFunctionInvocationFilter
{
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
{
try
{
// Try to invoke function
await next(context);
}
catch (Exception ex)
{
ex.Display();
context.Result = new FunctionResult(context.Result, "Function invocation failed. Please check...");
}
}
}
1
2
3
4
5
6
kernel.FunctionInvocationFilters.Clear();
kernel.FunctionInvocationFilters.Add(new ExceptionHandleFilter());
OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
var response = await kernel.InvokePromptAsync("What is the likely color of the sky in Beijing today?", new(settings));

response.Display();

提示:Weather data not available for Beijing.

审计过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private sealed class FunctionCallsAuditFilter : IAutoFunctionInvocationFilter
{
public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
{
context.Display();
var chatHistory = context.ChatHistory;
var functionCalls = FunctionCallContent.GetFunctionCalls(chatHistory.Last()).ToArray();
if (functionCalls is { Length: > 0 })
{
foreach (var functionCall in functionCalls)
{
Console.WriteLine($"Request #{context.RequestSequenceIndex}. Function call: {functionCall.PluginName}.{functionCall.FunctionName}.");
}
}
await next(context);
}
}
1
2
3
4
5
6
kernel.AutoFunctionInvocationFilters.Clear();
kernel.AutoFunctionInvocationFilters.Add(new FunctionCallsAuditFilter());
OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
var response =await kernel.InvokePromptAsync("What is the likely color of the sky in Boston today?", new(settings));

response.Display();
Request #0. Function call: HelperFunctions.GetCurrentDateTimeInUtc.


Request #1. Function call: HelperFunctions.GetWeatherForCity.

上下文增强过滤器

在用户请求中,添加额外上下文信息

1
2
3
4
5
6
7
8
9
10
11
12
13
kernel.Plugins.Clear();
kernel.ImportPluginFromFunctions("TodoPlugin",
[
kernel.CreateFunctionFromMethod((Kernel kernel) =>{
kernel.Data.Display();
var userId = kernel.Data["CurrentUserId"];
if (userId is "shengjie")
{
return new List<string> { "Buy groceries", "Walk the dog", "Write a blog post" };
}
return [];
}, "GetTodoList", " Gets the todo list."),
]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private sealed class ContextEnhancementFilter : IFunctionInvocationFilter
{
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
{
try
{
var currentUser = new { Name = "Shengjie", UserId ="shengjie", Phone ="1234567890", Email ="ysjxxx@live.com"};
// context.Arguments.Add("CurrentUser", currentUser);
context.Kernel.Data.Clear();
context.Kernel.Data.TryAdd("CurrentUserId", currentUser.UserId);

// Try to invoke function
await next(context);
}
catch (Exception ex)
{
ex.Display();
context.Result = new FunctionResult(context.Result, "Function invocation failed. Please check...");
}
}
}
1
2
3
4
5
6
7
kernel.AutoFunctionInvocationFilters.Clear();
kernel.FunctionInvocationFilters.Clear();
kernel.FunctionInvocationFilters.Add(new ContextEnhancementFilter());
OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
var response =await kernel.InvokePromptAsync("What need I do next?", new(settings));

response.Display();

审批过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using PolyglotKernel= Microsoft.DotNet.Interactive.Kernel;// 引入交互式的内核命名空间,以便用户输入

public class ApprovalFilter() : IFunctionInvocationFilter
{
public async Task OnFunctionInvocationAsync(FunctionInvocationContext context, Func<FunctionInvocationContext, Task> next)
{
if (context.Function.PluginName == "DynamicsPlugin" && context.Function.Name == "create_order")
{
Console.WriteLine("System > The agent wants to create an approval, do you want to proceed? (Y/N)");

var shouldProceed = await PolyglotKernel.GetInputAsync("Y/N");

if (shouldProceed != "Y")
{
context.Result = new FunctionResult(context.Result, "The order creation was not approved by the user");
return;
}
}

await next(context);
}
}
1
2
3
4
5
6
7
8
9
10
11
kernel.Plugins.Clear();
kernel.ImportPluginFromFunctions("DynamicsPlugin",
[
kernel.CreateFunctionFromMethod( (string userName, string skuId, int qty) =>
{
var orderId = Guid.NewGuid().ToString();
Console.WriteLine("System > Creating order...");
Console.WriteLine($"System > Order created! The order ID is {orderId}");
return $"Order {orderId} created!";
}, "create_order", "Create an order for a given SKU and quantity")
]);;
1
2
3
4
5
6
7
8
9
using Microsoft.SemanticKernel.Connectors.OpenAI;

kernel.FunctionInvocationFilters.Clear();
kernel.FunctionInvocationFilters.Add(new ApprovalFilter());

OpenAIPromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
var response = await kernel.InvokePromptAsync("Please place an order for Jery. She would like to purchase one iPhone16.", new(settings));

response.Display();
作者

步步为营

发布于

2025-04-05

更新于

2025-04-11

许可协议