目录
Q1: Tool Reduction 会影响工具调用的准确性吗?

一句话简介
深入探讨 Tool Reduction 的高级配置、生产环境最佳实践和性能优化策略,帮助开发者在企业级应用中充分发挥工具削减的价值。
🎯 核心价值
-
✅ 最佳实践:掌握何时使用、如何配置 toolLimit 和优化工具描述
-
✅ 高级配置:自定义策略属性、必需工具、相似度计算
-
✅ 集成优化:依赖注入集成、监控调试、性能优化
-
✅ 生产环境:完整的生产级配置方案和常见问题解答
📝 最佳实践
1. 何时使用 Tool Reduction?
| 场景 | 是否使用 | 原因 |
|---|---|---|
| 工具数量 < 10 | ❌ 不推荐 | 开销不大,削减意义不大 |
| 工具数量 10-30 | ✅ 推荐 | 开始有明显收益 |
| 工具数量 > 30 | ✅✅ 强烈推荐 | 显著降低成本和提升准确率 |
| 工具相关性低 | ✅✅ 强烈推荐 | 避免干扰项影响模型判断 |
| 上下文窗口紧张 | ✅✅ 强烈推荐 | 节省 Token 给对话历史 |
决策依据:
-
工具总数是关键因素
-
工具之间的相关性也很重要
-
上下文窗口大小限制
2. 选择合适的 toolLimit
// 场景 1: 通用场景(保留 5-8 个工具)
var generalStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 5);
// 场景 2: 严格控制(保留 3 个工具)
var strictStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 3);
// 场景 3: 宽松场景(保留 10-15 个工具)
var relaxedStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 15);
推荐配置:
| 工具总数 | 推荐 toolLimit | 说明 |
|---|---|---|
| < 20 | 5-8 | 保留较高比例的工具 |
| 20-50 | 8-12 | 平衡准确率和成本 |
| > 50 | 10-15 | 避免过度筛选导致遗漏 |
3. 工具描述的重要性
工具描述的质量直接影响 Tool Reduction 的效果。
❌ 糟糕的工具描述:
[Description("查询")] // 太简短,语义不明确
string Query(string param) => "...";
✅ 优秀的工具描述:
[Description("查询指定城市的实时天气信息,包括温度、湿度和天气状况")]
string GetWeather([Description("城市名称,如:北京、上海")] string city) => "...";
描述规范:
-
✅ 使用完整的自然语言描述
-
✅ 说明工具的用途和适用场景
-
✅ 参数描述也要清晰具体
-
✅ 包含关键词,提升语义匹配度
💻 高级配置
1. 自定义策略属性
EmbeddingToolReductionStrategy 提供多个可配置属性:
var advancedStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 5)
{
// 自定义工具的 Embedding 文本生成方式
ToolEmbeddingTextSelector = tool => $"{tool.Name}: {tool.Description}",
// 自定义消息的 Embedding 文本生成方式(只使用最后 3 条消息)
MessagesEmbeddingTextSelector = async messages =>
{
var lastMessages = messages.TakeLast(3);
returnstring.Join("\n", lastMessages.Select(m => m.Text));
},
// 自定义相似度计算函数(默认是余弦相似度)
Similarity = (a, b) => TensorPrimitives.CosineSimilarity(a.Span, b.Span),
// 标记某些工具为"必需"(始终保留,不计入 toolLimit)
IsRequiredTool = tool => tool.Name.StartsWith("Core") || tool.Name == "GetCurrentTime",
// 是否保持原始工具顺序(默认按相似度排序)
PreserveOriginalOrdering = false
};
可配置属性:
| 属性 | 说明 | 使用场景 |
|---|---|---|
ToolEmbeddingTextSelector | 自定义工具文本生成 | 优化工具描述的 Embedding 表示 |
MessagesEmbeddingTextSelector | 自定义消息文本生成 | 多轮对话中只考虑最近消息 |
Similarity | 自定义相似度计算 | 使用不同的相似度算法 |
IsRequiredTool | 标记必需工具 | 核心工具始终保留 |
PreserveOriginalOrdering | 保持原始顺序 | 保留工具注册顺序 |
2. 必需工具配置
某些核心工具需要始终保留,不受 toolLimit 限制:
var requiredToolStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 1)
{
// 将 Core* 开头和 GetCurrentTime 设为必需工具
IsRequiredTool = tool =>
tool.Name.StartsWith("Core") ||
tool.Name == "GetCurrentTime" ||
tool.Name == "LogError"
};
必需工具的特点:
-
✅ 始终保留,不计入 toolLimit
-
✅ 即使 toolLimit = 1,必需工具 + 1 个最相关工具都会保留
-
✅ 适用于核心系统工具、安全工具、日志工具等
应用场景:
-
系统监控工具(如 LogError、GetSystemStatus)
-
安全验证工具(如 AuthCheck、ValidateToken)
-
基础功能工具(如 GetCurrentTime、GetUserId)
🔧 集成与优化
1. 依赖注入集成
在生产环境中,推荐使用依赖注入管理 ChatClient:
var services = new ServiceCollection();
// 注册 Embedding Generator
services.AddSingleton<IEmbeddingGenerator<string, Embedding<float>>>(sp =>
{
var client = AIClientHelper.GetAzureOpenAIClient();
return client.GetEmbeddingClient("text-embedding-3-small").AsIEmbeddingGenerator();
});
// 注册 ChatClient 并配置 Tool Reduction
services.AddChatClient(sp =>
{
var chatClient = AIClientHelper.GetDefaultChatClient();
var embeddingGen = sp.GetRequiredService<IEmbeddingGenerator<string, Embedding<float>>>();
var strategy = new EmbeddingToolReductionStrategy(embeddingGen, toolLimit: 5);
return chatClient.AsBuilder()
.UseToolReduction(strategy)
.UseFunctionInvocation()
.Build();
});
依赖注入的优势:
-
✅ 统一管理组件生命周期
-
✅ 便于单元测试和模拟
-
✅ 支持配置动态更新
2. 监控和调试
添加监控中间件追踪 Tool Reduction 效果:
public static ChatClientBuilder UseToolListLogging(this ChatClientBuilder builder)
{
return builder.Use(
async (messages, options, innerClient, cancellationToken) =>
{
Console.WriteLine($"[Tools] {options.Tools?.Count ?? 0} 个工具被发送到模型");
foreach (var tool in options.Tools)
{
Console.WriteLine($" - {tool.Name}: {tool.Description}");
}
returnawait innerClient.GetResponseAsync(messages, options, cancellationToken);
},
null);
}
// 使用监控
var client = baseChatClient.AsBuilder()
.UseToolListLogging() // 筛选前监控
.UseToolReduction(strategy)
.UseToolListLogging() // 筛选后监控
.UseFunctionInvocation()
.Build();
监控要点:
-
✅ Tool Reduction 会修改
ChatOptions.Tools集合 -
✅ 修改发生在请求发送给模型之前
-
✅ 在
UseToolReduction()前后添加监控观察效果
3. 性能优化建议
| 优化点 | 说明 | 实施方法 |
|---|---|---|
| 工具分组 | 按领域分组,减少筛选复杂度 | 使用命名约定,如 "Weather_", "Database_" |
| 缓存 Embedding | 工具描述的 Embedding 自动缓存 | ConditionalWeakTable 自动管理 |
| 动态工具注册 | 根据上下文动态注册工具子集 | 在 ChatOptions 中只添加相关领域的工具 |
| 调整 toolLimit | 动态调整保留的工具数量 | 根据工具总数和上下文窗口调整 |
| 优化工具描述 | 详细描述提高相似度计算准确性 | 使用完整的自然语言描述 |
🏢 生产级配置示例
综合运用最佳实践,创建生产级的 Tool Reduction 配置:
// 创建生产级策略
var productionStrategy = new EmbeddingToolReductionStrategy(embeddingGenerator, toolLimit: 8)
{
// 只使用最近 5 条消息进行筛选
MessagesEmbeddingTextSelector = async messages =>
{
var recentMessages = messages.TakeLast(5);
returnstring.Join(" ", recentMessages.Select(m => m.Text));
},
// 核心工具始终保留
IsRequiredTool = tool =>
tool.Name.StartsWith("Core") ||
tool.Name == "GetCurrentTime" ||
tool.Name == "LogError",
// 保持相似度排序
PreserveOriginalOrdering = false
};
// 构建完整的客户端管道
var productionClient = baseChatClient.AsBuilder()
.UseLogging() // 1. 日志记录
.UseToolReduction(productionStrategy) // 2. 工具削减
.Use(async (messages, options, innerClient, cancellationToken) =>
{
// 3. 自定义监控
var sw = Stopwatch.StartNew();
var response = await innerClient.GetResponseAsync(messages, options, cancellationToken);
Console.WriteLine($"[监控] 响应耗时: {sw.ElapsedMilliseconds}ms");
return response;
})
.UseFunctionInvocation() // 4. 函数调用
.Build();
管道顺序说明:

💡 常见问题 FAQ
Q1: Tool Reduction 会影响工具调用的准确性吗?
A: 不会,反而会提升准确性。过滤掉无关工具后,模型面对的选择更少、干扰更小,更容易选择正确的工具。
Q2: 如何确认 Reduction 是否生效?
A: 验证方式:
-
启用日志中间件,查看发送给模型的工具数量
-
对比启用/禁用 Reduction 时的 Token 消耗
-
使用调试器查看
ChatOptions.Tools的内容 -
手动调用
SelectToolsForRequestAsync预览筛选结果
Q3: Reduction 策略如何判断工具相关性?
A: 基于 Embedding 相似度:
-
用户输入 → Embedding 向量
-
工具描述 → Embedding 向量
-
计算余弦相似度
-
选择相似度最高的前 N 个工具
Q4: toolLimit 设置多少合适?
A: 参考建议:
-
工具总数 < 20:toolLimit = 5-8
-
工具总数 20-50:toolLimit = 8-12
-
工具总数 > 50:toolLimit = 10-15
-
根据实际测试调整,观察准确率和成本平衡
Q5: 支持自定义 Reduction 策略吗?
A: 支持,实现 IToolReductionStrategy 接口:
public class MyCustomStrategy : IToolReductionStrategy
{
public async Task<IEnumerable<AITool>> SelectToolsForRequestAsync(
IEnumerable<ChatMessage> messages,
ChatOptions? options,
CancellationToken cancellationToken = default)
{
// 自定义筛选逻辑
return filteredTools;
}
}
Q6: 多轮对话中如何处理工具筛选?
A: Tool Reduction 会自动考虑对话历史:
-
使用
MessagesEmbeddingTextSelector自定义消息提取 -
默认考虑所有消息,可配置只使用最近几条
-
推荐只使用最近 3-5 条消息,提升筛选精度
🎯 总结
-
✅ 使用时机:工具数量 > 10 时启用,工具相关性低时强烈推荐
-
✅ toolLimit 配置:根据工具总数选择 5-15,平衡准确率和成本
-
✅ 工具描述优化:使用详细的自然语言描述,提升语义匹配准确性
-
✅ 高级配置:自定义 Embedding 文本、必需工具、相似度计算
-
✅ 集成优化:依赖注入管理、监控调试、性能优化
-
✅ 生产环境:完整的管道配置、日志监控、动态调整策略
生产环境建议:
-
使用依赖注入管理 ChatClient 生命周期
-
配置日志和监控,追踪 Reduction 效果
-
根据实际数据动态调整 toolLimit 和策略参数
-
定期评估工具相关性,优化工具描述
-
考虑多轮对话场景,合理使用 MessagesEmbeddingTextSelector
下一步: 探索更多 Microsoft.Extensions.AI 高级功能,如缓存策略、Chat Reducer 等。

&spm=1001.2101.3001.5002&articleId=161572086&d=1&t=3&u=508e3dc8868846be985ad858739f432e)
4166

被折叠的 条评论
为什么被折叠?



