本体注册表(Ontology Registry)实战指南:从 CURIE 前缀、分支根到重叠本体的选型决策
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
导读
在科学元数据工程中,"哪个本体拥有哪类术语"是一张必须随身携带的地图:UBERON管解剖、CL管细胞类型、MONDO管疾病、HP管表型……而这张地图上还有大量容易踩坑的例外(HP在本体服务里叫hp、Orphanet被服务为ordo、Cellosaurus 根本不在 OLS 中)。本文基于scientific-agent-skills仓库中 ontology-term-resolution 技能的 ontology-registry.md 展开,完整整理前缀到 OLS 本体 ID 的映射、--branch分支根的权威清单、重叠本体的选型判断,以及常见元数据字段应使用的本体,并结合仓库中的 resolve_terms.py、validate_terms.py 和 ols_client.py 源码说明这些映射如何真正作用于文本解析与 ID 校验。读完本文,你可以为 GEO、ENA、BioSamples、CELLxGENE、HCA、ISA-Tab 等提交场景正确选择本体并完成约束校验。
一、为什么需要一张"本体注册表"
本体标识符(CURIE,形如PREFIX:local)在形式上高度相似、在细节上却完全随意。一个看起来合理的UBERON:0002108是真实术语"小肠"(small intestine),而不是肝脏——下游流程无法发现这种替换,因为 ID 格式正确、本体也对,元数据却静默出错。因此仓库技能定下的铁律是:
绝不凭记忆写本体 ID,也绝不未经检查就接受任何 ID。
这条规则的具体落地方式是两张表:前缀 → OLS 本体 ID 映射(回答"去哪个服务查")和分支根(branch root)清单(回答"查回来的术语是不是正确的'那种东西'")。前者决定了查询请求发往哪个 OLS 本体文档,后者决定了--branch约束检查的锚点。两者的权威版本都记录在 ontology-registry.md 中,以下两张表的所有 ID 均已于 2026 年 7 月对 OLS 实测验证。
二、前缀(CURIE Prefix)到 OLS 本体 ID 的映射
OLS(EBI Ontology Lookup Service,基础地址https://www.ebi.ac.uk/ols4/api)的本体 ID 几乎总是 CURIE 前缀的小写形式,但存在明确例外。下表是完整映射,第三列标注了每个本体覆盖的概念范围:
| CURIE 前缀 | OLS id | 覆盖范围 |
|---|---|---|
UBERON | uberon | 解剖结构、组织、器官、体液(跨物种) |
CL | cl | 细胞类型 |
CLO | clo | 细胞系 |
MONDO | mondo | 疾病(合并后的疾病本体;优先于 DOID/NCIT 使用) |
DOID | doid | 人类疾病本体(大部分已被 MONDO 吸收) |
HP | hp | 人类表型异常——OLS id 是hp,不是hpo |
EFO | efo | 实验因素、检测方法、平台、细胞系 |
CHEBI | chebi | 化学实体、药物、代谢物 |
NCBITaxon | ncbitaxon | 生物体 |
GO | go | 生物过程、分子功能、细胞组分 |
OBI | obi | 检测方法、设备、实验方案、研究设计 |
PATO | pato | 质量属性——性别、颜色、量级、normal |
SO | so | 序列特征 |
HsapDv | hsapdv | 人类发育阶段 |
MmusDv | mmusdv | 小鼠发育阶段 |
ENVO | envo | 环境材料与生物群系 |
FOODON | foodon | 食品 |
NCIT | ncit | NCI 词表(临床/肿瘤学广度) |
MS | ms | 质谱仪器与方法 |
BAO | bao | 生物检测(BioAssay)描述 |
Orphanet | ordo | 罕见病——OLS id 是ordo,CURIE 中的前缀是Orphanet,且 OLS 报告的preferredPrefix是ORDO |
2.1 源码中的映射落地
这张表不是纸面文档,而是直接编码在 ols_client.py 中:
curie_to_ontology_id()默认取前缀小写,唯一例外来自ONTOLOGY_ID_OVERRIDES字典("orphanet": "ordo"),这正好对应表中Orphanet→ordo的特殊映射;- 测试 test_scripts.py 中的
CurieHelperTests验证了HP:0001250 → hp、NCBITaxon:9606 → ncbitaxon、HsapDv:0000001 → hsapdv等小写化规则,并用Orphanet:558 → ordo单独验证覆盖例外; - 一个实用的技巧是:当你在查询中需要把一个 CURIE 前缀翻译成 OLS 本体 ID 时,直接调用
curie_to_ontology_id()即可,它会自动处理小写化与Orphanet例外。
2.2 不在 OLS 中的词汇表
特别注意:Cellosaurus 完全不在 OLS 中。细胞系身份及其污染状态(RRID 形如CVCL_*)需要查询https://api.cellosaurus.org。厂商和仪器专用词汇表通常也不在 OLS 中。这意味着遇到CVCL_*之类的 ID 时,validate_terms.py不会给出有意义的结果,需要走独立的 Cellosaurus 通道。
三、分支根(Branch Roots):--branch约束检查的权威锚点
本体层级庞大,仅凭前缀无法确认一个术语是"对的种类"。例如疾病、表型、化合物都有自己的层级;--branch参数传入一个根 CURIE,断言目标术语必须是该根的子孙(descendant)。下表是完整的分支根清单:
| 根 | 标签 | 用途 |
|---|---|---|
UBERON:0001062 | anatomical entity | 任何解剖结构 |
UBERON:0000465 | material anatomical entity | 组织与器官 |
CL:0000000 | cell | 细胞类型 |
MONDO:0700096 | human disease | 人类疾病字段 |
HP:0000118 | Phenotypic abnormality | 表型字段 |
CHEBI:24431 | chemical entity | 化合物 |
NCBITaxon:1 | root | 生物体 |
OBI:0000070 | assay | 检测方法字段 |
PATO:0000001 | quality | 质量属性(含性别) |
GO:0008150 | biological_process | 仅 GO 生物过程 |
GO:0003674 | molecular_function | 仅 GO 分子功能 |
GO:0005575 | cellular_component | 仅 GO 细胞组分 |
EFO:0000001 | experimental factor | EFO 广度 |
SO:0000110 | sequence_feature | 序列特征 |
HsapDv:0000001 | life cycle | 人类发育阶段 |
MmusDv:0000001 | life cycle | 小鼠发育阶段 |
ENVO:00010483 | environmental material | 环境样本 |
CLO:0000031 | cell line | 细胞系 |
NCIT:C7057 | Disease, Disorder or Finding | NCIT 疾病子树 |
DOID:4 | disease | DOID 子树 |
3.1 分支根的实战用法
两个脚本都接受--branch:
# resolve_terms.py:把候选词限制为某个根的子孙 cd skills/ontology-term-resolution/scripts python3 resolve_terms.py "liver" --ontology uberon --branch UBERON:0000465 # validate_terms.py:断言每个 ID 都必须属于某个分支 python3 validate_terms.py --input tissue_ids.tsv \ --branch UBERON:0000465 --expect-ontology uberon在源码层面,resolve_terms.py会将--branch的 CURIE 通过iri_for()解析为 IRI,再传给 OLS/search的allChildrenOf参数(见 resolve_terms.py 的main());validate_terms.py则通过ancestor_curies()拉取术语的全部祖先集合,检查分支根是否在其中(见 validate_terms.py 的check_term())。ols_client.py中的ancestor_curies()使用 term-detail 返回的_links.hierarchicalAncestors.href分页拉取(?size=500并跟随_links.next)。
3.2 关于MONDO:0000001与MONDO:0700096的选择
MONDO:0000001可以解析(标签为disease),但它只能通过 ols4-api.md 中描述的IRI 回退机制解析成功——OLS 的obo_id索引存在空洞,这个活体术语从未被obo_id索引。因此首选MONDO:0700096作为人类疾病根。ols_client.py的term_detail()会自动执行这一回退,并把结果标记为_resolved_via: "iri"。
3.3 分支检查不能替代前缀检查(重要陷阱)
一个分支检查不能替代前缀检查。CARO 本体把cell放在anatomical structure之下,因此细胞类型能够通过解剖结构的分支测试(CL:0000182(肝细胞)在层级上确实属于UBERON:0000061的子孙)。所以细胞类型会被一个宽松的解剖分支检查放行。正确做法是同时约束两者:
python3 validate_terms.py --input tissue_ids.tsv \ --branch UBERON:0000465 --expect-ontology uberon--expect-ontology uberon负责卡住前缀/本体,--branch UBERON:0000465负责卡住分支,二者缺一不可。这正是 SKILL.md 中"API behaviour that will mislead you"一节反复强调的陷阱,测试 test_scripts.py 的test_wrong_ontology_is_caught也验证了CL:0000182(肝细胞)放入期望uberon的列时会被判定为wrong_ontology。
四、重叠本体的选型决策
同一概念往往被多个本体覆盖(MONDO 合并了 DOID、Orphanet、OMIM、NCIT 的疾病术语),注册表给出了明确的判断规则:
- 疾病:用 MONDO。它是 DOID、Orphanet、OMIM 和 NCIT 疾病术语的合并目标,并带有指向所有这些来源的交叉引用。只有当下游消费者明确要求 DOID 或 NCIT 命名空间时才使用它们。
- 疾病 vs 表型:诊断用 MONDO(如
asthma),观察到的异常用 HP(如Wheezing)。元数据字段通常只要两者之一,而不是两者都填。 - 组织 vs 细胞类型:样本的解剖来源用 UBERON,细胞本身是什么用 CL。
liver是 UBERON,hepatocyte是 CL——即使你在uberon限制下搜索hepatocyte会返回 CL 术语(作为被导入的副本)。 - 检测方法:EFO 优先,OBI 次之。基因组平台和文库构建策略在 EFO 中更丰富;OBI 更适合通用实验室检测类别。
- 化学物质:ChEBI用于任何有结构的物质。按商品名命名的药物产品属于药物词汇表(RxNorm、DrugBank),不属于 ChEBI。
- 性别:用 PATO(
PATO:0000384雄性、PATO:0000383雌性),不用 NCIT,也不用自由文本。 - "正常"/健康对照:
PATO:0000461(normal)是疾病字段无疾病时的惯用填充值,也是多个提交 schema 明确要求的取值。
4.1 源码如何佐证这些判断
resolve_terms.py的--ontology参数只接受OLS 本体 ID(如uberon、cl),而不是 CURIE 前缀——这就是为什么你必须查阅第二节的映射表,把UBERON写成uberon、把HP写成hp。同时,由于本体之间相互导入(trap 3:q=hepatocyte&ontology=uberon会返回CL:0000182且is_defining_ontology=false),ols_client.py中的dedupe_candidates()会按obo_id去重并保留is_defining_ontology: true的副本,rank_candidates()再按match_type(exact_label>exact_synonym>partial)排序。测试 test_scripts.py 的CandidateRankingTests对此有完整覆盖。
五、常见元数据字段与期望本体
不同存档的字段名各不相同,但每个概念背后的本体是稳定的。下表是概念层面的完整映射:
| 概念 | 本体 |
|---|---|
| 组织 / 器官 / 解剖部位 | UBERON |
| 细胞类型 | CL |
| 细胞系 | CLO;身份与污染状态用 Cellosaurus |
| 疾病 | MONDO(无疾病时用PATO:0000461) |
| 表型 | HP |
| 生物体 | NCBITaxon |
| 检测方法 / 平台 | EFO |
| 发育阶段 | HsapDv、MmusDv |
| 性别 | PATO |
| 化学物质 / 处理化合物 | ChEBI |
| 环境材料 | ENVO |
最重要的提醒:提交 schema(CELLxGENE、HCA、ENA/BioSamples checklists、ISA-Tab 配置)同时固定了字段名和允许的本体,并且会修订。必须阅读提交目标所对应的 schema 版本,而不是依赖上表或记忆——上表中的本体选择是稳定部分,字段名则不是。
5.1 把概念映射落进 CI 校验
理解概念 → 本体的对应关系后,可以把它变成一条条机器可执行的约束。例如把validate_terms.py用作元数据文件的 CI 门禁:
# 1) 每个 ID 都存在 python3 validate_terms.py --input metadata.tsv # 2) 无过时 ID(obsolete 术语大多带 term_replaced_by) # 3) 标签与 ID 一致(提供 label 列即可捕获复制粘贴漂移与幻觉 ID) python3 validate_terms.py --input metadata.tsv --strict # 4) 每列本体正确 python3 validate_terms.py --input metadata.tsv --expect-ontology uberon # 5) 每列分支正确(记住:分支检查不能排除细胞类型混入解剖列) python3 validate_terms.py --input tissue_ids.tsv \ --branch UBERON:0000465 --expect-ontology uberon--strict把警告提升为失败(matched_synonym、imported_only、not_a_class三个警告态),是 CI 门禁的正确设置。完整的状态语义(ok、obsolete、not_found、label_mismatch、wrong_ontology、wrong_branch、malformed_curie等)参见 SKILL.md 的状态表;validate_terms.py 中的FAIL_STATUSES/WARN_STATUSES常量与退出码逻辑(失败返回 1,全过返回 0,用法/网络问题返回 2)则给出了可编程的判定依据。
六、实践要点回顾
- 先查注册表,再写 ID:前缀 → OLS 本体 ID 的映射是查询请求的"寻址"基础,
HP是hp、Orphanet是ordo、Cellosaurus 走独立 API——这些例外必须牢记。 - 双约束才是完整约束:
--branch(种类)+--expect-ontology(命名空间)必须同时使用,因为 CARO 的层级会让细胞类型通过解剖分支测试。 - 重叠本体按场景选:疾病用 MONDO、表型用 HP、组织用 UBERON、细胞类型用 CL、检测用 EFO/OBI、化合物用 ChEBI、性别用 PATO、
normal用PATO:0000461。 - 概念表稳定、字段名不稳定:提交任何归档前,以目标 schema 版本为准。
- 验证优先于记忆:所有 ID 交给 validate_terms.py,所有自由文本交给 resolve_terms.py,并仔细阅读输出的
match_type与status列;partial与unresolved都是合法输出,绝不要用最近似的命中去填充未解析的单元格。
想深入 API 层面的全部陷阱(exact=true是精确 token 匹配而非精确标签、/search永不返回过时状态、obo_id索引空洞、IRI 模板例外、OxO 已退役等),请阅读 ols4-api.md;候选挑选流程与文本归一化策略见 curation-rules.md。
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考