给 Claude Code 挂上代码地图:token 省了 39%,但先看你的瓶颈在哪

0 阅读1分钟

氛围图

💡 一句话总结:约克大学把 5 种代码表示(AST/调用图/依赖图/文档/混合)做成 MCP 工具,在固定 Claude Code 栈上与纯搜索基线跑了 4 个仓库级基准的受控对比。结论:代码地图是省钱工具不是提分工具——定位是瓶颈的任务 token 省 25–39%、召回还在涨;瓶颈在"写对补丁/测试"的任务基本白挂。做 agent 基建的人值得读完。

导语:你的 agent token 都烧在哪了?

先问一个可能戳到你的问题:你有没有盯着 Claude Code(或任何 coding agent)的用量面板,看着它为一个其实不复杂的 issue 反复 grep、read、再 grep、再 read,最后烧掉几十万 token 才摸到那个该改的文件?

这种"探索税"几乎是所有仓库级 agent 的宿命。主流 agent(Claude Code、SWE-agent、Agentless、OpenHands)都把仓库当纯文本:靠词法搜索和 shell 命令一层层扒。"谁定义了这个符号?谁调用它?哪些模块依赖它?"——这些结构信息明明就在仓库里,agent 却要用一串昂贵的试错把它们重新拼出来。

于是"给 agent 发地图"成了个自然的主意:AST(代码的结构骨架)、调用图(谁调用谁)、依赖图(谁 import 谁)、文档(代码想干什么),这些都是程序分析领域玩了几十年的老视图。这两年也确实冒出一批把仓库图谱做成 MCP 工具的项目。

但一个尴尬的问题始终没人认真回答过:这些地图到底值多少钱? 注意,不是"有没有用"——几乎所有带图谱的系统都能发一篇"涨点了"的论文。问题是:涨的点,是图谱带来的,还是同时换掉的 scaffold、检索策略、修复循环带来的?账没人算过。

约克大学的这篇新论文(arXiv:2611.07286)就是来算账的。他们干了一件这个领域早就该干但一直没人干的事:把表示本身当受控变量。

想自己动手试?

这篇论文到底想解决什么问题?

前面的痛点拆开看其实是三个叠加的困惑。

第一,agent 的浏览成本高得离谱。 论文里的基线数据很直白:在 Linux 内核 bug 定位任务上,没有地图的 Claude Code 平均每个任务要 8 次文件读取、6 次 grep、10 次 shell 调用——这些动作绝大多数只是在重建"代码长什么样"的上下文,而不是在解 bug。

第二,"表示有用"的因果链从来没干净过。 此前的工作要么把图谱嵌进模型(GraphCodeBERT 一系),要么做进检索器(RepoCoder 一系),要么做进完整 agent 系统(ARISE、RepoGraph、LocAgent)。系统一换,模型、提示词、工具集全在变,你根本说不清改进来自哪一层。做采购决策的人面对这些论文只有一个感受:都不知道该信谁。

第三,没人告诉你"哪种地图配哪种任务"。 AST、调用图、依赖图、文档——它们暴露的是完全不同的关系(包含、调用、import、意图)。故障定位、补丁修复、测试生成、安全修补这些任务对关系的需求也不一样。但现成系统每家只押一种设计,你就当买彩票。

所以这篇论文的研究问题可以压缩成一句话:在其它一切都不变的前提下,给 agent 挂上代码地图,对任务成功、token 消耗、耗时、工具行为各改变多少?哪种地图对哪种任务划算?

它的思路是什么?

实验设计说起来朴素得可爱,但这恰恰是它值钱的地方。

固定一切,只变表示。 Agent 用 Claude Code,模型用 Haiku 4.5(effort=low),内建工具钉死为 Read/Edit/Write/Bash/Grep/Glob 六件套,提示词、任务 ID 全部跨组一致。唯一的变量:是否挂载一个代码表示 MCP 服务器,挂哪个。

五种地图,各看一个关系。 每种表示实现成独立的 MCP 服务器,agent 查询时先全文搜索出种子节点,再沿各自的边扩展邻域、用图中心性排序,把最相关的源码原文按文件分组返回:

  • 🌳 AST:文件 → 顶层定义 → 嵌套定义的包含森林,回答"代码住哪、怎么分组"
  • 🔀 调用图:caller → callee 的有向图,回答"控制流怎么走"
  • 📦 依赖图:文件间 import 关系,回答"模块怎么耦合"
  • 📚 文档视图:docstring/注释的全文检索(没有图边),回答"这段代码想干嘛"
  • 🧩 混合视图:把调用+import+包含合并成一张大图,外加变更"爆炸半径"估算

研究总体设计:同一 agent 栈 × 6 种工作流 × 4 个仓库级基准 图说:左边是固定的 Claude Code 栈,中间是基线与 5 种地图条件,右边是 4 个基准任务——整个实验就这张图的矩阵,全维度只让"地图"这一个东西变。

四个基准,四种瓶颈。 这是设计的精髓:故障定位(LinuxFLBench,找到 bug 在哪个文件)、程序修复(SWE-bench Pro,真实 GitHub issue 改代码)、安全补丁(SecBench,修 CVE)、测试生成(SWT-bench,写出能复现 bug 的测试)。这四个任务的瓶颈位置天然不同——定位型任务的难点是"找到",后三个的难点还有"改对/写对"。如果地图真有用,它的用武之地应该在定位上——这个假设正是论文想检验的。

除了冷冰冰的数字,他们还把每组与基线分歧的任务轨迹逐条人工读完(赢了哪些、输了哪些、哪些更省哪些更贵),归类出失败与省钱的具体模式。这部分是全文最有"人味"的产出,后面细说。

效果到底怎么样?

一句话剧透:地图是省钱工具,提分要看任务。

故障定位:全员受益,账算得过来

这是地图的主场。五种视图的 recall@10(正确文件进前 10 候选的比例,越高越好)全部超过基线的 0.717——混合视图冲到 0.829,文档和调用图 0.770。同时每个视图省 25–39% token,混合视图最省。

钱省在哪了?工具调用记录说得明明白白:地图组的 read 降到每任务最多 1.1 次、grep/glob 基本归零,浏览被 9–13 次地图查询整个替换掉了。

故障定位:各表示相对基线的成功率与 token 双向变化 图说:右上象限(更准且更省)挤满了所有五种视图——这在其余三个任务里再没出现过。

程序修复:省钱,但不涨分

到了 SWE-bench Pro,剧情开始分裂。token 照样省 17–26%,墙钟时间也从 269 秒降到 200 秒上下——但 resolution rate(补丁跑通的比率)和基线 49.0% 几乎重合,最好的(AST/混合 50.6%)在噪声里,最差的(文档 44.3%)还略亏。

为什么会这样?论文的轨迹分析给了一个特别诚实的答案:修复任务里地图组最多的失败模式是"定位对了、补丁写错"(每种表示 16–23 例)。地图把 agent 顺利送到该改的文件,然后 agent 在"怎么改"这一步栽了——这锅地图背不动。

安全补丁:调用图的个人秀

SecBench 是唯一成功率明显上涨的任务:调用图 +5.4 个百分点(34.3% vs 28.9%)。原因很直白——安全任务的提示里常带崩溃调用栈,"沿栈帧找补丁点"天生就是调用图的活。

安全补丁:调用图一枝独秀,但所有视图都更慢 图说:调用图是本任务唯一明显右移(更准)的视图;注意所有视图在时间轴上都是退化的——基线 66 秒,地图组 136–290 秒。

这里藏着一个反直觉的发现,我觉得是全文最值得咀嚼的细节:混合视图明明也包含调用边,但在"调用图解出、混合没解出"的 18 个案例里,14 个混合视图编辑了同一个文件却没产出有效补丁。作者的解释是信息稀释——额外的边把关键的执行流信号淹没了。多不等于好,信号要响。

测试生成:全军覆没(的账本)

到了 SWT-bench,地图彻底哑火:混合/文档最高也就 +3 个点,调用图反而 -6.8 个点,而且所有视图 token 和时间双双变贵。原因前面已经剧透了:测试生成的决定性一步是"写出那个能区分 bug 的断言",你给 agent 一张再漂亮的仓库地图,也帮不了它想出那个 assert。

轨迹分析里有个特别生动的配对案例。WiFi 驱动挂起 bug:真凶在 atmel.c,但它通过一条非直接调用的路径加载固件——调用图沿着固件/恢复链一路漂进 PCMCIA 胶水代码,压根没碰到真凶;而基线的傻瓜关键词搜索直接把正确文件排在第一位。地图的"聪明"在错误的假设下反而成了枷锁。反过来,NFS 挂载冻死内核的 bug,病根藏在两层调用之外的 RPC 客户端代码里,只有调用边能跨过 NFS→RPC 的子系统边界把它捞出来——基线折腾 42 个动作也没找到。同一张地图,救一种命,也误一种事。

测试生成:成功率变化小,token 与时间全面变贵 图说:四个任务里唯一"又贵又没赚"的象限分布——瓶颈不在找代码时,地图就是纯开销。

把四个任务并排放,规律清晰得像教科书:地图的收益严格跟随"定位是不是瓶颈"。是,则省钱又提分;不是,则最多省钱,甚至倒贴。

省钱的机制:读替换

那 token 到底省在哪?论文的轨迹编码给了一个可以写进工具设计文档的答案:读替换(read displacement)。地图查询返回的是源码原文,agent 把它"当作已读",于是整个 read 阶段被砍掉。故障定位上,读替换解释了每个视图七到九成的省钱案例。反过来的超支案例也很有画面感:报告里直接点名了文件的简单任务,基线几步就完事,文档视图却因为"查询太便宜"而忍不住反复探索一个已经找到的文件,最后烧掉基线 27.7 倍的 token。便宜的工具激发过度的勤奋,人类有的毛病 agent 也有。

为什么你要关心?

如果你在做 agent 基建、MCP 工具,或者只是给团队选型 coding agent,这篇论文有三条可以直接抄进方案的结论。

第一,先诊断瓶颈,再决定挂不挂地图。 你的 agent 任务里"找代码"占大头的(bug 定位、代码检索、影响面分析),挂地图稳赚:token 立省四分之一到近四成。瓶颈在生成质量的(写补丁、写测试),先把地图预算砍了,钱花在模型档位或测试反馈循环上更值。

第二,如果做地图工具,让它内联返回代码体。 读替换机制的前提是查询结果本身就是可用的源码,agent 才不会再去 read 一遍。只返回元数据的地图("相关文件列表")省不了读的成本——这篇论文的数据等于给"返回原文"的设计盖了章。

第三,警惕融合视图的信号稀释。 "把所有图拼一张大图"听起来是最优解,混合视图也确实在故障定位上是零失误的安全牌,但 SecBench 的 14 个同文件失败案例警告我们:合并的上下文可能淹没任务真正需要的那个关系。更稳妥的设计可能是"先路由再单视图"——让 agent 或一个轻量分类器先判断该用哪张地图。

再往远看一步:这篇论文其实给整个 MCP 工具生态立了一个方法论标杆——单变量受控实验。今年 MCP 服务器井喷,家家都有"用了效率翻倍"的体感,但像这样固定栈、固定任务、把账算到工具调用粒度的,这是第一份。工具作者们与其再刷一个 leaderboard,不如学这个实验设计。

理性看待

几盆冷水必须端上来。第一,处理效应是复合的:地图组带了"多用地图"的使用引导,修复任务上还有一个强制先查地图的钩子,所以省下的 token 不能全记在数据结构头上——纯挂载不引导,效果可能打折。第二,每个任务只跑一次(k=1),程序修复和测试生成上那几个百分点的差异,作者自己也承认可能是单次采样的方差。第三,也是最要紧的:全实验只用 Haiku 4.5 一个低推理档位的模型——弱模型恰恰是定位最痛的设定;换强模型或更高档位,agent 自主探索能力强了,地图的相对收益可能缩水。token 账本也没算地图构建与索引维护的一次性成本。所以这份账本读作"方向性结论"很扎实,读作"精确汇率"则要留一手。