知识图谱基础概念与架构

说实话,很多人一听到“知识图谱”就觉得是高大上的黑科技。我刚开始入行时也这么想,直到亲手搭了一套药物知识图谱,才发现它本质上就是个组织信息的工具。只不过这个工具比较聪明——它能理解实体之间的关系。

你能想象吗?传统的数据库里,“布洛芬”和“退烧”可能是两条毫无关联的记录。但在知识图谱里,它们之间有一条明确的线:“布洛芬 ➝ 用于治疗 ➝ 退烧”。这就是质的区别。

为什么药物行业需要知识图谱?

我遇到过不少药企的朋友,他们拿着堆成山的Excel、PDF文档,里面全是药品信息、临床试验数据、不良反应报告。数据在那,但查起来费劲——你想知道“阿司匹林和哪些药冲突”,得翻半天文档。

知识图谱把这一切串联起来。

  • 打通信息孤岛:化学结构、适应症、副作用、用药禁忌……原本分散在不同部门的数据,现在可以在图谱里自由穿行
  • 支持智能推理:比如A药含有成分B,B与C有相互作用,图谱能自动推演出A和C不能同服,这些在传统数据库里需要写复杂的JOIN
  • 质控可追溯:每个节点、每条关系都有源头,哪条数据出问题了,能一路追查到原始文献

核心概念:实体、关系、属性

知识图谱的基础其实特别简单,就三样东西:实体、关系、属性。说白了,就是“什么”和“什么”之间“有什么关系”。

概念 类比数据库 药物例子
实体 / 节点 表中的一行记录 “布洛芬”、“发热”、“默克公司”
关系 / 边 外键 + 业务含义 “布洛芬” ➝ 用于治疗 ➝ “发热”
属性 列字段值 “布洛芬”的分子量 = 206.28

你可以把实体想象成城市地图上的地标,关系就是连接它们的道路。属性则是每个地标的详细信息:这家医院的床位数量、那家药企的成立年份。

三元组:图谱的最小存储单元

知识图谱里,每条知识都被拆成一个三元组:(头实体, 关系, 尾实体)。这玩意儿太重要了,我写质控脚本时,80%的工作就是在折腾三元组。

# 三个真实药物三元组示例:
(阿司匹林, 治疗, 头痛)
(阿司匹林, 包含成分, 乙酰水杨酸)
(乙酰水杨酸, 禁忌合并, 华法林)

为什么会这样设计?你想想看,当所有知识都统一成三元组后,无论多复杂的查询,都变成了在图里找路径。系统不需要理解“禁忌合并”这个词到底什么意思,它只负责找到这条边,然后顺着走。

Schema:给图谱定规矩

光有数据不行,你总得告诉系统:药物的关系只能是“治疗”、“副作用”、“禁忌”这几种,不能乱写“药物爱生病”吧?

Schema就是干这个的——它定义了哪些实体类型允许存在,哪些关系类型可以使用。

# 知识图谱模式(schema)示例
实体类型: Drug, Disease, Symptom, Company, Ingredient
关系类型:
  - (Drug) --[treats]--> (Disease)
  - (Drug) --[has_ingredient]--> (Ingredient)
  - (Drug) --[side_effect]--> (Symptom)
  - (Drug) --[contraindicated_with]--> (Drug)
  - (Drug) --[manufactured_by]--> (Company)

我曾经接手过一个图谱项目,之前的团队没定好Schema,结果“布洛芬”这个节点既当药品又当公司名,查出来的数据乱七八糟。从那以后,我每次做质控,第一件事就是拉Schema出来核对。

主流知识图谱架构

实际项目中,架构通常分四层。我画了一张图帮你看明白:

知识图谱技术架构(四层模型) 数据源层 结构化数据 · 半结构化数据 · 纯文本 · 接口日志 数据获取与预处理 实体识别 · 关系抽取 · 实体对齐 · 命名统一 知识融合与更新 实体合并 · 冲突消解 · 版本管理 · 增量更新 存储与查询 图数据库 · SPARQL/Cypher 查询 · 推理支持 应用层:智能问答 · 决策支持 · 药物发现 质量控制重点 • 数据源可信度检查 • 实体命名唯一性 • Schema 一致性

关键技术栈

我平时做药物知识图谱,技术栈大致长这样。给大家列个清单参考:

分层 常用工具 我的推荐理由
数据获取 Scrapy, SpaCy, BERT SpaCy的中文NER模型对药物名识别效果不错
存储 Neo4j, ArangoDB, RDF4J Neo4j社区活跃,文档齐全,适合快速验证
查询 Cypher, SPARQL Cypher上手快,SPARQL适合标准RDF
推理 Apache Jena, OWL API Jena的推理器比较稳,大项目我选它
质控 自定义pipeline + 规则引擎 这部分我们后面会重点讲

一个真实的Cypher查询示例

假设你现在要查“哪些药物和布洛芬有相互作用”,在传统数据库里你要写三四个表连接。但在图数据库里很简单:

// 查找与布洛芬有相互作用的所有药物
MATCH (d:Drug {name: '布洛芬'})-[r:interacts_with]-(other:Drug)
RETURN other.name AS 药物名称,
       r.detail AS 相互作用详情,
       r.severity AS 严重程度
ORDER BY r.severity ASC

这段代码跑的很快。我见过最复杂的一个查询,跨了八个实体类型、十二条关系,Cypher写了二十几行,但执行时间还不到一秒。这就是图谱的威力——数据之间有路,不需要全表扫描。

Schema设计和质控的关系

嗯,这里要注意。很多人以为质控是数据落库之后才做的事,大错特错。质控从Schema设计就开始了。

我举个真实的坑。某个项目里,Schema给“药物”定义了“副作用”关系,但没规定目标实体类型。结果有人把“发热”写成了症状节点,有人写成了疾病节点,还有人写成了一串字符串字段。批次质控的时候气死我了,花了三天才把这些问题归拢好。

我个人习惯:设计Schema时,每个关系都明确标注目标实体类型,并且写好校验逻辑。比如 (Drug)-[side_effect]->(Symptom),就不允许指向 Disease 类型。

什么是好的知识图谱?

总结几个评判标准,都是我多年踩坑总结出来的:

  1. Schema整洁:实体类型不宜超过20种,关系类型不宜超过50种
  2. 实体唯一:同一个药物不能出现两个不同的节点,别名通过属性或关系处理
  3. 关系有源头:每条三元组都记录了来源文献或数据库ID,方便追溯
  4. 版本可追溯:每次更新都有记录,能回滚到任意历史版本

心里有了这些标准,你才敢说“我知道我手里的图谱是干净的”。我们后续所有的批次质控流程,都是围绕着这些核心概念展开的。