☰
Gtars Refget 实战指南:序列摘要、序列存储与 BEDbase 缓存的安全使用
2026/10/3 9:11:34 网站建设 项目流程

Gtars Refget 实战指南:序列摘要、序列存储与 BEDbase 缓存的安全使用

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

本文围绕 Gtars 的 refget 组件(gtars-refget==0.9.1,Python 侧gtars==0.9.2,CLI 侧gtars-cli==0.9.0)展开,讲解 GA4GH refget 序列摘要(sequence digest)的术语与计算方式、RefgetStore存储类的内存/磁盘/远程三种模式、远程存储的网络审批门禁、只读并发转换、gtars refget build命令行建库,以及独立的 BEDbasebbcache缓存命令。你读完可以立即在自己的流程中计算并校验序列摘要、构建和复用本地 refget 存储,并清楚远程存储与 BEDbase 下载在何种前提与限制下才能安全使用。

验证快照与版本基线

本文所有事实均以仓库文档记录的2026-07-23验证快照为准:

  • Python 绑定:gtars==0.9.2(PyPI,Requires-Python >=3.10,包含 PyO3 原生扩展);
  • Rust 直接组件:gtars-refget==0.9.1;
  • CLI 包:gtars-cli==0.9.0(安装后的二进制名为gtars)。

Gtars 上游有意对工作区各 crate、Python 绑定和 CLI 独立编号,因此数字相同不代表构件相同:例如gtars=0.9.0这个 meta-crate 自身固定的是 refget 0.9.0,而直接依赖gtars-refget则是 0.9.1,两者在补丁行为上不应假设一致。具体可对照 技能主文档 中的版本说明。由于仓库与上游文档可能存在漂移,实践前应以安装后的签名冒烟测试和带版本 tag 的源码为准。

序列摘要术语与计算

refget 是 GA4GH 定义的按内容寻址检索参考序列的规范,核心思想是:用序列内容本身计算出的摘要(digest)作为序列的稳定标识符。摘要变了,意味着序列内容变了;摘要稳定,就可以跨数据库、跨工具、跨环境地标识同一条参考序列。

当前 Python 函数集中在gtars.refget子模块:

from gtars.refget import ( compute_fai, digest_fasta, digest_sequence, load_fasta, md5_digest, sha512t24u_digest, ) digest = sha512t24u_digest("ACGT") assert digest == "aKF498dAxcJAqme6QYQ7EZ07-fiw8Kw2" assert md5_digest("ACGT") == "f1f8f4bf413b16ad135722aa4591043e"

几点必须澄清的术语事实:

  • sha512t24u的形态:Gtars 返回的是32 字符、不带SQ.前缀的字符串。GA4GH refget 规范推荐的序列标识符还要加上SQ.前缀:

    SQ.aKF498dAxcJAqme6QYQ7EZ07-fiw8Kw2

    在仓库的离线校验脚本 refget_digest_plan.py 中,该摘要的实现是hashlib.sha512(sequence.upper()).digest()[:24],再经 URL-safe Base64 编码并去掉=填充——也就是说,先对序列做全大写规范化,再取 SHA-512 截断的前 24 字节,最后 Base64URL 编码,这与_SHA512T24U = re.compile(r"^[A-Za-z0-9_-]{32}$")的形状校验(脚本第 30 行)完全吻合。

  • MD5 的定位:md5_digest仅为遗留系统查询保留,它不是抗碰撞的来源完整性哈希。需要独立保存一条 SHA-256 用于制品完整性校验——这与仓库技能一贯的“SHA-256 记录 + refget 域摘要”双轨策略一致。

  • 摘要计算的输入必须是规范化后的序列:GA4GH refget 在计算序列标识符之前会对序列内容做规范化。绝不能直接把原始 FASTA 字节丢进哈希函数就称为“序列摘要”。FASTA 头(header)、行折叠(line wrapping)、压缩方式和序列规范化属于不同层次:头信息不参与序列内容,\n折叠不该改变生物学序列,.gz压缩更是与序列内容无关。所以digest_sequence会先对序列字节做大写处理。

辅助函数的分工:

  • digest_sequence(data: bytes, name=None, description=None)——对序列字节做大写规范化,返回包含元数据与序列数据的SequenceRecord;
  • digest_fasta(path)——计算一个SequenceCollection;
  • load_fasta(path)——把序列数据载入内存;
  • compute_fai(path)——针对未压缩FASTA 计算索引(.fai)。

摘要正确性的可验证锚点

仓库测试 tests/gtars/test_scripts.py 中test_refget_digest_validation_uses_known_acgt_digest验证了 “ACGT” 这一已知摘要:测试构造了包含>chr1 synthetic与acgt的小型 FASTA,用sha512t24u(b"ACGT")(测试内与脚本内相同的实现)生成期望值,再调用refget_digest_plan.py校验,最终断言result["fasta"]["all_sequence_digests_match"]为真且contract["store_opened"]为假。这证明:同样的规范化规则在技能脚本与 Gtars 运行时之间保持一致,且校验过程完全离线、不打开任何存储。

RefgetStore:当前 Python 存储类

运行时类名是RefgetStore,而不是旧教程里的GlobalRefgetStore:

from gtars.refget import RefgetStore

已验证的构造函数:

RefgetStore.in_memory() RefgetStore.on_disk(cache_path) RefgetStore.open_local(path) RefgetStore.open_remote(cache_path, remote_url) RefgetStore.store_exists(path)

在设计上,SKILL.md 明确建议优先使用in_memory()或open_local(path);open_remote会联网并产生缓存副作用,必须走审批门禁(见下文)。迁移陷阱列表(SKILL.md 的 “Migration traps” 一节)也强调不要再使用过时的gtars.RefgetStore(顶层导入)形式。

内存模式与本地持久化

from gtars.refget import RefgetStore store = RefgetStore.in_memory() metadata, was_new = store.add_sequence_collection_from_fasta( "reviewed-reference.fa", force=False, namespaces=["refseq"], ) store.write_store_to_dir("approved-store") reopened = RefgetStore.open_local("approved-store")

各模式/方法的副作用边界:

  • in_memory()——不写任何文件,纯内存构造;
  • on_disk(path)——打开已有存储,或新建一个磁盘后端存储;
  • open_local(path)——读取存储的元数据/索引,惰性加载本地序列数据;
  • write_store_to_dir与enable_persistence——会创建/写入文件;
  • force=True——可以替换已有的 collection/sequence 条目。

操作前应先store_exists(path)判断选择“新建”还是“打开”。仓库的安全约定还要求拒绝符号链接、意外文件、输出冲突和未获批的存储目录(该约定与 scripts/_common.py 中local_path严格拒绝 URL、~展开、..穿越与符号链接的本地路径策略一致)。

批量导入

results = store.add_sequence_collections_from_fastas( ["ref-a.fa.gz", "ref-b.fa.gz"], file_list=None, jobs=1, force=False, namespaces=["refseq"], )

fastas参数还可以接受glob 或目录;jobs=0表示自动并发。对于受控运行,应显式枚举已审查的文件并设置一个正数、有界的作业数,避免通配符意外扩展到未审查文件。

元数据访问与序列访问的区分

RefgetStore刻意区分两类方法:

元数据方法(不加载完整序列内容):

collections_page = store.list_collections(page=0, page_size=100) sequence_metadata = store.list_sequences() one_metadata = store.get_sequence_metadata(sequence_digest) collection_metadata = store.get_collection_metadata(collection_digest)

数据方法:

record = store.get_sequence(sequence_digest) by_name = store.get_sequence_by_name(collection_digest, "chr1") piece = store.get_substring(sequence_digest, 100, 200) pieces = store.get_substrings(sequence_digest, [(100, 200), (500, 550)]) for chunk in store.stream_sequence( sequence_digest, start=0, end=1_000_000, chunk_size=65_536, ): consume_bounded(chunk)

关键语义:

  • 子串区间是0 基、半开区间([start, end)),务必校验0 <= start <= end <= length;
  • stream_sequence能约束峰值结果内存(按chunk_size分块),但如果下游把每个 chunk 都累积起来,流式依然可能被打败——所以仍要给下游累积设定显式预算;
  • 0.9.2 运行时还暴露load_sequence、load_collection、load_all_sequences、load_all_collections。这些方法会实体化更多数据,load_all_*尤其危险:没有显式的字节/内存预算就绝不调用。

远程存储必须经过审批门禁

# Network + cache side effects: do not call before approval. remote = RefgetStore.open_remote( approved_cache_path, approved_https_base_url, )

open_remote只接受缓存路径和基础 URL 两个参数。它会拉取远程元数据、创建/复用本地缓存状态,并且默认启用持久化。在 0.9.2 中:

  • get_substring可以发起远程字节区间读取(range read),而不必下载整条序列;
  • stream_sequence可以流式读取远程区间;
  • load_sequence是整条序列路径,并可能将其持久化。

重要限制:open_remote之后调用disable_persistence()并不能撤销已经执行的元数据/缓存工作;而且该构造器没有任何参数用于指定 revision、端点白名单、校验清单(checksum manifest)、字节配额或离线模式。换句话说,远程模式的所有防护都必须由调用方在调用之前完成。

在调用open_remote之前,文档要求完成 7 项审批动作:

  1. 对确切的 HTTPS 主机/路径和缓存目录取得显式批准;
  2. 拒绝 URL 中携带的凭据以及未经审查的重定向;
  3. 固定一个不可变的服务器/存储 revision 或内容寻址标识符;
  4. 记录期望的 collection/sequence 摘要,并在适用时记录独立的 SHA-256;
  5. 对元数据、单区间、总传输量、序列长度、缓存、重试、并发和时间设定上限;
  6. 披露:请求坐标/摘要和网络元数据会离开当前环境;
  7. 在科学使用之前校验返回的长度与摘要。

需要注意:即使公共参考基因组本身不敏感,定制/患者特异性组装体和请求区间也可能是敏感的。这与 SKILL.md 的“网络与缓存门禁”一节一致——所有网络能力调用前都要记录不可变 revision、期望 SHA-256、域摘要、组装号、大小配额与出处,并把下载内容当作不可信数据处理。

只读并发存储:into_readonly

readonly = store.into_readonly()

into_readonly()把可变存储转换为ReadonlyRefgetStore,用于并发读取。它有两条硬约束:

  • 它消耗/替换原可变存储对象;
  • 它不能惰性加载那些转换前未准备的 collections。

因此,转换之前只应加载所需的、有界的数据;不要反射性地使用load_all_*,否则会把超出预算的数据带入只读并发场景。

CLI 建库:gtars refget build

当前 refget 唯一的 CLI 子命令是本地存储构建(没有digest、verify或远程查询子命令):

gtars refget build reference.fa reference-alt.fa.gz \ --output approved-store \ --jobs 1

选项:

  • --file-list/-f PATH:一个文件,内含路径/glob/目录列表;
  • --output/-o DIR:必填;
  • --jobs/-j N:并发处理的 FASTA 文件数,默认0(自动);
  • --raw:使用原始存储,而不是默认的编码 2-bit 存储;
  • --force:覆盖已有条目。

注意--jobs 0是自动并发,与add_sequence_collections_from_fastas的jobs=0语义一致。旧技能中存在的gtars refget digest/verifyCLI 在当前版本不存在;需要摘要计算时请使用 Python 摘要函数、直接 Rust API,或在 preflight 之后做一次本地存储构建。CLI 层面也没有全局线程/内存/缓冲参数(cli.md 确认 0.9.0 无--threads、--memory-limit等全局选项),并发控制全部是命令级。

离线元数据/摘要计划:refget_digest_plan.py

技能附带了一个离线辅助脚本,接受一份保守的本地策略清单(manifest)。这是一份skill 策略清单,并非上游 refget 线上 schema:

{ "schema_version": "1.0", "assembly": "GRCh38.p14", "coordinate_system": "0-based-half-open", "collection_digest": "<32-char sha512t24u-like value>", "sequences": [ { "name": "chr1", "length": 248956422, "sha512t24u": "<32-char digest>", "md5": "<32 lowercase hex>" } ] }

运行方式(可选用本地 FASTA 重算序列级摘要):

python3 -B scripts/refget_digest_plan.py \ --metadata refget-metadata.json \ --fasta reference.fa.gz \ --assembly GRCh38.p14

从源码(refget_digest_plan.py)可以确认其行为边界:

  • 它不会重算 collection 摘要:collection_digest只做形状校验(32 字符[A-Za-z0-9_-]),并输出警告collection_digest_shape_only_not_recomputed(第 162-168 行);
  • 它校验清单结构与期望组装号/坐标系统:schema_version必须为1.0、assembly必须与--assembly完全一致、coordinate_system必须为0-based-half-open,否则报错;
  • 逐条序列校验长度、sha512t24u 与 MD5:提供--fasta时按名称比对,报告缺失序列、意外序列、长度不一致、sha512t24u 不一致与 MD5 不一致五类错误码,并输出 FASTA 文件的 SHA-256 与字节数;
  • 不联网、不开存储、不写输出、不 import gtars:报告的contract明确列出network_used: false、store_opened: false、cache_written: false、packages_imported: false(第 271-279 行);
  • 硬上限内置:默认--max-bytes 2 GiB、--max-records 5,000,000,且受 scripts/_common.py 中HARD_MAX_BYTES = 8 GiB、HARD_MAX_RECORDS = 10,000,000的硬边界约束;
  • 输出的approved_execution_plan是一组固定建议文本(如“优先RefgetStore.open_local”、“新存储用in_memory验证后再显式持久化”、“open_remote前记录白名单/固定 revision/期望摘要/缓存路径/字节配额/审批”等)。

最终 collection 的权威验证仍应使用Gtars 固定版本的 collection 实现(即实际调用gtars的 seqcol 逻辑)。

测试 tests/gtars/test_scripts.py 还验证了该脚本即使校验失败也只输出 JSON、不泄漏本地绝对路径(默认--path-mode redacted),并验证了 URL 形式路径会被拒绝。

BEDbase 缓存(bbcache)与 refget 的区分

BEDbase 缓存独立于 refget,它处理的是 BED 区间文件与 BED set 的缓存。CLI 0.9.0 中:

gtars bbcache cache-bed gtars bbcache cache-bedset gtars bbcache seek gtars bbcache inspect-bedfiles gtars bbcache inspect-bedsets gtars bbcache rm

标签源码中的默认值:

  • API 端点:环境变量BEDBASE_API,否则https://api.bedbase.org;
  • 缓存目录:环境变量BBCLIENT_CACHE,否则$HOME/.bbcache/(或/tmp/.bbcache/);
  • 已缓存 BED 文件:bedfiles/<first>/<second>/<id>.bed.gz;
  • BED set:bedsets/<first>/<second>/<id>.txt;
  • 缓存元数据包含经缓存依赖维护的 SQLite 状态。

重要副作用:构造BBClient就会创建根目录以及 BED/BED-set 子目录——即使只是 inspect/seek 也会产生目录副作用(SKILL.md 的“网络和缓存门禁”一节同样提示这一点)。cache-bed接受本地文件/目录、URL 或预期的 BEDbase 标识符;cache-bedset接受本地目录/列表或预期的 BEDbase ID;rm删除文件与缓存记录,并且可以连带删除 BED set 的成员 BED。

已知的 ID-only 下载缺陷

源码研究发现:v0.9.0 的BBClient.load_bed(id)会把裸 ID 委托给RegionSet::try_from,而核心源码中的“裸 BEDbase-ID 回退”已被注释掉。因此,在本版本中仅凭 ID 执行cache-bed/BED-set 下载可能失败,尽管公开文档宣称支持。文档明确要求:不要用猜测 URL 的方式绕过。应先在非敏感的已审批测试上验证安装后的实际帮助/行为,或通过已审查的 BEDbase 元数据解析出明确的官方文件 URL。

把下载当不可信数据对待

bbcache源码没有暴露期望 SHA-256/revision 参数,因此必须把每次下载都当作不可信输入:

  • 分别审批并白名单api.bedbase.org以及任何确切的数据主机;
  • 记录 BEDbase 记录 ID、API 响应 revision/时间、明确文件 URL、期望标识符/摘要和 SHA-256;
  • 使用有配额限制的缓存文件夹;
  • 索引之前校验 BED 的组装、边界和内容;
  • 绝不把一次成功的缓存写入当作完整性证明。

rm会删除本地内容,使用前同样要确认删除范围;缓存目录、SQLite 状态与输出路径都是需要外部管理的副作用。

Rust 依赖固定

直接使用最新 refget 组件时:

[dependencies] gtars-refget = "=0.9.1"

使用 0.9.0 包装层发布集合时:

[dependencies] gtars = { version = "=0.9.0", default-features = false, features = ["refget"] }

不要假设这两者暴露的 refget 补丁行为一致(0.9.0 meta-crate 固定的组件集合包含 refget 0.9.0)。技能主文档 SKILL.md 进一步建议完整功能面使用features = ["core", "overlaprs", "uniwig", "tokenizers", "refget"],并强调不要用 Git 分支或未经审查的发布版替换这些精确 pin。

一条完整的安全工作流

综合以上各节,推荐的安全流程是:

  1. 审查与固定:按 SKILL.md 的原生代码信任门禁审查并固定gtars==0.9.2/gtars-refget==0.9.1/gtars-cli==0.9.0,在隔离环境中安装验证;
  2. 离线预检:用refget_digest_plan.py校验策略清单与本地 FASTA 的摘要一致性(不联网、不开存储);
  3. 本地建库:RefgetStore.in_memory()加载并验证,必要时write_store_to_dir持久化;或直接gtars refget build --output approved-store --jobs 1构建磁盘存储;
  4. 只读复用:后续读取用open_local+into_readonly(),仅加载有界数据;
  5. 远程/BEDbase 仅在审批后:先完成 7 项审批动作(主机白名单、不可变 revision、期望摘要与 SHA-256、各项配额、泄露披露、返回校验),再调用open_remote或gtars bbcache,并把所有下载内容当不可信数据对待。

这套流程把“refget 内容寻址的便利性”与“网络/缓存副作用的可审计性”绑定在一起:摘要计算和本地存储可以完全离线、有界、可复现地完成,而任何离开本地环境的读取都必须在显式审批和记录留痕之后进行。更多细节可继续阅读 refget.md 本身,以及同一技能包下的 SKILL.md、cli.md 和 python-api.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),仅供参考

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

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

立即咨询