首页 / 资讯中心 / 文章详情

大语言模型如何通过编辑序列优化分子可合成性

大语言模型如何通过编辑序列优化分子可合成性 ★ FEATURED ARTICLE
大语言模型这三年的进展几乎是肉眼可见地改变了我们处理化学问题的方式。前几年做分子生成大家默认的路径还是图神经网络、变分自编码器、扩散模型那一套用离散图或者连续潜变量去描述分子。最近我重新刷 Nature Machine Intelligence 上那篇讲“引导大语言模型预测分子可合成性优化的编辑序列”的工作时突然觉得思路清朗了不少——它没有重复“从零生成一个分子”的老路而是把问题变成了一段一段有序的“编辑序列”让 LLM 去预测给定一个当前还比较难合成的分子你该按什么顺序做几步修改才能让它变得好合成同时尽量保持原本想要的性质。与其说这是一个生成模型不如说它更像一个“分子改造顾问”直接告诉合成化学家从哪下手。这篇论文很适合三类人看一类是做 AI4Science 的研究者想找个把 LLM 落到分子优化场景的比较有意思的切入点一类是药物化学、计算化学背景的从业者手里经常拿着活性还不错的分子但下一步就是不知道能不能做出来或者哪些修饰在合成上更划算还有一类是做提示工程、模型微调的人想看看 LLM 在化学这种强符号领域到底怎么才能“说人话”。我自己看完之后的直接感受是这个方向没有想象中那么玄核心还是数据的组织方式、原子映射的稳定性以及如何让模型真正输出机器可执行的序列而不是一本正经地胡扯。1. 项目整体设计与思路拆解1.1 为什么“可合成性优化”要比“直接生成可合成分子”更难过去我常用各种可合成性过滤器生成一个分子算一下 Synthetic Accessibility 得分低于某个阈值就淘汰。问题在于这类分数本质上是一个静态指标看到分数高只能说明“这个结构大概比较好蹭”完全没有告诉你“如果你手里已经有 XYZ 分子下一步应该怎么变”。分数是对最终产物的总结不是一个过程性的指导。论文把任务往前走了一步给定一个起点分子模型生成一个有序的编辑序列经过这些编辑之后产物的可合成性得分显著下降或者更严格地说逆合成可行性提高同时分子的核心骨架、目标口袋里的结合特性尽量不丢。这个思路类似于“从难合成的候选物到容易合成的等价物”之间架了一座桥而不是把分子拍到高维空间里再拿去撞墙。这样做还有个实际原因从头生成很容易得到一堆“纸面看起来很漂亮、做起来完全不是那么回事”的结构因为合成路线充满了顺序问题——某些官能团必须在特定步骤之前装上去某些保护基如果提前去掉后面就废了。所以真正决定一个分子能不能做出来的不是单一的分子图而是这个分子图背后的一长串操作顺序。把可合成性优化转成编辑序列的预测等于把“结果问题”转成“动作问题”信息量更大也更贴近化学家的工作习惯。静态可合成性打分只能给你一个数编辑序列给你的是六七步操作。操作顺序隐含了合成可行性同一个分子换不同顺序成功率完全不同。编辑序列天然支持人机协同——化学家可以只采纳第一步再按自己的知识往下走。1.2 为什么这次选择大语言模型而不是图神经网络如果用图神经网络做分子改造通常需要设计一个消息传递网络把原子和键编码成节点和边再通过某种解码器输出修改后的图。听起来没问题但图模型有一个天然短板它输出的是“最终改完的图”而不是“编辑操作本身”。少原子的替换、断键加环这类操作虽然也可以表示为图编辑谓词但要端到端学一个有序的图编辑策略解码空间会被撑得很大。大语言模型则不同。它天然以序列为单位而分子可以用 SMILES、SELFIES 或原子映射编号后的线性表示来编码。编辑序列本身就很好线性化“第一步把原子 7 和原子 12 之间的键断开第二步在原子 9 上加一个氟原子第三步把五元环扩成六元环。”本质上这就是一段化学语言语法。LLM 在大量文本上做预训练时已经学到了序列之间的统计依赖关系这种依赖关系恰好可以用来表示“先断键、后替换”的关系。还有一个更实际的理由如果连论文都跑到 LLM 这个赛道大概率是因为微调门的门槛对于大部分实验室来说更低。有很多开源权重可以直接用你也可以非常轻易地把分子编辑序列的示例塞进 prompt让模型先试跑一轮 few-shot再决定要不要做全量微调。图神经网络往往得从零开始训而且每次想改一个输入特征都要重新设计网络结构迭代成本高不少。图神经网络与 LLM 在编辑序列式分子优化上的对比维度图神经网络大语言模型输入表示原子图/键级矩阵需要额外区分原子映射SMILES、SELFIES、原子编号序列等一维文本输出方式一般输出修改后的完整图输出离散操作 token 序列天然有序顺序建模需要额外引入解码顺序或自回归自回归机制天然建模编辑顺序先验知识主要在化学图上学习在语言语料化学文本上有大量先验修改代价改一个任务网络结构通常要跟着动换 prompt 或微调指令就能适配新任务可解释性难解释“为什么这样改”每一步编辑都是显式文本化学家能看懂当然用 LLM 不是没有代价。最明显的是 token 化问题一个 SMILES 串被切成语义词元之后原子索引、环数字这些数字 token 容易错乱。所以后面所有工程上的严谨性都在围绕这个问题兜底。1.3 数据配方怎么把编辑序列变成模型的监督信号要训练模型去预测编辑序列首先得有一堆“编辑前的分子 编辑序列 编辑后的分子”三元组。论文里的做法我复现时是分成了三层来构造数据。第一层拿公开小分子库比如 ZINC、ChEMBL 里的中性小分子作为“目标性质良好但可合成性需要提升”的起点。第二层用一批有机反应模板比如酰化、还原胺化、铃木偶联、保护基引入等去反向生成“难合成的候选物”——大致思路是先随机抽取一个可合成的参考分子按若干步反应模板随机地加官能团或改骨架把它“弄乱”得到一个难合成的中间体。第三步把真实反应图反过来翻译成编辑序列从难合成中间体出发每应用一个逆合成步骤就对应一条编辑记录最终恢复成一个好合成的分子。整条链就是监督信号。这里有个容易被忽略的关键点编辑序列不是随便写的“修改清单”它必须对应真实的化学可操作性。比如 “把芳环上的溴变成硼酸”这种操作在现实中是要经过金属催化的偶联或者官能团互换的不能只把 SMILES 改一改就当可合成路径。所以数据构造阶段最好用带原子映射的反应模板让模型学到的每一步都能映射到现实中可执行的合成变换。另外数据里还要考虑样本平衡。如果数据集里全是三步以内的短编辑链模型会偏向偷懒看到一个难合成分子就只做一个浅层修饰完全不解决根本问题。最好按编辑步数分布采样让三到六步的中长编辑序列也占到一个合理比例模型才能真正学会多步规划。2. 核心细节解析与实操要点2.1 编辑序列的表示法原子映射是命门一提到“编辑序列”新手最容易犯的错误就是直接用原 SMILES 里的原子顺序号当操作目标。比如模型输出“把 C5 的氟原子换成甲氧基”如果这条序列不是在统一的原子映射语境下生成的那 C5 这个编号完全可能随着一个断键操作发生变化。你刚把第 3 步执行完第 4 步里的“C8”已经变成另一个原子了整个序列彻底失效。所以说让 LLM 学一个稳定的原子映射上下文非常重要。简单来说你要在模型的每轮输入里都给出“当前分子的带编号 SMILES”并且确保这个编号在对分子做原子删除、插入时能尽量保持稳定。具体实现里我比较推荐用 RDKit 的原子映射机制先把每个反应物原子标上规范映射号再做反应转化。模型看到的是一个带编号的线性式类似[C:10]1([H])N([H])Cc(c1)-c1ncc([F:13])cc1当模型输出编辑操作时引用的是这些稳定编号同时每执行完一步就把当前新分子重新生成新的编号方案再拼成下一步的上下文喂回给模型。这样虽然多几次 RDKit 调用但能避免绝大多数“索引越界”问题。这一步做得稳后面一切推理才可信。2.2 可合成性指标怎么选以及为什么要多指标共同约束论文标题里说的是“可合成性优化”但可合成性本身不是一个单一客观量。常见的 SACores 或 RAscore 都是从结构复杂度出发的启发式分数而严格意义上合成可行性是“是否存在一条可行的合成路线”。更贴近实际的是用逆合成模板库做一个可合成性判定给定一个分子看它能否在一到三步内匹配到已知反应模板。这种判定的结果更可靠但开销也更大。我在复现时采用了“模板库可合成性 SAScore RAscore”三者结合的指标。训练时主要用模板库结果作为强约束因为它是布尔判定直接反映了“编辑序列是否真的把分子推向可合成”。SAScore 和 RAscore 作为软指标用来平滑优化防止模型为了匹配模板而过度改变分子的核心结构。指标对比速查指标类型优点缺点适合场景SAScore启发式分数速度快零成本对复杂环系和立体化学判断粗糙大规模初筛RAscore随机森林预测比 SAScore 更接近人工判断依赖训练集分布可能偏移中规模筛选逆合成模板库判定基于规则/检索最贴近真实可合成性覆盖范围受模板库限制编辑序列数据构造与最终评估专家打分人工最可靠昂贵无法规模化下游实验前最终确认一个非常容易踩的坑是只优化一个指标比如用 SAScore可能导致模型发现“把所有环都拆掉”就能无限降低难度但那已经不是同一个分子了。因此设计损失函数时我会把编辑序列的前若干步设成“骨架不变”的操作只有后几步才允许较大改动。论文里更优雅一点的做法是在 prompt 里显式给出一个“最大编辑预算”和“核心骨架 SMILES”要求模型在核心骨架不变的前提下完成优化超过预算的输出一律判非法。2.3 提示词设计与输出解析让 LLM 老老实实吐序列如果直接用“帮我优化这个分子的可合成性”这种开放式的 prompt模型大概率会给你一段散文而不是机器可执行的编辑序列。这个方向的实际项目里最稳的方案是给模型规定输出格式并在输出层做一次语法校验。你可以把 prompt 设计成你是一个药物化学编辑器。输入是一个待优化分子 SMILES 和它的可合成性分数。 请只输出一个 JSON 对象包含一个列表每个元素为 {op: add|del|sub|ring_modify, target_atom: 7, value: F, reason: ...} 条件 - 最多 4 步编辑 - 保持核心骨架 SMILES 中的环系统不变 - 每一步之后更新原子映射实际推理时模型可能偶尔输出“我觉得应该先改这里的氟……”这种就靠解析器直接拦掉。更稳妥的方式是设置一个简单的状态机先要求模型强制输出一个带固定键名的 JSON用 json.loads 解出来解不出来就重试一次重试时把上一条非法输出贴回去当作负样例。除了限制输出格式还要限制模型“不要解释太多”。化学语境里让 LLM 解释原因很诱人但 token 一多指令跟随能力就会下降。所以 prompt 里要写清楚所有推理过程到思维链为止但最终输出必须仅保留可执行的部分。如果要评测我更倾向于把思维链藏在辅助字段里不参与后续的分子编辑执行。3. 实操过程与核心环节实现3.1 环境与工具选型这个方向并不需要特别夸张的算力。一张 24 GB 显存的消费级卡比如 RTX 3090/4090就能跑 7B 量级的开源模型微调。更省的做法是直接拿一个 3B~7B 的模型做 LoRA 微调OneCard 就能完成整个训练周期。不过要注意LLM 推理时嵌套 RDKit 的原子映射和毒理性检查这部分函数调用才往往是瓶颈跟 GPU 无关。具体软件栈我用的是这样一套# 核心环境 python 3.11 torch 2.x transformers 4.4x peft # 做 LoRA 微调 rdkit # 分子读写、反应模板、原子映射 rdchiral # 基于模板的逆合成扩展 json5 # 容忍大语言模型常见的小 JSON 格式问题除了这些建议数据结构层用 HDF5 或者 parquet 存编辑序列样本因为几百万条数据如果全放内存跑实验时会反复换页。我自己实际用到 50 万条左右的编辑链parquet 文件加起来不到 2 GB读取速度比 CSV 快得多。3.2 从公开数据库构造编辑序列数据集构造数据集是整条管线里最花时间的一步没有捷径。我把工作拆成了四个阶段筛选起始分子集合。从 ChEMBL 里随机抽 30 万个分子过滤掉分子量 600、含有金属原子或者明确包含不可合成基团的样品避免数据集里出现太多“宇宙分子”。编辑链反向生成。先用反应模板库对起始分子做逆合成扩展得到前体和产物。再从前体出发把整条逆合成路线翻成编辑序列每用一步模板就记录对应的操作类型和原子映射。数据清洗与平衡。剔除任何中间分子在 RDKit 里无法解析的样本按编辑步数和模板类别做分层采样防止某些反应类型占据绝对主导。标准化 token 化。把每个分子转成带原子映射的 SMILES然后把编辑操作映射到一组专门的 token比如ADD_ATOM、DEL_BOND、REPLACE_GROUP、RING_EXPAND、RING_CONTRACT。实际中还要做一步“副作用验证”每生成一条编辑序列就实际把它执行一遍确认从起点分子开始按序执行后真的能到达目标分子。这步不做的话你会在训练中引入大量“模型永远也学不会”的噪声标签。我当时第一次构造数据就偷懒跳过了验证结果训练集里大量序列执行到一半就断掉损失一直下不来后面花了整整两天排查才发现是数据问题。3.3 微调与推理策略温度、束搜索与自一致性模型选择上我试过两类一类是 ChemT5 这类本来就抠到化学语义的 encoder-decoder 模型另一类是通用代码模型比如 CodeLlama 和 Qwen2.5-Coder 这类。实践下来通用的代码模型在“输出 JSON 编辑序列”这种任务上反而更稳定可能是因为它们已经见多了结构化的 key-value 格式。如果你想快速起步直接拿一个 7B 的 Qwen2.5-Coder 做 LoRA 微调效果已经会非常可喜。训练阶段最重要的策略是“把编辑序列当作代码生成任务来做格式化”。训练样本的输入部分不仅包含当前分子 SMILES还要附上“当前核心骨架约束”和“已执行过的编辑步骤”输出部分则是严格的 JSON 列表。掩盖函数要确保损失只计算输出部分否则模型在复述输入上占用过多容量。推理阶段我推荐微调后用三个设置temperature 0.6~0.8给一定随机性但别太高。高于 1.0 时输出经常为了凑新序列而乱拆键。beam search 5~10在低温度下束搜索质量比 top-p 采样要好。self-consistency采 5 个候选编辑序列逐个用 RDKit 执行并检验最终分子是否达到了可合成性阈值选通过验证的那条。如果都有问题选与当前分子相似度最高的那条回退。这一套下来成功率比单次 beam search 高 10 到 20 个百分点尤其那些需要四步以上编辑的分子几乎离不开 self-consistency。代价就是推理时多几倍的解析耗时但考虑到一步验证开书最贵的是 RDKit 而不是模型推理这个取舍很划算。4. 常见问题与排查技巧实录4.1 非法 SMILES、索引越界等生成崩溃问题这类问题几乎每个人都会遇到。最典型的现象是模型输出的编辑序列引用了不存在的原子编号或者执行完一步后产物的 SMILES 解析失败。排查的第一步先把“模型输出”和“数据后处理”分开用一个小样本检查模型输出本身是否合法再检查 RDKit 执行端是否有 bug。我有一半的“模型很蠢”其实都是后处理代码写错了比如原子映射编号没有在每步之后重置或者执行删除操作时没更新键序。真正要根治还得靠推理时的状态校验。我采用“每步都调用一次 RDKit生成合法的新分子再进入下一步”的做法。同时在给模型拼接下一步输入时重新生成带原子映射的 SMILES。这一步虽然拖慢了推理速度但可靠性大幅提升。如果你需要批量跑大量分子可以给 RDKit 的解析和映射函数写一个缓存同一个中间结构不要反复计算。4.2 骨架漂移指标优化了分子却变成另外的分子你可能会看到模型输出了很长一串编辑序列算下来 SAScore 确实漂亮但最终分子跟原分子结构几乎毫无关系。这种问题在只用单一可合成性指标时特别常见因为模型很会钻空子把芳环全打断、把杂原子全删掉当然是“好合成”。解决骨架漂移我这里有三个土办法编辑预算硬限制在 prompt 里写明最多几笔并在概率解码时对输出 token 数做上限截断。核心骨架替换检测预先用 RDKit 提取分子的 Murcko 骨架编辑结束后重新提取如果骨架不一致直接判负。相似度惩罚在推理选序列时把最终分子与起始分子的 ECFP4 相似度作为一个加权条件相似度低于 0.3 的结果直接丢弃。论文里其实也把“保持核心骨架”作为一个可配置的提示条件并不是硬性限制每个人都要严格守。但在我的场景里骨架漂移是下游最不能接受的问题毕竟药化项目里骨架改变意味着一切都得重来。4.3 生成多样性差与局部收敛如果你的模型总是给不同起点分子输出几乎一样的编辑序列比如不管什么分子都“把某个位置的甲基换成氟”那大概率不是模型笨而是数据里这类操作占了绝对多数。解决办法是统计训练数据里编辑操作类型的分布如果不平衡就用采样器把低频操作加权放大。这个操作跟处理类别不平衡的方式如出一辙。还有一个容易被忽视的因素如果推理时温度过低且束搜索宽度很窄模型无论怎么跑都会收敛到同一条高分序列。你可以先设定温度 0.7 采样 20 个候选再看多样性是否上来。如果还不行就要回到数据层面看看是不是高频模板压制了其他模板的表达。4.4 推理速度与批量验证的工程优化这个方向容易被论文刷屏式宣传误导以为模型是瓶颈。实际上在每一步都要做 RDKit 验证的流程里LLM 推理只占不到一半时间另一半全消耗在分子解析、映射和算法评价上。我实测的一次跑批8000 个分子、每个 4 步编辑总耗时约 21 分钟其中 GPU 推理只占 9 分钟RDKit 相关操作占了 12 分钟。优化方向主要是批量化和缓存。比如所有分子转换都尽量用 RDKit 批量函数别一个一个走 Python 循环遇到相似度计算用 ECFP4 指纹的预计算缓存遇到 SAScore可以把同一个中间结构的评分结果存到内存里。另外RDKit 的原子映射重建很耗内存建议把映射结果持久化第二次跑就不需要再算一次。把工程这层优化后全流程能提速大约一倍。5. 后续扩展与个人实践建议5.1 把编辑序列接到逆合成工具链上论文这个方向最自然的扩展就是不让 LLM 停在“编辑建议”这一步而是把模型输出的每一步编辑直接作为逆向合成工具链的输入。比如模型先建议“在 N7 上加一个叔丁氧羰基保护基”下游就通过模板库搜索具体反应条件或者交给 retrosynthesis model 去补全详细路线。这样做的好处很明显LLM 负责高层策略和优先级规则系统负责低层精确反应两层结合出错率会显著下降。我实际做落地方案时会在编辑序列的每个操作 token 后面加一个“template_id”字段记录这条操作来自哪个反应模板。这个 id 可以作为下游验证的钥匙也能在过滤时排除那些没有可靠反应条件的编辑。没有模板支撑的编辑只能在最后一步被采纳前面的尽量不碰。5.2 用强化学习在线调整编辑路径历史数据训练出的编辑策略到了分布外的新分子上不一定还灵。更进阶的做法是引入强化学习把“可合成性提升幅度”和“骨架相似度保持”整合成一个 reward用策略梯度对生成编辑序列的 LLM 做在线调优。我记得前一阵也有人用类似思路做分子对接优化效果还不错。但强化学习在这个任务上有两个风险一个是 reward hacking模型总会发现你指标里的漏洞另一个是探索开销太大毕竟每一条编辑序列都要跑一遍完整的化学验证。稳妥的做法是先用离线数据微调出一个基本可用的模型再用 RL 做小批量小步长的适应别一上来就大规模探索。5.3 避坑清单数据泄漏、词表设计与版本兼容最后给四个我踩过的比较深的数据和工程坑。一是数据泄漏。如果你从同一个数据库里既抽了起点分子又用于可合成性评估那么模型很可能会“记住”某个分子的标准答案导致评估虚高。最好把评估集刻意与训练集按 Bemis-Murcko 骨架去重确保常见骨架至少在两两之间差异大于一定阈值。二是自定义 token 必须留白。当你在 LLM 词表里新增ADD_ATOM这类 token 时务必检查嵌入层规模和 tokenizer 的保留位不然扩容后位置编码错位很坑。我自己就遇到过 LoRA 微调后新 token 的 embedding 没初始化训练出一片奇怪的数字。三是RDKit 版本必须锁死。同一个分子在不同 RDKit 版本里的规范 SMILES 表示可能不同直接影响原子映射编号的一致性。项目初期就固定版本号并在 README 里写明否则隔一个月再看数据生成结果根本对不上。四是输出校验比模型重要。在真实项目中模型只需要有三四成概率生成合法序列配合状态机和多次采样最终可用率就能拉得很高。反过来模型再强如果输出端没有严格校验整个系统的成功率也会被无效调用拖垮。我个人做这套流程最大的体会是不要把 LLM 当成一个独立的“化学家”把它当成一个擅长提出建议但需要严密监督的实习生。你说清楚格式、给足上下文、为它准备好每一步要验证的工具它就能在编辑序列预测这种任务上给出相当惊艳的结果。但如果放任自由发挥它也很容易一本正经地输出一堆根本执行不了的分子。后续如果再有人拉我一起做分子优化项目我大概率会沿用这套“LLM 出策略、规则引擎做校验、模板库保底”的三角结构它虽然朴素但在真实合成场景里是少数能让化学家愿意点下“采纳”按钮的方案。
阅读完成 · 觉得有帮助?
咨询建站