附录 A · 方法与可复现性
核验方法、数据口径、局限
这本书里有三类可信度不同的句子,它们的可靠性差三个数量级:
- 「pyshacl 0.40.2 对 16 万三元组校验耗时 1.41 秒」——我在本机跑过。
- 「该仓库 2026-10-30 有 14342 星」——我查过 GitHub API。
- 「这条链理论上能接 Ontop」——我推出来的,没验证。
不加区分地混着写,是技术写作里最常见的失信方式。这一章交代每种说法背后的方法与边界,让读者能自己判断哪句话可以拿去做决策。
三级证据
| 级别 | 含义 | 本书中的写法 | 使用建议 |
|---|---|---|---|
| 实测 | 本机真跑,有命令与输出 | 「实测:」开头的段落,附环境与命令 | 可直接引用数字,但注意版本 |
| 核验 | 查过一手来源(API、仓库文件、原文) | 给字段、时间点、数值 | 引用时带上日期,星数会变 |
| 推断 | 逻辑外推,未验证 | 明确标「推断」「理论上」「未验证」 | 只能作为假设,不能作为依据 |
本书的比例大致是:实测约 5%,核验约 70%,推断约 25%。 这个比例本身值得说明——一个诚实的调研报告,推断一定占相当比例,因为把每个判断都验证一遍的成本远超一次调研的预算。问题不在于有推断,在于不标注。
仓库数据是怎么来的
时间点:2026-10-30 一次性快照。所有星数、建库时间、最后提交时间均为此日。
方法:对每个仓库逐个调用 GitHub REST API 的 /repos/{owner}/{repo},取以下字段:
stargazers_count created_at pushed_at
license.spdx_id language archived size
为什么逐仓库调而不是用搜索:搜索接口的星数是近似值且会滞后,逐仓库读单条记录能拿到精确字段,也能立刻发现 404。
核验结果:
- 原文列的 59 个仓库,58 个能原样找到。
- 星数差异全部在 ≤45 以内(快照时差导致,属正常)。
- 唯一一处硬错误:原文写作
RDFLib/OWL-RLL,该仓库不存在(404)。真名RDFLib/OWL-RL,181 星,2012-04-25 建库,Python,BSD-3。这条纠正已写进第 9 章。 - 另有一处可疑数据:某仓库的
pushed_at(2026-04-23)早于created_at(2026-04-24),且建库后零提交。这种「时间倒挂」是仓库被迁移或重建的痕迹,提示该项目的「活跃」是被制造出来的。
为什么值得花这个功夫:一篇索引文章里 59 个链接错 1 个,看起来是 98% 的正确率;但对读者来说,那 1 个错误会让全部 58 个都变得需要复核。索引类内容的价值全在准确率上。
活跃度的四档口径
「活跃」必须有定义,否则它只是感觉。本书用的口径:
| 档位 | 判据(距 2026-10-30) | 含义 |
|---|---|---|
| 🟢 活跃 | 最后提交 ≤ 90 天 | 有人在持续投入 |
| 🟡 放缓 | 90 天 – 1 年 | 维护模式,修 bug 不加功能 |
| 🔴 停滞 | 1 – 3 年 | 事实上不再演进,但可能仍可用 |
| ⚫ 死库 | > 3 年 | 不应作为新项目的依赖 |
这个口径不衡量质量。 一个「活跃」的仓库可能在堆功能,一个「停滞」的仓库可能已经完备(例如某些形式化的推理机,几年不改也不需要改)。正确的用法是:把活跃度当作「未来三年会不会有人回答你的 issue」的代理指标,而不是「好不好用」的指标。
原文的 59 个项目按此口径分布:活跃 45、放缓 5、停滞 5、死库 4。四个死库是:stardog-union/pellet(最后提交 2017-01-05)、audioset(2018)、kbpedia(2020)、Azure/opendigitaltwins-building(2024)。
还有一个值得记下的细节:第一类(企业本体平台)11 个项目里有 10 个建于 2026 年。这批项目全部处于「活跃」档——因为它们太新了,还没有机会变旧。用活跃度评价它们,等于用年龄评价婴儿的健康。
星数怎么用
星数是最容易被滥用的指标。四条规矩:
一、只看中位数与量级,不看单个数字。 78 个项目的中位数是 697.5;本体核心工具(rdflib 2542、Protégé 1617、Jena 1490、OWLAPI 944、pySHACL 364、OWL-RL 181)中位数 944。差 1.35 倍,属于同一量级——说明「本体工具」这个品类整体上没有被大规模采用。
二、不跨类比较。 分类中位数:GraphRAG 类 7897.5,企业平台 1045,Agent 记忆 880,词表 724.5,工具链 351,语义基础设施 301.5。用 GraphRAG 的星数去论证本体很热,是统计错误——它们服务的是不同的人群,热度来源也不同。
三、不把「结构索引」与「语义工具」并列。 星数最高的三个项目(139218 / 89016 / 75983)都是代码结构索引,与本体共享「图」这个词,不共享任何技术栈。第 9 章把这条单独拎出来,是因为它是最容易被误读的地方。
四、星数衡量注意力,不衡量质量。 Star 是「我以后可能要看」的收藏行为。一个 139218 星的项目可能只是一个好用的 CLI。
复核命令
所有仓库数据可以自己重跑。取出令牌后逐仓库查:
TOKEN=$(gh auth token)
for repo in RDFLib/rdflib apache/jena protegeproject/protege ; do
curl -s -H "Authorization: Bearer $TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$repo" \
| python3 -c '
import json,sys
d = json.load(sys.stdin)
if "stargazers_count" not in d:
print("NOT FOUND:", d.get("message")); raise SystemExit
lic = (d.get("license") or {}).get("spdx_id") or "NONE"
print("%-40s %6d* created=%s pushed=%s %-14s %s" % (
d["full_name"], d["stargazers_count"], d["created_at"][:10],
d["pushed_at"][:10], lic, d.get("language")))
'
done
注意两点:GitHub 未认证请求限速 60 次/小时,59 个仓库正好在边缘,必须带令牌;以及 license 字段可能为 null(无声明)或 NOASSERTION(有许可文件但无法识别为某个标准许可,常意味着多许可叠加,需要人读 LICENSE 文件)。
已知局限
诚实列出六条,任何引用本书数据的地方都应知道:
- 快照会过期。 2026-10-30 之后的所有数字都不再准确。星数、活跃度、许可变更都可能发生。
- 59 个仓库不等于全部。 这是原文的选目,不是系统性普查。遗漏的项目(尤其商业产品与非英语社区)不在统计内。
- **
language字段是主语言**,多语言项目会被归到单一一类。本次统计 Python 31、Java 12、TypeScript 8、Rust 6、Go 3,但实际技术栈远比这复杂。 - 许可字段需要人读。 12 个项目为
NOASSERTION,本书按「需法务审查」处理,没有逐个读 LICENSE 全文。 - README 自述不可全信,但不能不用。 本书区分了「原文/自述」与「实测/推断」——例如某项目的 README 自称「技术上已经是 Rust + Prolog」,实测仓库语言字段是 Prolog;某项目自述「很大程度上处于维护模式」,这条被当作一手声明采信,因为它对作者不利。
- 没有做功能 benchmark。 本书不比较「哪个推理机快」「哪个图库查询性能好」。这类结论需要统一的测试集与硬件环境,一次调研做不到,勉强做出来的数字比没有更危险。
本书不做什么
划清边界比声明范围更重要:
- 不做选型推荐。 分级(S/A/B/C)是「成熟度粗分」,不是「你该用哪个」。
- 不覆盖商业产品。 78 个全部是开源项目。商业平台(Stardog、Ontotext、Neo4j 等)在正文中被提及,但不在统计口径内。
- 不做学术综述。 引用文献是为解释概念,不是穷尽领域。
- 不预测市场。 第 9 章判定的是「原文的说法有多少证据支撑」,不是「这个方向会不会成功」。
- 不提供行业模板。 每个行业的模型都涉及具体监管与口径,通用模板的价值接近于零。
怎么更新
建议每季度重跑一次:
- 重跑上面的
curl循环,更新data/meta.json。 - 检查新增项目(尤其「企业平台」这一类,变动最快)。
- 重跑第 11 章的校验与规模实验(工具版本会变,
pyshacl的inference参数就曾变过合法值)。 - 更新第 9 章的八条判定——其中「证据不足」的两条最值得复查,因为它们的结论依赖「时间还不够」。
本版对应 2026-10-31 的状态。若发现数据错误,优先怀疑星数与活跃度(它们会变),其次怀疑许可(会变更),最不该怀疑的是实测数字(除非工具版本变了)。