虚拟器官插件开发教程(16):监管路径——把插件放进申报信封
版本声明块
- 监管文本:ICH E14/S7B Q&A Step 4(2022-02-21)、FDA Federal Register 2022-18515、FDAMA 2.0(2022-12-29 签署)、FDA《减少临床前安全性评价动物试验路线图》(2025-04,media/186092)及第一年进展报告(2026-04-20,media/191986)、欧委会 C(2026) 3497
- 工具/软件:Python 3.11 + PyYAML 6.x(申报附录生成);心脏插件口径见第 17 篇、肝插件见第 18 篇、验证见第 15 篇
- 本文目标:把插件的仿真输出,落成一份"模型能进申报信封"的合规骨架,并说清它在监管里的真实地位——支持性证据,不是强制替代
一句话结论:一个心脏安全插件要进申报,靠的不是"CiPA 取代了 TQT",而是 ICH E14/S7B Q&A 把多电流 + iPSC-CM + ECG 的非临床综合风险评估纳入totality of evidence(证据整体)作为支持性证据——把模型描述(含出处 DOI,如 CiPAORdv1.0 的10.3389/fphys.2017.00616)、输入溯源、验证结果(Li 202010.1002/cpt.1647口径)、限制声明四件套用build_appendix()从 YAML 渲染成 Markdown,就是申报附录的最小可交付。
〇、本篇要解决的认知问题
- 我的插件算出来的 qNet/肝细胞损失,监管到底认不认?它的确切地位是什么?
- "CiPA 已经取代 TQT 研究"这句话能不能写进申报材料?
- 模型自带的验证(第 15 篇)和申报文档(本篇)是什么关系,为什么缺一不可?
- FDAMA 2.0 与 FDA 2025 路线图,给"插件替代动物实验"提供了多大的政策空间,边界又在哪?
- 一份能被审评员接受的"模型申报附录"到底要包含哪几块,怎么把它自动化生成?
一、机制解析:模型证据在监管链条里的真实坐标
先破一个流传很广的误解。CiPA 官网的原话是:CiPA 的相关工作 “was used to inform the ICH E14/S7B Implementation Working Group”(被用于为 ICH E14/S7B 实施工作组提供参考)。“inform"是"提供参考输入”,不是"取代"。E14/S7B Q&A 的措辞也是:非临床综合风险评估(CiPA 式多电流阻滞 + hiPSC-CM + 临床 ECG)可作为totality of evidence的一部分支持促心律失常风险评估。这里的关键词是 totality of evidence(证据整体,首现给英文)——模型是证据链里的一环,而不是替代整条链。更要注意 CiPA 的 Steering Team(FDA/HESI/CSRC/SPS/EMA/Health Canada/日本 NIHS/PMDA)在官网挂了明确 Disclaimer:不提供背书或认证。这条免责恰好反过来指导我们——模型必须自带验证包,因为没有一个权威机构会替你的模型签字。
把监管坐标拆成三层,插件开发者要各就各位:
| 层 | 文本/事实 | 对插件的意义 | 表述红线 |
|---|---|---|---|
| 临床 ECG | E14/S7B Q&A 以C-QTc 为主要分析;接受TQT 替代路径(Q&A 5.1 与 6.1) | 你的 in silico 结论要与 C-QTc/I 期 ECG 证据互证 | 禁写"CiPA 已正式取代 TQT/成为强制方法" |
| 非临床综合 | 多电流 + iPSC-CM + ECG 纳入 totality of evidence(支持性) | 插件输出定位为支持性证据 | 写"支持性/weight of evidence",不写"决定性" |
| 算法使用细则 | IWG第二阶段 Q&A 主题=如何使用促心律失常预测算法/模型结果(概念文),仍在制定 | 模型进申报"有路但细则未定" | 写"算法使用细则仍在制定" |
再看 NAM(新 approaches methodologies,新途径学方法)这股东风给插件开发者开了多大的窗。FDAMA 2.0(2022-12-29 签署)把法规措辞从 “animal tests”(动物试验)改为 “nonclinical tests or studies”(非临床试验或研究),并点名了替代技术:细胞基检测、microphysiological systems (MPS), such as organ-on-a-chip(微生理系统,如器官芯片)、computer/algorithmic models(计算机/算法模型)、类器官、高通量筛选与组学。注意——computer models 是被法定点名的类别之一,这正是"虚拟器官插件"的合法性锚点。FDA 2025-04 路线图进一步设定"3-5 年内让动物研究从默认变例外",起点是单抗,2025-12-02 发布了取消非肿瘤单抗 6 个月 NHP 毒理的精简草案,2026-04-20 宣布第一年目标达成。欧盟侧有 Directive 2010/63/EU(3Rs 锚点)、欧委会 C(2026) 3497 化学品安全性评估动物试验逐步退出路线图,以及 REACH(2.0 修订)第 25 条"动物试验仅作last resort(最后手段)"。
这里必须给"替代动物实验"这句话划红线:政策方向是"减少依赖"(DILIsym 官方定位原话就是 “reducing reliance on animal testing”),REACH 的措辞是"最后手段",都不是"已全面禁止"。写申报材料时用"支持减少/替代部分动物试验",绝不写"已全面禁止动物试验"。
最后是文档落点。一个插件的仿真结果,要变成审评员手里的证据,需要申报四件套:
┌──────────────── 模型申报附录(四件套) ────────────────┐ │ (1) 模型描述 name/version/DOI/license/intended_use │ ← 铁律 2+3:出处与许可锁死 │ (2) 输入溯源 IC50/PBPK暴露/参照集,每个带 provenance │ ← 铁律 1+10:单位+批次 │ (3) 验证结果 灵敏度/特异度/错分率 + 不确定度(第15篇) │ ← Li 2020 10.1002/cpt.1647 │ (4) 限制声明 支持性地位 / 无背书 / 单指标不足 │ ← 铁律 9:监管表述克制 └────────────────────────────────────────────────────────┘第 15 篇教的是"算出验证数字",本篇教的是"把数字连同它的边界一起装进信封"。两者是同一条证据链的两端:只有验证数字没有限制声明是越权宣称,只有文档框架没有验证数字是空壳。
二、完整代码与逐行剖析
申报附录的正确做法是:结构化数据(YAML)与渲染(Markdown)分离。YAML 是单一事实源(可版本控制、可被注册表引用),Markdown 是给人和审评员看的成品。下面这段把四件套从一份 YAML 档案渲染成 Markdown,可运行、带自检。
代码 1:申报档案模板与生成器(YAML 单一事实源 → Markdown)
# -*- coding: utf-8 -*-"""申报附录生成器:一份 YAML 模型档案 -> Markdown 申报附录(四件套骨架)"""importyaml# 这是"单一事实源"。生产环境它由模型注册表(第19篇)与验证管线(第15篇)自动填充,# 这里手写一份最小心脏插件档案,字段严格对应申报四件套。TEMPLATE_YAML=""" model: # (1) 模型描述 name: "cardiotox-CiPAORdv1.0" version: "1.2.0" doi: "10.3389/fphys.2017.00616" # 模型出处 DOI 必须锁死(铁律2),错一处全盘证据失效 license: "GPL-3.0 (FDA/CiPA R code)" # 许可证登记(铁律3):GPL 代码要链接隔离 intended_use: "非临床综合风险评估中的支持性证据;不替代 TQT(ICH E14/S7B totality of evidence)" inputs: # (2) 输入溯源 - {name: "hERG IC50", source: "湿测电压钳", unit: "nM", provenance: "GLP lab / batch R-2043"} - {name: "游离药浓度", source: "PBPK (PK-Sim v12)", unit: "uM", provenance: "第11篇 CSV 契约"} - {name: "TdP 分层参照", source: "CiPA 28", unit: "category 0/1/2", provenance: "github.com/FDA/CiPA"} validation: # (3) 验证结果(第15篇口径) principle: "Li 2020, CPT 107:322-332, doi:10.1002/cpt.1647" dataset: "CiPA 28 (TdP 0/1/2)" sensitivity: 0.83 specificity: 0.80 misclassification: 0.19 uncertainty: "2000 参数抽样 -> qNet 置信区间(compute_qNet_CI 口径)" limitations: # (4) 限制声明 - "CiPA 证据在 ICH E14/S7B 为 totality of evidence 支持性地位;算法/模型使用细则 Q&A 仍在制定" - "本模型不提供监管背书(CiPA 官方 Disclaimer)" - "单 hERG 不足以判风险;须多电流投票(复极储备)" """defbuild_appendix(doc:dict)->str:m=doc["model"]L=["# 模型申报附录:%s"%m["name"],"","## 1. 模型描述"]L.append("- 名称/版本:**%s** / `%s`"%(m["name"],m["version"]))# DOI 用行内代码包裹,避免被 Markdown 里的下划线吃掉格式,也提醒读者这是锁死字段L.append("- 出处 DOI:`%s` | 许可证:`%s`"%(m["doi"],m["license"]))L.append("- 预期用途:%s"%m["intended_use"])# intended_use 是监管"用途声明",必须与地位一致L+=["","## 2. 输入溯源","| 输入 | 来源 | 单位 | 溯源批次 |","|---|---|---|---|"]foritindoc["inputs"]:# 每行一个 provenance:可追溯性是铁律10的文档化落点,缺批次=证据不可复现L.append("| %s | %s | %s | %s |"%(it["name"],it["source"],it["unit"],it["provenance"]))v=doc["validation"]L+=["","## 3. 验证结果","- 方法学:%s"%v["principle"],"- 数据集:%s"%v["dataset"]]# 三件套以"点估计"呈现,但下面紧跟不确定度一句话,防止审评员把点估计当铁板数字L.append("- 灵敏度 / 特异度 / 错分率:**%.2f / %.2f / %.2f**"%(v["sensitivity"],v["specificity"],v["misclassification"]))L.append("- 不确定度:%s"%v["uncertainty"])L+=["","## 4. 限制声明"]forlimindoc["limitations"]:L.append("- %s"%lim)# 限制声明是"合规刹车",越诚实越能过审评return"\n".join(L)if__name__=="__main__":doc=yaml.safe_load(TEMPLATE_YAML)# 先验证 YAML 合法,再生成——CI 里这一步失败就不许出报告md=build_appendix(doc)print(md)assert"10.3389/fphys.2017.00616"inmdand"totality of evidence"inmdassert"| hERG IC50 |"inmdand"0.83"inmdprint("\n[selfcheck] 申报附录四件套齐全,可解析、可渲染")逐行看关键设计。为什么intended_use要写"支持性证据;不替代 TQT"?因为监管地位是模型的"合同用途",一旦你在档案里把它写成"决定性"或"替代 TQT",就是越权宣称,审评会直接退回。为什么许可证 GPL-3.0 要显式登记进申报档案?因为模型代码的许可证决定了你商用交付的合法路径(第 19 篇的 SBoM 治理正是从这里长出来的)。为什么验证块后面必须跟"限制声明"块而不是收尾?因为 CiPA 官方不提供背书,模型的可靠性叙述必须自带边界——单 hERG 判风险会过度分档(第 05 篇)、算法使用细则仍在制定(第 16 篇机制),这些不写出来,反而显得不专业。
代码 2:把验证数字从注册表自动灌进档案(与第 19 篇审计合一)
申报档案最容易造假/过时的地方是"验证数字手填"。正确做法是让档案从一个只读的注册表派生,本节先演示"从字典读验证指标→校验范围→渲染"的最小闭环,完整 SQLite 版见第 19 篇。
# -*- coding: utf-8 -*-"""验证数字不手填:从一个"事实源"读入并做范围校验,越界即拒绝出报告。"""defassert_metric(name,val,lo=0.0,hi=1.0):# 申报级卫生:灵敏度/特异度/错分率必须在 [0,1],NaN 或 >1 直接判定为上游管线出错ifvalisNoneornot(lo<=val<=hi):raiseValueError("验证指标 %s=%r 越界(应在[%s,%s]),疑似上游未收敛"%(name,val,lo,hi))returnvaldefbuild_from_registry(reg):"""reg 来自模型注册表(第19篇)或验证管线(第15篇)的导出字典。"""v=reg["validation"]forkin("sensitivity","specificity","misclassification"):assert_metric(k,v[k])# 三个点估计逐个校验,任一越界整份档案作废# 错分率与灵敏/特异度非独立:这里做一致性交叉核对(1 - 准确率 近似量级),# 若三者自相矛盾(如灵敏度0.83特异度0.80错分率却写0.01)说明数字被手改过,要人审implied_err=1-(v["sensitivity"]+v["specificity"])/2ifabs(implied_err-v["misclassification"])>0.25:raiseAssertionError("错分率与灵敏/特异度不自洽,请回到第15篇重算")print("档案可签发:灵敏度=%.2f 特异度=%.2f 错分率=%.2f"%(v["sensitivity"],v["specificity"],v["misclassification"]))returnTrueif__name__=="__main__":reg={"validation":{"sensitivity":0.83,"specificity":0.80,"misclassification":0.19}}assertbuild_from_registry(reg)bad={"validation":{"sensitivity":1.4,"specificity":0.8,"misclassification":0.19}}try:build_from_registry(bad);raiseSystemExit("应拦截越界指标")exceptValueErrorase:print("[selfcheck] 越界指标被拦截:",str(e)[:40])为什么加"自洽性交叉核对"?申报造假最常见不是数字算错,是数字被事后手改到互相矛盾。用灵敏度与特异度的均值粗估错分量级,偏差超阈值就强制回退到第 15 篇重算——这是把"人工诚信"降级成"机器可检"。
| 手写档案 vs 派生档案 | 手写 | 派生(推荐) |
|---|---|---|
| 验证数字来源 | 人在文档里敲 | 注册表/验证管线只读导出 |
| 版本一致性 | 易与代码脱节 | 与模型 DOI/版本绑定 |
| 审计可追溯 | 无 | 每条 run 有哈希快照(第19篇) |
三、常见报错与排查
- 现象:申报里写"CiPA 已正式取代 TQT"。根因:把政策方向误读为已生效法规。解法:E14/S7B Q&A 只接受 C-QTc 为主要分析、TQT 替代路径见 Q&A 5.1/6.1,模型是 totality of evidence 的支持性证据;算法使用细则的第二阶段 Q&A 仍在制定。措辞改成"作为支持性证据纳入证据整体"。
- 现象:
yaml.safe_load(TEMPLATE_YAML)报 parser error。根因:模板里混用了未加引号的冒号或 Tab 缩进。解法:值里含:或#的整串加双引号;只用空格缩进;先在 CI 跑一遍safe_load再出报告。 - 现象:附录生成成功但缺"限制声明"。根因:把验证结果当成终点。解法:四件套是硬约束,
limitations列表为空时生成器应报错而非省略第 4 节——CiPA 官方 Disclaimer 决定了"没有边界叙述的模型档案"不完整。 - 现象:把"减少动物试验"写成"已全面禁止动物试验"。根因:误读 REACH。解法:REACH 第 25 条是"last resort(最后手段)“,DILIsym 官方定位是"reducing reliance on animal testing”;写"支持减少/替代部分动物试验",引用 FDAMA 2.0 与 FDA 2025 路线图的政策表述。
- 现象:验证指标灵敏度 > 1 或为 NaN 仍被写进附录。根因:上游未收敛。解法:用代码 2 的
assert_metric做范围闸门,越界即拒绝签发。
四、动手练习
- 把
TEMPLATE_YAML的intended_use改成"决定性证据,可完全替代 TQT 研究",运行生成器。判定标准:文档虽能渲染,但你应能在评审时一眼指出它违反铁律 9——正确做法是改回"支持性证据/totality of evidence"。 - 把
misclassification从 0.19 改成 0.01,运行代码 2。判定标准:AssertionError("错分率与灵敏/特异度不自洽…")被触发。 - 新增一个
inputs条目{"name":"ALT 代理阈值","source":"机制模型","unit":"fraction","provenance":"第18篇"}。判定标准:Markdown 第 2 节表格出现 4 行且 YAML 仍可safe_load。
五、小结与下一篇预告
本篇把"插件输出→申报证据"这条路走完:模型在 ICH E14/S7B 里的地位是 totality of evidence 的支持性证据,CiPA 官方不背书所以模型必须自带验证包,FDAMA 2.0/FDA 2025 路线图/欧盟 C(2026) 3497 给出了"减少动物试验"的政策窗口但边界是"最后手段"不是"全面禁止"。申报落点是四件套——模型描述、输入溯源、验证结果、限制声明,用build_appendix()从 YAML 派生、用范围与自洽校验把守。验证数字怎么来在第 15 篇详述,档案字段如何被注册表统一治理在第 19 篇展开。下一篇(第 17 篇)进入实战:把这套契约与文档,落地成一个端到端可跑、带 CiPA 28 子集回归的心脏安全插件 cardiotox。
本篇认知问题回显(FAQ)
Q1:ICH E14/S7B Q&A 下,心脏安全插件算出的 qNet 在监管里是什么地位?
A:属于非临床综合风险评估的一部分,作为 totality of evidence(证据整体)的支持性证据;C-QTc 是临床主要分析,TQT 替代路径见 Q&A 5.1/6.1。它是"支持性"不是"决定性",且如何使用算法/模型的第二阶段 Q&A 仍在制定。
Q2:能不能写"CiPA 已经取代 TQT"?
A:不能。CiPA 官网原话是其工作"was used to inform the ICH E14/S7B Implementation Working Group"(为工作组提供参考),且官方声明不提供背书。正确表述是"CiPA 式多电流 + iPSC-CM + ECG 证据纳入 totality of evidence 作为支持","CiPA 已取代 TQT"属过头表述。
Q3:为什么申报附录里必须包含"限制声明"和模型出处 DOI?
A:CiPA 官方不提供监管背书,所以模型必须自带验证与边界叙述。出处 DOI(如 CiPAORdv1.0 的 10.3389/fphys.2017.00616)错一处会让整条申报证据失效;限制声明写明"支持性地位、无背书、单 hERG 不足以判风险",缺它档案不完整。
Q4:FDAMA 2.0 与 FDA 2025 路线图给插件多大政策空间,边界在哪?
A:FDAMA 2.0(2022-12-29 签署)点名 computer/algorithmic models 与器官芯片(MPS, organ-on-a-chip)为合法替代技术,把"animal tests"改为"nonclinical tests or studies";FDA 2025 路线图欲在 3-5 年让动物研究从默认变例外。边界是"减少依赖/最后手段",不是"已全面禁止动物试验",措辞要克制。
Q5:申报附录的四件套具体指什么,怎么自动生成?
A:模型描述(name/version/DOI/license/intended_use)、输入溯源(每个带单位与批次)、验证结果(灵敏度/特异度/错分率+不确定度)、限制声明。用build_appendix()从一份 YAML 单一事实源渲染成 Markdown,yaml.safe_load先验合法性,指标越界即拒绝签发。