2. 生成分子数据表示与解析

在生成分子合成可行性评估工程中,生成模型输出的往往不是“分子”,而是一串字符、一个 token 序列或一段带噪声的文本。要让后续的合成可行性模型、逆合成规划器或可购买性打分器能够处理它,第一步必须把生成结果转换成化学上合法、语义上明确、结构上可比较的分子表示。本节围绕四种核心表示——SMILES、InChI、分子图、分子指纹——说明它们各自适合承担什么角色,并给出从模型输出到可评估结构的标准化解析与清洗流程。

四种表示的分工

SMILES 是生成模型最常用的输出形式,因为它是一维字符串,天然适配自回归语言模型。它的优点是紧凑、可读、生成方便;缺点是同一分子存在多种合法写法,例如乙醇可以写成 CCO,也可以写成 OCC。如果直接拿生成字符串做去重或相似性比较,会把同一分子当成多个不同样本。因此 SMILES 适合作为“生成接口”,但进入评估前通常需要先做规范化。

InChI 是一种分层、标准化的国际化学标识符,由 IUPAC 维护。它把分子拆成主层、电荷层、立体层、同位素层等,同一结构在不同来源下更容易得到一致结果。InChI 适合做跨库检索、结构确证和长期存档,但它对生成模型不友好——模型几乎不会直接输出合法 InChI。因此工程上常见做法是:模型输出 SMILES,解析成功后转换为 InChI 作为稳定键。

分子图 是化学结构最本质的表示:节点是原子,边是化学键,节点和边各自带属性(元素类型、电荷、芳香性、键级、立体标记)。图神经网络、图注意力模型、分子性质预测模型大多直接吃图结构。从 SMILES 到分子图的转换由 RDKit 等工具完成,这一步同时会做价键检查、芳香性感知和隐式氢补全。

分子指纹 是把分子图压缩成固定长度向量的表示,常见的有 Morgan/ECFP、MACCS、RDKit 指纹等。指纹不保留完整结构,但能高效计算相似性、聚类和检索。在合成可行性评估中,指纹常用于快速筛选“是否与已知可合成分子接近”,或作为可行性模型的辅助特征。

从生成模型输出到可评估分子结构的标准化解析与清洗链路 ① 生成模型输出 token 序列 / 原始字符串 "CCO" "c1ccccc1" "CC(=O)O" "C1=CC=CC=C1" 可能含非法字符、未闭合环 ② SMILES 解析 RDKit MolFromSmiles 价键检查 / 芳香性感知 隐式氢补全 / 环闭合验证 失败 → 记录错误类型 ③ 标准化清洗 去盐 / 去溶剂 / 中和电荷 互变异构规范化 去重(InChIKey 比对) 保留最大片段 ④ 多表示输出 规范 SMILES InChI / InChIKey 分子图对象 Morgan 指纹 常见生成噪声 • 未闭合环编号 • 非法原子符号 • 价键超限 • 括号不匹配 • 重复原子标记 解析关键检查 • 原子价态合法性 • 芳香性感知 • 手性标记保留 • 电荷平衡 • 环闭合一致性 清洗操作 • 去盐(保留最大片段) • 去溶剂化分子 • 中和电荷 • 互变异构规范化 • 去重(InChIKey) 表示用途 SMILES → 生成/存储 InChI → 检索/存档 图 → GNN 预测 指纹 → 相似性筛选 InChIKey → 去重键 ⑤ 可评估分子结构集合 规范 SMILES + InChIKey + 分子图 + 指纹 → 合成可行性评估模型输入 生成输出 解析 清洗 多表示 评估入口

标准化解析与清洗的实际操作

下面给出一段可直接参考的 Python 清洗流程,使用 RDKit 完成从原始 SMILES 到规范表示的转换。示例中的分子和参数均为教学假设,不代表任何实测结果。

from rdkit import Chem
from rdkit.Chem import AllChem, inchi
from rdkit.Chem.MolStandardize import rdMolStandardize

def standardize_smiles(raw_smiles: str):
    """将生成模型输出的原始 SMILES 标准化为可评估分子结构。
    返回 dict:规范 SMILES、InChI、InChIKey、分子图、Morgan 指纹。
    解析失败返回 None 并记录原因。
    """
    # 1. 基础解析
    mol = Chem.MolFromSmiles(raw_smiles)
    if mol is None:
        return {"error": "parse_failed", "raw": raw_smiles}

    # 2. 去盐:保留最大有机片段
    lfc = rdMolStandardize.LargestFragmentChooser()
    mol = lfc.choose(mol)

    # 3. 中和电荷
    uncharger = rdMolStandardize.Uncharger()
    mol = uncharger.uncharge(mol)

    # 4. 互变异构规范化
    enumerator = rdMolStandardize.TautomerEnumerator()
    mol = enumerator.Canonicalize(mol)

    # 5. 生成规范 SMILES
    canonical = Chem.MolToSmiles(mol, isomericSmiles=True)

    # 6. 生成 InChI 与 InChIKey
    inchi_str = inchi.MolToInchi(mol)
    inchi_key = inchi.MolToInchiKey(mol)

    # 7. 生成 Morgan 指纹(半径 2,2048 位)
    fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)

    return {
        "canonical_smiles": canonical,
        "inchi": inchi_str,
        "inchi_key": inchi_key,
        "mol": mol,
        "fingerprint": fp,
    }

这段代码的关键判断点在于:MolFromSmiles 返回 None 时说明字符串在化学上不合法,应直接归入“解析失败”桶,而不是强行修补。去盐和中和电荷的顺序会影响结果——先保留最大片段再中和,可以避免把盐的 counterion 也带入后续计算。互变异构规范化则保证同一分子的不同互变异构体在去重时被识别为同一结构。

清洗后的质量检查

清洗完成后,不能默认所有输出都可用。建议对每个批次做以下检查:解析成功率(合法分子数 / 总生成数)、去重后唯一分子数、平均分子量分布、以及 InChIKey 重复率。如果解析成功率低于某个阈值(例如 70%),说明生成模型本身需要调整;如果去重后唯一分子数远小于合法分子数,说明模型存在严重的模式坍塌,反复生成同一批结构。

实践提示:在合成可行性评估中,建议把“规范 SMILES + InChIKey”作为主键存储,分子图和指纹作为派生字段按需生成。这样既能保证去重和检索的稳定性,又不会因为指纹版本变化而影响主数据的可追溯性。
注意:InChI 的标准化程度高于 SMILES,但它对互变异构和电荷的处理规则与 RDKit 的标准化流程并不完全一致。如果同时使用两套工具,建议以 InChIKey 作为最终去重键,并在文档中明确记录所使用的 InChI 版本和标准化参数。

总结来说,从生成模型输出到可评估分子结构,核心是四步:解析、清洗、多表示生成、质量检查。SMILES 负责生成接口,InChI 负责稳定标识,分子图负责模型输入,指纹负责快速筛选。四者各司其职,缺一不可。只有把这条链路做扎实,后续的合成可行性评估才有可靠的数据基础。