内容
---
title: smiles2iupac
emoji: 🧪
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
pinned: false
license: mit
short_description: SMILES 到 IUPAC 命名转换(PubChem + OPSIN)
---
<!-- The YAML block above is HF Spaces config; it must be the very first thing
in the file. GitHub renders it as a thematic-break + paragraph, which is
ugly but harmless. HF Spaces requires it to discover sdk=docker / port=7860. -->
# smiles2iupac
> 免费、开源的 SMILES → IUPAC 命名转换,每次返回的名称都通过两个独立的 IUPAC 实现进行交叉验证。
[](https://github.com/gvmfhy/smiles2iupac/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[]()
[](https://agwgwa-smiles2iupac.hf.space)
> **状态:** alpha. Live at <https://agwgwa-smiles2iupac.hf.space>. 尚未在 PyPI 上发布。
>
> 每个返回的名称都通过 **两个独立的 IUPAC 实现** 进行结构验证 — PubChem 的 ChemAxon 命名,然后是 OPSIN 的 Cambridge 解析器往返 — 因此覆盖范围受限于 PubChem(~1.2 亿种化合物),但正确性很高。PubChem 未识别的结构会得到一个诚实的“未找到”而不是不可验证的猜测。
## 功能
一个库、CLI 和 Web 应用程序,使用分层管道将 SMILES 字符串转换为 IUPAC 命名:
```
SMILES → 分类 → 廉价增强 → SQLite 缓存 → PubChem(以 InChIKey 为键)
↓ 丢失
OPSIN 往返于 PubChem 名称
↓
{ 名称,置信度,来源,... }
```
每个结果都带有 **出处** 和 **置信度分数**。PubChem 命中的置信度为 1.0;缓存命中的置信度为 1.0;目前没有低置信度的结果返回。基于 ML 的结构生成是针对 PubChem 未识别的结构而记录的未来层级 — 请参见 [路线图](#路线图)。
## 快速开始
```bash
git clone https://github.com/gvmfhy/smiles2iupac.git
cd smiles2iupac
uv venv && uv pip install -e . # 或:python -m venv .venv && pip install -e .
.venv/bin/s2i 'CCO'
```
```
乙醇 (置信度:1.00,来源:pubchem)
分子式:C2H6O 分子量:46.069
InChIKey:LFQSCWFLJHTTHZ-UHFFFAOYSA-N
验证:https://pubchem.ncbi.nlm.nih.gov/#query=LFQSCWFLJHTTHZ-UHFFFAOYSA-N
```
现实世界的案例无需任何仪式即可正常工作:
```bash
s2i 'CC(=O)Oc1ccccc1C(=O)O' # 阿司匹林
# 2-乙酰氧基苯甲酸 (置信度:1.00,来源:pubchem)
# 分子式:C9H8O4 分子量:180.159
# InChIKey:BSYNRYMUTXBXSQ-UHFFFAOYSA-N
s2i 'CC(=O)[O-].[Na+]' # 醋酸钠(盐)
# 醋酸盐 (置信度:1.00,来源:pubchem)
# 警告:剥离 1 个反离子
# 验证:https://pubchem.ncbi.nlm.nih.gov/#query=QTBSBXVTEAMEQO-UHFFFAOYSA-M
s2i 'CC(=O)[O-].[Na+]' --trace # 查看管道执行的确切步骤
# 醋酸盐 (置信度:1.00,来源:pubchem)
# ...
# 管道推理:
# 1. 识别为盐 — 父:CC(=O)[O-];剥离 1 个反离子(s):[Na+]
# 2. 计算 InChIKey:QTBSBXVTEAMEQO-UHFFFAOYSA-M
# 3. 缓存未命中
# 4. PubChem InChIKey 查找 → 匹配:'acetate'
s2i 'CCO>>CC=O' # 拒绝:反应超出范围
# <错误:反应 SMILES 不受命名支持>
s2i --reverse 'aspirin' # 反向:名称 → SMILES(处理常用名称和 IUPAC 名称)
# CC(=O)Oc1ccccc1C(=O)O
s2i --reverse '(2S)-2-aminopropanoic acid' # IUPAC 名称通过 OPSIN(无网络,立体感知)
# C[C@H](N)C(=O)O
s2i --batch input.csv -o named.csv # 批处理,带进度条
s2i CCO --json # 完整的 JSON:InChI、InChIKey、分子式、分子量等
```
```python
from smiles2iupac import convert, lookup
result = convert("CC(=O)Oc1ccccc1C(=O)O") # 阿司匹林
print(result.name) # '2-乙酰氧基苯甲酸'
print(result.confidence) # 1.0
print(result.formula) # 'C9H8O4'
print(result.mol_weight) # 180.159
print(result.inchikey) # 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N'
# 反向方向:名称(常用或 IUPAC)→ SMILES
print(lookup("咖啡因")) # 'Cn1c(=O)c2c(ncn2C)n(C)c1=O'
```
## 安装
该软件包 **尚未在 PyPI 上发布**。从 GitHub 仓库安装:
```bash
git clone https://github.com/gvmfhy/smiles2iupac.git
cd smiles2iupac
uv venv && uv pip install -e . # 核心(PubChem + 缓存 + CLI)
uv pip install -e '.[ml]' # 添加 OPSIN 验证
uv pip install -e '.[web]' # 添加 Gradio + FastAPI
uv pip install -e '.[mcp]' # 添加 MCP 服务器(s2i-mcp)
uv pip install -e '.[all]' # 所有功能
```
| 额外 | 您得到什么 | Python | 操作系统依赖 |
|---|---|---|---|
| (核心) | PubChem 查找、缓存、CLI、增强 | 3.10–3.12 | 无 |
| `[web]` | Gradio UI + FastAPI 安装在 `:7860` | 3.10–3.12 | 无 |
| `[mcp]` | MCP 服务器(`s2i-mcp`)适用于 Claude Desktop / Cursor / Cline | 3.10–3.12 | 无 |
| `[ml]` | OPSIN 往返验证(`py2opsin`) | 3.10–3.12 | Java 17+ JRE |
## 为什么存在
截至 2026 年,没有免费、开源的在线 SMILES → IUPAC 工具,具有 API、验证层、批处理模式和稳定运行时间。PubChem 的 PUG-REST 是免费且权威的,适用于约 1.2 亿种化合物,但没有命名 UI,没有批处理,没有往返验证,也有限制速率。基于 ML 的工具(STOUT v2,Steinbeck 团队的 97.49% 准确率模型)作为研究成果存在,但今天并未作为服务打包 — STOUT 的上游权重下载 (`storage.googleapis.com/decimer_weights/models.zip`) 返回 404,截至本文撰写。
## 您获得什么
每次成功的转换都会产生一个完全填充的 `Result`:
| 字段 | 始终设置? | 备注 |
|---|---|---|
| `name` | ✓ 成功时 | IUPAC 名称 |
| `confidence` | ✓ | 0.0–1.0;基于来源 + 验证的分级 |
| `source` | ✓ | `pubchem` / `cache` |
| `canonical_smiles` | ✓ | RDKit 规范化 |
| `inchi` / `inchikey` | ✓ | 标准 InChI + 27 个字符的 InChIKey |
| `formula` | ✓ | 希尔符号 |
| `mol_weight` | ✓ | 平均分子量,g/mol |
| `kind` | ✓ | `molecule` / `salt` / `mixture` / `reaction` / `polymer` / `empty` |
| `warnings` | ✓ | 人类可读的注释(例如“剥离 1 个反离子”) |
| `alternatives` | 按需 | 常用名称同义词(`--synonyms`) |
| `structure_svg` | 按需 | 正方形 SVG 渲染(`--include-svg`) |
| `cas` | 按需 | CAS 注册号(`--include-cas`) |
| `error` | 仅在失败时 | 出了什么问题 |
## 它如何处理边缘情况
- **盐** — 按 `.` 分割;将最大的有机片段作为父节点;记录剥离的 `warnings`
- **混合物** — 命名最大的组分;将其他部分标记在 `warnings` 中
- **反应 (`A>>B`)** — 拒绝并设置 `kind="reaction"` 和明确的错误
- **聚合物 / 通配符 (`*`, `[*]`)** — 拒绝并设置 `kind="polymer"`
- **立体化学** — 通过 OPSIN 往返保存;InChIKey 键的 PubChem 查找匹配立体(完整键)和骨架(块-1)层级
- **重原子限制** — 超过 999 个原子的分子超出范围(可按调用配置)
- **InChIKey 键的 PubChem** — RDKit 和 PubChem 以不同方式规范化 SMILES;InChIKey 查找捕获 SMILES 键查找遗漏的分子
### 已知差距(来自实际基准测试)
- **复杂环肽** (例如环孢素) — PubChem 的标准化器拒绝并返回 `BadRequest`;今天不返回名称
- **偶尔的 PubChem 索引间隙** (例如看到的规范 SMILES) — 今天不返回名称
- **真正的新颖结构** — PubChem ~1.2 亿化合物索引之外的任何内容返回“未找到”而不是猜测。关闭此间隙是 [路线图](#路线图)上的主要项目。
## 基准测试
###命中率(PubChem 是否返回 *任何内容*?)
来自 `notebooks/benchmarking.ipynb`,针对 262 个多样化的 SMILES(药物、代谢物、杂环、材料、盐、立体化学、边缘情况)。此测量 *覆盖范围*,而非正确性 — 请参见下面的准确性部分以获取验证正确的速率。
| 指标 | 值 |
|---|---|
| PubChem 命中率 | **99.2%** (260/262) |
| 中位数延迟(PubChem 路径) | 620 毫秒 |
| 95% 延迟(PubChem 路径) | 1.15 秒 |
| 中位数延迟(缓存命中) | **0.32 毫秒**(≈1900 倍加速) |
| 未命中 | 2(环孢素标准化器错误, doxycycline 索引间隙) |
### 准确性(返回的名称实际上是否正确?)
来自 `tests/test_accuracy_offline.py`,针对 300 分子的分层子集,共 850 个 PubChem-OPSIN-交叉验证的参考对(完整库位于 `tests/fixtures/accuracy_dataset.csv`):
| 指标 | 值 |
|---|---|
| **第 2 级 — 结构正确性** (OPSIN 往返 InChIKey 匹配) | **95.0%** (285/300) |
| 第 1 级 — 严格的完全字符串匹配 | 95.0% |
| 第 3 级 — 名称出现在 PubChem 同义词列表 | 22.0% |
**按类别的第 2 级(结构正确性):**
| 类别 | 速率 | 备注 |
|---|---|---|
| 药物(n=53) | **100%** | |
| 立体化学(n=51) | **100%** | 通过管道保留 |
| 溶剂/脂肪族(n=36) | **100%** | |
| 杂环(n=35) | **100%** | |
| 病理性/奇异(n=25) | 96% | |
| 大型 >30 原子(n=35) | 94% | PubChem 标准间隙 |
| 不常见元素(n=11) | 82% | B/Si/Se 化合物很棘手 |
| 盐/两性离子(n=18) | 44% | 管道命名父片段;PubChem 的 `IUPACName` 连接多组件名称以分号 — 不同的约定,两者都合理 |
CI 门控如果第 2 级下降超过 1 个百分点,则失败。参见 [`docs/ACCURACY.md`](docs/ACCURACY.md) 以获取层级定义、基准测试方法和如何更新基准测试时准确性提高。
随时重新运行:
```bash
# 命中率基准测试(实时 PubChem)
jupyter nbconvert --to notebook --execute notebooks/benchmarking.ipynb
# 准确性基准测试(缓存的录音;确定性,<2 分钟)
.venv/bin/python -m pytest tests/test_accuracy_offline.py -v -s
# 从头重建参考库(~10 分钟,命中 PubChem)
.venv/bin/python scripts/build_accuracy_dataset.py --limit 1000 --seed 42
.venv/bin/python scripts/record_pubchem_cassettes.py --subset 300
```
## 比较
比较反映了此存储库中 **构建** 的内容与当前公开的替代方案的行。标记为“(计划)”的行描述了已提交但尚未部署的脚手架。
| 功能 | 此工具 | stout.decimer.ai | ChemAxon 命名 |
|---|---|---|---|
| 免费 + 开源 | ✅ MIT | ✅ MIT | ❌ 商业 |
| Python 库 | ✅ `from smiles2iupac import convert` | ❌ | ✅ |
| CLI | ✅ `s2i 'CCO'` | ❌ | ❌ |
| MCP 服务器(LLM 工具) | ✅ 4 工具,stdio | ❌ | ❌ |
| 批处理(CSV) | ✅ 流式 NDJSON | ❌ | ✅ |
| 往返验证 | ✅ OPSIN,4 级验证 | ❌ | 部分 |
| 置信度分数 | ✅ 基于来源 | ❌ | ❌ |
| InChI + InChIKey 输出 | ✅ | ❌ | 部分 |
| 盐剥离 + 原因跟踪 | ✅ | ❌ | ✅ |
| 自托管 REST API | ✅ FastAPI 在 `:7860` | ❌ | ✅ |
| 公共托管 URL(计划) | 为 HF Spaces 搭建 | ✅(经常离线) | 商业 |
| 运行时间监控(计划) | 搭建健康检查工作流 | ❌ | N/A | 依赖 HF_TOKEN 秘密 |
## 路线图
- **新型结构的新 ML 层级。** STOUT v2 最初是计划,但其上游权重下载 (`storage.googleapis.com/decimer_weights/models.zip`) 截至 2026 年 5 月返回 404,因此我们先发布仅限已验证的路径。选项:等待上游恢复权重,复刻并托管权重,或评估替代方案(例如针对相同参考数据集的微调 LLMs)。
- **PyPI 发布**,以便 `pip install smiles2iupac` 直接可用,无需检出。
- **重新启用 cron 健康检查工作流**,现在 Space 已启动。
## 架构
`src/smiles2iupac/`
| 模块 | 目的 |
|---|---|
| `pipeline.py` | 协调器 — 链接分类 → 缓存 → PubChem → OPSIN 往返 → 丰富 |
| `validator.py` | RDKit 规范化 + 重原子支持检查 |
| `validator_strict.py` | 反应/聚合物拒绝,盐剥离,分类 |
| `cache.py` | `~/.smiles2iupac/cache.db` SQLite 缓存 |
| `pubchem.py` | PUG-REST 客户端(令牌桶 5 req/s,指数级退化,InChIKey优先) |
| `opsin_check.py` | py2opsin 往返,具有 14/27 个字符的 InChIKey 层级 |
| `enrich.py` | InChI / InChIKey / 分子式 / 分子量 / SVG / CAS 助手 |
| `result.py` | Pydantic Result + Source 枚举 |
| `confidence.py` | 来源 → 置信度层级映射 |
| `cli.py` | `s2i` Click CLI |
`app/` — Gradio UI + FastAPI 安装在 `:7860`。端点:`GET /health`,`GET /convert?smiles=...`,`POST /batch`(NDJSON 流式传输)。
`deploy/` — Dockerfile(默认-jre-headless + Python 3.10-slim + RDKit X11 库)和 HF Spaces 部署说明。Space 在 <https://agwgwa-smiles2iupac.hf.space> 上运行。
`.github/workflows/` — `ci.yml`(pytest + ruff,在每个 PR 上运行)。`deploy-hf.yml` 和 `healthcheck.yml` 已提交但仅 `workflow_dispatch`(手动),直到添加 `HF_TOKEN` 秘密;它们针对 `agwgwa/smiles2iupac` 上的 Space。
## 在本地运行 Web 应用程序
```bash
uv pip install -e '.[web]'
python -m app.gradio_app
# 打开 http://localhost:7860
```
```bash
curl 'http://localhost:7860/convert?smiles=CCO' | jq .name
# "乙醇"
```
## 作为 MCP 服务器使用(Claude Desktop,Cursor,Cline)
该工具还将自己暴露为 [Model Context Protocol](https://modelcontextprotocol.io) 服务器,以便 MCP 感知型 LLM 客户端可以直接调用它。当您希望在聊天中获得可靠的化学命名,而不是让 LLM 产生 IUPAC 名称时,这很有用。
```bash
uv pip install -e '.[mcp]'
```
将 Claude Desktop 的 `claude_desktop_config.json` 添加到开发检查中(今天的工作配置):
```json
{
"mcpServers": {
"smiles2iupac": {
"command": "uv",
"args": [
"run", "--directory", "/path/to/smiles2iupac",
"--extra", "mcp",
"python", "-m", "smiles2iupac.mcp_server"
]
}
}
}
```
(重启 Claude Desktop。然后询问:“`CC(=O)Oc1ccccc1C(=O)O` 的 IUPAC 名称是什么?” — Claude 将调用我们的工具并返回 `2-acetyloxybenzoic acid`,带有出处和验证 URL。)
发布到 PyPI 后,更简单的表单 `"command": "s2i-mcp"` 将在 `pip install 'smiles2iupac[mcp]'` 后生效。尚未生效。
**公开的工具:**
| 工具 | 目的 |
|---|---|
| `smiles_to_iupac` | 正向转换。返回名称 + 置信度 + 来源 + InChIKey + 原因跟踪 + PubChem 验证 URL |
| `iupac_to_smiles` | 反向查找。OPSIN 首先(离线,立体感知)→ PubChem 备用(通用名称) |
| `classify_smiles` | 预飞行检查:它是盐吗?混合物?反应?返回父节点 + 反离子 |
| `enrich_smiles` | 纯 RDKit 元数据:InChI / InChIKey / 分子式 / 分子量 / SVG。无网络。 |
## 开发
```bash
git clone https://github.com/gvmfhy/smiles2iupac.git
cd smiles2iupac
uv venv && uv pip install -e '.[all]'
pytest # 140 个测试
```
缓存位于 `~/.smiles2iupac/cache.db` 并自动预热。随时可以删除 — 它将按需重新填充。
## 许可
MIT。参见 [LICENSE](LICENSE)。
## 致谢
基于:
- [OPSIN](https://opsin.ch.cam.ac.uk/) via [py2opsin](https://pypi.org/project/py2opsin/)(Cambridge,MIT)
- [RDKit](https://www.rdkit.org/)(BSD)
- [PubChem PUG-REST](https://pubchem.ncbi.nlm.nih.gov/docs/pug-rest)(NIH,公共领域)
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器