276 lines
15 KiB
Markdown
276 lines
15 KiB
Markdown
# STRING Tree Reference Resolution Design
|
||
|
||
日期:2026-07-20
|
||
|
||
状态:范围已确认,实施计划审查通过
|
||
|
||
## 目标
|
||
|
||
为 PPI 增加基于固定 STRING v12.0 物种注册表和 species tree 的通用物种解析:目标物种受 STRING 支持时直接查询;否则按 STRING tree 拓扑距离返回候选参考物种;有效缓存中仍无法得到候选时,推荐拟南芥作为明确标注的模型兜底,并在用户确认后才执行 Ortholog→PPI。本轮只闭合 STRING→Ortholog→PPI,不修订 KaKs 功能。
|
||
|
||
## 已确认决策
|
||
|
||
- 运行期只使用项目内固定快照,不联网刷新。
|
||
- 同时缓存 `species.v12.0.txt` 和约 97 MB 的 `species.tree.v12.0.txt`。
|
||
- PPI 的候选发现和排序只依赖 STRING 自身数据,不引入 NCBI taxonomy。
|
||
- 项目阶段身份继续使用 `Species_Code`;STRING 外部身份使用 TaxID。
|
||
- 返回稳定排序的 Top 3 STRING tree 候选。
|
||
- STRING tree 没有分类等级和分子枝长,因此只报告 LCA 节点与拓扑边数,不声称“同目”“最相似”或“进化距离最近”。
|
||
- 找不到候选时推荐 `Arabidopsis thaliana`(TaxID 3702)作为 `model_fallback`,必须由用户确认一次,不能静默执行。
|
||
- PPI 与 KaKs 保持独立 owner;KaKs 缺少 CDS 不得阻断可直接执行的 PPI。
|
||
- PPI-only fallback 只准备参考 PEP;只有调用方明确请求 KaKs 时才准备 CDS。
|
||
|
||
## 非目标
|
||
|
||
- 不修改 PlanningAgentV2 的 PPI 静态依赖。
|
||
- 不恢复 PPI→Ortholog 静态绑定。
|
||
- 不修改 TFBS 的 NCBI taxonomy 路径。
|
||
- 不让 KaKs 强制使用 STRING 物种。
|
||
- 不修改 KaKs 的算法、参数、参考物种选择、输入契约、Manifest 或结果展示。
|
||
- 不为 KaKs 新增 resolver,也不把 PPI 选中的 STRING 参考物种传给 KaKs。
|
||
- 不建设通用 taxonomy 服务或数据库。
|
||
- 不使用 LLM、模糊匹配或联网搜索猜测物种身份。
|
||
- 不删除、重命名或覆盖既有分析结果。
|
||
|
||
## 当前问题
|
||
|
||
当前 `gfa_core/ppi_string_policy.py` 仅维护少量 STRING code/TaxID 和 Ft→Spinacia 静态推荐。`recommended_string_reference_species()` 只是字典查询;`resolve_ppi_species_resolution()` 将空结果直接暴露为“无可用近源推荐”。因此前端虽然是数据驱动的,后端并没有通用候选发现能力。
|
||
|
||
另一个必须同时修复的边界是执行身份:当前 PPI 执行仍依赖少量三字母 code。新 resolver 即使找到 registry-only 物种,如果 TaxID 不能传到 STRING client,仍会出现“预检支持、执行不支持”的假通用化。
|
||
|
||
## 固定数据布局
|
||
|
||
```text
|
||
data/string/v12.0/
|
||
species.v12.0.txt
|
||
species.tree.v12.0.txt
|
||
source_manifest.json
|
||
```
|
||
|
||
`source_manifest.json` 必须记录:
|
||
|
||
- STRING 版本;
|
||
- 官方下载 URL;
|
||
- 下载时间;
|
||
- 文件大小;
|
||
- 每个文件的 SHA256;
|
||
- parser schema version;
|
||
- Viridiplantae 根节点和 Arabidopsis TaxID 校验结果。
|
||
|
||
缓存发布前必须验证:
|
||
|
||
- 每个 parent TaxID 都能在 tree 中解析,根节点除外;
|
||
- 官方根节点 `1 -> 1` 自环被识别为终止条件,且除此之外不存在任何环;
|
||
- `is_STRING_species` 只接受 `t/f` 并严格解析为布尔值,禁止使用 `bool("f")`;
|
||
- `is_STRING_species` 节点与 species registry 一致;
|
||
- Viridiplantae 根节点 TaxID 33090 存在;
|
||
- Arabidopsis TaxID 3702 存在且标记为 STRING species;
|
||
- 文件 SHA256 与 Manifest 一致。
|
||
|
||
运行期缓存缺失、损坏或校验失败属于系统资源错误,返回 `string_registry_unavailable` 或 `string_registry_integrity_failed`,不得伪装成“没有近源物种”,也不得因此自动回退 At。
|
||
|
||
## Resolver 输入与输出
|
||
|
||
### 输入
|
||
|
||
- `project_species_code`:项目身份,例如 `Ft`、`Os`;
|
||
- `target_scientific_name`:存在时优先用于匹配;
|
||
- `ppi_target_tree_taxon_id`:明确属于 STRING tree 的 TaxID,不复用含义不同的 NCBI 通用 taxid 字段;
|
||
- 固定 STRING snapshot 路径;
|
||
- `top_n=3`。
|
||
|
||
常用简称 alias 只用于将项目输入映射到 STRING tree 节点,不作为候选知识库。服务器维护最小的 PPI 默认 alias,例如 `Os -> 39947`,避免在没有更明确信息时把通用 NCBI 物种 TaxID 4530 错当成 STRING 实际使用的 japonica TaxID 39947。解析顺序固定为:明确的 `ppi_target_tree_taxon_id` → 科学名精确唯一匹配 → PPI 项目 alias 默认值。用户显式指定的 STRING tree TaxID 不得被 alias 覆盖。无法唯一匹配返回 `target_string_tree_unresolved`,不做模糊猜测。
|
||
|
||
### 输出
|
||
|
||
```json
|
||
{
|
||
"selection_mode": "exact_string|tree_nearest|model_fallback|unresolved",
|
||
"project_species_code": "Ft",
|
||
"target_tree_taxon_id": "62330",
|
||
"selected_string_taxon_id": "3562",
|
||
"selected_string_name": "Spinacia oleracea",
|
||
"lca_taxon_id": "...",
|
||
"lca_name": "...",
|
||
"target_edges_to_lca": 4,
|
||
"candidate_edges_to_lca": 3,
|
||
"tree_distance": 7,
|
||
"string_version": "12.0",
|
||
"snapshot_id": "...",
|
||
"requires_user_confirmation": true
|
||
}
|
||
```
|
||
|
||
## 解析算法
|
||
|
||
1. 加载并验证固定 snapshot。
|
||
2. 用显式 TaxID、科学名或现有常用 alias 将目标解析为 STRING tree 节点。
|
||
3. 若目标节点本身 `is_STRING_species=true`:
|
||
- 返回 `exact_string`;
|
||
- PPI 直接使用该 TaxID;
|
||
- 不插入 Ortholog。
|
||
4. 若目标节点存在但不受 STRING 支持:
|
||
- 候选池限定为 Viridiplantae 子树内 `is_STRING_species=true` 的节点;
|
||
- 计算目标与每个候选的 LCA 和双向拓扑边数;
|
||
- 排序键固定为 `(tree_distance, candidate_taxon_id, candidate_name)`;
|
||
- 返回 Top 3,模式为 `tree_nearest`;
|
||
- 用户确认候选后才准备参考 PEP、执行 Ortholog,再执行 PPI。
|
||
5. 若目标名称/TaxID 有歧义:
|
||
- 返回 `unresolved`,要求用户补充 STRING tree TaxID 或精确科学名;
|
||
- 不推荐 At,避免把可修正的身份问题伪装成生物学兜底。
|
||
6. 若目标完全无法解析且用户选择继续,或有效 tree 中没有植物 STRING 候选:
|
||
- 返回 `model_fallback`;
|
||
- 推荐 At/3702;
|
||
- 显示“远缘模型兜底,不是近源物种”;
|
||
- 用户确认一次后才进入 Ortholog→PPI。
|
||
7. 若缓存无效:
|
||
- 返回资源错误;
|
||
- 不提供 At 兜底,避免掩盖部署故障。
|
||
|
||
## 身份与依赖边界
|
||
|
||
项目级身份不变:
|
||
|
||
- `targetSpecies`、`referenceSpecies`、`scope_id`、`memberSetId` 和文件名继续使用 `Species_Code`。
|
||
|
||
新增 PPI 技术身份:
|
||
|
||
- `ppiSpecies`:唯一 STRING selector,可为旧 alias 或数字 TaxID;
|
||
- `ppiReferenceSpeciesCode`:可选旧项目 code,registry-only 候选允许为空;
|
||
- `ppiReferenceStorageKey`;
|
||
- `ppiReferenceTaxonId`;
|
||
- `ppiReferenceSelectionMode`;
|
||
- `ppiReferenceUserConfirmed`;
|
||
- `ppiReferencePolicyId`。
|
||
|
||
`snapshot_id = sha256(parser_schema_version + registry_sha256 + tree_sha256)`。`ppiReferencePolicyId` 由项目目标 Species_Code、目标 tree TaxID、选择的 STRING TaxID、selection mode、STRING version 和 `snapshot_id` 计算。它记录 PPI 如何选择和确认参考物种,不作为 Ortholog mapping 的复用身份,也不进入全局 gene-family `scope_id`。
|
||
|
||
Ortholog 另行计算 `orthologMappingIdentity`,至少绑定 target/member set、参考 Species_Code/TaxID、query/reference PEP SHA256、BLAST 参数和工具版本。只有该身份一致时,才可复用 final mapping 或 `ortholog/*_pairs.txt` 中间结果;PPI policy 改变但序列和 Ortholog 参数未变时,不应无意义重跑 BLAST。
|
||
|
||
STRING registry 不保证提供项目三字母 `Species_Code`。科学身份始终以 `ppiSpecies` 中的数字 STRING TaxID 为准;job-local 参考 PEP、ID map 和 Ortholog subject label 使用 `ppiReferenceStorageKey`。已存在唯一旧 code 时可兼容读取旧目录;registry-only 候选的 `ppiReferenceSpeciesCode` 为空,存储键固定按 `string_taxon_{taxid}` 生成,不得写回全局物种表或冒充项目 Species_Code。
|
||
|
||
现有 NCBI Datasets 下载器只可作为“按已选 TaxID 获取参考 PEP”的文件传输层,不参与候选发现、树排序或物种身份推断;本轮不建设 NCBI taxonomy 映射。
|
||
|
||
Ortholog 仍只是 producer:只有 `tree_nearest` 或已确认的 `model_fallback` 缺少目标→参考映射时才动态插入。PPI 是选择策略 owner。KaKs 不读取 PPI 的 STRING 候选;若用户另行要求 KaKs,独立检查其 reference CDS/PEP。
|
||
|
||
PPI fallback 只写 PPI 专用参数,并给动态 Ortholog 标记 `dependencyOwner="ppi"`。KaKs 调度路径必须忽略 `ppiReference*`、`ppiReferenceStorageKey` 与 `ppiReferencePolicyId`。fallback PPI 与 KaKs 同批且需要不同参考物种时,不在本轮自动生成两套 Ortholog;本轮联合验收只覆盖 direct Os PPI 不被 KaKs 阻断。
|
||
|
||
现有参考包下载函数不得为 PPI-only 请求隐式追加 `kaks`。`requested_stages=["ppi"]` 只要求参考 PEP;`requested_stages` 明确包含 `kaks` 时,既有 CDS/PEP 行为保持不变。此处只解除 owner 泄漏,不改变 KaKs 逻辑。
|
||
|
||
## 前端行为
|
||
|
||
- `exact_string`:不弹参考选择框,不显示 Ortholog。
|
||
- `tree_nearest`:显示 Top 3、TaxID、LCA 名称、拓扑距离、STRING 版本,用户选择后继续。
|
||
- `model_fallback`:单独警告“拟南芥是远缘模型兜底”,默认不勾选;用户确认后记录确认状态。
|
||
- `unresolved`:允许补充 TaxID/科学名、显式选择参考物种或跳过 PPI。
|
||
- 缓存错误:显示部署资源错误,不显示生物学 fallback。
|
||
|
||
同一 `ppiReferencePolicyId` 的确认在当前批次内只询问一次;参考物种或 snapshot 改变后必须重新确认。
|
||
|
||
STRING 候选的参考 PEP 可下载性初始标记为 `unknown`。NCBI Datasets 下载失败时保留当前候选和错误,允许用户选择第二候选或上传 PEP;不得自动换候选或静默回退 At。
|
||
|
||
单次 PPI 执行继续只解析一个目标物种。多目标请求不得把第一个目标的推荐偷用于其余目标,保持现有“需要显式参考/Ortholog mapping”的行为,不在本轮扩展为多目标自动推荐。
|
||
|
||
## Manifest 与诊断
|
||
|
||
预检、等待确认和等待参考 PEP 使用独立的 decision record,不写成最终 failed PPI Manifest。只有真正提交 PPI 执行后发生成功或失败时,execution Manifest 才记录:
|
||
|
||
- project Species_Code;
|
||
- 原始目标输入和解析方式;
|
||
- 目标 tree TaxID;
|
||
- 选择模式;
|
||
- 选中 STRING TaxID;
|
||
- LCA 和拓扑距离证据;
|
||
- snapshot 版本和 SHA256;
|
||
- `ppiReferencePolicyId`;
|
||
- 用户是否确认模型兜底;
|
||
- Ortholog mapping 路径及其参考 TaxID。
|
||
|
||
诊断代码至少区分:
|
||
|
||
- `string_registry_unavailable`;
|
||
- `string_registry_integrity_failed`;
|
||
- `target_string_tree_unresolved`;
|
||
- `no_string_tree_candidate`;
|
||
- `ppi_model_fallback_confirmation_required`;
|
||
- `ppi_requires_ortholog_mapping`;
|
||
- `stale_ortholog_reference_conflict`。
|
||
|
||
## 分任务与门禁
|
||
|
||
### T0 基线冻结
|
||
|
||
- 记录真实 9000 服务目录、测试结果和 Os/Ft/非 Ft 预检响应。
|
||
- 通过条件:现有聚焦测试绿色,错误现状可重复。
|
||
- 不通过:停止,不叠加新功能。
|
||
|
||
### T1 STRING snapshot 落地
|
||
|
||
- 下载两个官方文件,生成 Manifest,完成完整性和 tree 一致性校验。
|
||
- 通过条件:断网可加载;篡改任一文件会被拒绝;At 和 Viridiplantae 根节点校验通过。
|
||
- 不通过:不得进入 resolver 开发。
|
||
|
||
### T2 只读 registry/tree loader
|
||
|
||
- 建立内存索引并按文件 SHA256 缓存,避免每个请求重复解析 97 MB 文件。
|
||
- 通过条件:第一次加载可测量;后续请求复用同一只读索引;结果不受字典遍历顺序影响。
|
||
- 不通过:不得接 API。
|
||
|
||
### T3 通用 resolver
|
||
|
||
- 实现 exact、Top 3 tree-nearest、unresolved、At model fallback。
|
||
- 通过条件:Os direct;Ft 不靠静态表得到合理候选;第二个非 Ft 目标返回候选;无解析目标进入 At 确认分支。
|
||
- 不通过:不得修改生产预检。
|
||
|
||
### T4 TaxID 执行链
|
||
|
||
- 复用现有 `ppiSpecies` 作为唯一执行 transport,允许其承载数字 TaxID;backend、CLI、STRING client 和 Manifest 原样使用;旧 code 保持兼容,不新增平行 `ppiStringTaxonId` 字段。
|
||
- 通过条件:一个不在旧 12 项 map、但 registry 支持的物种能真实调用 STRING;请求、CLI 日志、API TaxID、Manifest 完全一致。
|
||
- 不通过:不得宣称通用支持。
|
||
|
||
### T5 PPI preflight、PPI-only 参考包和动态 Ortholog
|
||
|
||
- 用 resolver 替换 Ft 静态推荐;PPI-only 参考包只要求 PEP;保持 PPI/KaKs owner 隔离。
|
||
- 通过条件:direct PPI 无 Ortholog;tree nearest/已确认 At 才插 Ortholog;PPI-only 下载不索要 CDS;明确请求 KaKs 时原有 CDS/PEP 检查不变;KaKs 缺 CDS 不阻断 direct PPI。
|
||
- 不通过:不得进入 UI 完成验收。
|
||
|
||
### T6 前端确认与错误显示
|
||
|
||
- 复用现有动态弹窗,增加 Top 3 evidence 和 At model fallback 确认。
|
||
- 通过条件:前端选择的 TaxID 原样进入下载、Ortholog 和 PPI;缓存错误不显示 At;At 不能静默执行。
|
||
- 不通过:不得部署。
|
||
|
||
### T7 PPI/Ortholog Contract、Manifest、status 与 diagnosis 闭环
|
||
|
||
- 只同步 PPI/Ortholog 合同、Manifest provenance、旧映射冲突和状态复用;不修改 KaKs contract/Manifest/status。
|
||
- 通过条件:`/api/execute`、CLI 日志、Manifest、`/api/stage-status` 使用一致的 Species_Code/STRING TaxID/policy ID。
|
||
- 不通过:不得复用旧结果。
|
||
|
||
### T8 真实 9000 验收
|
||
|
||
- 重启真实服务和 worker,使用真实固定 snapshot 执行 direct 与 fallback 链路。
|
||
- 通过条件:Os direct;Ft tree nearest;第二个非 Ft;registry-only 物种;At 确认 fallback;缓存损坏;PPI/KaKs 隔离全部通过。
|
||
- 至少一个真实小家族完成“推荐→确认→参考 PEP→Ortholog→PPI→final artifacts→Manifest→status→前端展示”。
|
||
- 不通过:不得报告线上完成。
|
||
|
||
## 反模式约束
|
||
|
||
- 不继续扩充 `STRING_REFERENCE_RECOMMENDATIONS` 静态表。
|
||
- 不用 `species_code` 是否在旧 map 判断 STRING 支持。
|
||
- 不把 tree topology 描述成分子进化距离。
|
||
- 不因缓存错误静默使用 At。
|
||
- 不让前端重新计算或重新排序候选。
|
||
- 不只验证预检;必须验证 registry-only TaxID 能进入真实 STRING 请求。
|
||
- 不在错误工作副本测试后宣称真实 9000 已修复。
|
||
|
||
## 最终验收矩阵
|
||
|
||
1. Os:`exact_string`,无需 Ortholog。
|
||
2. Ft:由 tree 算法产生候选,无 Ft 特例读取。
|
||
3. 第二个非 Ft、非直接 STRING 植物:返回 Top 3。
|
||
4. 旧 12 项 map 外、registry 内物种:真实 PPI 成功。
|
||
5. 未知目标:进入用户确认 At 的 `model_fallback`。
|
||
6. cache missing/corrupt:资源错误,不回退 At。
|
||
7. 旧 mapping 与新 TaxID 冲突:拒绝复用。
|
||
8. Os PPI + 缺 CDS 的 KaKs:只作为隔离回归,证明 PPI 可继续;不改变 KaKs 的暂停原因或行为。
|