
简介一份拥有1.4亿中文实体与上亿条三元组的知识图谱开源数据包面向 NLP 研究者、知识图谱开发者和有一定编程基础的学习者旨在解决中文领域大规模结构化知识数据稀缺的问题可服务于智能问答、推荐系统、语义检索与搜索引擎优化等场景。压缩包约 819KB内含 4 个文件2 张 PNG 图片直观展示知识图谱的实体、关系与属性结构帮助快速建立可视化认知1 个 Python 脚本提供数据加载或查询处理的参考实现1 份 Markdown 文档说明数据集格式、字段含义与使用方式。该数据集已有 1726 人学习下载。借助脚本与图示读者可在低门槛下理解三元组主体-谓词-客体的组织逻辑并基于 ownthink 数据进一步构建知识补全、智能助手或语义分析应用无论是论文实验、课程设计还是产品原型验证都能从中获得扎实的数据支撑与实现参考。 在NLP和知识工程这个圈子里只要是碰过中文开放域知识图谱的人应该都绕不开这个项目KnowledgeGraphData。这个常被简称为“ownthink知识图谱”的开源数据集当年一放出来就引起不小震动官方口径是实体数量达到1.4亿、关系三元组2.2亿、概念类型46万左右至今仍是中文开放域知识图谱里规模最大的一档。对做KBQA、实体链接、知识增强RAG或者只是想在毕设里搞一个可视化Demo的同学来说这份数据几乎是绕不开的原材料。这篇内容我不会去念README而是直接按我实际下载、解压、解析、建图、踩坑的完整过程来写把每个环节容易翻车的地方都讲清楚。如果你正准备拿这份数据做实验手边最好备好一块500GB以上的硬盘和一颗“遇事不决先看格式”的耐心因为接下来的每一步都会教你重新认识“大数据”三个字。1. 这个项目到底是个什么来头1.4亿实体是怎么攒出来的1.1 先看懂这套数据的真实规模很多第一次接触的人会问1.4亿是啥是实体、三元组还是文件字节数这里需要先把口径理清楚。项目作者在发布时给出的数字是实体约1.4亿关系三元组约2.2亿实体类别/关系类型约46万。后面这个数字在各类转载里被写得比较乱所以你如果看到“2.2亿中文知识图谱”的说法通常指的就是关系三元组的数量而标题里的“1.4亿”更接近实体数。规模到底什么概念对比一下常见的开源中文知识图谱CN-DBpedia开放的核心数据在900万实体左右北大开源的PKUBASE约1100万实体复旦的CN-Probase概念图谱约1700万概念。这三者加起来都不到KnowledgeGraphData的一半。它有这个体量核心原因是数据来源覆盖了大规模中文百科类词条并且做了比较粗放的自动化抽取词条标题作为主体词条正文首段、信息框字段、分类结构统统被洗成“实体-关系-实体”的三元组。好处是覆盖极广几乎所有你见过的中文实体都能在里面找到代价是噪声不小这一点后面会专门讲。所以它最大的价值不是“精确”而是“广”。开放域问答里那种“任天堂是哪年成立的”“三体作者还写过什么书”这类问题靠领域知识图谱根本查不到但在这份数据里命中概率非常高。做实体链接、关系抽取、知识图谱问答、检索增强生成这类任务它都是很理想的基础语料。1.2 数据文件和三元组格式先搞懂再动手下载解压之后你会看到这样一组核心文件entity2id.txt实体ID映射表每一行是一个实体ID和它对应的实体名规模上亿级别指望用Excel打开。relation2id.txt关系ID映射表每一行是一个关系ID和对应的关系名几十万行起步。train.txt训练集三元组通常是体量最大的文件可能占到几十GB解压后空间。valid.txt验证集三元组。test.txt测试集三元组。三元组文件每一行是三个ID标准做法是“头实体ID、关系ID、尾实体ID”。但这里我必须认真提醒一句不同分发的版本、不同转载渠道给出的文件列顺序并不完全统一。我见过有人下载的版本是“头实体、尾实体、关系”也见过把实体ID直接写成实体名的版本。所以开工第一件事不是写解析代码而是先看文件头。这是我最推荐的第一步操作head -n 3 entity2id.txt head -n 3 relation2id.txt head -n 3 train.txt wc -l train.txt du -sh train.txt先弄清楚ID表里到底是“ID在前名字在后”还是反过来三元组三个数字哪个是头、哪个是关系。这一步决定了后面所有代码的正确性省下来的时间够你喝两杯咖啡。另外注意因为数据量太大很多官方下载包里的ID并不是连续数字而是字符串形式的哈希或编号所以写代码时不要默认ID等于行号。2. 下载与解压避坑指南2.1 去哪下载、怎么判断文件完整项目源码托管在GitHub上仓库名就是KnowledgeGraphDataReadme里会给出网盘下载地址。因为数据文件体积太大Git仓库本身只放说明和样例真正的大文件全靠外部网盘分发。这类网盘链接最大的问题就是——会失效。你照着别人三年前的文章点进去大概率遇见“文件已删除”。我的建议是不要信二手转载的链接直接去GitHub仓库的Issues页面搜“链接”“失效”“下载”这些关键词作者和网友通常会持续更新有效地址。另外下载之前先看Readme里的文件大小说明和下载完之后的实际大小做个比对。网盘下载大文件容易出错如果压缩包校验信息不完整最简单的办法就是压解压时注意是否报错。CRC错误、压缩包意外结束这类提示一旦出现基本就可以删掉重下了强行解压出来的数据缺行少列后面会让你排查到怀疑人生。2.2 解压和预处理第一课是给机器留够空间数据包通常是按压缩包形式分发解压之后体积会膨胀3到5倍。以我自己的经验光train.txt解压出来就可能达到几十GB。所以解压前先看一眼磁盘剩余空间别解到一半提示“No space left on device”然后发现系统直接给你生成一个半截文件。Linux下直接这样解unzip KnowledgeGraphData.zip # 或者 tar -xzf KnowledgeGraphData.tar.gz解压完成后用du -sh看看每份文件的实际大小做到心里有数。对于几十GB的train.txt任何文本编辑器都别想打开也别用pandas直接read_csv——内存直接爆掉。正确姿势是先做一次“格式侦察”再考虑怎么处理也就是我之前说的先head、再wc。如果后续要用到部分数据做实验我建议先拆分head -n 1000000 train.txt train_1m.txt一百万条三元组做格式验证和小规模测试完全够用等流程跑通了再换全量数据。这一步看似不起眼但能帮你把调试周期从“天”缩短到“分钟”。3. 实战把ID三元组变成能用的中文知识库3.1 从三元组到实体名第一行代码先跑通无论你准备做什么第一步几乎都是把ID映射回中文实体名否则对着“E128391”“R982”这样的编号你什么都做不了。如果你的entity2id.txt确实包含两列可以先用Python读成映射字典def load_id_name(path): id2name {} with open(path, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue parts line.split(\t) if len(parts) 2: continue # 假设第一列是ID第二列是名称 eid, name parts[0], parts[1] id2name[eid] name return id2name然后随便从train.txt里取三行三元组打印出来看看真实内容eid2name load_id_name(entity2id.txt) rid2name load_id_name(relation2id.txt) with open(train.txt, r, encodingutf-8) as f: for i, line in enumerate(f): if i 5: break parts line.strip().split(\t) if len(parts) ! 3: continue # 标准是 头实体ID、关系ID、尾实体ID h, r, t parts print(eid2name.get(h, h), rid2name.get(r, r), eid2name.get(t, t))如果打印出来的是“刘慈欣 作品 三体”这种结果说明列顺序正确。如果发现实体名出现在关系位或者出现某个实体映射不到名字那就要回头检查列顺序和编码。很多网上教程在这里含糊带过实际操作时踩坑的人一抓一大把所以千万别跳过这一步。3.2 小规模可视化Python和Vue3两条路线数据解析通了很多人第一个想做的就是可视化。毕竟“知识图谱可视化”这个关键词的搜索热度一直很高尤其是配合Vue3做前端展示已经是不少课程设计和大屏项目的标配。这里我给出两条可落地的路线。路线一快速出图用Python的pyvis适合本地验证from pyvis.network import Network net Network(height600px, width100%, bgcolor#ffffff, font_color#333333) # 以“三体”为中心抽一跳邻居 center 三体 net.add_node(center, labelcenter) with open(train.txt, r, encodingutf-8) as f: for line in f: # 假设三元组格式为 h\tr\tt且文件使用ID parts line.strip().split(\t) if len(parts) ! 3: continue h, r, t parts # 这里直接换成了名字实际要写成 eid2name.get(...) if h center: net.add_node(t, labelt) net.add_edge(h, t, labelr) if t center: net.add_node(h, labelh) net.add_edge(h, t, labelr) net.show(knowledge_graph.html)这段代码只演示思路实际使用时要把ID映射、去重、限制邻居数量都补上否则图会密到没法看。路线二Web展示用Vue3加ECharts的graph类型。做法是在后端或者预处理脚本里查询某个实体的一跳邻居输出成JSON前端用ECharts的force布局直接渲染。核心配置大概是const option { tooltip: {}, series: [{ type: graph, layout: force, roam: true, data: nodes.map(n ({ id: n.id, name: n.name })), links: edges.map(e ({ source: e.source, target: e.target, label: { show: true, formatter: e.relation } })), force: { repulsion: 300 } }] }这类页面的好处是交互性好、拖拽缩放都自带看上去很“产品级”实际代码量并不大。如果你只是要一个大屏装饰或者课程汇报这条路线性价比很高把节点数据换成后端接口就行。3.3 全量导入Neo4j想清楚再动手总有人一上来就想把2.2亿三元组全部灌进Neo4j我劝你三思。Neo4j不是不能处理这个量级是要付出不小的硬件和调优成本。如果你确实想体验一把全量图数据库查询建议按下面思路走。先把ID三元组转换成CSV实体文件和关系文件分开。关系CSV示例长这样start_id,end_id,relation E128391,E998211,作品然后用neo4j-admin import做离线导入neo4j-admin import \ --databasekg.db \ --nodesentity.csv \ --relationshipsrel.csv \ --delimiter, \ --skip-bad-relationshipstrue注意neo4j-admin import要求图数据库为空库而且csv文件格式要符合它的表头约定比如节点要带:ID、关系要带:START_ID和:END_ID否则报错能报到你怀疑人生。我的建议是先抽一个子图比如某个实体5000条邻居验证流程跑通了再决定要不要上全量。说实话在我自己实操过的场景里大部分任务用Python加NetworkX、或者直接用Neo4j的LOAD CSV流式导入就已经够了全量导入更像是一种“仪式感”。4. 基于这套数据能做的四类方向4.1 开放域问答与实体链接这是KnowledgeGraphData最经典的应用方向。传统KBQA的链路是问句先做实体识别把问题中的实体链接到知识库节点再在子图里查询关系路径。有了1.4亿实体的覆盖量开放域问答的召回率会明显提高不太容易出现“用户问的实体库里根本没有”这种尴尬。简单实现时实体链接可以先不做复杂的深度模型用候选实体名匹配就能跑通大半把用户问题分词然后在实体名映射表里做倒排索引命中的实体作为候选再根据上下文选择最可能的那个。这套baseline虽然糙但在很多垂直问题上效果已经够看。4.2 知识增强检索与大模型结合这两年大模型火起来之后知识图谱被越来越多地用在RAG检索增强生成场景里。相比纯文本切片的向量检索知识图谱能给到更结构化的上下文用户问“《流浪地球》的导演还拍过什么”传统RAG可能要去文档里翻半天图谱检索直接一跳就出答案。实操思路是先用实体链接定位问题里的核心实体然后在图谱里取该实体的两跳子图把三元组拼成自然语言文本作为上下文送给大模型。这个方案不要求大模型额外训练只需要prompt里把背景信息写清楚。1.4亿实体的体量保证了它面对开放域问题时很少会“无据可查”这在很多真实业务里是很值钱的能力。4.3 链接预测与图表示学习研究学术向的同学拿它做链接预测也很合适。经典的TransE、RotatE、GNN-based方法都需要大规模三元组语料这份数据天然就是训练集。但你要注意全量2.2亿三元组训练TransE单卡GPU可能要跑数天做实验之前一定先降采样。有一个常见做法先在领域子图比如影视、体育、医学上训练小模型验证pipeline正确再扩到更大范围。另外这份数据的关系类别数量很大很多低频关系本身噪声高学术实验时建议设定一个最小支持度阈值把出现次数少于50次的关系过滤掉效果往往反而更好。4.4 数据清洗与知识融合研究很多人忽略的一点是像这样大规模自动抽取的知识图谱本身就是研究知识融合、冲突检测的绝佳素材。同一实体在来源不同的词条里可能存在同名不同义、同义不同名的问题同一关系在不同上下文里也可能出现类型冲突。如何处理这些噪声本身就是不错的学术课题而且比“调参跑模型”更有实际意义。5. 常见问题与排查技巧实录5.1 ID映射对不上、乱码怎么办如果你发现打印出来的实体名全是乱码或者所有实体都映射不到名字优先检查两件事一是文件编码Windows下用记事本另存过的文件可能是GBKLinux下要指定UTF-8读取二是分隔符有的版本用\t有的用空格甚至逗号肉眼看起来都是空白但split的时候结果完全不同。我的习惯是先给ID映射表做一个随机抽检import random sample random.sample(eid2name.keys(), 10) for s in sample: print(s, eid2name[s])抽检结果正常再排查三元组文件的列顺序。5.2 文件过大、内存不足怎么办几十GB的train.txt任何一次全量read都是灾难。建议处理时坚持两个原则能用命令行就绝不用Python、能流式就绝不一次性load。统计行数用wc -l抽取用head、tail、shuf切分用split。Python里也坚持for line in f逐行读而不是f.readlines()。如果需要按ID筛选子图可以在内存里只维护一个小字典或者布隆过滤器边读边过滤。5.3 数据噪声和质量问题1.4亿实体看起来很爽但实际的自动抽取结果里噪声是肉眼可见的。实体名可能包含括号注释、空格、标点符号关系名可能不规范三元组重复量也很大。做实验前我建议至少清洗下面三层去掉训练集里完全重复的三元组。过滤实体名过短或含明显噪声字符的条目。过滤关系出现次数过少的低频关系。问题可能原因排查思路三元组读取数量对不上列分隔符不是\t用head查看原始字节改用空格split实体名全是乱码编码不是UTF-8Linux下用file命令确认重新转码同一实体多条名称映射到不同ID抽取时实体别名被独立编号做实体对齐或优先保留出现频次最高的ID图可视化节点太多卡死2.2亿全量无法前端渲染只取一跳子图限制最多50个节点最后再分享一个很个人的习惯拿到任何来源不明的数据集我都会先把Readme里描述的格式和自己实际head出来的前几行放在一起对照哪怕README再旧、再模糊也花不了三分钟。这份号称史上最大规模的中文知识图谱数据本身是很值得好好利用的只要在开头把格式和清洗问题处理干净后面能做的事比我上面写的还要多得多。本文还有配套的精品资源点击获取