蛋白突变排序是蛋白质工程里最常被问到的任务之一:给一个蛋白序列,再给一批单点突变,如何判断哪些突变更可能保持功能、哪些更可能破坏功能。过去这类任务主要交给进化序列模型或蛋白质语言模型,大语言模型能不能胜任,一直没有统一答案。哈佛大学团队提出的 PG-LLM,正是面向 LLM 的蛋白突变排序标准化评测基准,它用同一套数据组织方式、同一套提示词协议和同一套排序指标,评估了 13 款主流 LLM 和 95 种专业模型。对于做突变效应预测、蛋白质设计筛选、模型评测和 LLM 应用的人来说,理解 PG-LLM 的设计思路,比单纯记住某个模型的分数更有价值。这篇文章把 PG-LLM 解决什么问题、怎么评测、怎么复现、有哪些坑一次讲清楚。
1. 为什么蛋白突变排序需要 PG-LLM 这样的标准化基准
1.1 突变效应预测不等于分类
很多数据库把突变标注成“致病”和“良性”,这是二分类问题。但蛋白质工程实验里更常见的是 deep mutational scanning(DMS)这类高通量数据,实验输出通常是一个连续值,例如细胞存活率、酶活性、蛋白丰度或热稳定性。
连续值带来的问题不是简单标成“有害”或“无害”,而是排序:在同一蛋白背景下,突变 A 是否比突变 B 影响更大。排序任务和分类任务虽然相关,但评估方式不同。
- 分类任务看重 AUC、F1、准确率。
- 排序任务看重 Spearman、Kendall、Top-K 召回。
- 模型可能分类很好,但中间排名一团糟。
- 也可能绝对分数偏差很大,但相对顺序很好。
LLM 在突变效应预测里的价值,恰恰可能不是给出准确的绝对效应值,而是对一组突变给出合理的相对顺序。PG-LLM 把“排序”作为核心任务,是因为排序更贴近蛋白质筛选真实使用场景:实验验证成本高,先让模型把候选突变排好队,再取 Top 一批去做湿实验。
1.2 通用模型和专业模型的评估信号并不对齐
蛋白质突变效应预测的模型来源非常杂。
传统专业模型包括进化序列模型、蛋白质语言模型、结构模型、混合模型。它们的输入形式完全不同:有的吃多序列比对,有的吃单条序列,有的吃 PDB 结构,有的吃序列和结构混合特征。输出也不是统一格式:可能是能量分数、log-likelihood、masked logits、结构损失,甚至分类概率。
通用 LLM 更特殊。它吃的输入是文本,输出是文本。要让 GPT 这类模型预测突变效应,必须先构造提示词,把蛋白序列和突变写进去,再让模型输出一个数值或判断。同一个模型,换一种提示词,结果可能完全不一样。
PG-LLM 面对的核心矛盾就在这里:模型类型差异太大,如果不用统一接口、统一指标,结果毫无可比性。它选择把问题标准化成一个对 LLM 友好的文本任务,再对所有模型统一输出排序分数。
1.3 PG-LLM 标准化的四个维度
PG-LLM 称为“标准化评测基准”,重点在于它把评测链路里最容易失控的四个环节都固定下来。
第一是数据格式。蛋白编号、突变表示、实验分数方向必须统一。例如A123V和p.Ala123Val如果不做归一化,模型解析和指标计算都会出错。
第二是模型接入方式。通用 LLM 使用文本提示词,专业模型使用各自原生接口,但最终都必须输出一个“可排序分数”。
第三是指标计算。统一使用排序类指标,而不是直接比较不同模型的绝对误差。
第四是评测协议。包括训练集和测试集如何划分、是否控制同源序列、是否允许多次采样、随机种子如何设置。
这四个维度看似简单,实际任何一处不一致,都会让两篇论文的结果无法对照。这也是 PG-LLM 这类基准对社区最大的贡献。
2. PG-LLM 评测什么:对象、数据与指标
2.1 13 款主流 LLM 如何归类
标题里提到了 13 款主流模型,具体名单应该以论文附表为准。从评测角度来看,这 13 款模型不是简单堆数量,而是覆盖了不同接入方式。
| LLM 类型 | 常见接入方式 | 评测前需要确认的事情 |
|---|---|---|
| 闭源对话模型 | Chat Completion API | 输出长度限制、随机性、token 计费 |
| 开源指令模型 | Transformers / vLLM | 本地显存、上下文长度、量化效果 |
| 长上下文模型 | 多序列输入到 prompt | 长序列是否真的有效还是只处理了局部 |
| 推理增强模型 | 输出分析再打分 | 输出中夹杂原因,解析规则是否稳定 |
不要把“13 款主流模型”理解成 13 个一模一样的 LLM。它们之间的差异不仅影响最终分数,还影响评测脚本是否要针对性地处理输出格式。
2.2 95 种专业模型覆盖哪些技术路线
95 种专业模型的名单同样以论文为准,但理解评测结果不需要逐个记忆。可以把它们按技术路线归类。
| 专业模型类型 | 典型输入信号 | 打分形式 | 在排序评测中的注意点 |
|---|---|---|---|
| 进化序列模型 | 多序列比对 | 保守性/能量分数 | 对同源序列数量非常敏感 |
| 蛋白质语言模型 | 单条序列 | log-likelihood 或 embedding 分数 | 需要统一坐标和突变 tokenization |
| 结构模型 | PDB 结构或预测结构 | 结构稳定性分数 | 结构缺失时表现会退化 |
| 混合模型 | 序列 + 结构 + 注释 | 综合分数 | 特征对齐和缺失值处理复杂 |
| 监督学习模型 | 人工特征或已有标签 | 分类概率 | 训练集泄漏风险更高 |
这些模型和 LLM 放在一起评测,真正的意义是回答一个问题:通用大语言模型在蛋白突变排序上,到底有没有赶上专门为蛋白质设计的模型。
2.3 输入数据长什么样
在 PG-LLM 的评测框架里,最底层的数据是一张表格。每一行表示“某个蛋白的某个突变,实验测出来的效应值”。
一个简化后的数据格式如下:
protein,variant,experimental_score BRCA1,A123V,-1.25 BRCA1,D456N,0.68 BRCA1,E789K,-0.42 TP53,R175H,-2.10 TP53,Y220C,-1.85字段含义:
protein:蛋白标识,可以是基因名或 UniProt ID。variant:单点氨基酸突变,使用标准的A123V表示。experimental_score:实验测得的连续效应分数。
这里要特别注意experimental_score的方向。有的实验分数越高代表功能越强,有的越高代表破坏越大。如果不统一方向,Spearman 的正负号会反,评测结果会完全错误。
2.4 排序指标怎么选
PG-LLM 这类基准不会只看一个指标。常用的排序指标包括以下这些:
| 指标 | 计算对象 | 适合场景 | 注意点 |
|---|---|---|---|
| Spearman 相关系数 | 全部突变 | 判断整体单调关系 | 对离群点不敏感,适合通用排序 |
| Kendall tau | 全部突变 | 更关注逐对一致性 | 计算量略高 |
| AUROC | 二值化标签 | 判断正负分离能力 | 需要提前设定阈值 |
| AUPRC | 二值化标签 | 正样本很少时更准确 | 阈值选取影响结论 |
| NDCG@K | Top K 排序 | 关注头部排序质量 | 需要设定 K 和真实分数权重 |
| Top-K 召回 | Top K 排序 | 湿实验筛选场景 | 需要定义“真实阳性” |
对蛋白筛选来说,Top-K 召回往往比全局 Spearman 更实际,因为实验只会验证排名最靠前的几十个突变。PG-LLM 强调“排序”,意味着评测时应当优先看模型能不能把真正强的突变放到前面,而不是只看回归误差。
3. 本地搭建可复现的排序评测流程
3.1 环境准备
在本地复现 PG-LLM 的评估思路,不需要一次性搭建完整的大平台。先跑通一个小规模评测脚本,再逐步扩大。
推荐使用 conda 管理环境:
conda create -n pgllm-eval python=3.10 -y conda activate pgllm-eval pip install pandas numpy scipy scikit-learn matplotlib openpyxl如果后面要调用 LLM API,还需要安装对应 SDK。以 OpenAI 兼容接口为例:
pip install openai需要注意,这里安装的不是某一个固定工具,而是一套通用评测链路。实际项目中的依赖版本最好写入requirements.txt,避免换机器后结果无法复现。
3.2 数据字段统一
评测前必须先把突变表示统一成一种格式。常见写法有三种:
A123VAla123Valp.Ala123Val
推荐统一成一位氨基酸编码:
import re amino_acid_map = { "Ala": "A", "Arg": "R", "Asn": "N", "Asp": "D", "Cys": "C", "Gln": "Q", "Glu": "E", "Gly": "G", "His": "H", "Ile": "I", "Leu": "L", "Lys": "K", "Met": "M", "Phe": "F", "Pro": "P", "Ser": "S", "Thr": "T", "Trp": "W", "Tyr": "Y", "Val": "V", } def normalize_variant(variant: str) -> str: variant = variant.replace("p.", "") m = re.match(r"^([A-Z][a-z]{2})(\d+)([A-Z][a-z]{2})$", variant) if m: wt = amino_acid_map.get(m.group(1)) mut = amino_acid_map.get(m.group(3)) if wt and mut: return f"{wt}{m.group(2)}{mut}" return variant.upper()这段代码把p.Ala123Val转成A123V。如果输入本来就是A123V,则原样返回。
注意:突变坐标在绝大多数生物学数据库里是 1-based,也就是第一位氨基酸是 1。脚本中不要混用 0-based 和 1-based,否则会出现看似格式正确、实际位置错一位的隐蔽错误。
3.3 核心评测脚本
有了统一数据,下一步是按蛋白分组计算排序指标。下面这段脚本是 PG-LLM 评估流程的最小实现。
import pandas as pd from scipy.stats import spearmanr, kendalltau df = pd.read_csv("dms_data.csv") pred = pd.read_csv("model_predictions.csv") # 关键:按 protein 和 variant 合并 merged = pd.merge(df, pred, on=["protein", "variant"], how="inner") results = [] for protein, g in merged.groupby("protein"): # 样本太少或分数没有变化时,相关系数没有意义 if len(g) < 5: continue if g["experimental_score"].nunique() < 2: continue if g["model_score"].nunique() < 2: continue rho, _ = spearmanr(g["experimental_score"], g["model_score"]) tau, _ = kendalltau(g["experimental_score"], g["model_score"]) results.append({ "protein": protein, "n": len(g), "spearman": rho, "kendall": tau, }) summary = pd.DataFrame(results) print(summary) print("平均 Spearman:", summary["spearman"].mean())这里有一个容易忽略的点:pd.merge使用的键是protein和variant。如果模型预测文件里的蛋白名和实验数据里的蛋白名大小写不一致,就会丢失大量匹配行。合并完成后,应当先检查行数有没有明显减少。
3.4 接入 LLM 并解析输出
通用 LLM 的输出不是结构化 JSON,必须先定义提示词,再写解析器。
一段最小提示词模板如下:
PROMPT_TEMPLATE = """You are evaluating single amino acid mutations in a protein. Protein: {sequence} Protein name: {protein} Mutation: {variant} Return a single numeric score. Higher score means the mutation is more functionally tolerant, lower score means more deleterious. Output only the numeric score. """输出解析建议先提取最后出现的数字,而不是随便取第一个数字:
import re import math def extract_numeric_score(text: str) -> float: text = text.replace(",", "") numbers = re.findall(r"-?\d+\.?\d*", text) if not numbers: return float("nan") return float(numbers[-1]) def score_mutation(client, model_name, protein, sequence, variant): prompt = PROMPT_TEMPLATE.format( sequence=sequence, protein=protein, variant=variant, ) resp = client.chat.completions.create( model=model_name, messages=[{"role": "user", "content": prompt}], temperature=0, max_tokens=16, ) content = resp.choices[0].message.content return extract_numeric_score(content)temperature=0是为了降低随机性,但并不能保证绝对稳定。如果模型仍然输出解释性文本,比如“This mutation is likely harmful, score: -0.8”,上面的解析器会取-0.8。如果输出里出现多个数字,规则要提前固定,避免评测脚本在真实数据上“碰运气”。
3.5 用 vLLM 部署本地推理服务
如果评测的 LLM 是开源模型,推荐用 vLLM 部署成 OpenAI 兼容服务。这样上层评测脚本只需要改base_url,不需要为每个模型重写推理代码。
vllm serve meta-llama/Llama-3.1-8B-Instruct \ --port 8000 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9启动后,脚本里这样连接:
from openai import OpenAI client = OpenAI( base_url="http://localhost:8000/v1", api_key="EMPTY", )本地 vLLM 服务的api_key只是占位符,不需要真实密钥。模型名在调用时要换成启动时实际加载的模型名。
4. 决定结果可信度的关键设计
4.1 零样本还是微调
PG-LLM 这类基准首先要明确:模型是否允许先在训练集上微调。
如果允许微调,那么专业模型和 LLM 之间的对比会混入训练数据因素,很难判断提升来自模型能力还是数据拟合。更稳妥的做法是先做零样本评估,再看少样本提示、微调、适配器带来的增量。
实际复现时,建议把评测流程设计成支持“零样本 + 少样本”两种模式。零样本用来衡量模型原有能力,少样本用来衡量模型在少量示例下的适应能力。两者分开报告,不要混合成一个分数。
4.2 序列同源性和数据泄漏
蛋白突变预测最容易出现的问题不是模型写错,而是数据泄漏。
如果训练模型时见过同源蛋白的突变数据,测试时再放一个相似蛋白进来,分数会虚高。标准做法是使用序列聚类控制同源性,常见的相似度阈值是 30% 或 50% 序列同一性。
复现评测时至少要做两件事:
- 按蛋白序列聚类,保证训练蛋白和测试蛋白不落在同一个聚类里。
- 检查 LLM 是否在预训练阶段见过对应蛋白序列。这个问题无法完全规避,只能通过在低同源性测试集上的表现来近似判断。
不控制同源性,评测结论很容易变成“模型记住了训练数据”,而不是“模型学会了突变排序”。
4.3 提示词模板和模型先验
同一个模型,在不同提示词下的表现可能差很多。PG-LLM 的价值之一就是固定提示词协议,让不同模型面对相同任务。
提示词设计有几个细节会影响结果:
- 是否给出蛋白名称。给出名字会让模型调用已有知识,但不一定是对实验数据有用的知识。
- 是否给出参考序列。序列太长可能超出上下文窗口,太短又丢失上下文。
- 是否给出正负方向。如果不说明“高分代表功能保持”,模型可能按照自己的理解输出相反方向。
- 是否允许解释。解释会提高输出解析难度,也会增加 token 成本。
最佳做法是把提示词作为变量做一次消融实验,而不是直接认定某一种模板最优。
4.4 排序指标的统计边界
排序指标也有统计噪声,尤其是蛋白内突变数量少的时候。
一个只有 20 个突变的小蛋白,Spearman 的波动范围很大。某一轮测试可能因为一个离群点就从 0.3 变成 0.6。因此,不要只看所有蛋白的平均 Spearman,还要看:
- 蛋白数量。
- 每个蛋白的突变数量。
- 指标标准差。
- 置信区间。
标准做法是在报告里同时给出 weighted Spearman,也就是按每个蛋白的突变数量加权。这样样本量大的蛋白对结果影响更大,更接近真实筛选场景。
4.5 多突变和实验标签异质性
PG-LLM 如果只做单点突变,评测相对干净。但真实蛋白质工程经常涉及组合突变、插入缺失和截短体。
组合突变的难点是上位效应:两个单点突变单独看都可能无害,同时出现却可能破坏蛋白。通用 LLM 在单点突变上的排序能力,不能直接推广到组合突变。
另一个问题是实验标签异质性。有的实验测的是稳定性,有的是活性,有的是表达量。不同实验分数不能直接合并比较。跨蛋白比较时,必须对每个蛋白单独计算排序指标,再聚合,而不是把所有行放进同一个回归模型。
5. 复现 PG-LLM 流程时最常见的五个坑
5.1 突变命名不规范
现象:模型预测结果和实验数据合并后匹配率为 0。
原因:一边使用A123V,另一边使用p.Ala123Val,甚至出现小写a123v。
检查方式:查看两个文件里的 unique 突变格式。
处理建议:统一用normalize_variant做标准化,合并前先统计两种格式的重复表。
5.2 参考序列坐标不匹配
现象:样本量看起来很多,但 Spearman 普遍接近 0。
原因:参考序列来自不同版本,突变坐标对应不同氨基酸。
检查方式:对每个蛋白检查wt_seq[position - 1]是否等于突变中的原始氨基酸。
处理建议:建立自己的参考序列索引,所有突变坐标以统一参考序列为基准,并在脚本中增加断言。
5.3 排序指标出现 NaN
现象:某些蛋白的 Spearman 显示为nan。
原因:模型对所有突变输出同一个分数,或者实验分数本身完全相同。
检查方式:增加唯一值数量检查。
处理建议:样本量少于 5 或唯一值少于 2 时跳过该蛋白,并在日志里记录跳过原因。
5.4 LLM 输出随机性没有控制
现象:同一个模型跑两次,结果排序变化很大。
原因:模型调用没有固定 temperature,或者使用流式输出时解析到不完整文本。
检查方式:固定temperature=0,对同一个 prompt 重复三次对比分数。
处理建议:评测结果取多次运行的平均排名,而不是单次输出。
5.5 把绝对分数高当成排序好
现象:某个模型输出的分数区间很大,看起来很有区分度,但 Spearman 很低。
原因:模型分数偏离实验分数,或者方向不一致。
检查方式:画散点图,看是否单调。
处理建议:坚持用排序指标评估,不使用 MSE 作为唯一标准。
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 合并后匹配行很少 | 突变格式不一致 | 统计 unique variant 格式 | 统一归一化后再合并 |
| Spearman 普遍为负 | 实验分数方向未统一 | 检查正负相关方向 | 按实验定义翻转分数 |
| 指标出现 NaN | 常数预测或样本太少 | 打印每个蛋白唯一值数量 | 加过滤条件并记录日志 |
| 结果不稳定 | 随机采样未控制 | 同一模型跑 3 次 | 固定 temperature 并用平均排名 |
| Top-K 结果和 Spearman 矛盾 | 全局排序和头部排序不一致 | 分别计算 Spearman 和 NDCG@K | 两个指标都报告 |
6. 从 PG-LLM 基准到蛋白质筛选落地
6.1 研究复现与工程落地的差异
在论文里跑通 PG-LLM 评测,和在生产级蛋白质筛选流程里落地,是两个不同问题。
研究复现阶段要保证的是公平、可复现、控制变量。工程落地阶段要考虑的是吞吐量、成本、失败率、模型更新、缓存和监控。
| 环节 | 研究复现 | 工程落地 |
|---|---|---|
| 数据集 | 公开 DMS 数据 | 自有湿实验数据,需要质量控制 |
| LLM 推理 | 单机 GPU 或 API 小量调用 | 高并发服务,缓存和限流 |
| 指标 | Spearman / AUROC | Top-K 推荐命中率、实验回报 |
| 输出解析 | 少量手工检查 | 大规模异常检测和自动重试 |
| 模型更新 | 固定版本 | 版本管理和回归评测 |
如果只是用 LLM 从大量突变里初筛出 Top 100,再做湿实验,那么关注的重点应该是 Top-K 召回率和稳定复现,而不是全局 Spearman 的一点点提升。
6.2 落地前检查清单
在把 PG-LLM 评估流程接入自己的项目前,可以按下面清单逐项确认。
- 是否统一了突变表示和参考序列坐标。
- 是否确认了实验分数方向,高分代表功能强还是破坏强。
- 是否做了同源序列去重,避免数据泄漏。
- 是否固定了提示词模板,并做了至少一次模板消融。
- 是否固定了模型版本和采样参数。
- 是否同时计算 Spearman、Kendall、NDCG@K。
- 是否记录了每个蛋白的样本量和跳过原因。
- 是否预留了缓存机制,避免同一突变重复调用 LLM。
- 是否保存了每一次评测的原始输出,方便回溯。
- 是否为模型升级保留了旧版本评测结果,方便对比回归。
这个清单不是摆设。任何一个环节缺失,评测分数都可能不可信。
6.3 下一步可以尝试的方向
理解 PG-LLM 之后,下一步可以围绕三个方向深入。
第一是少样本和上下文学习。尝试在提示词里放入几个已知实验分数,让 LLM 参考这些示例重新排序,观察是否比零样本更稳定。
第二是模型融合和集成排序。不同模型的错误模式不同,可以通过 rank-based 融合把多个模型排名合并,再用 PG-LLM 的统一指标评估融合后的效果。注意融合的目标是改善排序,而不是追求绝对分数更接近实验值。
第三是异常检测和输出约束。LLM 输出经常不是纯数字,可以探索用函数调用或者 constrained decoding 强制输出 JSON,再接入排序管道。这样能大幅降低解析失败率,也更容易在生产环境长期运行。
蛋白突变排序评测不会止步于一个基准。PG-LLM 真正有用的地方,是让模型对比从“谁在某个数据集上分更高”变成“谁对突变相对效应排序更稳定”。如果你想把 LLM 放进蛋白筛选流程,建议先按文中的最小流程跑通一个蛋白,再扩展到全量数据。评测脚本稳定后,每一次提示词改动和模型升级都能被客观衡量,这才是基准对工程实践最大的价值。