news 2026/9/6 20:40:10

codegraph Explore Allocation Efficiency:用 agent-eval 反馈指标量化“返回字节里有多少真的被答案用上“

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
codegraph Explore Allocation Efficiency:用 agent-eval 反馈指标量化“返回字节里有多少真的被答案用上“

codegraph Explore Allocation Efficiency:用 agent-eval 反馈指标量化"返回字节里有多少真的被答案用上"

【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph

codegraph 的 agent-eval 测试框架(harness)在每次运行中都会输出三项反馈指标,其中allocation efficiency(分配效率,CG-9)回答的问题是:一次codegraph_explore响应所花费的字节里,有多大比例落进了 agent 最终答案真正引用的文件。本文完整讲解这个指标的定义、两条引用判定通道及其防误判护栏、基线数据、"新构建 vs 基线构建"的对比用法与它不回答的问题,并结合 parse-run.mjs 的源码实现说明每个判定的具体落地方式。读完本文,你可以直接在自己的 A/B 运行中解读这块指标输出,并理解它为何只能作为同题对比的相对指标使用。

指标定义:#1500 缺陷变成一个数字

Allocation efficiency 是 agent-eval 三指标体系 的第三项,定义如下:

allocation efficiency = bytes returned for files the final answer cited ─────────────────────────────────────────────── all bytes returned

也就是"最终答案引用过的文件所占返回字节"除以"全部返回字节"。这个比值把 codegraph 的 issue #1500(explore 响应预算在文件之间分配失衡)直接变成了一个可重复采集的数字。它的定位是对手工"信封视图"(envelope view,见 explore-allocation-ab-1500.md)的自动化替代:信封视图已经展示了响应在各文件之间如何切分,但"这些文件里哪些真正重要"此前需要人逐题手写--answer 'lib/response.js'来标注。allocation efficiency 直接从 agent 自己的最终答案里读出同一个交集,因此每次运行都免费产出该数字,无需任何人工标注。

两点使用前提必须记住:

  • 它是相对指标。归因依赖"引用",而 agent 完全可能使用了一个文件的源码却从未点名它——比如用它来排除嫌疑,或建立心智模型后从别处转述。误差是单向的,所以这个数字只用于同一问题下两个构建之间的对比,不能解读为"信封中 15% 是浪费"这类绝对断言。
  • 它是 harness-only 指标。与另外两项反馈指标一样,产品本身不输出任何东西,数据不出本机,全部解析自已经在写的运行 transcript(stream-json 日志或交互式会话日志)。

运行方式:每次运行都自动打印

所有调用parse-run.mjs的入口都会打印这块指标,包括 run-all.sh 和 ab-new-vs-baseline.sh。对已有日志单独跑:

node scripts/agent-eval/parse-run.mjs /private/tmp/cg22/ab-express/run-baseline-1.jsonl

输出形如(这是 express 基线运行的真实输出):

Explore allocation — share of returned bytes the answer used (2 calls, 4 files): efficiency 81.9% 17,465 of 21,319 chars (3/4 files cited; path-cited alone 64.9%) call 1: 84.0% 10,121/12,048 chars 2/3 files call 2: 79.2% 7,344/9,271 chars 2/3 files * 34.9% 7447 lib/response.js path * 30.0% 6396 lib/utils.js path 18.1% 3854 lib/express.js — * 17.0% 3622 lib/application.js symbol `compileETag`

要点逐项拆解:

  • 汇总行给出 run 级效率:17,465 of 21,319 chars,并注明 3/4 个文件被引用;括号里的path-cited alone 64.9%是只用路径通道计算的保守下限,与合并数字并列输出(见下文"两条通道")。
  • 逐调用(per call)行同样重要。run 级数字会掩盖最有诊断价值的形状——"call 1 打中目标、call 3 纯噪声"。逐调用行直接点名哪一次调用把预算花在了最终没有任何回报的文件上。
  • 文件列表中*标记被引用的文件,行尾标注归因依据:path(路径引用)、symbol \compileETag`(符号引用,并给出命中的符号名)或—`(未被引用)。

交互式运行没有 stream-json 日志,用 parse-session.mjs 读取项目目录下最新的 Claude Code 会话日志(~/.claude/projects/<escaped-cwd>/<session>.jsonl及子代理日志),输出同一块指标——它直接复用parse-run.mjs导出的computeAllocation/finalAnswerText/formatAllocation,两条路径的算法完全一致。

--answer <glob>--envelope两个参数仍然保留且行为不变:它们代表人工指定的 ground truth,适用于你想按"已知能回答问题的文件"来打分、而非按 agent 恰好点名的文件来打分的场景。这是 CG-1/CG-22 分配门槛 的"第 2 根标尺"(answer-set share)所用的接口。

文件如何被判"被使用":两条引用通道

判定逻辑集中在 parse-run.mjs 的answerCitationscomputeAllocation。共有两条通道,且刻意做了强弱排序,使较弱的一条可以单独剥离出来——这就是汇总行总要把path-cited alone与合并数字并排输出的原因。

通道一:路径(Path)

答案中出现了文件路径,形态包括:

  • 带行号的仓库相对路径:lib/response.js:126-220
  • 绝对路径
  • agent 写进正文里的裸文件名:utils.js:225

源码中对应的正则分两级(parse-run.mjs#L541-L547):先匹配"至少含一个目录分隔"的点分路径,再匹配裸 basename——但裸 basename 只有在扩展名确实出现在本次 envelope 中时才被接受。这道闸门的目的,源码注释写得很直白:res.sendmime.contentType和文件引用是同一种 token 形状,靠"envelope 实际携带过.send扩展名吗"来拒绝这类误判。

路径匹配还天然覆盖了同一文件的三种写法:lib/response.jslib/response.jsresponse.js或以它结尾的绝对路径引用,都视为同一文件(samePath做尾缀匹配)。

通道二:符号(Symbol)

答案在代码 span(反引号包裹)内引用了一个符号,且该文件的 section 头把它列为defined。这条通道专门捕捉"几乎全用符号名写成的答案"。它有三重护栏,方向全部一致:宁可低估效率也不虚高。

  1. 只认定义,不认调用点。explore 响应中每个文件的 section 头会渲染name(kind)对——这在产品侧由 src/mcp/tools.ts 的fileSectionHeader生成,前缀标记FILE_SECTION_PREFIX = '**'是唯一的、可 grep 的分段标记([tools.ts#L837](https://link.gitcode.com/i/75a2e120acf379f8faba80f06ae05fbb))。但头里列的不全是定义:shipped cluster 中的节点还包括**调用点**这类边(如某个只调用mutateElement的文件头上会出现mutateElement(calls))。若按这些归因,就会在 excalidraw 的真实运行中把dragElements.ts误判为"被使用",仅仅因为答案点名了mutateElement。因此解析侧维护了一张定义型 kind 白名单DEFINING_KINDS([parse-run.mjs#L414-L418](https://link.gitcode.com/i/fc207362a35353d4418d7da95ab5eca3#L414-L418)):functionmethodclassstructinterfacetraitprotocolpropertyfieldvariableconstantenumenum_membertype_aliasnamespacemoduleroutecomponent——与产品侧 [src/types.ts 的 NODE_KINDS](https://link.gitcode.com/i/aa423f7886d4d42608ed3c00fce25d8d) 对照一致(去掉file/import/export)。calls` 这类边 kind 不在白名单内,自动被过滤。
  2. 定义压过 import 别名。var compileETag = require('./utils')是一个variable节点。当 envelope 里同时存在"真正定义该名字的文件"和"只是重新绑定该名字的文件"时,variable/constant被放进弱集合,任何strong(真定义)存在时弱集合整体不生效(computeAllocation 中 symbolFiles 的 strong/weak 划分)。上面的输出样例里lib/application.js之所以归因到symbol compileETag之外——实际它命中的是lib/utils.js的定义——正是这条规则在起作用。
  3. 出现在 3 个及以上返回文件中的名字,谁都不指向。常量SYMBOL_AMBIGUITY_LIMIT = 3(parse-run.mjs#L528)。没有这条,sendget这种通用名会把半个 envelope 全标成"已使用",指标向乐观方向偏移——而这正是它唯一不允许偏移的方向。

另有两个细节约束:

  • 散文提及不算引用,只认代码 span。反引号是 agent 标记"这是代码"的动作,这本身就是全部信号。同时SYMBOL_STOPWORDS词表(functionreturnthisdata等)和MIN_SYMBOL_LEN = 4的长度下限进一步滤掉噪声 token。
  • 同一文件被返回两次,计两次账。因为它在上下文窗口里占据了两份空间。这与信封视图的口径完全一致。

答案文本从哪里来

finalAnswerText(parse-run.mjs#L679-L689)定义了"答案"的两种来源:

  • headless stream-json 会话:取result事件的文本。多轮会话经--resume分成多个 segment,每个 segment 一条result,每一条都是答案,全部入池(用\n\n拼接)。
  • 交互式 transcript 没有result事件:回退取主线程最后一条 assistant 文本,并刻意排除中间叙述("let me look at App.tsx" 若计入引用集会污染整个指标),也排除子代理线程(parent_tool_use_id非空的 assistant 事件)。

基线:103 个会话的扫描结果

在 CG-8 使用的同一语料上全量扫描(本机全部 A/B 日志):103 个会话至少有一次"已回答的" explore(74 个单题 + 29 个三轮多轮会话),共297 次 explore 调用、815 个文件 section、0 崩溃。

切片n池化中位数p25p75最小仅路径引用
全部10385.6%90.1%82.0%97.7%20.1%80.2%
单题7485.2%88.8%82.0%95.6%20.1%82.2%
多轮(3 轮)2986.2%92.1%85.0%100.0%57.4%77.5%

逐调用口径:中位数 94.7%,p25 79.2%。

绝对水平偏高,这是语料的性质,不是好消息。这些是"流程类"问题,答案会把链条上大多数文件逐个点名;指标又是字节加权的,由最大的分配是否落在被引用文件上主导——这正是 #1500 问的问题,也是典型 run 能拿八十几分的原因。判别力在p25 及更低的位置,而不是中位数附近。永远不要引用中位数说"codegraph 浪费了返回内容的 10%"。

尾部才是信号所在。语料中最低的一次运行是 20.1%:cg8-val——excalidraw 的canvasNonce问题,即文档中记录的数据流边界案例。三次 explore 返回 11 个文件 / 60,694 字符,答案只用到其中两个(Scene.tsStaticCanvas.tsx),其余靠阅读 envelope 从未交付的Renderer.tsApp.tsx重建。这复现了 CG-1 在 self-query 上手测的 16–30% 区间,且复现过程没有任何人标注答案集。

预定用途:新构建 vs 基线构建

对既有 CG-15/CG-21/CG-22 A/B 臂取中位数(两臂均开启 codegraph):

批次 / 仓库baselinenew
cg15 / express82.0%100.0%
cg15 / excalidraw90.1%92.8%
cg15 / client-go84.1%80.8%
cg21 / express84.1%100.0%
cg21 / excalidraw91.3%97.5%
cg21 / client-go67.1%95.0%
cg22 / express81.9%100.0%
cg22 / excalidraw89.3%79.2%
cg22 / client-go86.6%93.3%

Express 就是 #1500 案例,移动幅度最大:基线臂稳定地把 18% 的信封花在了lib/express.js上——一个没有任何答案引用过的文件——分配修复把它砍掉了。基线三次运行 81.9 / 82.0 / 81.9%,新构建三次 100.0 / 92.5 / 100.0%。这就是把"express 臂现在看起来更紧了"这句话变成数字的变化。

也有反向的一对(cg15/client-go −3pt,cg22/excalidraw −10pt)。cg22/excalidraw 的分布是基线 89.3 / 85.6 / 90.8% 对新构建 87.4 / 79.2 / 78.2%——真实存在,但 n=3 且该问题本身有已知的运行间方差。应报告区间,而不是三次的中位数。

这个对照实验的完整方法论(两臂均 codegraph-on、逐臂建索引、每 run 预热线 daemon、--model sonnet --effort high)见 三指标入口文档 与 CG-15/CG-21/CG-22 记录;CG-22 是 CG-1 epic 的门槛重跑,四项标尺全部通过,express 控制臂从"3/3 运行各读一次lib/utils.js"变为"0 Read"。

这个指标不回答什么

五条边界,全部来自文档原文,建议在引用该数字前逐条过一遍:

  • "未引用"不等于"未使用"。agent 读了文件、判断它不是答案、于是从不提及——这是有用的工作,该指标却把它记为浪费。误差是单向的,这正是数字只能在同题构建之间对比的原因。
  • "被引用"不等于"按这个大小是必要的"。指标问的是哪些文件赚到了自己的字节,不是被引用文件内部哪些行被交付了。答案引用某文件,该文件的 section 就计 100%,哪怕 agent 随后还得 Read 它去补被裁掉的部分。捕捉这一层的是充分性指标(explore-sufficiency.md)里的Read a file we returned桶;两个指标互补,CG-13 的 7 仓库战役同时报告二者。
  • basename 匹配可能落错文件。envelope 里的src/index.ts会匹配答案引用的packages/element/src/index.ts(尾缀匹配)。实践中罕见,但它是真实的假阳性通道。
  • 小样本。一次 run 只有 1–5 次 explore 调用,单次百分比很粗糙。要按批次(RUNS>=2,以及 CG-13 的 7 仓库战役)对比,从不以 n=1 下结论。
  • 效率不等于价值。一次响应可以 100% 高效同时毫无用处——比如只交付了一个被答案顺带点名的极小文件。要把它和充分性(explore-sufficiency.md)、残留上下文占用(residual-context-occupancy.md)放在一起读,三者接入同一次运行正是这个设计。

测试:--selftest 覆盖的分配用例

node scripts/agent-eval/parse-run.mjs --selftest # 68/68

自测试跑在带已知答案的合成 transcript 上,与占用(occupancy)、充分性(sufficiency)检查同文件内执行,合计 68/68 通过。属于 allocation 的用例包括(parse-run.mjs selftest 第 7 节):

  • 三选一形状:一个文件被引用、两个是噪声(40.1% 期望值);
  • 裸 basename 引用计数、以及必须匹配的点分表达式 token(res.sendmime.contentType);
  • 符号归因指向定义者而非调用者(excalidrawdragElements.ts案例的回归用例);
  • 定义压过 import 别名;
  • 3 文件歧义截断(handle出现在 3 个文件时效率必须为 0);
  • 散文提及 vs 代码 span(无引号的sendResponse不计);
  • 逐调用 vs 池化记账(call 1 全用、call 2 全浪费、run 级池化 50%);
  • 文件被返回两次计两次账;
  • 两个"最终答案"来源(result事件 / 交互式回退);
  • parseSession的端到端路径,含formatAllocation渲染与"无 explore 响应"的降级文案。

自测试刻意放在 parse-run.mjs 内部而非独立测试文件,源码注释给出了原因:新增的scripts/agent-eval/*.mjs脚本会被计入 self-query 评测 fixture 自身的语料、移动其数字。

小结

Allocation efficiency 把"explore 返回的字节值不值"从人工审视变成了每次运行自动产出的数字:两条引用通道(路径强、符号弱且带三重护栏)、逐调用与池化双口径、path-cited-alone 保守下限,加上明确的"只作同题构建对比"的相对性约束。它与 充分性、残留占用 三项指标共同接入 agent-eval harness 的每次运行,全部数据解析自本机 transcript,产品零改动、数据零外发。当你看到某次 A/B 的 allocation 数字移动时,逐调用行和文件级的path/symbol归因标注足以定位是分配、召回还是渲染出了问题,并可用 probe-explore.mjs 做无 agent 的确定性复现。

【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 20:33:48

三菱FX5U与温湿度变送器MODBUS RTU通信实战

简介&#xff1a;三菱FX5U系列PLC与温湿度变送器实现MODBUS RTU通信的编程示例文档&#xff0c;面向工业自动化现场工程师与PLC编程初学者&#xff0c;重点解决FX5U作为主站通过485串口读取温湿度变送器数据的问题。资源为单个docx格式文档&#xff0c;压缩包共1个文件&#xf…

作者头像 李华
网站建设 2026/9/6 20:33:05

MaxKB 部署教程:10 分钟跑通你的第一个知识库问答

MaxKB 部署教程&#xff1a;10 分钟跑通你的第一个知识库问答 【免费下载链接】MaxKB &#x1f525; MaxKB is an open-source platform for building enterprise-grade agents. 强大易用的开源企业级智能体平台。 项目地址: https://gitcode.com/GitHub_Trending/ma/MaxKB …

作者头像 李华
网站建设 2026/9/6 20:31:02

Buzz 离线语音转文字完整指南:从一段会议录音到批量自动化

Buzz 离线语音转文字完整指南&#xff1a;从一段会议录音到批量自动化 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz Buzz 是…

作者头像 李华
网站建设 2026/9/6 20:30:00

WeChatMsg 微信聊天记录导出完整指南:一键转成 HTML/Word/CSV 永久保存

WeChatMsg 微信聊天记录导出完整指南&#xff1a;一键转成 HTML/Word/CSV 永久保存 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_T…

作者头像 李华