MCP上下文加载
一个基准测试项目,用于评估模型上下文协议(MCP)工具调用和AI代理应用程序中数据库查询的直接上下文加载之间的成本和效率权衡。
概述
该项目为AI代理实现了两种不同的模式来访问数据库信息并测量其性能特征。目标是在MCP工具与上下文填充之间进行选择时,提供有关令牌使用、延迟和准确性的经验数据。
问题陈述
在构建需要查询数据库的AI代理时,开发人员面临着一个基本的选择:
- 上下文加载:预取数据并将其直接注入代理的上下文窗口
- 工具调用(MCP):通过模型上下文协议为代理提供按需查询数据的工具
每种方法在令牌消耗、响应延迟和信息准确性方面都有理论上的权衡。该项目根据经验衡量这些权衡。
建筑
核心组件
数据库层
- 具有适度复杂模式的SQLite数据库
- Alembic用于数据库迁移和版本控制
- SQLAlchemy 2.0 ORM与Pydantic设置验证
API层(Netflix调度模式)
- 为应用程序提供服务的FastAPI web框架
- 服务:异步业务逻辑和数据库操作
- 路由器:API端点定义和请求处理
- 模型:用于请求/响应验证的Pydantic模型
- 数据库:SQLAlchemy数据库模型
- 异常:域特定错误处理
- 用于代理交互的RESTful端点
代理层
- PydanticAI驱动的会话代理
- 双模操作:上下文加载与MCP工具调用
- FastMCP集成,用于基于工具的数据访问
基准层
- 两种方法的令牌使用跟踪
- 绩效指标收集
- 比较分析工具
设计理念
后端遵循 Netflix调度模式,按业务域(用户、产品、类别、订单、评论)而不是技术层组织代码。每个业务领域都是自包含的,具有一致的文件结构:
db.py -SQLAlchemy数据库模型定义了表模式、关系和约束。使用UUID主键进行安全和分发。仅包含ORM模型,不包含业务逻辑。
model.py -API验证的冗余模型。定义 Base, Create, Update,以及 Response 具有字段验证和序列化规则的模型。在API边界强制执行数据完整性。
service.py -异步业务逻辑层,与HTTP无关。包含所有数据库操作、业务规则和验证逻辑。引发特定于域的异常,而不是HTTP错误,从而实现了跨不同接口(REST、GraphQL、CLI)的重用。
router.py -FastAPI端点定义。处理HTTP问题(状态代码、请求/响应格式)。捕获服务层异常并将其转换为适当的HTTP响应。薄层仅专注于web协议。
exceptions.py -域的自定义异常层次结构。业务区域的基本异常类,继承了特定的异常。提供独立于传输层的清晰错误语义。
__init__.py -公共接口导出。公开模型和例外情况,供其他业务领域使用。需要时显式导入路由器,保持松耦合。
这种结构提供了明确的关注点分离:数据库访问、验证、业务逻辑和HTTP处理都隔离在专用文件中。该模式随着业务复杂性的增长而扩展良好,并使测试变得简单,因为每一层都可以独立测试。
数据流
上下文加载模式
User Query -> Agent (with pre-loaded context) -> Response
�
Database (pre-fetch)MCP工具模式
User Query -> Agent -> Tool Call -> Service Layer -> Database
�
Response技术栈
- Python 3.11+:核心语言
- 快速API:Web框架
- SQLite:数据库
- 蒸馏器:数据库迁移
- PydanticAI:代理框架
- FastMCP:模型上下文协议实现
- 紫外线:包管理
基准测试方法
该项目采用了一种轻量级的、专门为研究和比较分析量身定制的基准测试方法。虽然MLflow、Weights&Biases或LangSmith等企业级解决方案提供了全面的实验跟踪和生产监控功能,但由于以下原因,该实施优先考虑简单性和成本效益:
设计理念
研究型:主要目标是对两种特定模式进行比较分析,而不是生产部署监控。简化的基准框架可以减少运营开销,并保持对核心研究问题的关注。
成本约束:企业MLOps平台引入的基础设施成本和复杂性超过了本次调查的要求。使用标准Python库的自定义实现提供了足够的测量功能,而无需额外的服务依赖关系。
教育价值:从第一原则构建基准测试仪器,可以更深入地了解所测量的指标及其影响,这与项目的研究目标相一致。
可重复性:基准代码的自包含性确保了项目在不同环境中易于复制,而不需要访问外部平台或商业服务。
测量方法
基准层捕捉到:
- 通过API响应元数据的令牌计数
- 使用标准Python计时工具进行延迟测量
- 通过确定性验证集实现查询准确性
- 基于当前LLM定价模型的成本预测
结果被持久化到结构化文件(JSON/CSV)中,以便使用标准数据科学工具(pandas、matplotlib)而不是专用平台进行分析。
范围和限制
这种方法专为比较研究而不是生产模型监控而设计。对于需要实验版本控制、模型注册表、超参数优化或分布式训练协调的生产部署,企业解决方案仍然是合适的选择。
项目目标
- 构建一个具有有意义关系的现实数据库模式
- 实现上下文加载和MCP工具模式
- 创建用于测试的对话界面
- 测量和比较:
- 每次查询的令牌消耗 - 响应延迟 - 信息检索准确性 - 规模上的成本影响
- 记录调查结果和建议
预期成果
该基准将提供数据驱动的见解,包括:
- 何时使用上下文加载与工具调用
- 每种方法的成本影响
- 不同查询模式下的性能特征
- 混合实施的最佳实践
基准测试结果
我们使用模拟数据和真实数据库查询进行了全面的基准测试,比较了上下文加载和工具调用方法。这些结果验证了Speakeasy的研究结果,并证明了基于工具的架构的显著效率提升。
主要发现
代币使用减少:91.44%
- 上下文加载:36157个令牌(预加载500个实体)
- 工具调用:3094个令牌(按需提取50个实体)
实体效率
- 上下文加载:每种类型(用户、产品、类别、订单、评论)100个实体=总共500个
- 工具调用:通过5次工具调用,每种类型10个实体=总共50个
- 实体减少:90%
数据库操作
- 两种方法:5个数据库查询
- 上下文加载:0个工具调用(所有数据已预加载到系统提示符中)
- 工具调用:5次工具调用(根据需要按需获取)
对照研究验证
我们的发现与行业研究密切相关:
- Speakeasy报告:复杂工作流的令牌减少91.2%
- 我们的成果:使用真实数据库减少91.44%的令牌
- 一致性:模拟数据基准显示减少了91.21%,证实了可重复性
可视化
综合性能比较图表可在 benchmarks/results/:
agent_comparison.png-模拟数据基准测试(4面板比较)agent_comparison_db.png-真实数据库基准测试(4面板比较)benchmark_results.json-模拟数据详细指标benchmark_results_db.json-真实数据库详细指标
每个可视化包括:
- 令牌使用情况比较
- 加载的实体总数
- 按类型(用户、产品、类别、订单、评论)对实体进行细分
- 数据库查询和工具调用计数
实际意义
何时使用上下文加载:
- 小型静态数据集(\100个实体)
- 经常变化的动态数据
- 数据需求不断变化的多回合对话
- 成本敏感型应用程序(91%的代币减少=91%的成本减少)
- 需要选择性数据访问的复杂工作流程
混合方法: 考虑将这两种模式结合起来:
- 将频繁访问的静态数据(如类别层次结构、产品类型)加载到上下文中
- 使用工具进行可变/动态查询(例如,用户订单、库存水平、评论)
- 在延迟和令牌效率之间提供平衡
基准方法
数据库设置:
- SQLite数据库使用
rdb/seed.py - 5个业务领域:用户、产品、类别、订单、评论
- 现实的关系和数据分布
代理实施:
be/chat_context/:PydanticAI代理在系统提示中具有完整的数据库上下文be/chat_tools/:PydanticAI代理,带有10个注册工具包装服务层- 模特:克劳德3.5十四行诗(
claude-3-5-sonnet-20241022) - 代币计数:tiktoken
cl100k_base编码
测量脚本:
benchmarks/compare_simple.py:模拟数据基准测试(不需要数据库)benchmarks/compare_with_db.py:真实数据库基准测试(需要种子SQLite)- 两者都生成JSON指标和matplotlib可视化
运行基准
# Seed the database with test data
uv run python rdb/seed.py
# Run real database benchmark
uv run python benchmarks/compare_with_db.py
# Run mock data benchmark (faster, no DB required)
uv run python benchmarks/compare_simple.py结果保存到 benchmarks/results/ 带有时间戳的JSON数据和PNG可视化。
动态工具集仿真
除了比较上下文加载与静态工具之外,我们还评估了第三种方法: 动态工具集 基于 Speakeasy的研究此模拟回答: 在什么情况下,工具的数量会使静态工具集变得不切实际?
三种方法
| 方法 | 描述 | 令牌成本 | 延迟 |
|---|---|---|---|
| 完整上下文 | 将所有数据加载到系统提示符 | O(n)和实体 | 已修复 |
| 静态工具 | 预先注册所有工具模式 | O(n)与工具 | 最佳 |
| 动态工具集 | 三函数发现模式 | O(1)常数 | 变量 |
动态工具集使用发现模式:
search_tools-语义搜索以查找相关工具describe_tools-仅在需要时延迟加载模式execute_tool-执行发现的工具
关键发现:按周期计数的可变性能
动态工具集性能因需要多少发现周期而异:
| 周期 | 延迟 | 准确性 | 何时发生 |
|---|---|---|---|
| 2 | 2406ms | 91.2% | 简单查询,工具立即找到 |
| 3 | 3508ms | 89.1% | 平均病例数 |
| 4 | 4611ms | 87.8% | 需要改进 |
| 5 | 5714ms | 86.4% | 复杂的多工具查询 |
| 6 | 6816ms | 85.1% | 最坏情况:多次重试 |
仿真结果
| 工具 | 静态令牌 | 静态精度 | 动态令牌 | 动态精度 |
|---|---|---|---|---|
| 10 | 3,300 | 98% | 2,055 | 85-91% |
| 50 | 7,300 | 88% | 2,055 | 85-91% |
| 100 | 12,300 | 78% | 2,055 | 85-90% |
| 200 | 22,300 | 78% | 2,055 | 85-90% |
故障模式
每种方法都有不同的故障特征:
- 完整上下文:“中间丢失”效果-无论工具数量如何,精度都会降低至~83%
- 静态工具:刀具过载-15个刀具后,每个刀具的精度下降0.3%,触底为78%
- 动态工具集:循环复合-每个发现周期误差1.5%,稳定在85-91%
交叉点:约85个工具
在85个工具中,当权衡令牌节省与延迟开销时,动态工具集变得净有利。
| 工具计数 | 建议 |
|---|---|
| 1-15 | 静态工具(准确率98%,快速) |
| 16-40 | 静态工具(精度仍为90%+) |
| 41-70 | 根据优先级进行评估 |
| 71-100 | 动态工具集(静态下降到78%) |
| 100+ | 动态工具集(唯一可行的选项) |
运行模拟
# Generate all plots
uv run python -m be.chat_tools_speakeasy.simulation输出在 be/chat_tools_speakeasy/:
plot_tokens_vs_latency.png-与周期价差的主要权衡plot_accuracy_analysis.png-方法导致精度下降plot_cycle_impact.png-逐周期分解plot_complete_tradeoff.png-三维气泡可视化plot_crossover_analysis.png-盈亏平衡分析plot_monthly_cost.png-规模成本比较
看 be/chat_tools_speakeasy/README.md 了解详细的方法和模型参数。
发展路线图
- \[x\] 数据库模式设计与实现
- \[x\] Alembic迁移设置
- \[x\] 使用Netflix调度模式的FastAPI应用程序结构(服务、路由器、模型、数据库、异常)
- \[x\] 上下文加载实现(
be/chat_context/) - \[x\] PydanticAI代理设置(上下文和工具模式)
- \[x\] 工具调用实现(
be/chat_tools/) - \[x\] 基准测试框架(模拟和真实数据库)
- \[x\] 比较分析和可视化
- \[x\] 文件和调查结果
- \[x\] 动态工具集模拟(
be/chat_tools_speakeasy/) - \[\]FastMCP集成(可选增强)
- \[\]生产部署注意事项
许可证
有关详细信息,请参阅LICENSE文件。
