本体论术语策展规则实战:从候选选择到元数据表审计的完整决策流程(scientific-agent-skills 深度解析)
2026/9/12 2:00:42 网站建设 项目流程

本体论术语策展规则实战:从候选选择到元数据表审计的完整决策流程(scientific-agent-skills 深度解析)

【免费下载链接】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

导读

scientific-agent-skills仓库的ontology-term-resolution技能中,策展规则(Curation Rules)是连接"机器搜索"与"人类判断"的关键一环:OLS 检索工具能把自由文本映射为候选本体术语(CURIE),但是否接受一个候选、何时判定"无此术语"、如何审计一张已有元数据表,则是一套有纪律的决策流程。本文基于 skills/ontology-term-resolution/references/curation-rules.md 展开,并结合 resolve_terms.py、validate_terms.py 与 ols_client.py 的源码实现与测试用例,讲解如何在注释组织、细胞类型、疾病、表型等字段时产出可审查、可复现、不会静默出错的术语映射。


策展的本质:为每个字符串走一遍决策程序

策展规则的第一条原则极其克制:在候选项中做选择,并在诚实的答案是"无此术语"时正确收尾。它拒绝一切"看着像就填上"的捷径——因为一个格式正确的UBERON:0002108(小肠道)与UBERON:0002107(肝脏)在形式上毫无破绽,审查者也难以凭肉眼区分,这正是虚构 ID 能穿过审阅、混入已发表数据集的原因。

决策程序逐字符串运行,并在第一步给出站得住脚的答案时停止,共五步:

步骤情形处置
1在目标本体中找到精确标签匹配接受
2精确同义词匹配接受,但记录主标签而非同义词——元数据文件应携带本体自身的标签,以便与本体发布版本干净地对齐 diff
3精确匹配但本体错误通常是源数据列的分类错误而非命名问题:hepatocyte出现在 tissue 字段,说明该列混入了组织与细胞类型两类概念。修复数据列,不要强行凑匹配
4仅有部分匹配不得静默接受。要么规范化输入后重试,要么给出带标签的 Top 候选交由人工选择,要么标记为 unresolved
5毫无匹配标记 unresolved 并如实说明——unresolved 行是正确输出

从源码结构看,resolve_terms.py实现了第 1~4 步的搜索侧:其to_rows()函数把每个候选标记为exact_labelexact_synonympartial(resolve_terms.py),而"partial 是否可接受"这一判断留给你,工具不会替你决定。与之对应,ols_client.py 中的match_type()纯函数通过normalize_label比较查询与标签/同义词,明确区分三者——测试 test_scripts.py 中test_match_type_distinguishes_label_synonym_and_partial验证了 OLS 会把部分命中与精确命中混排,客户端必须自行区分。


值得重试的规范化:把 partial 变成 exact_label 的廉价重写

当仅得到部分匹配时,先不要放弃。以下廉价重写按产出率大致排序,可以把partial升级为exact_label

  • 去掉源数据附加的限定词liver (donor)liverLiver - left lobe [FFPE]liver left lobe
  • 展开实验室缩写PBMCperipheral blood mononuclear cellWT→ 实际基因型,M/Fmale/female
  • 反转倒置短语ventricle, leftleft ventriclecortex, kidneykidney cortex
  • 单数化hepatocyteshepatocyte——本体标签是单数形式。
  • 英式/美式拼写切换:本体标签两种都有,oesophagusesophagus都试。
  • 去掉物种前缀human liverliver(物种应放入单独的 NCBITaxon 字段)。

同时有一条红线:不要规范化掉连字符、希腊字母、数字或大写基因符号——CD4-positivealpha-beta T cell的表意必须原样保留。这正是 ols_client.py 中normalize_label()的设计哲学:它只折叠大小写与空白,其他一概不动。测试test_normalize_folds_case_and_whitespace_only(test_scripts.py)专门断言"CD4-positive"归一化后仍是"cd4-positive"——连字符承载语义,必须存活。

当普通搜索在实验室缩写上反复失败时,可以尝试带本体过滤的ZOOMA(详见 ols4-api.md):它基于策展人此前对该精确字符串的映射历史匹配,与纯词法搜索是不同且往往更优的信号。注意 ZOOMA 必须始终携带过滤参数(如propertyType=organism part&filter=required:[none],ontologies:[uberon]),未过滤时propertyValue=liver会返回gold.vocab之类的无关结果。


"unresolved"应当长什么样:宁可空白,不可虚构

永远不要为了填满单元格而发明 ID。一条 unresolved 行应当携带原始字符串、空的 ID 与原因:

  • 可见的空白:下游能清楚地看到缺口;
  • 虚构的UBERON:0002108:一个无声的错误,因为它看起来与真实 ID 一模一样,能骗过审阅存活至今。

从源码看,resolve_terms.pyto_rows()对无候选的查询输出match_type=unresolvedcurie=""的空行(resolve_terms.py);测试test_unresolved_query_becomes_a_visible_row(test_scripts.py)也断言"unresolved 术语绝不能携带 ID"。

如果概念确实无对应术语、而项目又依赖它,正确路径是向本体提出新术语申请(在本体追踪器上开 GitHub issue,附上定义与参考文献),而不是本地铸造一个标识符。


审计一张既有元数据表:高产出检查清单

策展规则给出了按优先级排序的审计步骤,每一步都对应validate_terms.py的一个能力:

  1. 每个 ID 都存在python3 validate_terms.py --input table.tsv
  2. 无过时 ID:过时术语通常携带term_replaced_by,修复近乎机械——但要审慎应用替换,因为替代项可能比原术语更宽或更窄。
  3. 标签与 ID 一致:提供标签列。不匹配之处正是复制粘贴漂移与虚构 ID 浮出水面的地方——ID 是真的、标签也是真的,但描述的是两回事。对应label_mismatch状态。
  4. 每列对应正确本体--expect-ontology
  5. 每列对应正确分支--branch,并记住它不能把细胞类型从解剖学中排除出去(详见 ols4-api.md 与 ontology-registry.md 的 CARO 陷阱)。

--strict将警告升级为失败,是 CI 门禁的正确设置。三种警告是:

警告状态含义
matched_synonym所声称的标签是同义词而非主标签
imported_only主本体已不再断言该 ID(只在导入者的副本中存在)
not_a_class术语是属性或个体,而非类

从 validate_terms.py 源码结构看,失败状态集FAIL_STATUSES包含not_foundobsoletelabel_mismatchwrong_branchwrong_ontologymalformed_curie,警告集WARN_STATUSES则为上述三者;check_term()按"格式 → 存在性 → 过时 → 本体 → 标签 → 分支 → 归属/类型"的顺序裁决,且失败优先于警告(测试test_failure_beats_warning验证了 wrong_branch 会压过 synonym 警告)。退出码为 0(干净)、1(有失败)、2(用法或网络错误),天然可作为 CI 门禁;test_clean_run_exits_zerotest_failure_exits_onetest_strict_makes_warnings_fail等测试(test_scripts.py)逐一固定了这些行为。

实际审计组合示例:

cd skills/ontology-term-resolution/scripts # ID + 标签列;捕捉"存在但标签是别的"的 ID python3 validate_terms.py --input metadata.tsv --strict # 组织列必须只容纳 UBERON 解剖实体 python3 validate_terms.py --input tissue_ids.tsv \ --branch UBERON:0000465 --expect-ontology uberon

--branch的实现细节值得注意:resolve_terms.py会先通过iri_for()把分支 CURIE 解析为 IRI 再传给 OLS 的allChildrenOf参数(resolve_terms.py),而validate_terms.py则用ancestor_curies()拉取被检术语的传递祖先集合并做集合成员判断(ols_client.py)。


过时术语:废弃不是删除

本体中的"废弃"不是删除——ID 依然可以解析,但其标签通常带有obsolete_前缀。这个前缀在任何元数据文件中都是有用的气味信号:

EFO:0001067 obsolete_parasitic infection -> replaced by MONDO:0005135

从实现看,validate_terms.pycheck_term()检测到is_obsolete后,会把term_replaced_by这条完整 IRI(如http://purl.obolibrary.org/obo/MONDO_0005135)通过iri_to_curie()转为 CURIEMONDO:0005135(ols_client.py)。iri_to_curie()最后一个下划线切分,因此能同时处理 OBO PURL、EFO 专属命名空间、Orphanet 命名空间以及APOLLO_SV_00000001这种多下划线前缀——测试test_multi_underscore_prefix_splits_on_the_last_underscore与 live 测试test_obsolete_term_carries_its_replacement均验证了该行为。

有些过时术语没有替代项,只有consider注解或什么都没有。此时必须手工重新策展,没有自动答案——这正是策展规则反复强调"不要发明 ID"的又一场景。


跨本体映射:OxO 已退役,两条可行路线

文档明确记录:OxO 已退役,返回的是带 HTTP 200 的 HTML 页面——一个朴素的curl | jq会困惑地失败而非干净地报错。两条可行路线是:

  • 术语交叉引用(cross-references)term_detail(curie)["annotation"]["database_cross_reference"]列出等价物——UBERON:0002107携带MESH:D008099NCIT:C12392FMA:7197UMLS:C0023884等:
from ols_client import term_detail xrefs = (term_detail("UBERON:0002107") or {}).get("annotation", {}).get( "database_cross_reference", [] )
  • SSSOM 映射集:由 Monarch 与 OBO 社区发布,当来源出处与映射谓词skos:exactMatchvscloseMatch)至关重要时使用。

文档给出关键警告:交叉引用由策展人以不同置信度断言,并非全部都是exactMatch。当映射驱动的是分析而非展示时,单个 xref 应视为线索而非证据。


报告规范:让结果可以被审查

把解析出的术语交还时,同时给出 ID 与标签,并说明每个是如何匹配的。一张裸 ID 表无法被审阅——没有人能用肉眼区分UBERON:0002107UBERON:0002108,而这恰恰是虚构 ID 能通过审阅的原因。这正是resolve_terms.py输出的 TSV 八列(query/rank/curie/label/ontology/match_type/strategy/defining_ontology,见 resolve_terms.py)中match_typestrategy两列存在的意义:它们让"这个 ID 是怎么来的"对下游完全透明。


决策流程背后的源码支撑

策展规则的五步决策程序并非停留在文档层面,resolve_terms.py用一套**策略阶梯(strategy ladder)**将其落地:exact(精确,限定 label/synonym 字段)→token(全字段整词匹配)→fulltext(无限制相关性搜索),在第一个返回候选的策略处停止(resolve_terms.py)。测试test_ladder_stops_at_the_first_strategy_that_hitstest_ladder_escalates_when_exact_finds_nothing验证了阶梯的停止与升级行为;--exact-only则禁用阶梯,任何非精确命中直接输出为 unresolved(对应决策第 5 步)。

阶梯的起点exact策略在底层依赖ols_client.search()query_fields="label,synonym"参数——这不是随意选择:ols4-api.md记录的陷阱 1 说明 OLS 的exact=true精确 token 匹配而非精确标签匹配(q=liver&ontology=uberon&exact=true会返回 161 条命中,加上queryFields=label才收敛到 1 条)。因此客户端在match_type()自己重新判定精确性,绝不相信服务端的排序(ols_client.py)。同理,rank_candidates()先把候选按exact_label → exact_synonym → partial分层、层内保留服务端相关度序、并让定义本体的副本压过导入副本(ols_client.py)——这正是决策第 1、2 步"精确匹配优先"与"同一术语在多个本体出现"陷阱的机器实现。


延伸阅读(仓库内)

  • SKILL.md:技能总览,两个方向的用法、状态机表格与全部 OLS 陷阱速查。
  • ols4-api.md:OLS4 端点、参数、响应字段与每个已验证的陷阱。
  • ontology-registry.md:前缀→OLS ID 映射、分支根、每个概念应归属哪个本体。
  • ols_client.py:纯函数实现(normalize_labelmatch_typeiri_to_curie等)。
  • test_scripts.py:离线单元测试 + 门控的 live 冒烟测试,是上述行为最精确的行为契约。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询