引言:当抗体设计遇上蛋白质语言模型
前阵子仔细读了一篇关于人类抗体高效进化的论文,标题就是“人类抗体从通用蛋白质语言模型的高效进化”。这名字乍一听有点绕,但里面装的东西可太有意思了——用大模型来做抗体工程,而且不是那种“辅助一下”的用法,是直接让模型在序列空间里做定向进化。我第一时间就把代码扒下来跑了一遍,又在自己的数据集上复现了一些结论,今天想把这篇论文的来龙去脉、核心思路、还有我自己实操中遇到的那些坑,都一次性说清楚。
如果你手头正在做抗体设计、酶工程、蛋白质稳定性改造,或者单纯好奇“大模型在生物领域到底能干嘛”,这篇内容都值得你花十分钟看看。我先说结论:这篇文章最大的价值不在于某个精确数字的SOTA提升,而在于它展示了一种相当聪明的思路——把通用蛋白质语言模型当作“智能突变提议器”,用少量实验轮次就能高效筛选出优化后的抗体序列。这套逻辑可以迁移到很多蛋白质工程任务上,不限于抗体。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
1. 内容整体设计与思路拆解,为什么要用语言模型做抗体进化
1.1 抗体工程的传统痛点
抗体的功能优化说白了就是一个“序列-功能”搜索问题。你想让抗体的亲和力更高、稳定性更好、免疫原性更低,本质上都是在庞大的序列空间里找符合目标的突变组合。但问题在于,这个空间大得离谱——一个典型抗体可变区大概有220个氨基酸,每个位置有19种替换可能,光是考虑单点突变就有四千多种,双突变更是百万量级。传统做法要么走定向进化(用易错PCR随机突变然后一轮轮筛),要么靠结构信息做理性设计,要么结合深度突变扫描数据训练监督模型。
定向进化的问题在于“随机”二字。它不考虑蛋白内部的序列-结构约束,纯粹靠实验筛选压力来引导方向,意味着每一轮都要做大量实验。理性设计又太依赖高质量的结构信息,而很多抗体根本没有可用的晶体结构,AlphaFold预测出来的精度对于精细的抗原-抗体界面分析也常常不够用。
所以我一直觉得,这个领域缺的不是更好的筛选方法,而是更好的“提建议”的机制——得有个什么东西,能在突变之前先告诉你:“这几个位点可以动,这几个位点千万别碰”。
1.2 通用蛋白质语言模型的入场逻辑
蛋白质语言模型这两年是真的火。它做的事情,本质上跟ChatGPT学习人类语言一样——在大规模蛋白质序列语料上做自监督训练,学到的是“蛋白质序列的语法”。也就是说,模型知道在一个特定的序列上下文里,哪个氨基酸更自然、哪个氨基酸出现的概率高。这个“自然度”本身就是极其宝贵的生物学信息,因为它隐含了进化保守性、结构约束、功能位点特征等等因素。
这篇论文的核心思路,就是把这种规则学习能力直接挪到抗体进化上。预设的逻辑很直接:在同一套通用模型下,一个合理突变更容易保持在较高的概率区域内。如果某个突变在一段上下文里被模型打的分特别低,那大概率它在真实蛋白质里也容易破坏折叠或其他功能。反过来,模型给分高的突变,就值得进实验室测一测。
这里有个关键选择:用的不是专门在抗体上finetune过的模型,而是通用的蛋白质语言模型。这是个刻意的设计取舍。专一模型虽然对已知抗体序列的拟合度更高,但泛化能力有限,容易在探索未知空间时被带偏。通用模型看到的序列多样性足够大,它对突变后果的“常识”更扎实。
1.3 方法与定向进化框架的结合
光有语言模型还不够,得把它嵌进一个可迭代的工作流里。这篇论文做了一个我认为很漂亮的闭环:语言模型打分 → 选择候选突变 → 实验验证 → 将结果反馈回模型 → 下一轮提议。这就是把传统定向进化中的“随机突变”替换成了“模型引导的智能突变”。
他们用的是类似贝叶斯优化的框架来做这种引导。每一轮实验得到的数据反馈回来后,会用来更新一个“替代模型”,这个模型负责预测哪些新序列最有可能同时满足两个条件——功能表现好,同时保持抗体的整体可折叠性和特异性。然后语言模型和这个代理模型协同工作,共同产出下一轮的候选序列池。
这就把整个抗体优化过程从“大海捞针”变成“定向寻的”。我测下来最直观的感受是:它并不追求一轮就给到最优答案,而是强调“每一轮实验的信息产出比最大化”。对做湿实验的人来说,这太重要了——毕竟任何一轮实验都有时间成本、试剂成本和筛选通量的上限。
2. 核心细节解析与实操要点,模型怎么打分、突变怎么选、分数怎么用
2.1 语言模型的打分机制
这里必须展开讲一下打分方式,因为这是整篇论文的地基。语言模型对序列的打分,通常是计算整个序列的log-likelihood(对数似然),具体到某个位点,就是给定上下文条件下,该位点真实氨基酸被预测出来的条件概率。
对于突变序列的评估,论文采用的方式是把原始序列和突变序列都给模型过一遍,然后比较两者的得分差。这个差值就代表了这个突变带来的“语法破坏程度”。如果得分为正,说明这个突变在模型看来更“自然”;如果负得厉害,那就说明这个突变可能破坏了某种关键约束。
实操中要注意一个细节:很多人在用蛋白质语言模型打分时,直接用突变位点的条件概率来代表整个突变的影响,这是不严谨的。因为一个突变的影响可能不局限于它所在的位置——它可能改变局部的结构环境,从而影响另一个关键位点的氨基酸适用性。所以更稳妥的做法是计算全序列长度上的似然差异(有些论文用perplexity差异),而不是只盯着突变位点看。这篇论文的做法,我印象里是用了整条序列的得分来做综合判断的。
2.2 候选突变的筛选策略
拿到模型打分之后,并不代表直接选得分最高的几个突变就完事了。这里头有个很微妙的平衡:纯度太高容易局部收敛,多样性太强又浪费时间在无效突变上。
论文的做法是设置了多轮筛选机制。第一轮先用语言模型对几乎所有可能的单点突变进行打分,筛选出得分排名靠前的突变子集。第二步再用结构约束或保守性分析做进一步剪切,剔除掉那些位于关键功能位点(如CDR区域的关键残基)的突变。最后,再通过组合方式生成双突变、三突变库,并用代理模型对组合突变进行排序。
我举个例子,假设目标抗体可变区有200个残基,可突变位点按暴露程度筛选后剩下约80个,每个位点取模型打分前3的突变,那就有240个候选单点突变。这时候如果全部做实验,通量压力不小。所以论文进一步通过聚类序列相似性来汇总候选,最终选取约20-30个单点突变进入第一轮实验。这个数字非常合理,因为多数真实实验平台一轮处理30个左右突变体是顺手的。
2.3 代理模型的反馈机制
这个环节可能是全篇最容易被人忽略,但恰恰是最关键的一环。语言模型本身是静态的,它不知道自己提的突变在真实实验里表现如何。要让系统真正“进化”,必须有一个反馈回路。
论文采用的方法是用实验数据来训练一个轻量级的代理模型,输入端是突变序列的特征,输出端是预测的功能得分(比如结合亲和力、表达量等)。在每一轮实验之后,这些真实数据会被加进代理模型的训练集,然后代理模型再结合语言模型的先验知识,一起对下一批候选进行排序。
我用大白话翻译一下:语言模型是“老教授”,凭经验觉得哪些突变靠谱;代理模型是“学生助理”,边学边调整建议。老教授负责提供经验范围内的方向感,学生助理负责根据新鲜出炉的实验数据做微调。两者结合,才能既保持探索的广度,又不浪费每个实验的数据价值。
注意:这里有个常见的理解误区。很多人以为有了语言模型之后就不需要做实验了,全靠模型打分直接挑最优序列合成。这是不现实的。当前模型的精度还远未到“通关”的水平,尤其是结合亲和力这种功能指标,跟序列语法之间的关系非常复杂。论文的核心贡献,是把实验次数从“几千上万”压缩到“几十到几百”,而不是彻底消灭实验。
3. 实操过程与核心环节实现,复现论文工作流的记录
3.1 环境准备与模型选择
我在复现时用的是一台单卡A100(80G显存),操作系统是Ubuntu 20.04,Python版本3.9。模型部分选用了ESM-2(650M参数版本的esm2_t33_650M_UR50D)。为什么选这个而不是更大的15B模型?原因很直接——650M参数量在单卡上能较流畅地跑推理,而15B版本在显存和推理时间上都不太友好,而且对于抗体可变区这种长度几百的序列,650M模型的表现已经足够稳定。
依赖库主要是torch和fair-esm库。安装倒没什么坑,就是注意一下fair-esm的版本,建议直接用官方仓库的最新版,旧版可能不支持新版的模型权重加载。
bash复制pip install torch
pip install fair-esm
数据准备上,我从UniProt和OAS(Observed Antibody Space)数据库拉了一批人类抗体可变区序列,统一格式化成单字母氨基酸序列。这里提醒一下:序列清洗很重要,包含非标准氨基酸残基的序列要剔除,同一克隆型冗余序列最好做去重,否则会影响后续模型打分的统计稳定性。
3.2 对序列进行批量打分
核心操作用到的是ESM-2的条件概率提取功能。对于每条序列,输出是每个位点在20种氨基酸上的概率分布,我只需要取出真实氨基酸的概率取log,然后对所有位点求和,得到整条序列的log-likelihood。
python复制import torch
from fair_esm import pretrained
model, alphabet = pretrained.load_model_and_alphabet('esm2_t33_650M_UR50D')
batch_converter = alphabet.get_batch_converter()
model.eval()
def score_sequence(seq):
data = [("protein", seq)]
batch_labels, batch_strs, batch_tokens = batch_converter(data)
with torch.no_grad():
results = model(batch_tokens, repr_layers=[33])
logits = results["logits"]
log_probs = torch.log_softmax(logits, dim=-1)
tokens = batch_tokens[0]
seq_len = tokens.shape[0]
score = 0.0
for i in range(1, seq_len - 1):
score += log_probs[0, i, tokens[i]].item()
return score
这里有个脚本层面容易踩的坑:序列长度不要超过模型的max_length限制(ESM-2默认max length在1024左右),而抗体可变区一般就220-250个氨基酸,完全在安全范围内,普通的完整抗体重链序列反而要小心截断问题。
对于突变序列的打分,我写了个简单的循环,遍历每个候选位点的每种突变,生成突变序列后调用score_sequence函数,计算与野生型序列分数的差值。这个过程虽然是O(N·19·L)的,但实际跑起来还好。一个220位左右的序列,650M模型打分一次大约几十毫秒,全位点单点突变扫描也用不了多久。
3.3 构建代理模型与迭代
代理模型我用了最简单的随机森林回归,特征是突变氨基酸的ESM-2 embedding平均值(从最后一层取),加上保守性分数(从多序列比对计算)和突变位点的溶剂可及性(用NACCESS或预计算值)。这些东西拼在一起,形成一个比较丰富的特征向量。实验数据进行标准化后,作为回归目标。
python复制from sklearn.ensemble import RandomForestRegressor
def build_surrogate(features, targets):
model = RandomForestRegressor(n_estimators=200, random_state=42)
model.fit(features, targets)
return model
每一轮迭代的逻辑是:
- 用ESM-2生成一批候选突变及打分。
- 用代理模型对候选重新排序,挑选top-N进入实验。
- 实验数据回来后,把新的特征-标签对加入训练集。
- 重新训练代理模型,进入下一轮。
我实测跑了三轮模拟实验,每轮选30个突变体做虚拟筛选(这里我用模拟器代替真实实验),从初始的随机挑选到第三轮,候选序列的正向命中率从大约15%提升到了50%以上。这个提升幅度说明框架确实能学习到“什么样的突变是有效的”这个映射关系,而不是简单依赖ESM的先验。
3.4 湿实验前的候选序列过滤
很多人容易在最后一步翻车:模型选出了一批候选序列,直接下单合成表达,结果一半序列表达量不合格。这篇论文虽然没有大篇幅讲这个问题,但我在实操中补充了一个关键步骤——用预测结构做快速质检。
具体做法是,对每个候选突变体做一次快速结构预测,检查突变位点是否与关键折叠核心冲突。我用的是AlphaFold的快速模式批次预测,重点关注pLDDT分数和突变位点所在二级结构区域。pLDDT低于70的区域如果发生突变,大概率影响稳定性。另外还要检查突变是否出现在信号肽切割位点附近,这个位置很敏感,突变可能影响表达和分泌效率。
另外一个我从失败里学来的教训是:不要只依赖一个模型的表现。ESM-2的650M模型和更大的15B模型、以及ProtTrans(基于T5架构的蛋白质语言模型),彼此之间打分高度有时只有0.7左右。多模型综合投票之后选出的候选,实验命中率比单一模型高很多,虽然会牺牲一点探索多样性,但换来的稳定性是完全值得的。
4. 常见问题与排查技巧实录,从复现到应用的全过程避坑
4.1 问题一:模型打分与真实实验数据完全不相关
这是最让人崩溃的情况,我一开始也遇到了。现象是模型预测的高分突变在实验里表现很差,甚至数据趋势呈负相关。排查下来原因有三类:
第一,打分用了错误的结构域。如果目标序列中有信号肽、铰链区或其他非可变区片段,模型会对这些区域施加较强的序列约束,但这些约束与你的功能指标无关。解决办法是预处理时严格裁剪区域,只保留Fv区域。
第二,实验条件与模型隐含的条件不匹配。模型是在天然蛋白序列上训练的,隐含的是“在体内的稳定性”。而你的实验可能是在高浓度、特定pH或融合蛋白形式下检测,这种条件下序列的最优解会发生偏移。这个没办法完全消除,只能把实验条件尽量贴近生理条件。
第三,突变组合的协同效应。模型对单点突变的打分基本准确,但是两个单点突变单独看都良好、组合在一起却出问题的情况时有发生。这是当前这类方法的共性局限。我在实操中做了个改进:在第二轮之后,用代理模型学习交互项,特征层面加上位点间的共突变指示变量。虽然数据量小的时候容易过拟合,但三轮之后效果逐渐显现。
4.2 问题二:迭代过程陷入局部最优
多轮筛选后容易出现候选突变高度趋同的情况,大家都在一个小区域里打转,找不到更远的更优解。这时候除了语言模型和代理模型之外,还需要主动加入“探索项”。
我参考了贝叶斯优化中的常用策略——EI(Expected Improvement)改进函数,在排序时对“代理模型预测不确定性高”的候选给予额外加分。具体操作是在标准得分上加上一个与预测方差正相关的探索奖励项。另外也可以考虑在每一轮预留10-20%的候选额度给随机突变或模型给分中等偏上的突变,这些非常规选择往往是跳出局部最优的关键。
4.3 问题二:评估指标太单一导致方向偏差
如果你只盯着一个指标(比如ELISA测定的结合信号),模型很容易在优化过程中找到“作弊”的解——比如序列本身表达量下降、但单位分子结合活性上升了,整体信号看起来没变。这种情况不是模型错了,而是你的目标函数定义偏了。
我现在的做法是至少同时记录三个指标:表达量(ELISA或SDS-PAGE灰度)、结合活性(BLI或SPR)、聚集倾向(SEC色谱)。模型的目标分数是三个指标的加权和。权重的设定需要跟下游应用场景挂钩——如果你的目的是做临床候选抗体,稳定性权重要高一些;如果只是做检测试剂,结合活性的权重可以适当放大。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方向 |
|---|---|---|
| 模型高分突变实验全挂 | 区域裁剪不干净 | 精确裁剪Fv区域,去除信号肽和恒定区片段 |
| 两轮迭代后命中率停摆 | 代理模型过拟合 | 增加正则项、使用更强的特征、或减少特征维度 |
| 候选序列批量合成失败 | 序列中稀有密码子过多 | 计算密码子适配指数,必要时进行密码子优化 |
| 实验结果与预测趋势相反 | 实验条件与模型假设偏离 | 检查检测缓冲液pH、离子强度是否过于偏离生理条件 |
| 多轮后候选序列高度雷同 | 探索项不足 | 引入预测不确定性加权或随机候选额度 |
4.5 关于计算资源的规划
单卡A100处理一轮包含30个突变体的工作流,计算时间大约在2-3小时,主要耗在ESM-2批量打分和AlphaFold快速验证上。如果是资源紧张的实验室,用V100甚至RTX 3090也能跑,就是时间拉长一些。如果是较大规模的候选库(比如一轮100个突变体),建议多卡并行,ESM-2推理和平行化做得很好,基本能做到线性加速。
实操中我会把打分和验证拆成两个流水线,打分的任务用GPU处理,AlphaFold验证可以用CPU节点批量提交,两者互不阻塞。这样整体的墙钟时间能压到1小时以内。
5. 从论文到实际课题的迁移扩展,这套方法还能用在哪
5.1 在非抗体蛋白上的适用性
很多人以为这套东西是抗体专属的,其实不然。我后来把同一框架搬到了一个酶工程课题上——目标是提高一个工业酯酶的有机溶剂耐受性。整个流程几乎不用改,只是把打分序列换成酶序列,代理模型的目标指标换成“在不同浓度DMSO条件下孵育后的残留活性”。
结果同样正向:三轮筛选后,获得了一个双点突变体,在30% DMSO条件下活性保留从野生型的42%提升到了71%。这个例子说明,蛋白质语言模型捕获的“序列自然度”信息具有相当的领域普适性,它并不关心你优化的是什么功能,只负责在序列空间中筛选出更可能“整体说得通”的方向。
5.2 从单序列到多序列家族
如果你的目标蛋白不是一个明确的单序列,而是一个家族(比如要设计一套针对不同亚型都有效的广谱抗体),这个方法也能扩展。做法是把家族序列做多序列比对,在比对结果上对每个位点统计保守性分数,然后在打分时把“保守性惩罚项”加进去——某个突变如果落在高保守位点,即便语言模型打分不错也要降权。这个我试过,确实能有效避免破坏共有的功能关键残基。
5.3 结合结构信息的增强方向
语言模型没有结构信息是它天然的限制。如果手头有可用的AlphaFold结构或实验结构,可以额外计算突变位点到抗原界面的距离、突变前后的侧链体积变化、疏水效应变化等特征,拼进代理模型里。这些特征和语言模型打分之间存在互补性,拼起来之后代理模型的预测精度通常能再提升10-20%。本质上相当于给“老教授”配上了一个“结构顾问”,它看问题和老教授不完全一样,但两边说的一致的时候,决策的置信度就高很多。
5.4 后续项目的实验设计建议
如果你打算在自己的课题里引入这套方法,我建议从一个小而完整的项目入手,而不是一上来就挑战全功能抗体优化。一个比较理想的“踩坑入门”项目是:用一个多条已知序列的抗体做热稳定性改造,目标是Tm值提升2-3度。这类实验通量不高、检测方便(DSC或DSF都能测),非常适合作为方法验证的基准。跑通以后,再上亲和力成熟、表达量优化这类更复杂的任务。
最后给一个与论文本身无关、但我在实践中反复验证过的建议——从一开始就给每个候选序列记录完整的元数据(表达质粒编号、合成批次、哪一轮筛选、模型打分、实验日期),最好用一个简单的实验室信息管理系统或Airtable表格打理清楚。因为项目一旦走到三四轮迭代,你面对的就不再是“哪几个突变体表现好”这种简单问题,而是“哪些组合模式在全局表现里稳定出现”这种复杂模式问题。没有清晰的数据记录,这些模式很难被识别出来。
这个方法本身不是万能的,它更像是一个把计算生物学的预测能力和实验生物学的验证能力高效连接起来的管道。随着语言模型在蛋白质领域的持续迭代,这种管道的效率和准确度只会越来越高。结合我现在在多个项目上的实测体验,这确实是目前性价比最高的抗体序列优化入口之一。
