ToolScout
一种使用MCP(模型上下文协议)服务器进行动态工具发现和执行的智能代理系统,具有向量相似性搜索和对话历史优化功能。
概述
ToolScout是一个基于 微软代理框架 它解决了构建具有广泛功能的AI代理时的两个关键挑战:
- 管理大型工具集:随着代理通过MCP服务器访问数十或数百个工具,由于令牌限制和延迟增加,将所有工具加载到代理的上下文中变得不切实际。这也会导致上下文分心和混乱,不相关的工具描述会干扰代理的决策(参见 上下文如何失败).
- 长期对话:扩展的多回合交互会积累对话历史,其中不仅包括用户查询和响应,还包括工具调用细节,这些细节会使上下文窗口变得混乱并浪费令牌。
ToolScout通过以下方式应对这些挑战:
- 向量相似性搜索:动态发现并加载每个查询的3-5个最相关的工具,将工具上下文减少80-90%(50→3.8个平均工具)
- 智能历史过滤:自动从对话历史记录中删除工具调用和结果消息,仅保留用户查询和助手响应
- 动态上下文管理:结合这两种优化,使代理能够在扩展对话中与20-30多种工具有效协作,而不会耗尽上下文窗口
这种方法显著减少了令牌的使用(节省了约47%),同时在复杂的多回合对话中保持了完整的功能。
基准测试
模型:GPT-5-Mini。\ 场景:场景3(总迭代次数312)
| 配置 | ToolScout+滚动窗口+消息清除 | ToolScout+无滚动窗口+信息清除 | 所有工具+无滚动窗+无消息清除 |
|---|---|---|---|
| 最大输入令牌数 | 11332 | 45672 | 83307 |
| 平均输入令牌 | 7344 | 23972 | 45166 |
| 输入令牌总数 | 2291272 | 7479400 | 14091813 |
| 平均每转刀具数 | 3.8 | 3.8 | 50 |
| 持续时间(分钟) | 51 | 65 | 76 |
性能提升
- 最大输入令牌减少: ~45% (83K → 46K个最大输入令牌)
- 代币总减少量: ~47% (14M → 7.5M个总输入令牌)
- 时间缩短: ~14% (76分钟→ 65 最小执行时间)
背景
这项调查的灵感来自Anthropic对高级工具使用模式和基于嵌入的工具搜索的研究:
- 高级工具使用 -代理系统中优化工具调用的技术
- 使用嵌入进行工具搜索 -演示基于向量的工具发现的Cookbook示例
特性
- 🔍 基于矢量的工具发现 使用Azure OpenAI嵌入
- 🧠 智能对话历史记录 具有自动工具消息过滤功能
- 🔧 多服务器MCP支持 具有并发服务器连接
- 📊 优化指标 显示令牌减少和工具选择统计数据
- 🎯 可配置阈值 相似性和历史限制
- 🐛 调试模式 用于会话历史检查
构建于
- 微软代理框架 -代理人工智能应用框架
- Azure OpenAI -LLM和嵌入模型
- 快速MCP -模型上下文协议服务器实现
- 紫外线 -快速Python包管理器
建筑
┌─────────────────┐
│ User Query │
└────────┬────────┘
│
▼
┌─────────────────────────────┐
│ Vector Similarity Search │ ← Embeddings
│ (Tool Registry) │
└────────┬────────────────────┘
│
▼
┌─────────────────────────────┐
│ Selected Tools (3-5) │
└────────┬────────────────────┘
│
▼
┌─────────────────────────────┐
│ Agent Execution │ ← Filtered History
│ (Azure OpenAI Responses) │
└────────┬────────────────────┘
│
▼
┌─────────────────────────────┐
│ Result + History Update │
└─────────────────────────────┘设置
先决条件
- Python 3.13+
- 紫外线 包管理器
- Azure OpenAI访问:
- 聊天模型部署(例如gpt-4o、gpt-4o-mini) - 嵌入模型部署(例如,text-embedding-3-small)
- 用于身份验证的Azure CLI
安装
- 克隆存储库
git clone https://github.com/corradocavalli/toolscout.git
cd toolscout- 安装依赖项
uv sync- 配置环境
cp .env.sample .env
# Edit .env with your Azure OpenAI details- 使用Azure进行身份验证
az login配置
编辑 .env 使用您的设置:
# Azure OpenAI Configuration
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o-mini
AZURE_EMBEDDING_MODEL_DEPLOYMENT_NAME=text-embedding-3-small
# Tool Discovery Settings
TOP_K=3 # Number of tools to select per query
SIMILARITY_THRESHOLD=0.3 # Minimum similarity score (0-1)
# History Management
MAX_HISTORY_MESSAGES=50 # Maximum messages in conversation history用法
启动MCP服务器
在单独的终端中:
cd mcp
./start_servers.sh这将启动3个演示MCP服务器:
- 服务器1 (端口8000):用户管理、电子邮件、天气
- 服务器2 (端口9000):库管理
- 服务器3 (港口10000):股票交易
运行交互模式
uv run main.py使用场景运行
uv run main.py --scenario scenario_1调试模式
查看传递给代理的对话历史记录:
uv run main.py --scenario scenario_1 --debug禁用优化
将性能与加载的所有工具进行比较:
uv run main.py --scenario scenario_1 --optimize false命令行选项
uv run main.py [OPTIONS]
Options:
--scenario TEXT Run a scenario file (e.g., scenario_1)
--optimize BOOL Enable tool selection optimization (default: true)
--debug Show conversation history in output
--help Show this message and exit项目结构
toolscout/
├── main.py # Main application entry point
├── tool_registry.py # Vector search and tool indexing
├── tool_manager.py # Tool discovery and loading
├── conversation_store.py # Custom history with message filtering and lenght limitation
├── utils.py # Helper functions for display
├── mcp/ # Demo MCP servers
│ ├── server1.py # General tools
│ ├── server2.py # Library management
│ ├── server3.py # Stock trading
│ └── start_servers.sh # Launch all servers
├── scenarios/ # Test scenarios
│ ├── scenario_1.txt # Simple multi-turn
│ ├── scenario_2.txt # Complex interactions
│ └── scenario_3.txt # Extended scenario
└── pyproject.toml # Project dependencies关键概念
工具发现
ToolScout使用查询嵌入和工具描述嵌入之间的余弦相似性来选择相关工具:
- 启动时,所有工具描述都被嵌入并索引
- 对于每个查询,计算查询嵌入
- 查找相似度高于阈值的前K个工具
- 仅将选定的工具加载到代理上下文中
历史优化
海关 LimitedHistoryChatMessageStore 提供两种操作模式:
优化模式(默认):
- 过滤掉工具调用消息
- 过滤掉工具结果消息
- 仅保留用户查询和助手响应
- 修剪到最后N条消息
- 在典型的多工具场景中,将上下文大小减少约50%
完整历史记录模式 (--optimize false):
- 保留所有对话历史记录,包括工具调用和结果
- 未应用过滤或修剪
- 消耗更多的令牌和上下文空间
- 可用于比较性能或调试工具交互
何时使用此方法
当使用时,这种优化策略变得有益 20~30+工具低于该阈值,向量相似性搜索和工具选择的开销可能超过减少上下文所节省的令牌。对于较小的工具集(\<20个工具),将所有工具直接加载到代理上下文中通常更简单、更高效。
局限性和未来改进
刀具选择精度
由于工具选择依赖于语义相似性,因此对于某些查询,某些工具可能无法正确识别。在调整时 SIMILARITY_THRESHOLD 参数可以提供帮助,更有效的解决方案涉及两阶段方法:
第一阶段:动作提取
在查询工具注册表之前,使用代理从用户的请求中提取所需的操作:
User: "If it is raining, book a taxi"
↓
Agent extracts actions: "get_weather, book_taxi"
↓
Registry searches: ["get_weather", "book_transport", "fetch_weather", "book_driver", "book_taxi"]第二阶段:工具优化
通过让代理基于原始请求从候选工具中进行选择,进一步细化选择:
Input:
- Original query: "If it is raining, book a taxi"
- Candidates: ["get_weather", "book_transport", "fetch_weather", "book_driver", "book_taxi"]
↓
Agent selects: ["get_weather", "book_taxi"]性能注意事项
这种增强方法的主要挑战是侦察阶段引入的额外延迟:
- 云LLM:使用小云模型进行大致侦察 双打 总响应时间
- 本地法学硕士:使用本地模型,如 TinyLlama-1.1B-Chat-v1.0 将开销减少到 15-20%,当需要最大的刀具选择精度时,这可能是可以接受的
推荐:对于大多数用例,当前的向量相似性方法在准确性和延迟之间提供了良好的平衡。仅当工具选择精度至关重要且额外延迟可接受时,才考虑两阶段方法。
替代嵌入模型
当前的实现使用Azure OpenAI的嵌入模型,这需要API调用并产生成本。一个潜在的改进是使用轻量级的本地嵌入模型来评估性能,例如 全迷你LM-L6-v2,这可能:
- 消除嵌入API的成本和延迟
- 启用完全脱机操作
- 提供更快的工具索引和搜索
这将需要基准测试,以确保嵌入质量足以进行准确的工具选择。
对话总结
除了消息过滤和长度限制之外,另一个针对超长对话的优化是实现基于LLM的历史摘要。当对话超过某个阈值(例如,100+条消息)时,LLM可以:
- 将对话的旧部分总结成简洁的上下文
- 完整保留最近的消息细节
- 用摘要替换原始消息以保存令牌
这种方法将能够维护扩展会话的上下文,同时保持令牌使用的可管理性。摘要可以按可配置的时间间隔或消息计数自动触发。
贡献
这是一个示范项目。请随意分叉并适应您的需求!
