RAG 把答案交给模型去写,慢、贵、又容易错。这几个毛病都出在同一个环节。XERJ Query-1 反着来:模型只写一段几行的查询程序,引擎替它跑,答案连证据一起返回。这套思路值不值得信,我把它的 benchmark 和安装过程都过了一遍。
写程序,不写答案
RAG 检索只要几毫秒。真正慢的是模型把结果写成人话那一步。XERJ Query-1 把这一点挑明了。模型读你的问题,输出几个程序步,像 LOOKUP #12、PICK_GT。引擎在你存的事实上执行它们。官方 README 给的对照数字很硬:同一组 160 道题,Query-1 每道 220ms(p50),Opus 5.5 写 RAG 答案要 1.5 到 2.3 秒。错答只有 1 题,RAG 要错 9 到 15 题。每百万问题 42 美元,RAG 要 13400 美元。这些是在 rc.101、4 个模型线程、笔记本 CPU 上测的,原文有标注。
它快在哪。答案不是模型生成的文字,是程序执行的输出。查一个身高,程序是 LOOKUP 之后 RETURN。引擎把一个事实的 subject、relation、typed value、字符跨度一起拿出来。你看到的不是一句「她 170 厘米」。而是一个事实 id 加一段原文引用。错了能追到是哪个事实、哪个版本、哪个字符位置。RAG 错了,你只能重读喂给它的那些记录。
它还省 token。官方 case study 给了一组 reference coding 实测:8 个任务、4 种语言、每条路 16 次跑,真实 claude -p 数 token。纯靠记忆输出 260916 个 output token,花 11.18 美元,解出 11/16。grep 驱动的 Agent 输出 26477 token、3.27 美元、16/16。XERJ 只要 9982 token、1.58 美元、也是 16/16。同一个解题率,token 少了 2.7 倍。这个数我核过出处,是官方 case study 里的表,不是我拍的。
我装它,卡在下载
我想在本机跑一遍,结果先栽在安装上。官方给的命令是一键脚本:
curl -fsSL https://xerj.org/get | sh
我跑了。脚本本身能拉到,但它要从 github.com 下载 30.4MB 的 release 二进制。这一步挂了。30.4MB 这个数是我从 api.github.com 的 release 元数据读出来的,字段写的是 31914453 bytes。直连 github.com 下载,curl 报 curl: (16) Error in the HTTP2 framing layer。再试一次,报 curl: (28) Failed to connect to github.com port 443 after 75016ms。这个报错不是我猜的,是本机当场吐出来的原文。
我换了条路。改走 api.github.com 的 asset 端点。本机这次能连上,但被限速到约 1.3KB/s。实测 200 秒只下了 264KB。整个包要六个多小时。这个进度是本机拿 curl 的 -w 参数亲眼看到的,不是估算。装不动,我放弃了。回头把它文档里的真实请求逐条读了一遍。下面这些命令我没能亲手执行,但形参和返回结构都来自官方 capabilities 文档,不是我编的。这个跑不通,卡在下载,不是卡在引擎。
程序就几个操作符
它的程序语言很小。比较两个事实用 LOOKUP 两次再加一个 PICK_GT。计数用 SET 接 FIND、FILTER、AGG COUNT。一个真实请求长这样:
curl -s localhost:9200/_facts/hr/_ask -H 'content-type: application/json' -d '{"question": "谁更高,Ana 还是 Bo"}' | jq '{final_status, final_answer, program}'
官方文档里的返回是 final_status: "ANSWER",final_answer 给出结果。program 字段是这么一串:
[["LOOKUP", 0, null], ["LOOKUP", 1, null], ["PICK_GT", null, null], ["RETURN", null, null]]
四步:查第一个事实,查第二个,比大小,返回。关键是它内建了拒绝。查不到就回 UNKNOWN。两个事实打架就回 CONFLICT。这个机制 RAG 没有。RAG 只会硬着头皮写一个答案出来。
我数了数它省在哪。文档给的一个 handler_ms 是 36.5ms。那是在 2 个事实的命名空间上,x86 笔记本、4 个模型线程,十次热请求的中位数。同一套题 Opus 5.5 写 RAG 答案要 1.6 秒,检索本身不到 2ms。大头全花在写答案上。所以 Query-1 快,不是因为检索快,是因为它根本不写答案。
计数这条线要单独说。计数题走 SET 接 FIND、FILTER、AGG COUNT。它返回的不是被数的那几条记录,而是一个程序哈希。这是有意为之。官方文档说,一个「多少人」的问题,答案不该把 95 条记录全吐出来,只该给一个数。哈希能让这个数被复查,又不泄露原始记录。这个取舍在隐私和可审计之间,我觉得对。
它现在还不算数
有两件事它明确做不好,官方自己写出来了。一是求和,一道 sum 题可能被它答成成员个数。二是大事实集。官方文档里,一个 95000 条事实的命名空间,中位数 0.82 秒,20 道测试题全部被拒绝。它比 LLM 更爱说「我不知道」。这是故意的。
我的判断是:别拿它做聚合统计,那是 SQL 的活。它适合查一个确定的事实、比较两个数、数一数满足条件的记录,而且要能接受「答不了」三个字。模型默认是关的。不带 --facts-model-dir 启动,/_facts 路由直接回 404。rc.101 还会在第一次写入时把数据目录升到 format 4。rc.100 就打不开了。升级前得先想好要不要动数据目录。
所以它值不值得上,我说个分界。数据是私有的、内部的、模型没背过的,它那套写程序查事实能省 token 又能追证据,值得试。你就想在公开网页上做问答,RAG 够用了。别为了追新上一个要单独维护模型的组件。它的模型随二进制打包,训练数据还没公开,出问题你只能信它家那份 benchmark。