Smart Explore 基准测试¶
Smart Explore 利用 tree-sitter AST 解析,通过三个 MCP 工具——smart_search、smart_outline 和 smart_unfold——提供结构化代码导航。本报告记录了与标准 Explore agent(使用 Glob、Grep 和 Read 工具)的严格 A/B 对比,以量化 token 节省与质量权衡。
执行摘要¶
| 指标 | Smart Explore | Explore Agent | 优势 |
|---|---|---|---|
| 发现(跨文件搜索) | ~14,200 tokens | ~252,500 tokens | 便宜 17.8 倍 |
| 定向读取(特定符号) | ~5,650 tokens | ~109,400 tokens | 便宜 19.4 倍 |
| 端到端(搜索 + 读取) | ~4,200 tokens | ~45,000 tokens | 便宜 10-12 倍 |
| 完整性 | 5/5 返回完整源码 | 4/5(最长方法被截断) | Smart Explore 更可靠 |
| 速度 | 每次调用低于 2 秒 | 每次调用 5-66 秒 | 快 10-30 倍 |
方法论¶
测试环境¶
- 代码库:claude-mem(
src/目录,194 个 TypeScript 文件,1,206 个解析符号) - 模型:两种方法均使用 Claude Opus 4.6
- 测量方式:来自工具响应元数据的 token 计数(Explore agent 使用
total_tokens,Smart Explore 使用自报的~N tokens for folded view)
控制条件¶
Explore agent 被明确告知:“不要使用 smart_search、smart_outline 或 smart_unfold 工具。只能使用 Glob、Grep 和 Read 工具。” 这一限制在最初一轮中被证明是必要的,因为当时 agent 会投机性地使用 Smart Explore 工具,导致对比无效。
查询¶
我们选择了五个查询来代表常见的探索任务:
- “session processing” —— 横跨多个服务的横切功能
- “shutdown” —— 涉及 6+ 个文件的基础设施关注点
- “hook registration” —— 关于插件系统的架构问题
- “sqlite database” —— 数据层中针对特定技术的搜索
- “worker-service.ts outline” —— 单个大文件(1,225 行)的结构理解
第 1 轮:发现¶
“有什么?在哪里?” —— 在整个代码库中查找相关文件和符号。
结果¶
| 查询 | Smart Explore | Explore Agent | 比例 | Explore 工具调用次数 |
|---|---|---|---|---|
| session processing | ~4,391 t | 51,659 t | 11.8x | 15 |
| shutdown | ~3,852 t | 51,523 t | 13.4x | 18 |
| hook registration | ~1,930 t | 51,688 t | 26.8x | 37 |
| sqlite database | ~2,543 t | 58,633 t | 23.1x | 16 |
| worker-service outline | ~1,500 t | 38,973 t | 26.0x | 15 |
| 总计 | ~14,216 t | 252,476 t | 17.8x | 101 |
各自的返回结果¶
Smart Explore(每次 1 次工具调用):返回 10 个带签名、行号和 JSDoc 摘要的排序符号,以及所有匹配文件的折叠结构视图,显示每个函数/类/接口且主体已折叠。
Explore Agent(每次 15-37 次工具调用):生成综合性的叙述报告,包含架构图、设计模式分析、数据流说明、完整接口转储和文件结构图。解释性文字明显更多。
分析¶
token 差距在范围狭窄的查询(“hook registration”为 26.8 倍)中最大,因为 Explore agent 会读取多个完整文件来查找相对较少的相关符号。对于范围广泛的查询(“session processing”为 11.8 倍),更多文件内容与查询相关,从而缩小了比例。
Smart Explore 始终如一的单次工具调用模式意味着其成本是可预测的。Explore agent 的成本随其读取的文件数量以及综合处理量而变化——在可比范围内从 15 到 37 次工具调用不等。
第 2 轮:定向读取¶
“给我看看这个具体的函数。” —— 在发现阶段之后读取已知符号的实现。
基于第 1 轮的结果,我们选择了五个具体符号作为自然的深入目标:
| 目标符号 | 文件 | 行数 |
|---|---|---|
SessionManager.initializeSession |
services/worker/SessionManager.ts | 135 |
performGracefulShutdown |
services/infrastructure/GracefulShutdown.ts | 48 |
hookCommand |
cli/hook-command.ts | 45 |
DatabaseManager.initialize |
services/sqlite/Database.ts | 27 |
WorkerService.startSessionProcessor |
services/worker-service.ts | 158 |
结果¶
| 符号 | Smart Unfold | Explore Agent | 比例 | 完整性 |
|---|---|---|---|---|
| initializeSession (135 行) | ~1,800 t | 27,816 t | 15.5x | 两者均返回完整源码 |
| performGracefulShutdown (48 行) | ~700 t | 19,621 t | 28.0x | 两者均返回完整源码 |
| hookCommand (45 行) | ~650 t | 18,680 t | 28.7x | 两者均返回完整源码 |
| DatabaseManager.initialize (27 行) | ~400 t | 22,334 t | 55.8x | 两者均返回完整源码 |
| startSessionProcessor (158 行) | ~2,100 t | 20,906 t | 10.0x | Smart Unfold:完整。Explore:被截断 |
| 总计 | ~5,650 t | 109,357 t | 19.4x |
分析¶
比例与符号大小成反比。 最小的函数(initialize,27 行)显示出最大的差距,为 55.8 倍,因为 Explore agent 仍然会读取整个 235 行的文件来提取 27 行。最大的方法(startSessionProcessor,158 行)则缩小到 10 倍,因为文件中“有用”的内容更多了。
Smart Unfold 返回了更完整的代码。 对于最长的方法(158 行),Explore agent 用 "... error handling continues ..." 截断了错误处理部分,而 smart_unfold 返回了完整的实现。这是因为 smart_unfold 按 AST 节点边界提取,无论符号大小如何都能保证完整性。
对于定向读取,Explore agent 不会增加任何独特信息。 当您已经知道文件路径和符号名时,agent 的开销纯粹是浪费——它读取文件、定位函数,然后将其原样返回。唯一增加的只是一段简短的解释性文字。
组合工作流¶
实际的工作流是先进行发现,再进行定向读取。以下是理解单个函数的端到端成本对比:
Smart Explore:搜索与展开¶
smart_search("shutdown", path="./src") ~3,852 tokens
smart_unfold("GracefulShutdown.ts", "performGracefulShutdown") ~700 tokens
────────────────────────────────────────────────────────────────
Total: ~4,552 tokens (2 tool calls, under 3 seconds)
Explore Agent:单一查询¶
"Find and explain the shutdown logic" ~51,523 tokens
────────────────────────────────────────────────────────────────
Total: ~51,523 tokens (18 tool calls, ~43 seconds)
端到端比率:11.3 倍——Smart Explore 工作流能提供实际源代码,而 Explore Agent 给出的只是叙述式摘要,可能会改写或截断内容。
质量评估¶
两种方法并非绝对地谁优谁劣,它们针对不同的目标进行优化。
Smart Explore 优势¶
- 可预测的成本:每个操作只需 1 次工具调用,Token 范围稳定
- 完整的源代码:基于 AST 的提取保证完整的符号主体
- 结构上下文:折叠视图显示匹配文件中的每个符号
- 速度:亚秒级响应支持快速迭代
- 可组合性:搜索、大纲和展开可以自然地串联使用
Explore Agent 优势¶
- 综合理解:生成架构说明、数据流图和设计模式分析
- 跨文件解释:能够连接多个文件中的概念,这是单独读取符号无法做到的
- 入门引导质量:输出读起来像文档,而不是原始代码
- 错误处理洞察:识别需要阅读多个相关函数才能发现的边界情况和设计决策
- 无需先前知识:无需知道文件路径或符号名称即可回答开放式问题
按任务类型的质量对比¶
| 任务 | 更合适的工具 | 原因 |
|---|---|---|
| “X 在哪里定义?” | Smart Explore | 一次调用,精确答案 |
| “这个文件里有哪些函数?” | Smart Explore | 大纲返回完整的结构地图 |
| “展示这个函数” | Smart Explore | 展开返回精确源码,绝不截断 |
| “功能 X 如何端到端工作?” | Explore Agent | 阅读多个文件并综合叙述 |
| “这里用了哪些设计模式?” | Explore Agent | 需要阅读和解读,而不仅仅是提取 |
| “帮我理解这个代码库” | Explore Agent | 生成入门级文档 |
何时使用哪种方式¶
在以下情况使用 Smart Explore:
- 你知道自己要找什么(函数名、概念、文件)
- 你需要源代码,而不是解释
- 你在快速迭代(读取、修改、再读取)
- Token 预算很重要(大型代码库、长时间会话)
- 你需要一眼看清文件结构
在以下情况使用 Explore Agent:
- 你需要综合性的跨文件理解
- 问题是开放式的(“这个系统是如何工作的?”)
- 你在编写文档或架构评审
- 你需要理解为什么,而不仅仅是是什么
- 你在上手一个不熟悉的代码库
在以下情况两者结合使用:
- 先用 Smart Explore 进行发现和导航
- 仅在需要多文件综合的深度分析时才升级到 Explore Agent
- 这种混合方式能获得大部分 Token 节省,同时保留在需要时进行深度理解的能力
Token 成本参考¶
| 操作 | Token | 使用场景 |
|---|---|---|
smart_search |
2,000-6,000 | 跨文件符号发现 |
smart_outline |
1,000-2,000 | 单文件结构地图 |
smart_unfold |
400-2,100 | 单个符号的完整源码 |
smart_search + smart_unfold |
3,000-8,000 | 端到端:查找并读取 |
| Explore Agent(定向) | 18,000-28,000 | 单个函数及解释 |
| Explore Agent(跨文件) | 39,000-59,000 | 架构级理解 |
| 读取(完整文件) | 8,000-15,000+ | 完整文件内容 |
各工作流的节省¶
| 工作流 | Smart Explore | 传统方式 | 节省 |
|---|---|---|---|
| 理解一个文件 | outline + unfold (~3,100 t) | 读取完整文件 (~12,000 t) | 4 倍 |
| 在代码库中查找函数 | search (~3,500 t) | Explore agent (~50,000 t) | 14 倍 |
| 查找并读取特定函数 | search + unfold (~4,500 t) | Explore agent (~50,000 t) | 11 倍 |
| 浏览一个 1,200 行的文件 | outline (~1,500 t) | 读取完整文件 (~12,000 t) | 8 倍 |
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/claude-mem