念念不忘
回看 2013 年自己发的一些微博,当年的很多看法,现在看来都是错误的。十年后的 2023 年,百科项目又成为我不堪重负、最终离职的直接原因。照理说,这件事应该就此放下了,可我还是念念不忘。
所以后来又做了是语人物志。某种意义上,它只是一个纪念:我想用一个尽可能小的集合,再把结构化实体库做一遍。
这里的“小”,不是说只做几个人、几条数据,而是把边界收紧。以前做百科,总想把世间万物都装进去;人物、地点、作品、组织、物种、天体,似乎只要能够定义,就应该成为一种实体。可一旦真正开始建设,就会发现定义一个类型很容易,持续获得可靠的数据却很难。类型越多,数据源越杂,最后越难说清楚库里究竟有什么、为什么收录、又凭什么相信。
推倒重来
IsEntity 前后已经做了四个版本。
v0 从 Wikidata 出发,设计了 72 类实体,最后导入了几十万条数据。它看起来很大,但问题也很明显:广而浅,很多实体只有名字和少量属性;数据虽然来自 Wikidata,却缺少我真正想要的结构、出处和约束。
v1 换了一条完全不同的路线,直接从《史记》原文中抽取人物、关系和语句。这个版本做完了《史记》全 130 篇,证明从史书原文建立人物知识库是可行的。但原文抽取很难自然扩展成一套足够宽的百科,做一本史书可以,继续做完二十四史,需要的是另一种组织方式。
v2 又把范围扩展到 60 个类型,希望通过 Schema、名单和多个权威库,建立一个更完整的历史实体库。结果是,大多数类型都没有足够可靠的权威数据源,只能不断从 Wikidata 捞候选,再靠规则和人工清理。库越来越大,质量问题却怎么也擦不完。
于是到了 v3,我又把它缩了回来。现在的核心只围绕人物、地区、国号和年号展开。人物以 CBDB 和二十四史传主为主要收录依据,地区和国号是人物活动的舞台;所有实体都能够对应到 Wikidata,每条结构化语句也必须能够映射到 Wikidata 属性。不是因为 Wikidata 没有问题,而是必须给数据划出一条明确、可检查、可以重建的边界。
经过几次推倒重来,我越来越觉得,做知识库最困难的并不是抓到多少数据,而是决定什么不做。
现在的“人物志”
现在的是语人物志有约 12 万个实体,其中人物接近 11.6 万。它不再试图成为包罗万象的百科,而是围绕二十四史组织内容:从史书目录进入本纪、世家和列传,再从传主进入人物卡片。人物的姓名、字号、生卒、籍贯、亲属、功名、职业和所属朝代,被整理成结构化信息;需要继续阅读时,还可以进入对应的百科正文。
Android 版本把整个库放进了安装包,不需要网络,也不申请额外权限。它主要有三种使用方式:上下滑动认识不同人物,左右翻阅人物正文,或者直接搜索全库。卡片里出现的人名、地区、国号和职业,也可以继续在库内跳转。
我想做的不是一个缩小版的网页百科,而是一种适合随手翻阅的人物志。它不要求先知道自己要找谁,也不只是给出一个搜索框。打开它,可以随机遇到一个人,读完一页,再沿着时代、地域和人物关系继续走下去。
Schema
这个项目一直坚持 Schema:先定义实体是什么、允许有哪些属性、每个属性的值应该是什么类型,再开始填数据。现在的建库流程可以概括为四步:
Schema → List → Map → EntityDB
Schema 规定结构;List 决定谁可以进入;Map 负责把权威库中的对象对齐到 Wikidata;最后再把通过约束的数据物化成 EntityDB。CBDB、CHGIS、二十四史目录等资料主要用来决定“收谁”和“属于什么类型”,结构化属性则来自 Wikidata。这样做不一定能得到最多的数据,但每一步都可以解释,也可以从头重放。
大语言模型出现以后,做结构化知识库似乎更显得不合时宜。很多问题直接问模型就能得到答案,未必还需要先设计 Schema,再做名单、映射和数据校验。但模型给出的回答和一座边界明确的知识库,终究不是一回事。至少在这里,我知道每个人为什么被收录,每条属性从哪里来,哪些东西尚未解决。
这个项目可能还是会继续推倒重来。它也未必能弥补 2023 年留下的什么,只是有些事情,做过一次没有放下,就还是想再做一次。
项目地址:Ismantic/IsEntity