CodeGraph 实战 v2:带工具调用硬证据的 A/B 基准
摘要
v1 实战篇用 --output-format json 跑了 baseline vs after,得到 -50.8% input / -46.4% 成本,但没有”模型每个 turn 实际调了哪些工具”的证据。v2 改用 stream-json 流式输出落盘每个 tool_use 块,并修正 baseline 端”无引导污染”问题,给出了铁证:baseline 5 题 57 次工具调用里 codegraph_* 出现 0 次;after 5 题 30 次工具调用里 codegraph_* 出现 14 次(10× explore + 5× node)。token 节省幅度从 v1 的 -50.8% 修正到更真实的 -25.8%,turns 仍然 -43.5%、时延 -40.3%、成本 -23.1%;Q1/Q4 这种跨多文件的问题在 after 端只用 2 次 codegraph_explore 就完成 baseline 11–13 turns 的工作。基于工具用量证据把日常代码问题重新分成 3 类——位置已明型(A)、跨包依赖型(B)、已知符号型(C)——并给出了对应的工具决策口诀。基于工具用量证据把日常代码问题重新分成 3 类——位置已明型(A)、跨包依赖型(B)、已知符号型(C)——并给出了对应的工具决策口诀。
研究问题
- v1 的”AI 真的用上了 CodeGraph 吗”如何用证据闭合,而不是凭推断?
- 把对 baseline 的提示对称地修正后,节省幅度还有多大?
- 哪些题型 CodeGraph 实质参与了、哪些 CodeGraph 反而没派上用场?
- 跨 Agent(Claude Code / Claude 内部代理 / CodeBuddy CLI)如何同时让模型主动调用 CodeGraph?
发现
硬证据:codegraph_* 调用次数 0 vs 14 — baseline(
--strict-mcp-config --mcp-config '{"mcpServers":{}}')5 题共 57 次工具调用,全部是 Read/Bash/Glob/Grep,codegraph_* = 0。after 5 题共 30 次工具调用,codegraph_* = 14(10×codegraph_explore+ 5×codegraph_node),占 47%。每个 turn 的工具名直接来自 stream-json 的tool_use.name字段(如mcp__codegraph__codegraph_explore)。Q1 / Q4 是最干脆的硬证据 — 这两题只用 2 次
codegraph_explore就完成了 baseline 11–13 turns 拼图:- Q1 架构总览:baseline 11 turns(6× Read + 4× Bash),after 3 turns(2× codegraph_explore),input -66.8%、成本 -55.2%。
- Q4 鉴权流程:baseline 13 turns(8× Bash + 4× Read),after 3 turns(2× codegraph_explore),input -72.4%、成本 -64.4%。
总和 5 题:input -25.8% / 成本 -23.1% / turns -43.5% — 量级与 CodeGraph 官方 7 仓中位数(-47% Token / -16% 成本)一致。比 v1 的 -50.8% / -46.4% 低,是因为 v2 用对称提示修复了 baseline 端的”绕弯效应”——这是更真实的长期收益估计。
指标 Baseline After Δ Input tokens 合计 2,820,726 2,093,667 -25.8% Output tokens 合计 10,336 6,127 -40.7% Turns 合计 62 35 -43.5% 时延合计 (s) 406.9 243.0 -40.3% 成本合计 ($) 5.4949 4.2262 -23.1% 工具调用总次数 57 30 -47.4% codegraph_* 调用次数 0 14 — 反例同样有硬证据:Q2 / Q3 都属于”位置已明型”问题 — 一开始我把 Q2 归为”列目录型”、Q3 归为”读 N 个明确文件型”,看起来像两类——其实是事后归因偏差:同一题型只是模型这一次随机选了 Glob 多 / Read 多两条路径。真正的共同特征只有一个:用户在 prompt 里把答案的文件位置直接说出来了(”
pages/“、”middleware/“、”shared-store/“)。模型一看路径名就知道去哪找,CodeGraph 的”按符号定位”在这类问题上反而是绕路。- Q2 入口与路由 +227% input:after 13 turns(5×Glob + 4×Read + 2×codegraph_explore + 1×Bash),模型在 codegraph 给出 Nuxt 路由信号后又加了一轮 Read 验证。
- Q3 状态管理 +80% input:after 用 5×
codegraph_node一个个拿符号,比 baseline 直接 Read 三个 store 文件费力。
结论:当 prompt 里出现具体目录或文件路径时,AI 应该直接 Glob/Read,不要走图谱。
修复 baseline 污染才能拿到公平数据 — v1 baseline 偏低效(11–34 turns 反复 grep)的部分原因是它没被告知”codegraph 不可用、别绕弯”。v2 在 baseline 端 prompt 头部加 “【环境提示】codegraph MCP 工具在本会话中不可用,请直接使用 Read / Grep / Glob”,after 端加 “【环境提示】本仓库已索引 CodeGraph,请优先使用 codegraph_*“——两侧对称提示,差异才完全归因于”工具是否真存在 + 是否真被调”,而不是 prompt 注入差异。
跨 Agent 配置已落盘 — 为了让 Claude Code、Claude 内部代理、CodeBuddy CLI 三套都能”主动用 CodeGraph”,需要分别在各自的配置体系里落规则:
文件 作用 ~/.claude-internal/.claude.json顶层 mcpServers.codegraphClaude 内部代理 MCP 注册 ~/.claude-internal/CLAUDE.md新增 CODEGRAPH_START/END 段决策树 + 串行调用规则 ~/.codebuddy/mcp.json加 codegraph 节CodeBuddy IDE 插件 ~/.codebuddy/CLAUDE.md新增 CODEGRAPH 段同上 ~/.codebuddy/rules/codegraph-usage.mdc新建全局 always-apply 规则 <repo>/.codebuddy-cli/settings.json(codebuddy mcp add写入)CodeBuddy CLI 真正读的位置 <repo>/.codebuddy/rules/codegraph-usage.mdc新建项目级规则 <repo>/CLAUDE.md新建项目级”工作目录就是仓库根” + 工具决策树 CodeBuddy CLI 与 IDE 配置是两条路 —
codebuddy mcp add写到的是**当前 cwd 的.codebuddy-cli/settings.json**,不是~/.codebuddy/。~/.codebuddy/mcp.json是 IDE 插件读的,CLI 不读。需要在每个项目根重新跑codebuddy mcp add codegraph codegraph serve --mcp才能让 CLI 拿到 codegraph。
单题对比(含工具调用硬证据)
| ID | 题目 | Input(base→after) | Δ% | Turns | 时延 s | $ | Δ% | baseline 实际工具 | after 实际工具 |
|---|---|---|---|---|---|---|---|---|---|
| Q1 | 架构总览 | 449,253 → 149,337 | -66.8% | 11 → 3 | 74.9 → 31.0 | $0.8718 → $0.3901 | -55.2% | 6×Read, 4×Bash | 2×codegraph_explore |
| Q2 | 入口与路由 | 238,632 → 780,389 | +227.0% | 6 → 13 | 56.3 → 80.8 | $0.5082 → $1.4516 | +185.6% | 3×Glob, 2×Bash | 5×Glob, 4×Read, 2×codegraph_explore, 1×Bash |
| Q3 | 状态管理 | 208,556 → 374,675 | +79.7% | 6 → 7 | 37.9 → 39.8 | $0.4352 → $0.7496 | +72.2% | 4×Read, 1×Glob | 5×codegraph_node, 1×codegraph_explore |
| Q4 | 鉴权流程 | 551,797 → 152,477 | -72.4% | 13 → 3 | 80.4 → 26.3 | $1.0870 → $0.3873 | -64.4% | 8×Bash, 4×Read | 2×codegraph_explore |
| Q5 | 商业化逻辑 | 1,372,488 → 636,789 | -53.6% | 26 → 9 | 157.5 → 65.2 | $2.5926 → $1.2475 | -51.9% | 24×Bash, 1×Read | 4×Read, 2×codegraph_explore, 1×Glob, 1×Grep |
问题分类:什么时候该用 CodeGraph
整理本次 5 道题的 prompt 文本与工具用量后,我把”日常代码问题”重新分成 3 类——比 v2 初稿的”列目录 / 读 N 个文件”二分类更准确,也更好记。
分类表
| 类型 | 共同特征 | 推荐工具 | 来自 v2 的证据 |
|---|---|---|---|
| A. 位置已明型 | prompt 里出现具体目录或文件路径(pages/、config.ts 等) |
Glob / Read(别用 CodeGraph) | Q2、Q3:after 比 baseline 多花 +80% ~ +227% token |
| B. 跨包依赖型 | 只有功能/概念,不知道在哪些文件 | codegraph_explore / codegraph_callers / codegraph_impact |
Q1、Q4:after 节省 -55% ~ -72% input |
| C. 已知符号型 | 知道符号名(函数/类/组件),要源码 + 上下游 | codegraph_node |
Q5 部分:用 codegraph_explore 定位 + Read 看具体行 |
日常开发常见问题归类
A 类(位置已明 → 直接 Glob / Read)
- “项目里有哪些页面 / 路由?”
- “
components/下都有哪些组件?” - “
api/目录下有哪些接口定义?” - “
tests/下有哪些测试文件?” - “
migrations/下有几个数据库迁移?” - “
scripts/文件夹都有什么脚本?” - “看一下
eslint.config.js我们启了哪些规则” - “
tsconfig.json里 paths 是怎么配的?” - “
vite.config.ts装了哪些 plugin?” - “
Dockerfile干了啥?” - “
shared-utils/index.ts都 export 了什么?” - “
store/index.ts注册了哪些 module?” - “项目装了哪些 npm 依赖?”(这种连读都不用,看
package.json即可)
B 类(跨包依赖 → codegraph_explore / callers / impact)
- “鉴权流程怎么走的?”
- “整个项目的架构是什么?给我画个调用图”
- “登录后的请求拦截器在哪里挂的?”
- “用户点击付款,最终调到哪个后端接口?”
- “
UserCard这个组件被哪些页面引用了?” - “如果删掉
oldHelper(),会牵连哪些测试?” - “改
usePurchaseFlow会影响哪些 admin 页面?” - “这个错误码是谁抛出来的?谁捕获的?”
- “全站的国际化加载流程是怎么走的?”
- “事件总线
emit('foo')在哪里被监听?”
C 类(已知符号 → codegraph_node)
- “看下
useAiStore这个 store 的源码 + 谁在用” - “
getOperation()这个工具函数是怎么实现的?被哪些地方调?” - “
<EntryContext>组件的源码贴出来” - “
PurchaseNavigationOptions这个类型在哪里定义的?被哪些地方引用?”
决策口诀
1 | prompt 里有路径吗? |
把这条口诀写进项目 CLAUDE.md 或 .codebuddy/rules/codegraph-usage.mdc 的”决策树”段,能进一步把 A 类的反向亏损消掉——让模型自己学会”该 Glob 时不要用图谱”。
问题分类:什么时候该用 CodeGraph
整理本次 5 道题的 prompt 文本与工具用量后,我把”日常代码问题”重新分成 3 类——比 v2 初稿的”列目录 / 读 N 个文件”二分类更准确,也更好记。
分类表
| 类型 | 共同特征 | 推荐工具 | 来自 v2 的证据 |
|---|---|---|---|
| A. 位置已明型 | prompt 里出现具体目录或文件路径(pages/、config.ts 等) |
Glob / Read(别用 CodeGraph) | Q2、Q3:after 比 baseline 多花 +80% ~ +227% token |
| B. 跨包依赖型 | 只有功能/概念,不知道在哪些文件 | codegraph_explore / codegraph_callers / codegraph_impact |
Q1、Q4:after 节省 -55% ~ -72% input |
| C. 已知符号型 | 知道符号名(函数/类/组件),要源码 + 上下游 | codegraph_node |
Q5 部分:用 codegraph_explore 定位 + Read 看具体行 |
日常开发常见问题归类
A 类(位置已明 → 直接 Glob / Read)
- “项目里有哪些页面 / 路由?”
- “
components/下都有哪些组件?” - “
api/目录下有哪些接口定义?” - “
tests/下有哪些测试文件?” - “
migrations/下有几个数据库迁移?” - “
scripts/文件夹都有什么脚本?” - “看一下
eslint.config.js我们启了哪些规则” - “
tsconfig.json里 paths 是怎么配的?” - “
vite.config.ts装了哪些 plugin?” - “
Dockerfile干了啥?” - “
shared-utils/index.ts都 export 了什么?” - “
store/index.ts注册了哪些 module?” - “项目装了哪些 npm 依赖?”(这种连读都不用,看
package.json即可)
B 类(跨包依赖 → codegraph_explore / callers / impact)
- “鉴权流程怎么走的?”
- “整个项目的架构是什么?给我画个调用图”
- “登录后的请求拦截器在哪里挂的?”
- “用户点击付款,最终调到哪个后端接口?”
- “
UserCard这个组件被哪些页面引用了?” - “如果删掉
oldHelper(),会牵连哪些测试?” - “改
usePurchaseFlow会影响哪些 admin 页面?” - “这个错误码是谁抛出来的?谁捕获的?”
- “全站的国际化加载流程是怎么走的?”
- “事件总线
emit('foo')在哪里被监听?”
C 类(已知符号 → codegraph_node)
- “看下
useAiStore这个 store 的源码 + 谁在用” - “
getOperation()这个工具函数是怎么实现的?被哪些地方调?” - “
<EntryContext>组件的源码贴出来” - “
PurchaseNavigationOptions这个类型在哪里定义的?被哪些地方引用?”
决策口诀
1 | prompt 里有路径吗? |
把这条口诀写进项目 CLAUDE.md 或 .codebuddy/rules/codegraph-usage.mdc 的”决策树”段,能进一步把 A 类的反向亏损消掉——让模型自己学会”该 Glob 时不要用图谱”。
对比与判断
- v1 vs v2,应该看哪份?
- 想问”用户什么都不调整、装 vs 不装” → 看 v1(节省 50%+)
- 想问”两边都做了合理提示、CodeGraph 工具优势有多大” → 看 v2(节省 25–40%)
- 工程上以 v2 为准,因为它更接近真实”模型有引导、能正常路由”的长期场景。
- CodeGraph 真正强的场景:跨多文件的架构问答 / 调用链追溯(Q1/Q4 -55% ~ -64% 成本,3 turns 完成 baseline 11–13 turns 的工作)。这一类问题接 CodeGraph 几乎是”白送”。
- CodeGraph 不如裸 Read 的场景(v2 仍存在):位置已明型问题——只要 prompt 里出现具体目录或文件路径(如 Q2 的
pages/、Q3 的shared-store/),模型就该直接 Glob/Read。CodeGraph 的”按符号定位”反而绕路。详见上文《问题分类》。建议在项目级 CLAUDE.md 决策树里加一条:**”prompt 里能看到路径 → 直接 Glob/Read,不要用图谱”**。 - 流式日志(stream-json)是测 MCP 工具用没用的标准方法:result 模式(json)只给汇总,没法溯源;stream-json 模式每个 turn 落盘
tool_use.name,可以一行grep验证。
不确定性
- v2 在每题前注入”环境提示”对模型有非零影响:可能让 baseline 比真实”裸 Claude Code”略快、让 after 比真实”模型自由选择”略偏 codegraph。两者方向相反,差异应该有限。要彻底干净,需要写一个 fork 版 prompt 集,提示词里完全不提工具策略。
- 5 题样本量小、单次跑(无 N=3 中位);A 类(位置已明)反向亏损的具体百分比可能在更大样本上回归,但方向是稳定的——只要 prompt 里给出路径,CodeGraph 就拿不到位置定位的红利。
- v2 初稿曾把 Q2 / Q3 拆成”列目录型”和”读 N 个文件型”,是事后归因偏差——同一题型不同模型选路造成的工具用量差异,被错误地当成了两类问题。修订后只保留”位置已明型”一类。
- 模型自动调度 sonnet/haiku 比例会随提示词变化;
total_cost_usd是 Anthropic 计价口径下的合成值,和你看到的内部账单可能差几个百分点。 - 仅测探索类问题。生成/修改类(”加个 store” / “重构 X 函数”)尚未测,CodeGraph 的收益形态可能不同。
- CodeGraph 索引 95 MB SQLite 没入版本库,团队同步靠每人自己
codegraph init。索引版本不一致时,工具返回会差异化,目前无机制检测。
后续行动
- 加测代码生成 / 修改类问题,用同一套 stream-json 框架跑一遍。
- 把 v2 的”环境提示”也去掉再跑一组,量化”自然 Claude Code”在 v2 框架下的真实收益。
- 在 1–2 个不同形态的仓库(纯 TS 后端 / Python 单包)上重跑 v2 prompt 集,看跨仓收益曲线是否一致。
- 把
aggregate.py的硬证据生成逻辑(解析 stream-json 出工具次数)泛化成通用 A/B 评测库。
来源
- 测试产物归档:
research/bench/codegraph-shield/(含REPORT_v2.md/prompts.txt/run_bench.sh/aggregate.py/baseline/Q*.stream.jsonl/after/Q*.stream.jsonl/archive/v1-XXXX/) - v1 实战篇:《CodeGraph 实战:在 shield monorepo 上做 A/B 基准测试》
- 调研篇:《CodeGraph 深度研究:本地代码知识图谱与 AI Agent 加速器》
- CodeGraph GitHub
- CodeGraph 官方站点