ContactSeek:利用AlphaFold 3接触概率评估基因编辑特异性
基因编辑是近十年生命科学领域最受关注的技术之一但“如何保证编辑器只改目标位点、不误伤其他相似序列”始终是落地难点。传统方法大多从序列比对角度评估脱靶风险而蛋白质结构信息往往被忽略。北大、华东师大等团队提出的 ContactSeek尝试把 AlphaFold 3AF3预测出的接触概率引入基因编辑器特异性评估为这个老问题提供了一个新视角。本文将围绕这一工作拆解 AF3 接触概率是什么、ContactSeek 的核心思路是什么以及如果你想在自己的项目中复现类似流程应该怎么做。1. 背景基因编辑器特异性为什么重要1.1 基因编辑器的核心问题以 CRISPR-Cas9 为代表的基因编辑工具工作原理可以简单概括为通过向导 RNAgRNA与目标 DNA 序列的碱基互补配对引导 Cas 蛋白结合到目标位点并完成切割。理想情况下gRNA 只与目标序列结合但实际基因组中存在大量与目标序列相似但不完全相同的位点Cas9 有可能在这些位点发生结合和切割这就是“脱靶效应”off-target effect。脱靶效应带来的风险非常直接在基因治疗场景下如果编辑器在非目标位点造成切割可能引入新的突变甚至激活原癌基因在作物育种场景下脱靶则会导致性状不可控。因此不管是在基础科研还是临床转化中特异性评估都是基因编辑器走向实际应用前必需的一步。1.2 现有特异性评估方法的局限目前主流的方法可以分为三类类别代表方法核心思路局限基于序列比对Cas-OFFinder、MIT 特异性评分在基因组中搜索与 gRNA 相似的序列统计错配位置和数量忽略了三维空间结构对远端错配的评估不够准确基于实验GUIDE-seq、Digenome-seq在细胞内高通量检测真实切割位点成本高、耗时长不同细胞类型结果差异大基于机器学习Elevation、CFD 评分用已有实验数据训练模型预测脱靶率依赖训练数据的分布泛化能力有限仔细观察可以发现上述方法几乎都把基因编辑过程简化为一维序列的匹配问题。但真实世界中Cas9 识别的是三维空间中的 DNA 双螺旋结构gRNA 与靶标 DNA 形成 R-loop 的过程是否稳定除了碱基互补之外还受到空间构象、氢键网络、结构域间的物理接触等因素影响。也就是说三维结构信息是有可能提高特异性预测准确率的重要信号。1.3 结构信息为什么能帮上忙当 gRNA 与目标 DNA 形成复合物时Cas9 蛋白的各个结构域会与核酸链产生大量原子层面的接触。这些接触位点的形成与否直接决定了复合物的稳定性。如果 gRNA 与一个候选脱靶位点的序列匹配度不算高但结构上恰好能够形成足够多的稳定接触那么它仍然可能被切割反过来如果序列匹配度很高但结构上存在位阻冲突或者接触模式异常实际切割效率可能并不高。ContactSeek 的基本出发点正在于此借助 AF3 预测蛋白质-核酸复合物结构的能力把“序列匹配”扩展为“序列结构接触”双重评估。简单来说不是只看 gRNA 和目标序列是否长得像而是看它们在一起时能不能形成稳定的结构接触。2. 理解 AlphaFold 3 与接触概率2.1 AlphaFold 系列的演进AlphaFold 是 DeepMind 团队开发的蛋白质结构预测工具。第一代在 2018 年的 CASP13 上初露锋芒第二代在 2020 年的 CASP14 上实现了接近实验精度的单链蛋白质结构预测。而 AlphaFold 3 在 2024 年发布关键突破在于可以预测蛋白质与其他分子类型DNA、RNA、小分子配体、离子等形成的复合物结构。这意味着AF3 不仅能看到蛋白质自身的折叠方式还能推断蛋白质与核酸结合时的整体构象。对于基因编辑领域这提供了一个此前难以获得的工具我们可以在计算机里模拟 Cas9-gRNA-DNA 三元复合物的空间排布并量化各部分之间的接触关系。2.2 接触概率AF3 输出中的关键信号在 AF3 的预测结果中除了最终的三维坐标还包含一组置信度相关的辅助信息。与本文相关的核心是“接触概率”contact probability它描述的是预测模型中两个残基/碱基之间形成空间接触的置信程度。这里要注意一组容易混淆的概念距离图distance map预测结构内部任意两个残基之间的空间距离矩阵。接触图contact map将距离图按某个阈值二值化距离小于阈值的标记为 1否则为 0。接触概率contact probabilityAF3 在推理过程中对每个残基对是否接触给出的概率估计可以理解为结构预测的“信心分数”。接触概率与静态距离图的本质区别在于距离图是从最终采样结构中直接计算出来的而接触概率往往来自对多个结构模型或对模型中不同区域的综合评估。后者包含了对结构不确定性的考量——如果某个接触在所有采样模型中反复出现那么这个接触的概率值就会很高说明该接触对复合物稳定性至关重要。2.3 为什么用接触概率而不是直接看三维坐标直接比较三维坐标看起来更直观但在实际计算中存在两个问题坐标系对齐不同结构预测结果之间没有天然的坐标系对应关系需要做结构叠加superposition这会引入额外的计算偏差。微小扰动的影响蛋白质和核酸都是柔性分子局部构象的微小变化可能造成坐标数值的大幅波动但不会改变整体的接触模式。相比之下接触概率是抽象化、离散化的描述天然规避了上述问题。即便两个结构的整体坐标略有不同只要接触模式一致接触概率矩阵就保持稳定。这也是 ContactSeek 选择接触概率作为核心输入的原因之一。3. ContactSeek 的核心思路拆解3.1 整体技术路线根据公开资料和团队的研究方向推断ContactSeek 的总体技术路线可以概括为四个阶段构建候选位点集合 → 生成 AF3 结构预测 → 提取接触概率特征 → 训练/评估特异性模型第一步给定一个 gRNA在目标基因组中检索所有可能结合的候选位点包括完全匹配位点和小错配位点。这一步与传统的脱靶预测方法类似。第二步对每个候选位点构建 Cas9-gRNA-DNA 复合物序列送入 AF3 进行结构预测。得到的是每个候选位点对应复合物的三维结构模型。第三步从 AF3 输出中提取接触概率矩阵重点分析 gRNA 与 DNA 链之间的跨链接触、Cas9 蛋白与核酸链之间的蛋白-核酸接触。第四步将接触概率特征输入特异性评估模型或者直接与实验脱靶数据做对比验证结构特征对脱靶预测的增益效果。3.2 关键创新点把结构信号压缩为可计算特征直接输出整个接触概率矩阵并不适合作为传统机器学习模型的输入因为矩阵维度高、噪声大。ContactSeek 的工程难点在于如何把高维接触概率矩阵压缩成稳定的特征表示。比较合理的做法是设计一组“接触统计量”目标链内部的接触密度非目标链与蛋白结构域的接触热点分布gRNA 与 DNA 互补区域的跨链接触强度接触概率的不对称性指标。这些统计量把复杂的结构信息压缩成几十维的特征向量再与序列特征、位置特征拼接形成完整的特征空间。3.3 与已有方法的关系有必要说明的是ContactSeek 并不是要完全替代现有工具。从逻辑上讲它是在现有方法之上的增强先用传统序列比对方法得到候选位点再用结构接触概率进行精细化筛选。这种两阶段策略在工程上是合理的因为基因组中 gRNA 的候选结合位点可能成千上万对每个位点都做 AF3 预测的成本很高所以先用低成本的序列筛选缩小范围再对高优先级位点做结构分析。4. 环境准备与数据流转如果你想在自己的项目中尝试这条技术路线需要提前准备一套可运行的生物信息学环境。下面列出的是最基础的工具链。4.1 推荐环境清单工具用途说明Python 3.10数据处理和建模主要开发语言AlphaFold 3结构预测需要申请使用权限或使用官方服务器BioPython解析结构文件处理 CIF/PDB 文件NumPy / SciPy数值计算计算距离矩阵和接触图scikit-learn 或 PyTorch构建预测模型根据任务复杂度选择基因组注释文件候选位点注释如 hg38.fa、基因注释 GTF 文件4.2 数据流转流程整个流程的数据流可以描述为gRNA 序列 ↓ 序列比对 → 候选位点列表含染色体位置、链方向、错配信息 ↓ 构建复合物序列 → AF3 结构预测 ↓ CIF 结构文件 JSON 置信度文件 ↓ 提取接触概率 → 构建特征矩阵 ↓ 特异性评估 / 脱靶风险排序每一步都会产生中间文件建议在项目开始时就把文件命名和目录结构规范好避免后续分析中数据集混乱。4.3 示例项目目录contactseek_demo/ ├── data/ │ ├── gRNA.txt # gRNA 序列 │ ├── genome.fa # 参考基因组 │ ├── candidates.tsv # 序列比对得到的候选位点 │ └── af3_output/ # AF3 预测结果 │ ├── model_0.cif │ └── model_0_conf.json ├── src/ │ ├── predict_structure.py # 调用 AF3 预测 │ ├── extract_contacts.py # 提取接触概率 │ ├── build_features.py # 构建特征矩阵 │ └── evaluate.py # 特异性评估 └── README.md5. 从 AF3 输出中提取接触概率代码示例5.1 解析 AF3 的 CIF 结构文件AF3 输出的是一个标准的 mmCIF 格式结构文件。可以用 BioPython 读取# 文件路径src/parse_cif.py from Bio.PDB import MMCIFParser def parse_af3_structure(cif_path): 解析 AF3 输出的 mmCIF 文件返回 structure 对象。 注意AF3 的 CIF 文件可能包含多个 model默认读取第一个。 parser MMCIFParser(QUIETTrue) structure parser.get_structure(af3_complex, cif_path) return structure if __name__ __main__: structure parse_af3_structure(data/af3_output/model_0.cif) for model in structure: for chain in model: print(fChain {chain.id}, residues: {len(list(chain.get_residues()))})运行后会打印出复合物中每条链的残基数量可以快速确认 CIF 文件是否被正确解析。5.2 计算 Cα 原子级别的距离矩阵要得到接触图首先需要计算残基两两之间的 Cα 原子距离# 文件路径src/compute_contact_map.py import numpy as np from Bio.PDB import MMCIFParser def get_ca_coordinates(structure, chain_idA): 提取指定链上所有残基的 Cα 原子坐标。 coords [] residue_ids [] for model in structure: for chain in model: if chain.id chain_id: for residue in chain: # 跳过水分子和异常残基 if residue.id[0] ! : continue if CA in residue: coords.append(residue[CA].coord) residue_ids.append(residue.id[1]) return np.array(coords), residue_ids def compute_contact_map(coords, threshold8.0): 根据距离阈值构建接触图。 默认 8 埃是蛋白质接触图中常用的距离阈值。 n coords.shape[0] contact_map np.zeros((n, n), dtypenp.int8) for i in range(n): for j in range(i 1, n): dist np.linalg.norm(coords[i] - coords[j]) if dist threshold: contact_map[i, j] 1 contact_map[j, i] 1 return contact_map if __name__ __main__: parser MMCIFParser(QUIETTrue) structure parser.get_structure(complex, data/af3_output/model_0.cif) coords, res_ids get_ca_coordinates(structure, chain_idA) print(f提取到 {len(res_ids)} 个残基的 Cα 坐标) contact_map compute_contact_map(coords, threshold8.0) print(f接触对数量: {contact_map.sum() // 2})这里的计算方式是逐对计算复杂度为 O(n²)。对于蛋白质-核酸复合物通常几百个残基来说足够用。如果以后扩大到更大体系可以改用 scipy.spatial.distance.cdist 加速from scipy.spatial.distance import cdist def compute_contact_map_fast(coords, threshold8.0): dist_matrix cdist(coords, coords) contact_map (dist_matrix threshold).astype(np.int8) return contact_map5.3 解析 AF3 的置信度 JSON 文件AF3 在输出结构的同时还会生成一个 JSON 文件其中包含 pLDDT每个残基的预测局部距离误差和 PAE预测对齐误差等置信度信息。这些信息可以作为接触分析的辅助特征# 文件路径src/parse_confidence.py import json def parse_af3_confidence(json_path): 解析 AF3 输出中的置信度信息。 with open(json_path, r, encodingutf-8) as f: data json.load(f) # 不同版本的 AF3 输出字段略有差异这里按常见字段名读取 # 实际使用时需要根据你得到的 JSON 结构调整 plDDT None if atom_plddts in data: plDDT data[atom_plddts] # 提取链级别的 pLDDT 汇总 result { mean_plddt: None, min_plddt: None, max_plddt: None, atom_plddts: plDDT, } if plDDT: result[mean_plddt] sum(plDDT) / len(plDDT) result[min_plddt] min(plDDT) result[max_plddt] max(plDDT) return result if __name__ __main__: conf parse_af3_confidence(data/af3_output/model_0_conf.json) print(平均 pLDDT:, conf[mean_plddt])pLDDT 高的区域代表 AF3 对局部结构预测非常自信这部分区域的接触关系更值得信赖。在特征工程中可以用 pLDDT 对接触概率做加权降低低置信度区域对结果的干扰。5.4 构建跨链接触矩阵在基因编辑复合物中最有分析价值的是不同链之间的接触尤其是 Cas9 蛋白链与 gRNA 链、gRNA 链与 DNA 靶链之间的接触。下面给出一个提取跨链接触的示例# 文件路径src/extract_cross_chain_contacts.py import numpy as np from Bio.PDB import MMCIFParser def extract_cross_chain_contacts(cif_path, chain1A, chain2B, threshold8.0): 提取两条链之间的接触对。 chain1 和 chain2 是链 ID具体取值需要根据 AF3 输出的链命名规则确定。 parser MMCIFParser(QUIETTrue) structure parser.get_structure(complex, cif_path) coords1, ids1 [], [] coords2, ids2 [], [] for model in structure: for chain in model: if chain.id chain1: for residue in chain: if residue.id[0] and CA in residue: coords1.append(residue[CA].coord) ids1.append(residue.id[1]) elif chain.id chain2: for residue in chain: if residue.id[0] and CA in residue: coords2.append(residue[CA].coord) ids2.append(residue.id[1]) if not coords1 or not coords2: print(未找到指定链请检查链 ID) return [], [] coords1 np.array(coords1) coords2 np.array(coords2) cross_contacts [] for i in range(len(coords1)): for j in range(len(coords2)): dist np.linalg.norm(coords1[i] - coords2[j]) if dist threshold: cross_contacts.append((ids1[i], ids2[j], round(dist, 2))) return cross_contacts if __name__ __main__: contacts extract_cross_chain_contacts( data/af3_output/model_0.cif, chain1A, chain2B ) print(f跨链接触对数量: {len(contacts)}) for c in contacts[:5]: print(c)5.5 一步到位的接触概率提取工具函数结合上面的逻辑可以封装一个函数一次性提取接触图、跨链接触和置信度信息# 文件路径src/extract_contacts.py import json import numpy as np from Bio.PDB import MMCIFParser from scipy.spatial.distance import cdist def extract_all_contacts(cif_path, json_pathNone, threshold8.0): 从单个 AF3 输出中提取全部接触相关信息。 parser MMCIFParser(QUIETTrue) structure parser.get_structure(complex, cif_path) # 收集所有链的 Cα 坐标 chain_data {} for model in structure: for chain in model: coords, res_ids [], [] for residue in chain: if residue.id[0] and CA in residue: coords.append(residue[CA].coord) res_ids.append(residue.id[1]) if coords: chain_data[chain.id] { coords: np.array(coords), residue_ids: res_ids, } results { n_chains: len(chain_data), chain_ids: list(chain_data.keys()), contacts: {}, } # 计算每条链内部的接触图 for chain_id, data in chain_data.items(): dist_matrix cdist(data[coords], data[coords]) contact_map (dist_matrix threshold).astype(np.int8) results[contacts][fintra_{chain_id}] { contact_map: contact_map, contact_count: int(contact_map.sum() // 2), } # 计算两两链之间的跨链接触 chain_list list(chain_data.keys()) for i in range(len(chain_list)): for j in range(i 1, len(chain_list)): c1 chain_list[i] c2 chain_list[j] dist_matrix cdist( chain_data[c1][coords], chain_data[c2][coords] ) contact_map (dist_matrix threshold).astype(np.int8) results[contacts][finter_{c1}_{c2}] { contact_map: contact_map, contact_count: int(contact_map.sum()), } # 解析置信度文件 if json_path: with open(json_path, r, encodingutf-8) as f: conf json.load(f) results[confidence] conf return results if __name__ __main__: result extract_all_contacts( data/af3_output/model_0.cif, data/af3_output/model_0_conf.json ) print(链数量:, result[n_chains]) for key, value in result[contacts].items(): print(f{key}: {value[contact_count]} 对接触)这个函数直接为你后续的特征工程提供输入。每一条链的内部接触和每两条链之间的跨链接触都可以继续加工成特异性评分特征。6. 基于接触概率评估特异性的算法思路6.1 定义特异性评分拿到接触特征后接下来要解决的是怎样从接触信息中量化评估“这个 gRNA 在候选位点上的切割特异性”一个直观的思路是构建一个参考分布。对于目标位点我们期望 gRNA 与 DNA 靶链形成紧密、稳定、高接触概率的双链结构而对于候选脱靶位点即便序列上只有几个错配其结构接触模式也应与目标位点有明显差异。具体来说可以设计以下评分函数# 文件路径src/scoring.py import numpy as np def contact_difference_score(target_contact_map, candidate_contact_map): 计算目标位点与候选位点的接触图差异。 差异越大说明候选位点与目标位点的结构接触模式越不同 越有可能是安全的不容易切割。 这里使用简单的逐元素差异比例作为评分。 if target_contact_map.shape ! candidate_contact_map.shape: raise ValueError(两个接触图的维度不一致请确认序列对齐是否正确) total_pairs target_contact_map.size diff_pairs np.sum(target_contact_map ! candidate_contact_map) # 归一化到 0~1数值越大表示差异越大 score diff_pairs / total_pairs return score def contact_stability_score(contact_map, plDDT_weightsNone): 计算接触稳定性评分。 如果提供 plDDT 权重则对接触图进行加权低置信度区域的接触会被降权。 if plDDT_weights is not None: if plDDT_weights.shape ! contact_map.shape: raise ValueError(plDDT 权重矩阵维度与接触图不一致) weighted contact_map * plDDT_weights return float(weighted.sum()) return float(contact_map.sum())6.2 结合序列特征和接触特征单纯使用接触特征还不够因为序列信息仍然是最基础的判据。建议将两类特征拼接成一个综合特征向量再输入到一个简单的分类器如梯度提升树或逻辑回归中# 文件路径src/build_features.py import numpy as np def build_feature_vector( seq_identity, # 序列一致性0~1 mismatch_count, # 错配数量 mismatch_positions, # 错配位置列表 contact_diff_score, # 接触图差异 contact_stability, # 接触稳定性 mean_plddt # 平均 pLDDT ): 将序列特征和结构接触特征拼接为一个特征向量。 这是输入模型的最终表示。 features np.array([ seq_identity, mismatch_count / 20.0, # 归一化 len(mismatch_positions) / 20.0, # 归一化 contact_diff_score, contact_stability, mean_plddt / 100.0, # pLDDT 归一化到 0~1 ]) return features6.3 一个简化的实验验证流程整个评估流程可以按下面的步骤组织选取一组已发表的 gRNA以及对应的实验验证脱靶数据例如 GUIDE-seq 数据。对所有 gRNA 的已知靶向位点和候选脱靶位点进行 AF3 预测。提取接触特征和序列特征。用一部分数据训练分类器有脱靶实验信号/无脱靶信号。在剩余数据上评估模型性能对比仅用序列特征和加入接触特征后的 AUC 差异。如果加入接触特征后 AUC 显著提升说明结构信息确实对脱靶预测有增益这也正是 ContactSeek 的核心逻辑。7. 常见问题与排查思路7.1 AF3 预测结果可信吗问题现象常见原因解决思路预测结构的 pLDDT 整体偏低复合物体系过大或输入序列有误检查序列是否完整尝试拆分复合物分步预测不同运行批次结果差异大AF3 的随机采样增加预测次数取多次预测的平均接触概率接触概率与实验数据矛盾忽略了离子/辅因子确认是否需要添加 Mg²⁺ 等金属离子7.2 基因编辑 DNA 复合物预测的注意事项AF3 本身是一个通用结构预测工具并非专门为基因编辑设计。在处理 Cas9-gRNA-DNA 体系时需要注意gRNA 和 DNA 是核酸分子AF3 对核酸的结构预测精度整体上低于蛋白质。建议结合实验结构如晶体结构、冷冻电镜结构交叉验证。Cas9 蛋白分子量大约 160 kDaAF3 推理时间较长。如果只关心 gRNA-DNA 接触区段可以考虑截取核心结构域进行预测。同一 gRNA 在不同的缓冲液、离子条件下构象可能不同AF3 预测只反映静态结构无法完全模拟动态过程。7.3 代码运行中的常见报错问题现象常见原因解决思路MMCIFParser 报错无法解析文件版本或编码问题确认 AF3 输出的 CIF 文件完整升级 BioPython 到最新版本键不存在 CA核酸链没有 Cα 原子对核酸链应检查 P 原子或 C4 原子而不是 CA链 ID 不匹配AF3 链命名规则与预期不一致先遍历打印所有链 ID再调整参数JSON 读取字段不存在AF3 版本升级导致字段名变化打印 JSON 的 keys 字段按实际字段名读取7.4 计算成本控制AF3 预测一个复合物结构通常需要较长时间和较高显存。如果候选位点数量很大建议采用分级策略第一级用 Cas-OFFinder、MIT 评分等传统工具把候选位点缩小到几十个。第二级对候选位点做聚类按序列相似度去重。第三级只对去重后的代表性位点做 AF3 预测。第四级用接触特征对预测结果排序再对排名靠前的位点做更精确的实验验证。8. 最佳实践与工程建议8.1 序列准备阶段在构建 gRNA 和候选位点的复合物序列时建议统一格式并仔细检查链的方向gRNA 一般以 5→3 方向书写靶向 DNA 链需要明确是正义链还是反义链AF3 预测时蛋白链、gRNA 链、DNA 链的顺序要固定便于后续跨样本对比。8.2 特征工程层面接触概率特征不要只保留二值化的接触图。建议同时保存原始距离值便于后续调整阈值接触概率的波动值反映预测稳定性关键区域如 PAM 序列附近、种子区附近的局部接触统计。这些细粒度特征在后续建模中可能比单一全局统计量更有区分度。8.3 模型层面不要一上来就用复杂的深度学习模型。接触概率特征本身维度有限先用逻辑回归、随机森林这类可解释模型快速判断特征的有效性。如果确认有增益再逐步过渡到更复杂的模型。可解释性在这个领域的价值非常高因为研究人员需要知道“为什么这个位点被判定为高风险”而不是只拿到一个黑盒分数。8.4 实验验证层面所有计算预测最终都需要实验验证。建议在项目设计之初就预留实验对照阳性对照已知的高效率靶向位点。阴性对照已知的无活性脱靶位点。不确定性对照通过结构预测本身置信度低的区域。计算预测的意义是缩小实验范围、提高实验效率而不是替代实验。8.5 安全与合规基因编辑技术涉及生物安全和伦理问题。在开展任何基因编辑相关的计算分析和实验之前请务必确认实验方案符合所在机构、地区的伦理审查要求数据使用符合相关规定涉及人类基因组数据的注意数据隐私和授权要求不要将相关技术用于违法或不道德的目的。这一点需要放在所有技术讨论之前和之上。9. 总结这篇文章从基因编辑器特异性的痛点出发介绍了 ContactSeek 的核心思路利用 AlphaFold 3 预测复合物结构的接触概率将结构信息与传统的序列比对信息结合用于基因编辑器的脱靶风险评估。文中给出了一套从 AF3 输出中提取接触图的 Python 工具代码并讨论了特征工程、模型构建和计算成本控制等工程问题。值得重申的是ContactSeek 所代表的趋势并不仅仅是“用一个新的深度学习模型预测脱靶”而是把结构生物学工具引入基因编辑的安全性评估让计算预测从“看序列是否匹配”走向“看结构是否兼容”。这种思路在 AI for Science 的大背景下具有很强的延展性——凡是要理解分子相互作用的地方都可能用到类似的方法。如果你对这条路感兴趣下一步建议从这几个方向深入熟悉 AlphaFold 3 的实际使用方式重点看它如何输出核酸相关的置信度指标。找一批公开的 gRNA 脱靶实验数据尝试复现类似 ContactSeek 的特征提取流程。对比加入接触特征前后的模型性能差异体验结构信息带来的增益到底有多大。持续关注该研究团队的后续版本和开源代码了解他们是如何工程化落地的。技术迭代的速度很快但“结构决定功能”这个底层规律不会变。谁能把大模型的结构预测能力转化成可用的生物信息学工具谁就能在基因编辑这个赛道上走得更远。希望这篇文章能帮你理清思路也欢迎在实际复现中回来交流。