agentsclimarketplace

Bioc fulltext fetch

Skill EthanYoQ/Skill-hub/skills/06-data-search/bioc-fulltext-fetch

Reusable AI agent skills for Codex, Claude Code etc. — AI coding workflows, SKILL.md templates, and automation practices. 面向 Codex、Claude Code等agents 的可复用 AI Agent Skill 技能库:AI 编程工作流、SKILL.md 模板与自动化实践。

Install
npx -y skills add EthanYoQ/Skill-hub --skill bioc-fulltext-fetch

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

从 PubMed/PMC 论文取结构化全文并按章节切分为 RAG 友好的 chunk。当用户需要批量抽取论文全文、按 Methods/Results 等章节分段、提取表格上下文、构建文献向量库时,使用本 skill。支持 PMID(标题+摘要)和 PMCID(全文,开放获取子集)。token 级 RAG chunking 不跨章节,支持缓存与限流。

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

10.5 KB, as published. Nobody here has run it

BioC Fulltext Fetch

封装 NLM BioC API,把 PubMed / PMC 文献转成 RAG 友好的结构化全文 chunk。只做全文抽取与切片,不做检索、不做实体标注、不做向量化。

1. 何时使用

触发场景:

  • "把这批 PMID 的全文取下来准备入 ChromaDB / 我有 PMCID 列表要按章节切分做 RAG"
  • "提取 Methods 章节段落 / 找出表格周围的语义文本"
  • "Build vector index from PMC open access papers"
  • "PMC1234567 的全文段落 + 章节标签"
  • "把 100 篇血液 IFI PMID 入向量库"

不要使用本 skill:

  • 用户只要标题/摘要纯文本 → 用 pubmed-eutils efetch
  • 用户要做语义检索找文献 → 用 pubmed-search / europepmc-search
  • 用户要实体标注(基因/疾病/化合物)→ 用 pubtator-entity-search(可在本 skill 输出之上叠加,不替代)
  • 用户要做证据等级评分 → 用 medical-evidence-grading(其内部会调用本 skill 抽 Methods 段落)

2. 跨 skill 协作(显式)

上游 / 下游 skill协作方式
pubmed-eutils.elink_pubmed_to_pmc()上游,把 PMID 列表转换成 PMCID 列表,喂给本 skill
europepmc-search.get_full_text_links()替代源,当 PMC OA 不可用时回退到 Europe PMC 的开放获取链接
pubtator-entity-search后置叠加,在本 skill 产的 chunk 上做实体标注,不替代本 skill
medical-evidence-grading下游,调 extract_paragraphs 取 Methods 段落做 sample size / study design 检测

典型 pipeline:

europepmc-search ──► PMID list ──► pubmed-eutils.elink ──► PMCID list
                                                              │
                                                              ▼
                                            bioc-fulltext-fetch (本 skill)
                                                              │
                                                              ├─► [可选] pubtator-entity-search 实体叠加
                                                              ├─► [可选] medical-evidence-grading 证据评分
                                                              └─► LangChain / LlamaIndex 入库

3. 两个 BioC 端点

端点输入覆盖内容
BioC PubMedPMID全 PubMed (~37M)标题 + 摘要 + MeSH(结构化)
BioC PMC OAPMCIDPMC 开放获取子集(~10M,约占 PMC 25%)全文章节、段落、表格、图注
摘要级:  https://www.ncbi.nlm.nih.gov/research/bionlp/RESTful/pubmed.cgi/BioC_json/{PMID}/unicode
全文级:  https://www.ncbi.nlm.nih.gov/research/bionlp/RESTful/pmcoa.cgi/BioC_json/{PMCID}/unicode

格式细节、section_type 取值、字符 offset 一致性见 references/bioc-format-spec.md

4. 推荐工作流

PMID list
  │
  ▼
[可选] elink PMID→PMCID  (调 pubmed-eutils)
  │
  ├─ PMCID 存在且 OA ──► fetch_fulltext_bioc(pmcid) ──► extract_paragraphs / extract_tables_context ──► to_rag_chunks
  │
  └─ 不可用/非 OA ─────► fetch_abstract_bioc(pmid) ─────────────────────────────────────────────────► to_rag_chunks

5. 核心能力(5 个函数 · 跨平台签名)

5.1 fetch_abstract_bioc(pmid: str) -> BioCDocument

取标题 + 摘要 + MeSH 的 BioC 结构化版本。

doc = fetch_abstract_bioc("39523456")
# doc.passages → [{"infons": {"section_type": "TITLE"}, "text": "..."},
#                 {"infons": {"section_type": "ABSTRACT"}, "text": "..."}]
# doc.infons["mesh"] → ["Leukemia, Myeloid, Acute", "FLT3 Mutation", ...]

5.2 fetch_fulltext_bioc(pmcid: str) -> BioCDocument

取 PMC OA 全文,按章节切分(section_type ∈ {TITLE, ABSTRACT, INTRO, METHODS, RESULTS, DISCUSS, CONCL, REF, FIG, TABLE, ...})。

doc = fetch_fulltext_bioc("PMC10234567")
# 不可用时抛 NotOpenAccessError,调用方应回退到 fetch_abstract_bioc

5.3 extract_paragraphs(doc: BioCDocument) -> list[Paragraph]

按 BioC passage 提取段落数组,保留 section 标签 + 字符 offset。

paragraphs = extract_paragraphs(doc)
# [{"section_label": "METHODS", "text": "Flow cytometry was performed...",
#   "offset_start": 2890, "offset_end": 3401}, ...]

要点:跳过 REF / FIG_LABEL 纯标签段;合并同 section 内 < 50 字符短 passage;offset 来自 BioC passage.offset

5.4 extract_tables_context(doc: BioCDocument, window: int = 200) -> list[TableContext]

提取每个表格的上下文(前后 200 字),帮 RAG 给表打语义标签。

tables = extract_tables_context(doc, window=200)
# [{"table_id": "T1", "caption": "Patient baseline characteristics",
#   "before_context": "...", "after_context": "...", "section": "RESULTS"}, ...]

表格本体(cell 数据)不解析;只取 caption + 周围文本。

5.5 to_rag_chunks(doc: BioCDocument, chunk_size: int = 512, overlap: int = 50) -> list[Chunk]

把 BioC 文档切成 RAG 入库 chunk。token 单位、不跨章节、段落优先、可追溯 chunk_id

chunks = to_rag_chunks(doc, chunk_size=512, overlap=50)
# {
#   "chunk_id": "PMC10234567_METHODS_2890",
#   "text": "...",
#   "metadata": {"pmcid": "...", "pmid": "...", "section": "METHODS",
#                "offset_start": 2890, "offset_end": 3401, "doi": "...",
#                "year": 2024, "is_oa": True, "title": "...", "journal": "..."}
# }

切片策略详见 references/chunking-strategies.md

6. 速率限制 + 缓存

  • 速率:BioC 不强制 RPS,但建议 ≤ 5 RPS(批量 > 100 篇时降到 3);用 asyncio.Semaphore(5)aiolimiter
  • 缓存~/.cache/bioc/{id}.json + SQLite 索引 index.db(key, file_path, fetched_at, is_oa, doi, year)
  • TTL:默认 30 天(BIOC_CACHE_TTL_DAYS),force_refresh=True 绕过

7. 错误处理

所有错误继承 BioCFetchError 基类。

错误类型处理
404 (PMC OA)NotOpenAccessError调用方回退 abstract
404 (PubMed)NotFoundErrorPMID 不存在,跳过
429RateLimitError指数退避 1s/2s/4s,最多 3 次
5xxBioCServerError重试 3 次后抛出
JSON 解析失败BioCParseError记录原始响应,跳过
超时(默认 30s)BioCTimeoutError重试 1 次

8. 失败模式与避坑(必读)

  1. OA 不可用:PMC OA 子集仅占 PMC 的 ~25%,大量 PMID 没有可用全文。必须在调用方实现 abstract 兜底路径,不要假设 fetch_fulltext_bioc 总能成功。
  2. 章节标签不统一:不同期刊的 section_type 命名有差异(Methods vs Materials and Methods vs Subjects and Methods),BioC 已部分归一化但仍有例外(综述偶尔出现 INTRO_RESULTS 合并段)。下游过滤时用集合而非精确匹配。
  3. 公式与 unicode 丢失:BioC unicode 端点把数学符号转 Unicode,但希腊字母 / 上下标偶尔丢失。关键公式建议从 BioC_xml 端点取,或解析时检测 ? 占位符。
  4. chunk 跨章节切碎:朴素的 token 切片会让 Methods 末尾和 Results 开头被切到同一 chunk,破坏 section 过滤检索。to_rag_chunks 默认按 section 分组,不要绕过。
  5. 缓存命中但 TTL 过期:批量任务跨天运行时,第二天命中缓存的旧条目可能与新条目混用(DOI 元数据已更新)。检查 fetched_at 而非只看文件存在。
  6. BioC API 超时:单篇大文档(> 1MB BioC JSON)在网络抖动时易超时。timeout 不要低于 30s;批量任务必须有失败隔离(failed.jsonl),不能让一篇阻断整批。
  7. 大文档内存:单篇 PMC 全文 BioC JSON 可达 1–3 MB,1000 篇并发会吃 3 GB RAM。批量处理用流式读写或分批 flush。
  8. 不要走 PubTator3 全文端点替代:PubTator3 的 BioC 输出绑定标注模型版本,体积更大;本 skill 保持纯净结构化全文,标注由 pubtator-entity-search 后置叠加。

9. RAG 集成

LangChain / LlamaIndex / 元数据过滤检索 / pubtator 实体叠加 / medical-evidence-grading 联用的完整代码示例见 references/rag-integration.md

10. 环境与依赖

[project]
dependencies = [
  "httpx>=0.27",       # 异步 HTTP
  "aiolimiter>=1.1",   # RPS 限流
  "tiktoken>=0.7",     # token 计数
  "tenacity>=9.0",     # 退避重试
  "platformdirs>=4.0", # 缓存目录
]

环境变量:BIOC_CACHE_DIR(默认 ~/.cache/bioc)、BIOC_CACHE_TTL_DAYS(30)、BIOC_MAX_RPS(5)、BIOC_TIMEOUT_SEC(30)。

11. 测试要点

测试预期
fetch_abstract_bioc("39523456")返回 title + abstract passages
fetch_fulltext_bioc("PMC10234567")返回章节切分的全文
fetch_fulltext_bioc("PMC1") 非 OANotOpenAccessError
extract_paragraphs(doc)段落 ≥ 3,每段有 section_label
extract_tables_context(doc)上下文左右各 ≤ 200 字
to_rag_chunks(doc, 512, 50)chunk token ≤ 512、overlap ≈ 50、不跨章节
缓存命中第二次调用 < 50ms,无网络请求
429 退避模拟 429 后能在 3 次内成功

最低单元测试覆盖率 80%,集成测试用 5 篇真实 PMCID 跑端到端。

12. References

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.