前几天讲的都是「AI 怎么运转」。今天换个角度:AI 怎么帮人类做出真正的新科学发现——不是写代码、答问题,而是折叠出实验测不出的蛋白、找到人没想到的新材料、给数学家提示新定理。共同的机制是一个后端人熟悉的模式:把昂贵的「真实验证」换成廉价的「模型预测」,再用预测去引导有限的验证资源。
蛋白质就是一条一维氨基酸序列,会确定性地折叠成一个三维形状——但这个「序列→形状」的映射人类解不出闭式解。类比后端:像拿到一段序列化的字节流(没有 schema),要反推出它在内存里的对象图布局。传统实验测结构(X 射线晶体学、冷冻电镜)像「跑一次几个月、几十万美元的全量物理扫描」;AlphaFold 像「训好的模型几分钟直接预测」。
蛋白质的功能由 3D 形状决定(酶的活性口袋、抗体的结合位点)。但实验测结构极慢——五十年只解出约 10 万个,而已知序列有上亿个,这就是所谓「序列-结构鸿沟」。AlphaFold2(Jumper et al. 2021)的机制核心是两点:
(1)MSA(多序列比对,Multiple Sequence Alignment)——把同一个蛋白在不同物种里的同源序列排在一起,当成「进化留下的分布式副本」。关键洞见:如果两个氨基酸位点在 3D 里相邻(接触),它们往往会共同演化——一个位点突变,另一个跟着补偿突变来维持结构稳定。这就像代码里「总是一起改动的两个模块」暗示它们在架构上耦合。AlphaFold 就从这种共变(co-evolution)信号反推出哪些氨基酸在空间上挨着。
(2)Evoformer——一个基于 attention 的模块,在「序列表示」和「配对表示(谁和谁接触)」两张表之间反复交换信息,最后由 structure module 直接吐出每个原子的三维坐标。2024 年的 AlphaFold3 进一步扩展到蛋白-DNA-小分子的复合体。
# 用 ESM Atlas 的 ESMFold 公共 API 折叠一条序列(无需 GPU) import requests seq = "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQAPILSRVGDGTQDNLSGAEK" # 你的氨基酸序列 r = requests.post( "https://api.esmatlas.com/foldSequence/v1/pdb/", data=seq, timeout=120, ) with open("predicted.pdb", "w") as f: f.write(r.text) # 返回标准 PDB 文件,可直接丢进 PyMOL / py3Dmol 看 # PDB 里每个 ATOM 行末尾的 B-factor 列,ESMFold 用它存 pLDDT 置信度 # pLDDT > 90 高可信;< 50 通常是柔性/无序区域,别当真 print("结构已保存,用置信度过滤后再下结论")
在巨大的晶体组合空间里找「稳定的新材料」,就像在庞大的配置空间里搜一个有效配置。判断一个候选材料稳不稳,传统要算DFT(密度泛函理论)——像「实际跑一遍昂贵的集成测试」,一个材料要几小时到几天 CPU。GNoME 用 GNN 把晶体建成图(原子是节点、化学键是边),直接预测能量——像用「静态分析器」秒判这段配置能不能过,省掉绝大部分昂贵验证。
新材料(电池、超导、催化剂)的瓶颈是搜索空间爆炸——元素怎么组合、原子怎么排布,组合数天文级,逐个 DFT 算不完。GNoME(Merchant et al. 2023,Google DeepMind)不是一次性预测,而是一个主动学习闭环(active learning loop):
GNN 先对海量候选预测稳定性 → 只把「最有希望稳定」的一小批送去做真 DFT 验证 → 验证结果(无论对错)回填训练集 → GNN 变得更准 → 再预测下一批。这个循环本质就是后端人熟悉的「便宜粗筛 + 贵资源精验 + 反馈回填」CI 闭环,也和强化学习的探索-利用同构。论文报告用它找到约 38 万个新的稳定晶体结构。
# 用 Materials Project API 查一个材料的 DFT 形成能(判断稳定性的基准量) from mp_api.client import MPRester with MPRester("YOUR_MP_API_KEY") as mpr: # materialsproject.org 免费申请 docs = mpr.materials.summary.search( formula="Li3PO4", # 一种固态电解质 fields=["material_id", "formation_energy_per_atom", "energy_above_hull"], ) for d in docs: # energy_above_hull == 0 → 位于凸包上 → 热力学稳定 stable = "稳定" if d.energy_above_hull < 1e-6 else "亚稳/不稳" print(d.material_id, round(d.formation_energy_per_atom, 3), stable)
这里 AI 不直接吐答案,而是「生成假设,让人(或自动器)去验证」——像 AI 帮你生成一堆候选查询计划/索引方案,你再 benchmark 哪个真的快。数学发现有两条截然不同的 AI 路线,都是这个套路。
路线 A — 引导人类直觉(Davies et al. 2021,DeepMind × 数学家):在大量数学对象(如纽结)的数据上训 GNN,让它找出「哪些不变量之间存在意料之外的相关性」,把这个模式当提示喂给数学家,人再去证明成严格定理。成果之一是纽结理论的一条新定理。这里 AI 是直觉放大器,不是证明机——最后的证明仍由人完成。
路线 B — 进化式程序搜索(FunSearch,Romera-Paredes et al. 2024):关键洞见是搜「程序」而非「答案」——不去存「解长什么样」,而去进化出「怎么构造解的函数」(有点像 procedural vs declarative)。机制:LLM 当变异算子(对已有程序做改写、生成候选),一个自动 evaluator 当适应度函数(给每个程序打分),保留高分的、再迭代——就是遗传算法,但用 LLM 生成「后代」。它在 cap set(极值组合学)上找到超越已知的构造,在装箱问题上找到更好的启发式。
# FunSearch 骨架:LLM 变异一个启发式函数,evaluator 打分,保留最优 from anthropic import Anthropic client = Anthropic() # 需要 ANTHROPIC_API_KEY def evaluate(code): # 适应度函数:真正跑候选程序、量化好坏 ns = {}; exec(code, ns) return score_on_benchmark(ns["heuristic"]) # 你的评分逻辑 best = ("def heuristic(x): return x", evaluate("def heuristic(x): return x")) for _ in range(50): # 进化 50 代 msg = client.messages.create(model="claude-opus-4-8", max_tokens=512, messages=[{"role": "user", "content": f"改进这个启发式使评分更高,只回代码:\n{best[0]}"}]) cand = extract_code(msg.content[0].text) try: s = evaluate(cand) if s > best[1]: best = (cand, s) # 只保留严格更优的 except Exception: pass # 变异可能语法错,跳过
把大模型的「预训练一次,处处微调」范式搬进自然科学。核心反直觉:数据驱动的模型,在很多问题上比第一性原理的物理求解更准,还快几个数量级——因为真实数据里藏着模型没显式写进方程的规律。
例一 — GraphCast(Lam et al. 2023,Science):传统天气预报要在超算上数值求解大气偏微分方程,像「每次预报都从头全量计算」。GraphCast 用 GNN 在 40 年再分析数据上学出一个「从当前状态直接映射到未来状态」的函数——像一张预计算好的物化视图,一分钟出 10 天预报,在约 90% 的验证指标上超过顶级数值系统。
例二 — ESM-2 / ESMFold(Lin et al. 2023,Science):把蛋白序列当「语言」,用掩码预测(masked prediction)做自监督预训练——和 BERT 训练一模一样。当模型规模推到 150 亿参数时,结构信息「涌现」:它不看 MSA 也能折叠蛋白,比 AlphaFold 快约一个数量级(代价是精度略降)。这说明「序列的统计规律」里本就编码了结构。
共性机制:大数据自监督预训练 → 学到领域的通用「表示」→ 下游任务微调,与 LLM 的路子完全同构。
# 用小号 ESM-2 (8M 参数, 可 CPU 跑) 提取蛋白序列的表示向量 import torch from transformers import AutoTokenizer, AutoModel name = "facebook/esm2_t6_8M_UR50D" # 最小的 ESM-2 tok = AutoTokenizer.from_pretrained(name) model = AutoModel.from_pretrained(name).eval() seq = "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQ" inp = tok(seq, return_tensors="pt") with torch.no_grad(): out = model(**inp) # 每个氨基酸一个向量;平均池化得到整条序列的「指纹」,可做下游分类/检索 emb = out.last_hidden_state.mean(dim=1) print(emb.shape) # torch.Size([1, 320]) —— 拿去接你自己的任务头微调