首页
/ CodeGraph /agent-eval:用 A/B 评测框架在真实仓库上量化代码知识图谱的检索价值

CodeGraph /agent-eval:用 A/B 评测框架在真实仓库上量化代码知识图谱的检索价值

2026-09-03 15:22:33作者:殷蕙予

本文围绕 CodeGraph 仓库中的 agent-eval 技能(/agent-eval)展开:它是一套"带 CodeGraph 的 Agent vs 只用 grep/read 的 Agent"对照实验流程,用于在选定的真实开源仓库上审计某个 codegraph 版本(本地开发构建或已发布的 npm 版本)的检索质量。读完本文,你将掌握完整的六步审计工作流、audit.sh 的底层四阶段管线、A/B 双臂的污染控制机制,以及如何解读每次运行产出的三项检索反馈指标与对照表。

这个 Skill 解决什么问题

CodeGraph 把代码库预索引成符号与调用关系图谱,供 Claude Code、Codex、Cursor 等 Agent 通过 MCP 工具查询。"它对 Agent 到底有没有帮助、帮助多少"不能靠感觉回答,必须做受控实验:同一个真实仓库、同一个问题、同一个模型,唯一变量是 Agent 能否使用 CodeGraph。

.claude/skills/agent-eval/SKILL.md 就是这个实验的操作手册(Skill 定义)。它的定位是:

Measures how much CodeGraph helps an agent versus plain grep/read, for a chosen codegraph version on a chosen real-world repo.

它驱动的全部执行逻辑在 scripts/agent-eval/ 目录的脚本簇中:audit.sh 是入口,run-all.sh 是 A/B 引擎,parse-run.mjs / parse-session.mjs 负责从运行日志里还原工具调用序列与指标。Skill 本身只负责"问对人、传对参数"。

前置条件

SKILL.md 明确要求的环境(macOS / Linux):

  • tmux 3+(交互式 harness 需要);
  • 已登录的 claude CLI(headless 与交互两种模式都用它);
  • nodegit
  • 必须在 codegraph 仓库根目录下执行(audit.sh 依赖仓库内的 scripts/local-install.sh 来构建/恢复本地开发链接)。

六步审计工作流

SKILL.md 给出的标准检查清单是:

- [ ] 1. Pick version (local or npm)
- [ ] 2. Pick language
- [ ] 3. Pick repo by size
- [ ] 4. Pick harness (headless / tmux / both)
- [ ] 5. Run audit.sh in the background
- [ ] 6. Report results

下面逐步说明,并补充每一步在源码中的实际行为。

Step 1 — 选择被测版本(VERSION token)

询问用户测试哪个 codegraph 版本,并映射为三个取值之一:

用户选择 VERSION token 实际行为
Local dev build local 在 codegraph 仓库内执行 local-install.sh,构建当前代码并 npm link 成全局 codegraph
Latest published latest npm install -g @colbymchenry/codegraph@latest
手输具体版本号(如 0.7.10 该字符串 npm install -g @colbymchenry/codegraph@0.7.10

这个映射在 audit.sh 中落地:local 走本地构建脚本,其余一律通过 npm 全局安装对应版本,随后用 codegraph --version 打印实际生效版本用于日志留痕。

Step 2 — 选择语言

语言清单不是写死的,而是从语料库 .claude/skills/agent-eval/corpus.json 动态读取。该文件按语言组织条目,目前覆盖 TypeScript、JavaScript、Go、Python、Rust、Java、Kotlin、Swift、C#、Ruby、PHP、C、C++、Dart、Svelte、Lua、Luau、Objective-C、Mixed iOS(Swift+ObjC)、React Native(legacy bridge / Fabric / TurboModule)、Expo Modules、R、COBOL、VB.NET、Erlang、Solidity、CUDA、Terraform、ArkTS、Nix 等约 30 个语言/技术栈分类,每类通常按 Small / Medium / Large 三档各备一个仓库(如 TypeScript 的 excalidraw 约 600 文件、vscode 约 10000 文件)。

Step 3 — 按规模选择仓库

从所选语言的条目中挑仓库,SKILL.md 要求选项标签带上规模与文件数,例如 excalidraw — Medium (~600 files)。每条 corpus 条目包含五个字段:

  • name:corpus 目录名,也是 audit.sh 的第二个参数;
  • repo:git 仓库 URL(缺失时由 harness 浅克隆);
  • size / files:规模档位与文件数估计(Small < ~150、Medium ~150–1500、Large > ~1500,见 corpus.json 头部注释);
  • question:一个能考察"跨文件理解"的代表性架构问题,例如 "How does Excalidraw render and update canvas elements?"。这个字符串会作为 Agent 收到的提示词原样传入。

Step 4 — 选择 harness(MODE token)

用户选择 MODE token 运行方式 特点
Headless headless claude -p + stream-json 精确的 token/cost 统计与干净的工具调用序列;每臂 2 runs,快、无 TTY
Interactive (tmux) tmux tmux 内驱动真实 Claude TUI 复现用户实际可见的 Explore 子代理行为,指标从 session 日志解析;每臂 2 runs,较慢
Both all 上面两种都跑 共 4 runs

两种模式各自的实现值得看一眼:

  • headless 臂run-all.shheadless() 函数驱动:在目标仓库目录下执行 claude -p "<question>",带 --output-format stream-json --verbose--permission-mode bypassPermissions--model sonnet --effort high--max-budget-usd 4,以及关键的 --strict-mcp-config --mcp-config <cfg>。模型策略在 agent-eval-feedback-metrics.md 中被标注为"不可谈判":所有臂统一 sonnet + high effort——在最低配模型上成立的能力增强,才能向更强模型泛化。
  • 交互式臂itrun.sh 实现:tmux new-session 开一个 230×60 的宽面板(避免 TUI 硬折行),自动应答"是否信任此目录"对话框,用"输入并校验首 24 字符落屏"的循环绕过欢迎页与 MCP 初始化的按键竞争,最后以"面板内容稳定 16 次轮询(约 8 秒)且出现提示符"判定 Agent 完成——注释里解释了为什么不能依赖 spinner 字符串:扩展思考模型在流式输出最终答案阶段不显示忙碌指示,基于 spinner 的短超时会在答案中途杀掉运行。

run-all.sh 还支持多轮问题:用 || 分隔多个问题,第 2 轮起通过 --resume <session-id> 续接同一会话(run-all.sh)。这是有意设计——工具响应会一直占住上下文窗口,单轮 A/B 结构性地看不到这份"后续轮次要买单"的成本。

Step 5 — 后台运行 audit.sh

确认四个选择后,在 codegraph 仓库根目录后台启动:

scripts/agent-eval/audit.sh <VERSION> <repo-name> <repo-url> "<question>" <MODE>

参数即前四步的产物,例如 scripts/agent-eval/audit.sh local excalidraw <url> "How does Excalidraw render and update canvas elements?" headless。从源码看,audit.sh 内部是四阶段管线:

  1. 设置被测版本locallocal-install.sh,其余 npm install -g @colbymchenry/codegraph@<VERSION>,并打印 PATH 上实际解析到的 codegraph 及其版本;
  2. 确保语料仓库就位:corpus 目录默认 /tmp/codegraph-corpus(可用环境变量 CORPUS 覆盖),目录缺失则 git clone --depth 1,已存在则直接复用;
  3. 清库重建索引rm -rf "$REPO/.codegraph" 后在目标仓库执行 codegraph init -i。SKILL.md 的 Notes 解释了这一步不可省略的原因——索引必须由提供查询的同一个二进制构建,因为不同版本的抽取行为不同;
  4. 跑 A/B:委托给 run-all.sh <repo> "<question>" <MODE>

结束后 audit.sh 会再次执行 local-install.sh 把全局 codegraph 恢复为开发构建(audit.sh);恢复失败会打印 WARN 提示手动执行。整个流程需要数分钟,所以 SKILL.md 明确要求后台运行。

Step 6 — 读取日志并汇报

任务结束后,按臂(arm)读取日志汇报:

  • headless 臂parse-run.mjs):总工具调用数、Read 文件次数、Grep/Bash 次数、codegraph 工具调用次数、耗时、总花费
  • 交互式臂parse-session.mjs):VERDICT: codegraph_explore used Nx | Read N | Grep/Bash NTOKENS: 行;
  • 两条路径都会追加输出三项检索反馈指标——residual context occupancy(残留上下文占用)、explore sufficiency(explore 充分性)、allocation efficiency(分配效率)——headless A/B 收尾还会打印并排的 ARM COMPARISON 对照表(由 compare-arms.mjs 生成)。

SKILL.md 对汇报方式有明确纪律:先看对照表的污染行CLI calls that RETURNED output > 0 意味着该臂通过 Bash 绕过了 MCP 直连了 codegraph,这组数据整体作废。其余指标的解读入口是 docs/benchmarks/agent-eval-feedback-metrics.md,其中强调"以 cost + 工具/Read 次数为先导信号;原始 token in/out 被子代理委派与 prompt caching 混淆,不可单独引用"。最后要说明两点结论:codegraph 是否降低了工作量,以及两臂是否都给出了正确答案。

A/B 框架的核心:把"唯一变量"做到物理级

run-all.sh 的头部注释一句话概括了设计:codegraph 是唯一的变量——with 臂挂只含 codegraph 的 MCP 配置(指向本次安装的 CG_BIN),without 臂挂空 MCP 配置;两臂都保留内置 Read/Grep/Bash。围绕这个不变式,源码里有三道防线,值得逐一了解。

1. 中性化环境 prompt-hook。 ~/.claude 下可能存在的 CodeGraph prompt-hook 会向每个提示词注入代码上下文,这会同时污染 without 臂(白送结构信息)和 with 臂(重复计数)。run-all.sh 在两臂统一导出 CODEGRAPH_NO_PROMPT_HOOK=1 关闭它。

2. 两层 CLI 封锁。 without 臂的仓库里躺着 .codegraph/ 索引,codegraph 二进制也在 PATH 上——Agent 完全可以绕开 MCP 直接调 CLI,把"无 codegraph 臂"变成"CLI 版 codegraph 臂"。实测事故写在 no-cli-shim.sh 注释里:某次 7 仓库批量跑中 15 个 without 臂里有 14 个都这么干了;后来 Agent 被 PATH 拦截后又执行了 find / -iname "*codegraph*" 用绝对路径调用。于是封锁做成两层:

  • PATH 层:把包含 codegraph 的目录就地替换为一个镜像目录——符号链接指向原目录里除 codegraph 外的所有条目,保持 PATH 顺序与优先级不变(不能整个目录删掉,因为 claude 等工具与它同目录);
  • PreToolUse hook 层:生成一个 hook-settings.json,对 Bash 工具做正则审查(只匹配命令位置,grep codegraph src/ls .codegraphwhich codegraph 这类"查看"行为放行),命中即输出 permissionDecision: deny。脚本最后还有自检探针:必须能拦截绝对路径调用、同时不误伤纯提及,否则拒绝开跑。

3. 污染计数器(检测半边)。 预防措施会静默失效(比如二进制换位置后 PATH 层失配),所以 parse-run.mjs 用独立的正则 CG_CLI_RE 复核每条 Bash 命令,区分"被拦截的尝试"(无输出进入窗口,良性)与"实际返回了输出的调用"(污染,该臂数据作废),并在 ARM COMPARISON 表中作为 contamination 行展示。

此外,MCP 配置以文件形式生成到输出目录(mcp-codegraph.json / mcp-empty.json)而不是内联 JSON,避免穿过 tmux 的引号转义问题;输出目录默认 /tmp/agent-evalAGENT_EVAL_OUT 可覆盖),并可用 CG_ARMS=with|without 只重跑单臂而不重做另一臂。

三项反馈指标:表回答"动没动",块回答"为什么"

parse-run.mjs 每次运行都输出三个指标块,compare-arms.mjs 再把两臂并排。三者各答一个问题,且一次检索改动可能只移动其中一个:

指标 回答的问题
Residual context occupancy(CG-7) 运行结束时,该臂的检索结果还占着窗口多少 token——即后续每一轮必须在多小的剩余空间里工作
Explore sufficiency(CG-8) 某次 explore 的响应"够不够":看 Agent 随后做了什么(再次 explore / Read 已返回文件 / Read 未返回文件 / Grep / 直接作答)
Allocation efficiency(CG-9) 响应花掉的字节里,有多大比例流向最终答案真正引用的文件

实现上有几个从源码可以直接确认的细节:

  • 占用是测出来的,不是 bytes/4 估的。每次 assistant 请求的 usage(input + cache_read + cache_creation)之和就是该请求完整 prompt 的精确 token 数,相邻请求的差值按追加内容的字符比例分摊到各工具结果上;再用"≥80% 由工具结果构成的 gap"集合标定 chars/token 比率,实测 explore 输出约 2.3 chars/token,bytes/4 会低估约 40%。
  • 微压缩按 FIFO 驱逐。窗口中途缩水时,最旧的 tool_result 先被丢弃,解析器按此模拟驱逐;compact_boundary 事件则整体清空。
  • sufficiency 桶与修复方向一一对应(见 parse-run.mjs):explore again → 响应没答上(分配或召回问题,需看后续 query 判别);Read a file we returned → 分配 bug(文件对、字节错);Read a file we did not return / Grep/Glob → 召回 bug(文件根本没浮出);moved on / answered → 充分(但不等于正确)。分类只在同一"线程"内匹配(子代理工具调用带 parent_tool_use_id 被交错注入同一 stream),委派类动作按子代理的首个实际动作判分。
  • allocation efficiency 是相对指标。归因靠答案中的引用(路径引用 + 代码 span 内的符号引用,出现于 ≥3 个返回文件的符号被丢弃以防偏乐观),因此只适用于同一问题下两个构建的横向比较,不能引用为绝对浪费率。
  • 解析器自带 --selftest(合成转录 + 已知答案回归),文档记载当前为 68/68 全过;agent-eval-feedback-metrics.md 还说明了为什么它故意不拆成独立模块——新的 scripts/agent-eval/*.mjs 会落入自查询评测 fixture 自己的语料并污染数字。

一份真实的 ARM COMPARISON 示例(express 仓库,new vs baseline,各 3 runs)在反馈指标文档中给出了完整形态:behavior 区(duration、Read、codegraph calls)、CG-7 区(codegraph residual、file-access residual、retrieval residual、share of final context)、CG-8 桶分布、CG-9 的 pooled / per-run efficiency,以及收尾的 contamination 两行;所有数值都以 median [min–max] 呈现——因为单次运行只有 1–5 次 explore 调用,百分比天然粗粒度,必须报区间。

注意事项(SKILL.md Notes 的完整继承)

  • 每次运行都重建索引audit.sh 会清掉 .codegraph 再索引——不同版本抽取方式不同,索引必须与提供服务的是同一二进制;
  • 临时改动全局安装audit.sh 会暂时替换全局 codegraph,结束后用 local-install.sh 恢复开发链接;跑完请检查日志确认恢复成功;
  • corpus 复用:语料仓库克隆到 /tmp/codegraph-corpus,已存在则复用不重克隆(意味着不会自动跟踪上游更新);
  • 扩展语料:直接编辑 corpus.json,字段固定为 namereposizefilesquestion;新条目会自动进入 Step 2/3 的选项列表。

延伸:同一脚本簇的其它评测入口

audit.sh 面向"某版本 vs 裸 grep/read"的采用类问题;若要回答"某次检索改动到底改了什么",仓库还提供配套入口,全部复用同一套污染防护与指标解析:

  • ab-new-vs-baseline.sh:新构建(HEAD)对基线构建(git ref),两臂都开着 codegraphRUNS=n 控制每臂重复次数,每轮预热 codegraph daemon(否则 Agent 会在 codegraph 2–3 秒冷启动期间转投 Read/grep,测到的是附加延迟而非检索质量);
  • run-agent.sh:单臂 headless 快速运行,打印完整 stream-json 与 per-tool 拆解,适合临时探查;
  • probe-explore.mjs:指标块定位到"哪次 query 掉队、Agent 转去读了哪个文件"后,用它复现单次 explore 的返回内容;
  • bench-readme.sh + parse-bench-readme.mjs:7 个 README 仓库 × 3 轮 × N 次/臂的批量战役与聚合。

理解这三个指标的取舍、各桶指向的修复、以及"small-n 必须报区间"等读表纪律,以 docs/benchmarks/agent-eval-feedback-metrics.md 为准——它同时声明这三项指标是 harness-only 的:全部从已有转录解析,产品侧零新增输出,数据不出本机。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341