为 Croissant 添加语义
RoboCroissant 文件说明了知识图谱包含哪些文件以及它们的列内容。此技能则为数据添加含义:哪些列共同描述一个基因或疾病、一行数据断言了什么、列的 ID 使用了哪个标识符前缀、代码代表什么。它使用 Croissant 1.1 结构将这些写入一个新的 croissant 文件,并记录每条声明的做出原因。
你将生成一个计划(JSON 格式,按布局组织),脚本将应用并检查该计划。你无需手动编辑 croissant 文件。
输入与输出
- 输入:一个 croissant 文件(
croissant.json或croissant.json.gz)和一个输出目录,以及 croissant 文件旁边的维护人员文件semantics_answers.json(如果存在)。 - 输出(在输出目录中):
semantics_plan.json— 计划(格式:reference/plan-format.md)croissant.semantic.json(或.json.gz,如果输入是 gzip 压缩的)— 结果文件check_report.md—check.py的输出(以及check_report.load_errors.txt,当记录加载失败时包含完整的 mlcroissant 错误)notes.md— 决策、未包括的布局及其原因、以及给知识图谱维护人员的问题
输入的 croissant 文件永远不会被修改。请将下载、辅助脚本和其他临时工作文件放在 OUT/work/ 目录下,而非其他位置。
脚本
所有脚本都位于 scripts/ 目录下,可直接运行(它们是 uv run --script 文件,会自动安装自身依赖)。在任何脚本上使用 --help 参数可查看帮助。
| 脚本 | 用途 |
|---|---|
inventory.py CROISSANT [--layout ID] [--json F] [--common-columns] | 列出所有布局(不同的列集合),从大到小排列;描述某个布局的列、记录集和文件;列出大多数记录集共享的列 |
sample.py CROISSANT --layout ID | 从该布局的三个文件中读取真实行;显示每列的示例值及其形状(CURIE 及其前缀、裸 ID、列表、代码) |
dialects.py list/show/detect/read | 已知文件格式(VCF、GAF、MITAB、CTD 等)作为可计算方言;检测某个布局的文件由哪种格式读取;仅使用 croissant 对文件的描述来读取记录 |
vocab.py class/slot/search/associations/prefix/identify/term/ols/infores | 查询 Biolink 类和槽位(包含近似匹配建议)、主语/宾语对的关联类、标识符前缀(Biolink + Bioregistry)、适合裸 ID 的前缀、本体术语(通过 ID 或文本)、以及资源名称的 infores ID |
apply_plan.py CROISSANT PLAN OUT | 将计划写入一个新的 croissant 文件 |
check.py CROISSANT PLAN OUT --report R --load-records | 先执行 --plan-only:在数秒内检查术语、前缀、方言和单位。然后执行完整检查:对照 Biolink 和采样数据检查术语、前缀、代码和方言,运行 MLCommons 验证器,通过 mlcroissant 读取少量记录(从每个文件开头读取,而非完整下载),并报告覆盖率 |
工作流程
-
调查阶段。 如果 croissant 文件旁边存在
semantics_answers.json,先读取它:其中包含了知识图谱维护人员对先前问题的回答(见下文“维护人员回答”)。不要再问这些相同的问题;apply_plan.py和check.py会自动将这些答案应用到你的计划中。然后运行inventory.py CROISSANT。记录知识图谱的信息(croissant 中的名称、描述、URL)以及记录集如何在布局中分布。大型知识图谱可能有数百个布局;从列表顶部开始处理。现在查找知识图谱自身的 infores ID(使用
vocab.py infores NAME;尝试其全名、缩写和 URL)并将其设置为计划的infores。它命名了这些文件所属的资源,图构建者将其作为从文件中读取的所有内容的来源引用:没有它,转换阶段将根本无法构建知识图谱。当多个条目匹配时,选择发布这些文件的资源的 infores 值,而不是重新提供这些资源的服务(例如使用infores:reactome,而不是infores:automat-reactome)。check.py会将其与计划其余部分的内容进行比较:单一的聚合器或 provided_by 常量也会命名知识图谱(HCOP 的直系同源由infores:hgnc聚合),不匹配则是一个需要解决的警告。如果没有匹配的条目,则提议一个新 ID:格式为
infores:后跟知识图谱短名称的小写单词,以短横线连接(例如infores:bioplex、infores:expression-atlas),并在计划中设置"infores_proposed": true。然后使用vocab.py infores-entry CROISSANT --id infores:NAME编写其目录条目,如果文档清晰,则添加--knowledge-level和--agent-type参数,并将结果放在notes.md中,标题为 要注册的 Infores ID(靠近顶部)。在该处说明用户应通过向 infores 注册表提交拉取请求来注册该 ID(命令会打印注册位置),并且该 ID 可能在审核过程中更改。check.py会对提议的 ID 保留警告,直到它被注册为止;不要解释性地忽略该警告。 -
选择要处理的布局。 目标是覆盖大多数记录集和核心内容(关联和主要实体表)的布局——通常是前 5 到 15 个布局,或者直到剩余的布局变得次要(类似自述文件、日志、每个版本的计数)。如果存在许多小布局(
inventory.py会提示这一点),则记录集可能共享核心列:使用inventory.py --common-columns并计划这些列一次,通过match.has_columns机制。你放弃的所有内容都放在计划的skipped列表中,并附上原因。少处理几个布局,但做得好,比处理很多布局但做得差更好。 -
对于每个布局,在决定任何内容之前先查看数据。
- 使用
inventory.py CROISSANT --layout ID查看列、描述和文件名。标记为MIXED的列在不同记录集中具有不同的原子类型(管道按文件推断);根据数据决定其类型并设置atomic。 - 对于表格,
dialects.py detect CROISSANT --layout ID查找文件在已知格式中的编写方式(注释行、是否有表头、分隔符)。众所周知的历史格式(VCF、GAF、MITAB)有公开的规范;依赖它们而不是重新发现格式。如果没有匹配的格式,则内联描述方言(reference/dialects.md)。然后使用--dialect NAME进行采样,以便按照格式规定的方式读取行,而不是猜测。 - 使用
sample.py CROISSANT --layout ID获取真实值。它读取该布局的三个文件(名称看起来最新的、最大的、最小的),因为单个文件——通常是旧的快照或筛选后的子集——可能隐藏某些值(如N/A占位符、额外的代码值、其他 ID 类型)。--files N可以采样更多文件;--record-set ID可以采样特定文件。如果采样失败(文件过大、压缩包、文件集),请在计划的basis中说明并降低置信度。 - 对于代码列(类型、证据、关系、来源),采样可能会遗漏稀有值。使用
sample.py CROISSANT --record-set ID --profile COL1,COL2读取整个文件并计算每个不同值的计数;重复--record-set可以添加多个文件。根据分析结果映射,而不是样本。 - 对知识图谱的服务器保持温和。 每次针对一个知识图谱只运行一个采样或检查命令,切勿并行运行多个:主机会通过机器人挑战来阻止突发流量,然后后续所有请求都会失败。脚本会自我调节请求并缓存下载(位于
~/.cache/croissant-semantics/downloads中;--refresh则重新下载),因此重新运行成本很低(在更大的--max-mb下缓存的一份副本可以服务于更小的副本)。如果脚本报告机器人挑战或 HTTP 403 错误,则停止对该主机进行采样,不要尝试绕过,并在notes.md中说明哪些检查无法运行。此后脚本会拒绝该主机一小时(跨运行),并从缓存文件中工作。 - 电子表格(xlsx 和旧版 xls)、SQLite 数据库和 Parquet 文件也可以被采样和分析:工作表或表是记录集名称结尾所指示的那个(例如 "file.xlsx — Sheet1"、"file.xlsx: Sheet1"),采样在无法确定时会失败而不会猜测。这些文件会被完整读取,因此如果需要,请为
check.py也增加--max-mb。mlcroissant 无法读取电子表格或数据库,因此不会加载它们的记录。 - XML、RDF(Turtle、RDF/XML、OWL)、FASTA 及其他非表格文件无法被采样:脚本会提示这一情况。如果某个布局很重要,请使用
OUT/work/中的一个小脚本检查其 ID(对于 RDF 使用uv run --with rdflib;使用xml.etree.ElementTree.iterparse流式处理 XML),并在notes.md中说明检查方法。它们的字段通常没有extract,因此没有工具可以读取它们:这是一个需要报告的发包方问题。 --profile配合--layout用于分析该布局的--files个记录集(默认为 3,或使用all)而不是使用--record-set逐一命名。--prefixes计算每个值的前缀或标签,适用于所有分析列或仅列出的列(--prefixes COL1,COL2);--by COL针对另一列进行交叉表分析(每个代码与哪些对象类型一起出现);--split SEP统计列表单元格的项目数;--per-file对每个记录集独立分析(以检查 ID 在每个文件中是否唯一);--stop-mb N在 N MB 后停止处理每个文件,适用于数 GB 的大文件(计数因此仅覆盖文件开头;在以物种或 ID 排序的文件中,这可能仅是一个组,因此需要说明这一点)。- 在信任主要布局的 ID 列之前,先对其进行分析(使用
--profile COL --shapes):数据检查会读取几个文件的前几行,因此某个列在后面的行中可能缺少 ID 或包含另一类 ID,但仍然能通过检查。多个知识图谱在数百行拥有全部 ID 的行之后,发现有 20–30% 的行缺少 ID。 - 一个覆盖多个布局的
match.has_columns条目,其check.py仅会在少数几个文件上采样。在信任它之前,先对其涵盖的不同布局进行采样(使用--record-set-name、--files)。 - 脚本使用操作系统的证书存储。如果下载仍然因证书错误而失败,请连同输出一起报告;不要关闭验证。
- 如果文档受到机器人检查的保护(如“验证你是人类”、Cloudflare 或 ALTCHA 挑战),不要尝试绕过;根据数据和名称进行计划,并对仅凭文档才能确认的含义将置信度上限设为
medium。Croissant 的出处信息可能引用了后来被置于检查之后的页面:仅引用你能读取到的内容。 - 在大文件中,前几行可能不具有代表性(CTD 的 3 GB
genes_diseases文件以数千条推断行开头)。请分析同一布局中较小的文件(精选子集),而不是流式处理整个大文件。 - 要按名称选择记录集,请使用
--record-set-name REGEX(代替--layout),而不是在 shell 中构建--record-set参数列表(zsh 不会将变量拆分为单词)。--per-file分别显示每个采样文件,适用于文件间存在差异的布局(每个文件一种 ID 类型)。 - 数据检查读取几个文件的前几行。列的后面行可能不同(200 个 IRI 之后出现空白节点、稀有的代码):使用
--profile(读取整个文件)确认 ID 形式和代码。 inventory.py在布局之后列出随数据一起提供的文档文件(zip 内的 README.pdf、数据字典)。阅读相关的文件:sample.py CROISSANT --dump FILE将文件打印为文本,--member NAME打印归档文件中的成员(zip 会被完整读取,因此对于大文件请增加--max-mb)(当名称错误时,它会列出 zip 的成员),--sheet NAME打印电子表格的工作表。sample.py会标记声明类型与值不匹配的列(例如sc:Integer列中存放着27152464|29518214)以及行数比表头更宽或更窄的文件。两者通常是流水线问题:使用atomic修复类型,并进行报告。- 当脚本无法读取来源时,请自行获取文件(一次一个,放入
OUT/work/),并使用--url-map OLD=file:///abs/path/将它们指向脚本,以便其检查仍能运行,而不是自己编写分析器。下载会被缓存,~/.cache/croissant-semantics/downloads/index.tsv将每个缓存文件映射到其 URL。 - 如果某个布局的“列名”实际上是数据(没有表头行,因此流水线将第一行数据当作列名,并且每个文件都成为自己的布局),则跳过它并在
notes.md中将其报告为流水线问题。 - 如果数据 URL 已失效(HTTP 404),知识图谱可能已迁移到更新的版本。从其下载页面找到当前的 URL,并将
--url-map OLD=NEW传递给sample.py和check.py(例如--url-map 202607=202610)。当更改的内容不仅仅是版本号时(如路径或文件名也有变化),请映射整个 URL,每个文件一个--url-map OLD_URL=NEW_URL。当 URL 本身包含=(查询字符串)时,请使用OLD=>NEW的格式。在notes.md中说明这一点;这也是一个流水线问题。返回 JSON 的 SPARQL 端点 URL(而 croissant 描述为表格)通常需要映射&format=csv(或text/csv)参数。 - 归档文件:zip 和 tar 归档文件中的成员可以被采样。Zip 文件会被完整下载(最大
--max-mb);tar 文件会流式处理,直到找到成员,因此位于巨大 tar 文件深处的成员可能会超过--max-mb。曾经失败的归档文件不会再次尝试,采样在多次失败后停止。如果有必要,请自行将某个成员提取到OUT/work/中,并在notes.md中记录你检查了什么以及如何检查的。 - 如果数据需要登录或 API 密钥(HTTP 401/403,或 croissant 的
conditionsOfAccess声明了此要求),请不要寻找凭据。仅根据文档和列名进行计划:source为documentation或agent,confidence最多为medium,并且notes.md中说明未对数据做任何检查。 - 查找随附的数据字典...
- 使用