AI Research

CodeGraph 实战 v2:带工具调用硬证据的 A/B 基准

2026-06-15 #research#ai-models#claude-code#mcp#code-intelligence#benchmark#codebuddy

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?

发现

  1. 硬证据: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)。

  2. 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%。
  3. 总和 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
  4. 反例同样有硬证据: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,不要走图谱。

  5. 修复 baseline 污染才能拿到公平数据 — v1 baseline 偏低效(11–34 turns 反复 grep)的部分原因是它没被告知”codegraph 不可用、别绕弯”。v2 在 baseline 端 prompt 头部加 “【环境提示】codegraph MCP 工具在本会话中不可用,请直接使用 Read / Grep / Glob”,after 端加 “【环境提示】本仓库已索引 CodeGraph,请优先使用 codegraph_*“——两侧对称提示,差异才完全归因于”工具是否真存在 + 是否真被调”,而不是 prompt 注入差异。

  6. 跨 Agent 配置已落盘 — 为了让 Claude Code、Claude 内部代理、CodeBuddy CLI 三套都能”主动用 CodeGraph”,需要分别在各自的配置体系里落规则:

    文件 作用
    ~/.claude-internal/.claude.json 顶层 mcpServers.codegraph Claude 内部代理 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 新建 项目级”工作目录就是仓库根” + 工具决策树
  7. 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
2
3
4
5
6
prompt 里有路径吗?
├── 有 (A 类) → Glob / Read,别走图谱
└── 没有
├── 有具体符号名 (C 类) → codegraph_node
└── 只有功能描述 (B 类) → codegraph_explore
└── 关心调用链/影响范围 → codegraph_callers / codegraph_impact

把这条口诀写进项目 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
2
3
4
5
6
prompt 里有路径吗?
├── 有 (A 类) → Glob / Read,别走图谱
└── 没有
├── 有具体符号名 (C 类) → codegraph_node
└── 只有功能描述 (B 类) → codegraph_explore
└── 关心调用链/影响范围 → codegraph_callers / codegraph_impact

把这条口诀写进项目 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 官方站点
评论
分享