跳转到正文
官方

使用 Ollama + RDKit 搭建本地化学助手

使用 RDKit 计算分子性质,再通过明确的 Python 连接脚本交给本地 Ollama 模型解释,避免模型凭记忆生成数值。

难度: 中等 费用: 免费 隐私: 本地 ~30 分钟
开始安装

你将能够

  • 根据 SMILES 计算分子式、分子质量和 TPSA。
  • 由本地语言模型解释已有计算结果。

你将构建什么

方案范围

Python 脚本先确定性地计算 RDKit 描述符,再向本机 Ollama 对话 API 提交结果。这是命令行助手,不宣称自动接入 MCP。使用 Python 3.11、RDKit 2025.3.1 和本地 Ollama;解释模型选用 qwen2.5:3b(下载约 1.9 GB,采用 Qwen 许可),记录下载后的模型摘要与 Ollama 版本。硬件需求取决于模型及上下文,不承诺 GPU 性能。

本地运行

初始安装与模型下载需要联网。脚本固定使用 127.0.0.1,选择本地模型后,描述符计算与推理在本机完成。模型解释可能有误,脚本先打印的 RDKit JSON 才是计算结果依据。

确定性分子计算

RDKit

组合组件

RDKit

确定性分子计算 · ==2025.3.1

由附带 Python 脚本调用;Ollama 是单独安装的运行前提。

费用与许可请核对上游及客户端、服务账号条款。

查看资源

兼容环境

客户端操作系统架构版本要求
Python macOS不限>= 3.11
Python Windows不限>= 3.11
Python Linux不限>= 3.11
Local AI / Ollama macOS不限见组件版本要求
Local AI / Ollama Windows不限见组件版本要求
Local AI / Ollama Linux不限见组件版本要求

安装与测试

1. 准备 Python 与 Ollama

全部平台

从官方渠道安装 Python 3.11 与对应系统的 Ollama,打开 Ollama;Linux 按官方安装指南操作,服务未启动时使用 ollama serve。选择本地模型。

官方来源

预期结果

本地 Ollama 可用,记录版本。

2. 安装独立 Python 依赖

macOS

在新的工作目录执行。此命令适用于 macOS/Linux,Windows 使用单独步骤。

python3.11 -m venv .venv
.venv/bin/python -m pip install rdkit==2025.3.1
.venv/bin/python -m pip freeze
官方来源

预期结果

依赖安装完成,记录实际解析版本。

3. 安装独立 Python 依赖

Linux

在新的工作目录执行。此命令适用于 macOS/Linux,Windows 使用单独步骤。

python3.11 -m venv .venv
.venv/bin/python -m pip install rdkit==2025.3.1
.venv/bin/python -m pip freeze
官方来源

预期结果

依赖安装完成,记录实际解析版本。

4. 在 Windows 安装 Python 依赖

Windows

使用 PowerShell,直接调用虚拟环境解释器。

py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install rdkit==2025.3.1
.\.venv\Scripts\python.exe -m pip freeze
官方来源

预期结果

依赖安装完成,记录实际解析版本。

5. 下载本地解释模型

全部平台

在安装 Ollama 后执行,记录模型摘要并核对其许可。

ollama --version
ollama pull qwen2.5:3b
ollama list
官方来源

预期结果

本地模型出现在列表中,未选择云端模型。

6. 保存 Python 连接脚本

全部平台

保存为工作目录中的 local_chemistry_assistant.py。代码先计算再发送请求,不执行模型生成的代码。

"""RDKit calculations followed by explanation using a local Ollama model.

Sources: https://www.rdkit.org/docs/GettingStartedInPython.html
         https://docs.ollama.com/api/chat
This example has been source-reviewed, but has not been executed.
"""
import argparse
import json
import urllib.error
import urllib.request

from rdkit import Chem, rdBase
from rdkit.Chem import Descriptors, rdMolDescriptors


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("smiles")
    parser.add_argument("--model", default="qwen2.5:3b")
    parser.add_argument("--prompt", default="Explain the supplied molecular descriptors and their limits.")
    args = parser.parse_args()
    if not args.smiles.strip():
        parser.error("Empty SMILES; no model request was sent.")
    molecule = Chem.MolFromSmiles(args.smiles)
    if molecule is None:
        parser.error("Invalid SMILES; no model request was sent.")
    results = {
        "smiles": args.smiles,
        "rdkit_version": rdBase.rdkitVersion,
        "formula": rdMolDescriptors.CalcMolFormula(molecule),
        "molecular_weight_g_mol": Descriptors.MolWt(molecule),
        "tpsa_square_angstrom": rdMolDescriptors.CalcTPSA(molecule),
    }
    print(json.dumps(results, ensure_ascii=False, indent=2), flush=True)
    request = urllib.request.Request(
        "http://127.0.0.1:11434/api/chat",
        data=json.dumps({
            "model": args.model,
            "stream": False,
            "messages": [
                {"role": "system", "content": "Explain only the supplied RDKit results. Preserve their numbers and units. Do not invent measurements, toxicity, efficacy or additional calculations. Reply in the user's language."},
                {"role": "user", "content": args.prompt + "\nRDKit results:\n" + json.dumps(results)},
            ],
        }).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
        with opener.open(request, timeout=180) as response:
            body = json.load(response)
        message = body.get("message", {}).get("content")
        if not isinstance(message, str) or not message.strip():
            raise ValueError("Ollama did not return message.content.")
        print(message)
    except (urllib.error.URLError, ValueError, TimeoutError) as error:
        parser.exit(1, "Local Ollama request failed; RDKit results remain available above. " + str(error) + "\n")


if __name__ == "__main__":
    main()
官方来源

预期结果

脚本与 .venv 位于同一工作目录。

7. 运行阿司匹林流程

全部平台

macOS/Linux 使用 .venv/bin/python,Windows 使用 ..venv\Scripts\python.exe。通过 --prompt 传入下方提示词。

.venv/bin/python local_chemistry_assistant.py "CC(=O)Oc1ccccc1C(=O)O" --prompt "请解释 RDKit 已计算的阿司匹林结果,保留分子式、质量、TPSA 数值与单位,区分计算描述符和实验观察。"
官方来源

预期结果

先检查 RDKit JSON:C9H8O4、质量约 180.16 g/mol、TPSA 约 63.6 Ų;再核对解释是否保留原数值,未新增无依据的毒性或疗效结论。这是预期检查,不是本次实测结果。

8. 拒绝非法输入

全部平台

用上述平台解释器,将输入替换为 not-a-smiles。

.venv/bin/python local_chemistry_assistant.py "not-a-smiles"
官方来源

预期结果

脚本在请求 Ollama 前退出,并明确提示非法 SMILES。

故障排除

  • 连接被拒绝:打开 Ollama 或启动本地服务,检查 11434 端口。
  • 找不到模型:下载准确的本地标签并查看 ollama list。
  • 缓慢或内存不足:缩短上下文或改用较小的本地模型,记录变更。
  • RDKit 导入失败:安装与运行必须使用同一个虚拟环境解释器。
  • 解释数值发生变化:拒绝该解释,以先打印的 RDKit JSON 为准。
  • 非法 SMILES:修正原始输入,不让模型编造分子。
仍无法运行

替代方案

可只用 RDKit 获取同样的 JSON,无需语言模型。改用云端解释服务会改变隐私边界,应另行记录。