scientific-agent-skills 本体论词条解析 Skill 实战:基于 EBI OLS4 的文本解析与 CURIE 校验 scientific-agent-skills 本体论词条解析 Skill 实战基于 EBI OLS4 的文本解析与 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本体论ontology标识符是生物医学元数据的隐形地基——UBERON:0002107代表肝liverUBERON:0002108代表小肠两者只差一位数字却会被下游所有工具当作完全不同的事实。本文以 scientific-agent-skills 仓库中的ontology-term-resolutionSkill 为核心系统讲解如何基于 EBI OLS4 服务把自由文本解析成本体论词条 ID、如何校验存量 CURIE 是否真实且未废弃以及如何把校验流程接入 CI 门禁。读完你将掌握resolve_terms.py与validate_terms.py两个标准库零依赖脚本的完整用法、OLS4 API 的 8 个容易误导人的行为陷阱、本体论选型表与策展决策流程能够安全地为 GEO、ENA、BioSamples、CELLxGENE、HCA、ISA-Tab 等提交元数据标注词条 ID。什么时候该用本 Skill任何要写下或信任一个本体论标识符的时刻都该使用本 Skill标注元数据列、填写提交模板、审计别人产出的表格、或检查旧文件里的 ID 是否仍然有效。具体场景包括标注 tissue、cell type、disease、phenotype、assay、chemical、organism、sex、developmental stage 等字段为 GEO、ENA、BioSamples、CELLxGENE、HCA 或 ISA-Tab 提交准备元数据审计一张满是词条 ID 的元数据表检查某个词条是否已废弃obsolete以及被什么替代在不同本体论之间做映射。Skill 的 frontmatter 还给出了触发词清单ontology term、ontology ID、CURIE、controlled vocabulary、UBERON、CL:、MONDO、HPO、EFO、ChEBI、NCBITaxon、GO term、PATO以及任何emit or verify 一个形如PREFIX:0001234的标识符的请求。铁律绝不凭记忆写 ID绝不未经校验就接受 ID本 Skill 的核心规则只有一条Never write an ontology ID from memory, and never accept one without checking it.绝不凭记忆写本体论 ID绝不未经校验接受一个 ID。原因在于本体论 ID 在形式上非常好记细节上却完全随意。一个看似合理的UBERON:0002108小肠并不是肝UBERON:0002107而下游没有任何环节会拦住这种替换——ID 格式合法、本体论正确元数据却悄悄错了。审稿人也无法凭肉眼发现这正是这类错误能一路存活到已发表数据集里的原因。因此本 Skill 的承诺是每一个它发出的 ID 都来自实时的 OLS 查询每一个交给它的 ID 都会被验证。两个方向文本到 IDID 到判定Skill 用两个脚本覆盖双向工作流方向脚本回答的问题text → IDresolve_terms.pyleft ventricle 对应的词条是什么ID → verdictvalidate_terms.pyEFO:0001067是真实、现行、且标签与文件声称一致吗两者都支持单个值或文件输入输出 TSV 或 JSON且除标准库外不依赖任何第三方包需要 Python 3.11 与对https://www.ebi.ac.uk/ols4的网络访问公共服务无需 API key。两个脚本的 docstring 都带有 PEP 723 元数据块因此既可python3 resolve_terms.py ...直接运行也可用uv run resolve_terms.py ...执行。方向一用 resolve_terms.py 把文本解析为词条基础用法单字符串 限定本体论cd skills/ontology-term-resolution/scripts # 单个字符串限定到应定义它的本体论 python3 resolve_terms.py liver --ontology uberon输出示例TSVquery rank curie label ontology match_type strategy defining_ontology liver 1 UBERON:0002107 liver uberon exact_label exact true批量解析文件输入与模糊匹配# 一列组织名任何非精确命中的项都会被报告而不是猜测 python3 resolve_terms.py --input tissues.txt --ontology uberon \ --exact-only --format tsv -o resolved.tsv # 接受模糊回退然后人工审查部分命中项 python3 resolve_terms.py left ventrical of heart --ontology uberon --top 3策略阶梯escalating search ladder从源码 resolve_terms.py 的STRATEGIES常量可以看到搜索按exact → token → fulltext三级升级并在第一个返回结果的策略处停止同时在输出中报告命中的是哪个策略STRATEGIES ( (exact, {exact: True, query_fields: label,synonym}), (token, {exact: True, query_fields: None}), (fulltext, {exact: False, query_fields: None}), )exactexacttrue且只匹配label,synonym字段——这是真正的精确标签/同义词匹配tokenexacttrue但放开到全部索引字段——整词匹配见下文 OLS4 陷阱 1fulltext无精确约束的相关性检索。--exact-only会把策略截断到第一级任何非精确命中直接标记为unresolved。--branch UBERON:0000465则把候选限制为某个词条的后代通过把 CURIE 解析为 IRI 后传给allChildrenOf实现。使用结果前必须读 match_typeexact_label和exact_synonym是安全的partial表示 OLS 对一个按原样并不存在的字符串返回了它的最佳猜测需要人来决策unresolved是合法输出——先看 curation-rules.md 里值得重试的规范化改写再决定怎么办。参数总览参数作用默认值text位置参数一个或多个待解析字符串—--input文件输入每行一个字符串-表示 stdin#开头为注释行—--ontology限定 OLS 本体论 id逗号分隔如uberon,cl不限--branch要求候选是某 CURIE 的后代如UBERON:0000465不限--top每个查询报告几个候选5--exact-only只接受精确标签/同义词命中其余报 unresolved关闭--format输出格式tsv或jsontsv-o, --output写入文件而非 stdoutstdout输入会保序去重见 read_inputs没有输入时以退出码 2 报错。输出列固定为query, rank, curie, label, ontology, match_type, strategy, defining_ontology其中defining_ontology表示该候选是否来自其定义本体is_defining_ontology。所有无法解析的查询都会产生一行match_typeunresolved、curie为空的记录——绝不猜测、绝不填最近命中项。方向二用 validate_terms.py 校验存量 ID基础用法python3 validate_terms.py UBERON:0002107 EFO:0001067 UBERON:9999999输出示例id status actual_label ontology replacement detail UBERON:0002107 ok liver uberon EFO:0001067 obsolete obsolete_parasitic infection efo MONDO:0005135 obsolete; replaced by MONDO:0005135 UBERON:9999999 not_found no such term in the ontology this prefix names注意EFO:0001067它已被废弃标签被加上obsolete_前缀且通过term_replaced_by字段指出后继词条MONDO:0005135由 IRIhttp://purl.obolibrary.org/obo/MONDO_0005135转换而来。状态语义表状态含义判定ok存在、现行、与所有断言一致passmatched_synonym声称的标签是同义词主标签不同warnimported_only所属本体已不再声明该 IDwarnnot_a_class词条是 property 或 individual 而非 classwarnnot_found不存在该词条failobsolete已废弃replacement在存在时给出后继faillabel_mismatchID 与声称的标签描述的不是同一个东西failwrong_ontologyID 类型对但对这个列而言本体论不对failwrong_branch不是所要求根节点的后代failmalformed_curie不符合PREFIX:local形式fail--strict会把 warn 升级为 fail。源码 validate_terms.py 中的FAIL_STATUSES与WARN_STATUSES正是这两个集合。作为 CI 门禁使用退出码设计使其天然适配 CI全部通过返回 0有任一失败返回 1用法或网络问题返回 2。# id label 两列能抓住ID 存在但标签是别的东西的复制粘贴漂移 python3 validate_terms.py --input metadata.tsv --strict # 一个组织列必须只含 UBERON 解剖实体 python3 validate_terms.py --input tissue_ids.tsv \ --branch UBERON:0000465 --expect-ontology uberon输入文件格式--input接受 TSV 或 CSV按首行是否含制表符自动探测。它会自动识别多种表头命名ID 列可以是id、curie、term_id、ontology_term_id、obo_id标签列可以是label、term_label、name、ontology_term_label见 ID_HEADERS / LABEL_HEADERS。无表头的两列文件按第一列 ID、第二列标签处理#注释行和空行被跳过。源码级机制ols_client.py 如何避免假阴性两个 CLI 共享同一个标准库 OLS 客户端 ols_client.py。它的设计要点直接对应着正确性要求docstring 中明确注明均对照实时 API 验证过/search封装exacttrue是精确 token 匹配而非精确标签匹配因此客户端把queryFields限制为label,synonym才得到真正精确的结果query_fieldsNone就是模糊回退的写法search。term_detail双重查询/ontologies/{id}/terms?obo_id是唯一会报告is_obsolete与term_replaced_by的端点但它的obo_id索引有空洞——MONDO:0000001是真实且被 11 个本体导入的现行词条却查不到。因此 term_detail 在obo_id查询 404/为空时自动回退到/terms?iri按 IRI 查询并优先选择home ontology 且is_defining_ontologytrue的副本最后用_resolved_via与_home_ontology标记路径。IRI 候选由 candidate_iris 生成且绝不凭空模板化 IRI——只有 EFO 与 Orphanet 的命名空间例外其余走 OBO PURL 模板。match_type分类OLS 会把 partial 命中与精确命中混在同一个结果里所以 match_type 在客户端自行判断exact_label/exact_synonym/partial绝不信任服务端排序。去重与排序dedupe_candidates 按obo_id折叠同一词条的多个导入副本并保留定义本体副本rank_candidates 把精确命中排到最前定义本体副本优先于导入副本。保守的标签归一化normalize_label 只折叠大小写与空白刻意保留连字符、希腊字母和数字——CD4-positive和alpha-beta T cell就该保持原样。IRI→CURIE 转换iri_to_curie 按最后一个下划线切分同时兼容 OBO PURL、EFO 命名空间、Orphanet 命名空间以及多下划线前缀如APOLLO_SV_00000001。祖先查询ancestor_curies 通过_links.hierarchicalAncestors.href分页拉取?size500跟随_links.next支撑--branch检查。OLS4 API 的 8 个陷阱这些陷阱都在 ols4-api.md 中对照实时服务验证过是本 Skill 提供脚本而非一段 recipe的根本原因陷阱后果exacttrue是精确token匹配liver在 UBERON 里命中 161 条加上queryFieldslabel才返回 1 条/search永不返回is_obsolete或term_replaced_by即使在fieldList里点名也会被静默丢弃只有 term detail 端点能回答这个 ID 是否仍现行ontologyefo会返回 MONDO 和 CL 的命中本体论相互导入必须自己按 CURIE 前缀过滤同一词条在每个导入它的本体里各出现一次按obo_id去重保留is_defining_ontology: true的副本obo_id索引有空洞MONDO:0000001是现行词条却未按obo_id建立索引必须做 IRI 回退否则会误报not_foundIRI 不全是 OBO PURLEFO 和 Orphanet 用自己的命名空间——按需解析 IRI不要模板化OxO 已退役以 HTTP 200 返回 HTML 升级通告naive 的curl | jq会迷惑性地失败改用 term 交叉引用或 SSSOMbranch 检查不排除 cell typeCARO 把cell放在anatomical structure之下前缀检查也必须同时做其中陷阱 1 的原始验证数据为qliverontologyuberonexacttrue - numFound 161 qliverontologyuberonexacttruequeryFieldslabel - numFound 1陷阱 3 的验证数据qparasitic infectionontologyefo - includes MONDO:0016472, CL:0001069 qhepatocyteontologyuberon - CL:0000182, is_defining_ontologyfalse补充要点/search默认排除废弃词条obsoletestrue才包含term detail 对不存在的词条返回 HTTP 404 JSON 体404 是正常答案而不是要崩溃的异常UBERON:0002107通过/terms?iri可看到 42 个导入副本/ontologies/{id}/terms/roots对 MONDO 这类合并本体不可靠返回裸数字 id 和无关的 BFO/CHEBI/FOODON 条目不要在其上构建逻辑。IRI 命名空间对照前缀IRI多数 OBO 前缀http://purl.obolibrary.org/obo/{PREFIX}_{local}EFOhttp://www.ebi.ac.uk/efo/EFO_{local}Orphanethttp://www.orpha.net/ORDO/Orphanet_{local}另外可留意 EBI 的ZOOMA服务它在无过滤时不可用propertyValueliver会返回 GOLD 词汇的无关结果必须带propertyType与ontologies过滤例如?propertyValueliverpropertyTypeorganismpartfilterrequired:[none],ontologies:[uberon]它能返回UBERON:0002107及confidence: HIGH|GOOD的命中。当 OLS 搜索在实验室简写词上失败时值得一试因为它记录的是策展人此前映射过该字符串的历史。选择正确的本体论前缀到 OLS 本体论 idOLS 的 ontology id 几乎总是小写化的 CURIE 前缀注意例外。完整表见 ontology-registry.md节选CURIE 前缀OLS id覆盖范围UBERONuberon解剖、组织、器官、体液跨物种CLcl细胞类型MONDOmondo疾病合并后的一体化疾病本体优先于 DOID/NCITHPhp人类表型异常——id 是hp而非hpoEFOefo实验因子、assay、平台、细胞系CHEBIchebi化学实体、药物、代谢物NCBITaxonncbitaxon生物体GOgo生物过程、分子功能、细胞组分PATOpato质量——性别、颜色、大小、normalOrphanetordo罕见病——id 为ordoCURIE 前缀为OrphanetOLS 报告preferredPrefix: ORDO不在 OLS 中的本体Cellosaurus细胞系身份RRIDCVCL_*需查询https://api.cellosaurus.org厂商与仪器词汇表一般也不在 OLS 中。此映射在客户端由 ONTOLOGY_ID_OVERRIDES 与curie_to_ontology_id()实现。分支根节点传给 --branch根节点标签用途UBERON:0001062anatomical entity任意解剖UBERON:0000465material anatomical entity组织与器官CL:0000000cell细胞类型MONDO:0700096human disease人类疾病字段HP:0000118Phenotypic abnormality表型字段CHEBI:24431chemical entity化合物NCBITaxon:1root生物体OBI:0000070assayassay 字段PATO:0000001quality质量包括性别GO:0008150/GO:0003674/GO:0005575biological_process / molecular_function / cellular_componentGO 各分支EFO:0000001experimental factorEFO 广度SO:0000110sequence_feature序列特征HsapDv:0000001/MmusDv:0000001life cycle人/小鼠发育阶段ENVO:00010483environmental material环境样本CLO:0000031cell line细胞系NCIT:C7057Disease, Disorder or FindingNCIT 疾病子树DOID:4diseaseDOID 子树注意MONDO:0000001虽然可解析label 为disease但只能通过 IRI 回退得到作为人类疾病根节点应优先用MONDO:0700096。再次强调branch 检查不能替代前缀检查——CARO 把cell放在anatomical structure下细胞类型会通过解剖 branch 测试必须同时约束前缀。重叠本体之间的取舍疾病用 MONDO它是 DOID、Orphanet、OMIM、NCIT 疾病词条的合并目标并携带回指各源本的交叉引用。只有下游消费者明确要求某命名空间时才用 DOID 或 NCIT。疾病 vs 表型MONDO 放诊断asthmaHP 放观察到的异常Wheezing。元数据字段通常二者取一而非任一都行。组织 vs 细胞类型样本解剖来源用 UBERON细胞是什么用 CL。liver是 UBERONhepatocyte是 CL——即使限定在uberon搜索hepatocyte也会返回 CL 词条的导入副本。AssayEFO 优先OBI 次之基因组学平台与建库策略在 EFO 里更丰富OBI 更适合通用实验室 assay 类。化学物ChEBI用于任何有结构的物质按商品名的药品属于药物词汇RxNorm、DrugBank不属于 ChEBI。性别PATOPATO:0000384male、PATO:0000383female不用 NCIT不用自由文本。正常/健康对照PATO:0000461normal是疾病字段无疾病时的常规填充值也是多个提交 schema 的要求。常见元数据字段与期望本体概念本体组织 / 器官 / 解剖部位UBERON细胞类型CL细胞系CLO身份与污染状态用 Cellosaurus疾病MONDO无疾病时用PATO:0000461表型HP生物体NCBITaxonassay / 平台EFO发育阶段HsapDv、MmusDv性别PATO化学物 / 处理化合物ChEBI环境材料ENVO这些概念与本体之间的对应是稳定的但提交 schema 的字段名不是——CELLxGENE、HCA、ENA/BioSamples checklists、ISA-Tab 配置会固定字段名与允许的本体并持续修订务必读取目标提交所对应的 schema 版本。策展规则候选选择与诚实的无解curation-rules.md 给出逐字符串的决策过程停在第一步给出可辩护答案的位置在期望本体中、来自其定义本体的精确标签匹配——接受。精确同义词匹配——接受但记录主标签而非同义词元数据应携带本体自己的标签以便与本体发布版本干净 diff。精确匹配但本体错误——通常是源列的类别错误而非命名问题hepatocyte出现在组织字段说明该列混淆了组织与细胞类型。修列不要强行匹配。只有部分匹配——不要静默接受。要么规范化输入重试要么展示前几个候选标签让人选择要么标记 unresolved。什么都没有——标记 unresolved 并明说。unresolved 行是正确的输出。resolve_terms.py实现了前四步的搜索侧并把每个命中标记为exact_label/exact_synonym/partialpartial 是否可接受是人的判断工具不会替你决定。值得重试的规范化改写按产出率大致排序去掉源数据附加的限定词liver (donor)、Liver - left lobe [FFPE]展开实验室简写PBMC→peripheral blood mononuclear cell、WT→ 实际基因型、M/F→male/female反转倒装短语ventricle, left→left ventricle、cortex, kidney→kidney cortex单数化hepatocytes→hepatocyte本体标签是单数英式/美式拼写都试oesophagus与esophagus去掉物种前缀human liver→liver物种应放在独立的 NCBITaxon 字段。不要归一化掉连字符、希腊字母、数字或大写基因符号——CD4-positive与alpha-beta T cell含义就在原样里而normalize_label()刻意只折叠大小写与空白。unresolved应该长什么样绝不编造 ID 来填空。unresolved 行携带原始字符串、空 ID 与原因。在下游这是一个可见的缺口而一个编造的UBERON:0002108是静默错误因为它看起来与真实 ID 一模一样能骗过审稿。如果某个概念确实没有词条且项目依赖它正确路径是向本体提出新词条请求在词条跟踪器上开 issue附定义与参考文献而不是本地铸造一个标识符。审计存量元数据表按优先级排列的高产出检查每个 ID 都存在validate_terms.py --input table.tsv没有废弃 ID废弃词条常携带term_replaced_by修复多为机械操作——但要谨慎应用替换因为后继词条可能比原词条更宽或更窄标签与 ID 匹配提供标签列。复制粘贴漂移与幻觉 ID 就在这里现形ID 是真的、标签也是真的但它们描述的不是一个东西每列本体正确--expect-ontology每列分支正确--branch并记住它不会把细胞类型排除出解剖列。--strict把警告升级为失败是 CI 门禁的正确设置。警告项是matched_synonym标签是同义词而非主标签、imported_only所属本体已不再声明该 ID、not_a_class。废弃词条的处理废弃不是删除——ID 仍可解析标签通常被加上obsolete_前缀。这个前缀是元数据文件里一个很有用的气味信号EFO:0001067 obsolete_parasitic infection - replaced by MONDO:0005135部分废弃词条没有替代只有consider注解或什么都没有这时必须人工重新策展没有自动答案。跨本体映射OxO 已退役且以 HTTP 200 返回 HTML两条可用路线词条交叉引用term_detail(curie)[annotation][database_cross_reference]列出等价词条——UBERON:0002107携带MESH:D008099、NCIT:C12392、FMA:7197、UMLS: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 当作线索而非证明。测试验证与如何运行Skill 自带完整的离线单元测试 tests/ontology-term-resolution/test_scripts.py所有网络调用都被 stub 掉不触碰 EBI 即可运行uv run --with pytest python -m pytest tests/ontology-term-resolution -q # 少数 live 冒烟测试验证脚本所依赖的真实 API 行为 OLS_LIVE_TESTS1 uv run --with pytest python -m pytest tests/ontology-term-resolution -q测试覆盖了本文章提到的所有关键行为is_curie对真实/伪造前缀的判定、Orphanet:558 → ordo的覆盖映射、三种 IRI 命名空间与多下划线前缀的iri_to_curie转换、normalize_label保守归一化、match_type区分 label/synonym/partial、按定义本体去重、策略阶梯在 exact 命中后停止、--exact-only不升级、unresolved 行必须携带空 ID、obsolete 术语带替换、imported_only/not_a_class警告、--strict提升警告、退出码语义、TSV/CSV 表头探测等。Live 测试则钉住了本文第四节列出的真实服务行为exacttrue非精确标签、/search不含废弃字段、MONDO:0000001的 IRI 回退等。结果报告规范交还解析结果时给出 ID 和标签并说明每个是如何匹配的。一张只有裸 ID 的表格无法被审阅——没有人能凭肉眼分辨UBERON:0002107与UBERON:0002108这正是编造 ID 能骗过审稿的原因。对 unresolved 词条要显式声明而不是用最近命中项填充。参考文档索引ols4-api.md——端点的参数、响应字段与全部已验证陷阱ontology-registry.md——前缀/本体 id 对照、分支根节点、各本体论的概念归属curation-rules.md——候选选择流程、值得重试的规范化、存量表审计、废弃词条、跨本体映射ols_client.py——标准库 OLS4 客户端与共享纯函数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),仅供参考