ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

构建可对抗“营销数字“的 Token 基准测试:XERJ 检索 vs grep 的三臂测量 Harness

构建可对抗“营销数字“的 Token 基准测试:XERJ 检索 vs grep 的三臂测量 Harness
  • 人工智能
  • 搜索引擎
  • 本地部署
  • 后端
  • MCP 服务

【免费下载链接】xerj

XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.

项目地址:https://gitcode.com/GitHub_Trending/xe/xerj
点击查看免费下载

这篇技术文章源自 XERJ 仓库中的一份 Agent 现场报告(user-feedback/16-agent-field-reports/2026-08-18-token-benchmark-harness.md):一位 Agent(Claude Opus 5 / Claude Code)在 2026-08-18 受命验证"检索比 grep 节省 token"这一公开主张,最终没有急着交出漂亮数字,而是先建了一套带盲评、对账与校准的测量 harness。本文以该报告为核心骨架,结合仓库中完整落地的 benchmarks/grep-vs-retrieval-lucene 目录,逐层拆解这套 harness 的设计动机、运行方式、诚实性防线与试点结论。读完你会掌握:为什么"token 节省"这类数字极易被操纵、如何用三臂对照 + 盲评 + 缓存中性成本构造可信测量,以及如何把一次失败的试点变成比胜利更有说服力的证据。

一、任务背景:为"40% token 浪费在 grep"这句话建一个测量装置

报告要测量的目标声明(用户原话,等待数据修正)是:

"your claude code / codex wastes 40% tokens just on grep/sed files; XERJ reduces it many times."

这句话有两个互相独立的半句,任何一半都可能单独被证伪:

  • 半句 A:40% 的 token 花在 grep/sed/read 上;
  • 半句 B:XERJ 能把 token 消耗"减少很多倍"。

报告的原始动机是为一条营销推文产出数字。但第一次真实运行就暴露出这类基准最典型的陷阱——先有数字,后验正确性。本文的主角不是"XERJ 到底省了多少 token",而是"如何测量才不会被一个好看的数字骗到"。

这套测量装置在仓库中的完整实现位于 benchmarks/grep-vs-retrieval-lucene。它的 README 开宗明义地写着:harness only. No results are published here yet——测量矩阵尚未全部跑完,因此在全部运行被分级之前,目录中刻意不放results.json、runs/或logs/。这正是该目录与一般 benchmark 目录的最大区别:在结果被盲评之前,没有结果可以被引用。

这份 harness 还补上了 docs/case-studies/reference-coding/CASE_STUDY.md 里点名指出的缺口——"测量 harness(三臂 runner、专用参考库、隐藏测试任务规范)不在本仓库中,只有输出在"。这份就是那个"被交付出来的 harness"。

二、What worked:索引 6,012 个 Lucene 文件,xq返回带path:line的评分命中

报告的第一段经验很朴素:索引 Lucene 源码树(6,012 个文件)并查询符号没有任何意外。

索引后,检索臂拿到的是一个名为xq的检索工具。它返回的不是文件名列表,而是带真实path:line的评分命中,包括符号类型、签名和函数体。这意味着检索臂可以把"实际实现"直接交到 Agent 手里,而不是给一个文件名让 Agent 自己去翻文件。这正是"检索 vs grep"之争的核心差异:grep 给你的是"命中的行",索引给你的是"命中的符号及其上下文"。

xq的实现见 benchmarks/grep-vs-retrieval-lucene/xq:

  • 它是一个"故意迟钝"的查询工具:接受模型提供的任意自由文本查询,跑一个固定的 ES 查询模板(multi_match于code、name_text(boost 3)、sig(boost 2)、doc字段,minimum_should_match: 1),返回符号级命中:path:line、kind、签名和函数体;
  • 每次命中代码上限1,600 字符(MAX_CODE_CHARS = 1600),防止单次调用把整个语料库倒进上下文;
  • 默认k=5,范围被钳制在 1–10。

设计上最重要的一条约束写在xq的 docstring 里:"如果这个文件包含针对特定问题的逻辑,基准就被作弊了,所以它必须保持通用"。没有任何逐题手写的查询、没有针对特定答案的 rerank。这个"通用性"是整个对照实验有效性的前提——如果检索臂拿到的是人肉调过的查询,测量就变成了"展示我们多会调 ES"。

三、What bit me:第一次运行就产出了 35%——一个"既漂亮又毫无价值"的数字

报告最核心的教训是这一段:

首次运行:native 64,487 tokens vs xerj 42,068。这是一个可以引用的 35%,但它一文不值,因为两个答案都还没有被分级——更便宜的错误答案是一种损失,不是胜利。

这组数字在 benchmarks/grep-vs-retrieval-lucene/README.md 的试点小节中得到了完整复现(n=1 个问题,每臂 1 次重复,两臂都答对了 q01 的 256):

指标nativexerj
billed tokens 总计64,48742,068
工具调用次数2(Glob+Grep)1(xq)
估算的工具输出 token1451,072
工具占 billed token 比例0.5%5.1%
缓存中性成本$0.3283$0.2153
原始成本$0.0999$0.2345

这份数据至少证伪了半句 A 在试点上的表现:在一个目标精准的问题上,native 臂只花了约 145 个 token 在 grep 输出上,占 billed token 的 0.5%,远不是"40%"。两臂真正的成本大头是每次 API 调用都要重新计费的固定 ~24k token 系统提示 + 工具定义(native 3 次调用 vs xerj 2 次)。XERJ 在这里的 token 优势(约 1.53×)主要来自更少的回合数,而不是"grep 输出很大"。

这也解释了报告的结论为什么如此坚决:token 节省数字可以被"答得更差"轻易地操纵。一个不检查正确性的 token 基准,衡量的是错误的东西——它奖励放弃或幻觉。所以最终构建的 grader 被设计成拒绝给未分级的运行打分,报告为 UNKNOWN,因为默认路径会产出一个没有正确性检查支撑的好看数字。

四、三臂对照:native / xerj / hybrid,谁都不能被暗中照顾

harness 的核心是三臂对照(benchmarks/grep-vs-retrieval-lucene/run.sh):

arm工具cwd代表什么
nativeGrep, Glob, Read(禁用Bash)真实 Lucene checkout今天的 Claude Code 用户
xerj仅Bash(xq:*)(禁用Grep/Glob/Read)空目录光靠索引能否回答问题?
hybridGrep, Glob, Read, Bash(xq:*)真实 checkout真实的产品体验

三个设计要点:

  1. xerj臂运行在空目录里,物理上无法回退去读源码树——这是对"仅检索"的严格测试;
  2. hybrid是最公平的正面交锋:两边都是 agentic,各自选择策略,这个数字应该成为公开文章的锚点;xerj是严格的底线;
  3. 两臂都是 agentic 的,自己写查询,没有人类调好的查询。xq是唯一的检索途径,且刻意通用。

对应三臂的精确 CLI 命令(verbatim 自run.sh):

# native:真实 checkout + 常规文件工具 cd /home/claude/.xerj-code/corpora/lucene-meta/lucene && claude -p "$RULES\n\nQUESTION: $q" \ --output-format stream-json --verbose \ --allowedTools "Grep,Glob,Read" --disallowedTools "Bash,WebSearch,WebFetch,Task" # xerj:空 sandbox,唯一工具是 xq(经 Bash 调用) cd outreach/bench/.sandbox && claude -p "$RULES ... xq \"<query>\" [k] ...\n\nQUESTION: $q" \ --output-format stream-json --verbose \ --allowedTools "Bash(xq:*)" --disallowedTools "Grep,Glob,Read,WebSearch,WebFetch,Task" # hybrid:两者都可用,模型自己选 cd /home/claude/.xerj-code/corpora/lucene-meta/lucene && claude -p "$RULES ... xq ...\n\nQUESTION: $q" \ --output-format stream-json --verbose \ --allowedTools "Grep,Glob,Read,Bash(xq:*)" --disallowedTools "WebSearch,WebFetch,Task"

每轮运行把完整的原始stream-json转录保留在runs/。采集时不做任何摘要,因此文章里的任何数字都可以从原始证据重新推导——这是"可审计"的具体含义。

xerj臂的 prompt 还明确警告了索引内容:索引里含有 backward-codecs 和 test 副本,很多类存在近似重复,所以在信任每个命中之前要检查它的路径——这个警告直接对应后面 q01 的真实陷阱。

五、问题集:10 个真实问题、3 个类别、写答案前先写 ground truth

完整问题集在 benchmarks/grep-vs-retrieval-lucene/questions.jsonl,共 10 个,每个都携带确切的文件、行号以及判定对错的事实,且在写下来之前全部对照语料库验证过。

id类别问什么ground truth(已验证)
q01_block_sizeprior_hostile当前默认 postings 格式的ForUtil.BLOCK_SIZE256,lucene104/ForUtil.java:34——五个 backward-codecs 副本说 128
q02_hnsw_levelmechanismHNSW 如何决定新节点的层级ml = M==1?1:1/Math.log(1.0*M);(int)(-log(u)*ml)
q03_mmap_chunkprior_hostileMMapDirectory 的DEFAULT_MAX_CHUNK_SIZE不是常量:JRE_IS_64BIT ? (1L<<34) : (1L<<28)
q04_merge_scoremechanismTieredMergePolicy 如何给 merge 打分mergeScore=skew、*= pow(totAfterMergeBytes, 0.05)、deletesPctAllowed=20.0
q05_hnsw_limitslookupLucene99HnswVectorsFormat 的硬上限MAXIMUM_MAX_CONN=512、MAXIMUM_BEAM_WIDTH=3200、HNSW_GRAPH_THRESHOLD=100
q06_bm25_k3prior_hostileBM25Similarity 是否有查询侧饱和参数k3存在,默认-1f(禁用),((k3+1)*qtf)/(k3+qtf)
q07_iwc_flushlookupIndexWriterConfig 默认 flush 触发DEFAULT_RAM_BUFFER_SIZE_MB=16.0、DEFAULT_MAX_BUFFERED_DOCS=DISABLE_AUTO_FLUSH
q08_osq_paramslookupOptimizedScalarQuantizer 默认值DEFAULT_LAMBDA=0.1f、DEFAULT_ITERS=5、MINIMUM_MSE_GRID
q09_exhaustive_countindex_hostile统计包含implements Accountable的文件数43(grep -rl ... \| wc -l)
q10_tragic_eventmulti_hop记录 tragic exception 的方法tragicEvent(...):1869 vsonTragicEvent(...):713——两个不同的方法

三个类别是故意设计的:

  • prior_hostile(q01/q03/q06)——checkout 与模型记忆矛盾。q01 是 256 而外界普遍说 128;q06 的k3在上游 Lucene 根本不存在。从记忆作答的 Agent 在这里得0 分。它们存在的理由是构建过程中发现的问题(见下节 4.1):模型曾不调用任何工具就从记忆里回答了 Lucene 问题,这类题让"参数泄露"可检测而非沉默。
  • index_hostile(q09)——刻意让 XERJ 输的对照题。跨整棵树的穷举计数正是 top-k 检索做不到、而 grep 做得完美的事。把它放进集合,是为了让结果可以"对自己不利"地报告,延续 docs/research/wordpress-verification-and-xerj-vs-grep.md 的先例。
  • lookup/mechanism/multi_hop——普通的中间地带,覆盖查常量、机制理解和多跳调用链。

选择这些题而非 trivia 的理由:每一道都是工程师在改索引或向量搜索行为之前真正会问的问题——我的 postings 会用多大的块、HNSW 图该设多大、为什么 merge 没触发、什么触发了 writer flush、为什么量化器有损。没有任何一道能靠读 README 答出来。

六、数据从哪里来:claude -p --output-format json的真实字段与三个陷阱

token 与成本数字来自claudeCLI 自己的记账(claude -p --output-format json),不是估算或字节代理。README 用一次真实的临时运行验证了真实返回的字段(而非假设):

is_error duration_api_ms duration_ms num_turns stop_reason session_id uuid subtype total_cost_usd usage modelUsage permission_denials terminal_reason api_error_status fast_mode_state fast_mode_disabled_reason result ttft_ms ttft_stream_ms time_to_request_ms type

usage形如:

{"input_tokens":6,"cache_creation_input_tokens":5956,"cache_read_input_tokens":68601, "output_tokens":608,"output_tokens_details":{"thinking_tokens":89}, "server_tool_use":{"web_search_requests":0,"web_fetch_requests":0}, "service_tier":"standard", "cache_creation":{"ephemeral_1h_input_tokens":5956,"ephemeral_5m_input_tokens":0}, "iterations":[ ... ]}

modelUsage按模型细分:inputTokens, outputTokens, cacheReadInputTokens, cacheCreationInputTokens, costUSD, contextWindow, maxOutputTokens, canonicalModel, provider。

但它不暴露的东西才是关键(这是整个基准的核心事实):

  1. 没有任何 per-tool 的 token 归因字段。没有任何字段说 Grep 或 Read 花了多少 token。"40% 花在 grep 上"这个数字不能直接从这份 JSON 读出来,必须从转录中重建,而重建就是估算。因此:头条数字必须建立在精确的东西上("答对同样问题少花 N 倍 token"),而不是重建出来的占比上。
  2. input_tokens是个陷阱。一次真实运行里它是2,而实际计费输入约 24,000 token——几乎一切都落在cache_creation_input_tokens和cache_read_input_tokens里。引用input_tokens会把成本低估约 1000 倍。计费输入 =input_tokens + cache_creation_input_tokens + cache_read_input_tokens。
  3. usage.iterations不是完整的逐调用日志。一次 3 次 API 调用的运行里它只有1条(最后一条)。逐调用数据必须来自--output-format stream-json --verbose,并按message.id去重assistant事件。
  4. 流式的output_tokens是部分值。求和得到 9,真实值是 608。输出必须取自最终的result事件(ledger.py对此做了断言:input 与 cache 计数器精确对账,output 取自result)。
  5. 有第二个模型在计费。每次运行还会调用claude-haiku-4-5(约 $0.001)。它与检索策略无关,被单独报告,绝不记到任何一臂头上。

七、ledger.py:转录 → 可审计 token 账本,对不上就拒发

benchmarks/grep-vs-retrieval-lucene/ledger.py 是整个诚实性机制的技术核心。它的存在理由写得很直白:claude -p --output-format json只给汇总,没有 per-tool 字段,所以"Agent 在 grep/read 上烧掉 X% token"必须重建,而它拒绝发出无法与 CLI 计费汇总对账的数字。

方法:

  • 逐调用用量从流的assistant事件恢复,按message.id去重(每个 id 在流式期间发出多个事件,保留每个计数器的最大值——即该消息的最终值);
  • 计费输入=input_tokens + cache_creation_input_tokens + cache_read_input_tokens;
  • 工具结果归因按字符,用本语料实测的常量:calibrate.sh用两个相差 20,000 字符真实 Lucene 源码的 prompt,测得 billed token 差 7,181,得2.785 chars/token。常见的 chars/4 规则会低估 Java 源码约 30%,用它就会低估 grep 成本;
  • 输出 token 取自权威的result事件,并断言重建的 input/cache 计数器与 CLI 汇总精确对账(reconciled字段),不匹配就拒绝发数字;
  • 主模型与 sidecar(haiku)按modelUsage隔离,sidecar 成本永不记到任何一臂头上。

ledger.py还报告三种不同的占比,因为它们回答不同的问题:

  • share_of_unique_ctx_pct——"Agent 读过的所有东西里,grep/read 输出占多少";
  • share_of_billed_pct——"你实际付的钱里,grep/read 输出占多少"(高于前者,因为第 2 轮拉进来的工具结果会在之后每一轮按 cache-read 价格重新计费);
  • share_of_dollars_pct——同上,但按 token 类别的真实价格加权(cache read 约为 fresh input 的 10%)。

报告用户的那句"40%"是 billed/dollar 风格的声明——必须说清楚你指的是哪一种。

另外两个被实测过的细节:

  • 价格模型是推导出来的,不是假设的:通过求解 CLI 报告的costUSD与其自身计数器,精确恢复出$5.00/Mtok 输入、$25.00/Mtok 输出。这还抓到一个错误:这些运行用的是1 小时缓存(写乘数 2.0×)而非 5 分钟缓存(1.25×)——假设 1.25× 会推出负的输出价格。
  • 备选估算器(连续调用间cache_creation增量)被试用后否决:开了扩展思考后,该增量被重发的 thinking-block 签名 blob 主导,819 字符的 grep 输出读出了 1,613 token(约 5 倍高估),只保留为宽松上界。

还有一份并行的逐工具归因实现 benchmarks/grep-vs-retrieval-lucene/attribute.py,它用"两次 API 调用之间的 billed-prompt 增量减去本调输出"来测工具输出——即提供方自己的计费表计量的工具输出,不需要 tokenizer 和估算;单次调用发出多个工具时按字符占比分摊并打标记。

八、analyze.py:两阶段盲评,机械检查只能判 FAIL,永不判对

benchmarks/grep-vs-retrieval-lucene/analyze.py 实现了两阶段分级:

阶段 1(机械):从questions.jsonl读取must_match/must_not_match字符串检查。廉价、确定、可审计。它只能把运行判为 FAIL-certain 或 NEEDS-JUDGE,永远不能独立判对——因为子串存在不等于理解(一个答案可以包含"256"却在断言错误的东西)。

阶段 2(盲评):所有 NEEDS-JUDGE 答案写入judge_queue.jsonl,去掉 arm 标签并按固定种子(random.Random(20260818))打乱,让评分者无法看到答案来自哪个臂。判定从judge_verdicts.jsonl读回。

头条指标是tokens per CORRECT answer(每答对一题消耗的 token),不是每轮 token。一个因为放弃或幻觉而便宜的臂不能赢;答错的运行只计成本、不给信用——这是"N 倍更少 token"有意义的唯一方式。统计用中位数而非均值:一次失控的 agentic 运行不应决定头条。

analyze.py输出还包含 per-arm 摘要表、per-question-class 的 token/准确率矩阵,以及逐题的按臂对比——任何由单一类别驱动的胜利都会暴露。

九、校准:calibrate.sh实测本语料的 chars/token

benchmarks/grep-vs-retrieval-lucene/calibrate.sh 通过向 CLI 发送两个仅差已知字符数的相同 prompt 来测量本语料的 chars/token,不需要 API key 也不需要 tokenizer:

# 用 head -c 取 2000 与 22000 字符的真实 Lucene 源码作为参考材料 # 分别跑 claude -p,读出 cache_creation_input_tokens 的差值 # chars_per_token = (22000-2000) / (cc_22000 - cc_2000)

2026-08-18 记录的结果:20,000 字符 → 7,181 token ⇒ 2.785 chars/token(常见 chars/4 规则低估 Java 源码约 30%)。

十、完整运行流程:从校准到盲评再到出表

cd benchmarks/grep-vs-retrieval-lucene # 仓库内对应 outreach/bench ./calibrate.sh # 为这个语料重新推导 chars/token REPEATS=3 ./run.sh all all # 3 臂 × 10 题 × 3 次重复 = 90 轮 python3 analyze.py # 生成 judge_queue.jsonl(去标签、打乱) # 盲评 judge_queue.jsonl -> judge_verdicts.jsonl,然后: python3 analyze.py # 输出 head-to-head 表,未分级按 UNKNOWN 处理并排除

每轮run.sh输出原始 stream-json 转录到runs/,stderr 到logs/;已存在的运行被跳过(支持断点续跑)。run.sh也支持单臂单题单次重复(如./run.sh native q01 1)用于调试。

十一、七条诚实性防线:什么会让这个基准作弊,以及如何阻止

README 第四节逐条列出"什么会让这变成骗局"以及对应措施,每条都有代码与试点证据:

  1. 4.1 把答案写进 prompt——构建中实测发现:早期探测中模型零工具调用就从记忆回答了 Lucene 问题("codec header 是9 + codecName.length字节")。对记忆化的 Lucene trivia 做基准测不到任何检索。缓解:显式要求"只根据本次会话检索到的内容作答"、强制file:line引用、外加三道prior_hostile题让记忆给出错误答案,使参数泄露可检测而非沉默。
  2. 4.2 缓存暖热——最大威胁,且真实发生。试点中xerj少用 1.5× token 却多花 2.4× 美元($0.2345 vs $0.0999):native跑在暖的前缀缓存上(57,945 个廉价 cache-read),xerj跑在冷的缓存上(21,693 个昂贵的 cache-write)。两臂 prompt 前缀不同(工具集、cwd 不同)所以永远无法共享缓存,暖热取决于运行顺序和 5 分钟/1 小时 TTL。应对:原始美元不是公平的跨臂指标;报告 token,并报告cost_usd_cache_neutral(所有输入按 fresh input 计价,移除暖热运气)。试点里 cache-neutral 比值(1.52×)与 token 比值(1.53×)吻合,而原始美元是反转的。同时:交错各臂、重复 3 次、用中位数、丢弃热身轮。
  3. 4.3 挑选适合索引的问题——q09 的存在就是为了让 XERJ 输,且结果按问题类别报告,单一类别驱动的胜利无处可藏。ground truth 在任何臂运行之前写好;看到结果后从不删题;results.json保留每一轮。
  4. 4.4 让 native 臂不像真实用户——native 臂在真实 checkout 里恰好得到Grep, Glob, Read,不多不少:不被削弱(不强迫整文件读),不被帮助(无 Bash、无预置路径)。同时xq输出上限 1,600 字符/命中,索引臂也不能倾倒语料库。
  5. 4.5 对你喜欢的臂评得更宽松——盲评:arm 标签剥离、固定种子打乱;机械字符串检查只能判 FAIL 或 NEEDS-JUDGE,永不判对。
  6. 4.6 忽视检索可能主动误导——真实观察:q01 时xq先返回了无关的CharBlockArray,第二个是错误的ForUtil(backward-codecs lucene103,BLOCK_SIZE = 128),第三个才是正确的 lucene104。索引里有 backward-codecs 和 test 近似副本。完整运行中如果这误导了模型,必须报告。
  7. 4.7 "索引零成本"的说法——"索引不花 token"只对LLMtoken 成立。索引构建是 6,012 个文件上的 CPU/磁盘/墙钟时间,外加 75,578 个保持存活的文档。如果文章说"免费",应该写**"无 LLM token"**,而不是"免费"。

十二、试点结论:一个诚实的失败案例比胜利更买信任

试点(n=1 题,每臂 1 次重复)的直接结论是:这不支持"40% 浪费在 grep 上"。在目标精准的问题上,native 臂只花了约 145 token 在 grep 输出上——0.5%的 billed token。两臂的成本大头是固定的 ~24k token 系统提示与工具定义,在每次 API 调用上重新计费。XERJ 的 token 优势主要来自更少的回合。

报告建议的措辞值得一字不差地引用(这是整份文档的灵魂):

"任何大的胜利很可能来自回合数减少,任何大的'grep 占比'只会在探索密集、Agent 在多个文件间搜索的问题上出现。到底是 40%、18% 还是 3%,正是完整矩阵要回答的。"

对应地,README 预承诺了证伪条件:

  • 半句 A 被证伪:如果 native 臂工具输出占 billed token 的中位数明显低于 40%(比如 <25%)——试点已测到 0.5%,这半句已经严重存疑,帖子里的数字必须改。
  • 半句 B 被证伪,如果出现任一情况:hybrid/xerj的每正确答案 token 中位数没有明显低于 native(比值低于 ~1.3× 称不上"很多倍");XERJ 省了 token 但输了准确率;优势只在原始美元里、在cost_usd_cache_neutral下消失;优势由单一问题类别撑起而在其他类别反转(q09 预期对 XERJ 不利;如果mechanism和multi_hop也输,就没有故事了)。

预承诺的报告规则:无论测出什么数字,都原样进文章,包括 XERJ 输掉的 q09,以及被修正过的 40% 数字。如果半句 A 塌了但半句 B 成立,诚实的帖子应该是"grep 不是你 token 的去处——回合才是;检索把每正确答案的 token 砍了 N 倍"——这比原声明更好、更经得起辩护。

十三、Suggestion:把失败案例链接进 README

报告的第三条建议直接引用了一个文件:

Linkdocs/research/wordpress-verification-and-xerj-vs-grep.mdfrom the README. It publishes a case where XERJ lost, with the mechanism, and that buys more trust with skeptical engineers than the wins do.

该文件确实存在于仓库中:docs/research/wordpress-verification-and-xerj-vs-grep.md。它记录了一次 XERJ输给grep 的实测:

方法结果判定
grep -rl wp_safe_remote_*14 个文件完整
XERJ full-text(matchoncode)9 个函数完整、函数级
XERJ 预建调用图(termoncalls)1沉默的假阴性

安全审计中最严重的错误是"假的不可达",而结构化调用图恰好产出了这个。根因是真实的 XERJ 查询层 bug(数据确实在_source里):XERJ 忽略keyword映射、对数组 keyword 字段做分词(wp_safe_remote_get被切成[wp, safe, remote, get],于是{term:{calls:"wp_safe_remote_get"}}→ 0),且booleanterm被当字符串匹配({term:{has_source:true}}→ 0,{term:{has_source:"true"}}→ 440)。只有多 token 和 boolean 两种情形会静默失败,所以这个 bug 极易漏掉。

这份文档给出了一个诚实的裁决,与本文的基准哲学完全一致:

  • 原始可达性("谁调用了 X"、"Y 用在哪"):grep 与 XERJ full-text 完整可靠,预建结构化调用图目前比 grep 差(静默少报);
  • 预建索引真正赢的地方是 grep无法表达的函数内计算指纹(消毒序列顺序、SSRF 范围覆盖、cap-object 作用域)——它们带来了实测的约 2,700× token 缩减;
  • 净结论:XERJ 作为文档存储、≈带函数作用域的 grep 的 full-text 层、以及预计算语义指纹的载体是真实帮助;其"结构化数据库"表面(精确 keyword/booleanterm)有 bug,在修复前不能用于安全可达性判断。

这正是报告建议把它链进 README 的原因:一个带机制的失败案例,比十个胜利更能买来持怀疑态度的工程师的信任。这种"发布自己输掉的结果"的规则,同样适用于本文的 token 基准——README 明确声明:本仓库对 XERJ 输在哪里有着一以贯之的先例,同样的规则适用于这个 harness 测出的一切。

十四、对任何"token 节省"类基准的可移植清单

结合本 harness 与 docs/TOKEN_USAGE.md(后者给出了一个可直接复用的模型:tokens ≈ envelope_overhead + answer + materialized_intermediate_data),可以把这套方法提炼为可移植的七条规则:

  1. 测量线上的字节,而不是工具调用数——token 来自请求/响应载荷;两次 30 字节的调用胜过一次 15 KB 的调用;
  2. 节省只在双方都答对的任务上成立——返回更少字节但没返回有用信息不是节省;排除任何一方答错的任务;
  3. 基线只使用问题自身的词汇——已经知道答案位置的人写的 grep 不是基线;
  4. 双方同等调优——基线是合格的,XERJ 侧就必须用filter_path、size:0与原生模式;用调好的基线与没调优的引擎比,是另一种不诚实;
  5. 变化查询以击穿结果缓存,报告第一次、未缓存的时间;
  6. 把timed_out:true与 bucket-vs-hits.total不一致判为错误,而不是"快";把部分答案当完整答案是失败的极限形态;
  7. 每个比值旁必须报告语料构成——检索节省随 prose 比例放大,分析节省随记录数放大,单一头条 token 数字跨两类语料毫无意义。

这套规则在仓库里由 demo/agent-gate/gate.py 用代码强制实施:没有语料构成就拒绝打印比值。

总结

这份 agent 现场报告最终没有交付一个数字,而是交付了一个能拒绝交付数字的系统。它的全部价值浓缩在三件事里:

  1. 数字本身会骗人——claudeCLI 的 JSON 没有 per-tool 归因,input_tokens是陷阱,缓存暖热可以让原始美元反转,而"更便宜的答案"在没有盲评时会被误读为胜利;
  2. 可信度来自结构性约束——三臂对照 + 空目录隔离 + 通用xq+ 预写 ground truth + 盲评 + 每正确答案 token 指标 + 缓存中性成本 + 预承诺的证伪条件,每一步都把"操纵空间"压缩到极限;
  3. 最有说服力的证据是诚实的失败——无论是 q01 的 35% 空头数字、q09 的故意反 XERJ 控制题,还是 WordPress 审计里调用图对 grep 的完败,公开"哪里输了、为什么输"买来的信任,远超一切胜利。

如果你要在自己的项目上复刻这套方法,起点就是 benchmarks/grep-vs-retrieval-lucene 目录里的六个文件:questions.jsonl(问题与 ground truth)、run.sh(三臂 runner)、xq(刻意通用的检索工具)、ledger.py(可审计账本)、analyze.py(盲评出表)、calibrate.sh(语料校准)。它们共同定义了"一个不假设结论、只测量结论的装置"长什么样。

  • 人工智能
  • 搜索引擎
  • 本地部署
  • 后端
  • MCP 服务

【免费下载链接】xerj

XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent memory, using 40x fewer tokens than grep. Elasticsearch compatible, so existing clients just work.

项目地址:https://gitcode.com/GitHub_Trending/xe/xerj
点击查看免费下载

相关推荐

上一篇:UMAP近邻数量选择:n_neighbors参数对聚类结果的影响
下一篇:如何掌握boardgame.io游戏阶段与回合顺序:打造专业桌游体验的终极指南

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进