Syntheseus 完整教學:模組化逆合成規劃框架

1. 專案定位與核心價值

1.1 什麼是 Syntheseus?

Syntheseus 是 Microsoft Research 開發的 Python 套件,專為逆合成規劃 (retrosynthetic planning) 設計。逆合成分析的目標是:給定一個目標分子 (target molecule),反向推導出一條或多條從商業可購買的起始物料 (building blocks) 到目標分子的合成路線 (synthesis route)。

Syntheseus 的核心價值在於模組化:它將逆合成問題拆解為兩個可獨立替換的組件——

  1. Single-step model(單步反應模型):預測一步逆合成反應——給定一個分子,預測哪些反應物可以合成它
  2. Multi-step search algorithm(多步搜尋演算法):將單步預測組合成完整的合成路線,直到所有起始物料都可購買

這種設計讓研究者可以自由組合不同的模型與搜尋策略,進行公平的基準測試比較。

1.2 為什麼對 Lead Optimization 有價值?

在 lead optimization 階段,medicinal chemist 需要對新設計的 analog 進行 retrosynthesis 評估:

  • 合成可行性 (synthetic feasibility):這個分子能不能合成?
  • 合成步驟數 (step count):需要幾步?步驟越少越好
  • 起始物料可購買性 (building block availability):所需的 building block 是否能從供應商購買?
  • 路線多樣性 (route diversity):有沒有備選路線?

Syntheseus 直接解決這些問題:

  • 內建 MolInventory 介面,可載入供應商 building block 清單
  • 搜尋演算法會在找到可購買起始物料時自動終止
  • 支援提取多條路線,按時間序或成本排序
  • 可設定 max_expansion_depth 控制最大合成步驟數

2. 架構概覽

2.1 三層架構

 1┌─────────────────────────────────────────────────┐
 2│                    CLI Layer                     │
 3│         syntheseus search / eval-single-step     │
 4├─────────────────────────────────────────────────┤
 5│               Search Layer                       │
 6│   Retro* │ MCTS │ BFS │ PDVN │ Random            │
 7│   AND/OR Graph │ MolSet Graph                     │
 8│   Route Extraction │ Visualization                │
 9├─────────────────────────────────────────────────┤
10│             Interface Layer                       │
11│   Molecule │ Reaction │ Bag │ Models              │
12│   BackwardReactionModel │ ForwardReactionModel     │
13│   MolInventory                                    │
14├─────────────────────────────────────────────────┤
15│         Reaction Prediction Layer                 │
16│   8 Single-step Model Wrappers                    │
17│   Chemformer │ LocalRetro │ MEGAN │ MHNreact      │
18│   Graph2Edits │ RootAligned │ RetroKNN │ GLN       │
19│   Filters (Forward, Scoring)                      │
20└─────────────────────────────────────────────────┘

2.2 資料流

 1Target SMILES
 2 3 4Molecule(smiles)  ──→  SearchAlgorithm.run_from_mol()
 5 6                             ├──→ 建立 Graph(AND/OR 或 MolSet)
 7 8                             ├──→ 迭代展開節點:
 9                             │       │
10                             │       ├── MolInventory.is_purchasable(mol)?
11                             │       │     └── 是 → 標記為 leaf,不展開
12                             │       │
13                             │       └── BackwardReactionModel([mol])
14                             │             └── 回傳 [SingleProductReaction, ...]
15                             │                   └── 加入 Graph 作為子節點
1617                             ├──→ 終止條件:
18                             │       time_limit / iteration_limit / first_solution
1920                             └──→ 輸出 Graph
212223                        Route Extraction
242526                    Visualization (PDF)

3. 安裝與環境設置

3.1 Core 安裝(僅搜尋,不含模型)

適合只需要使用搜尋演算法、已有自己模型的情況:

1# 建立 conda 環境
2conda env create -f environment.yml
3conda activate syntheseus
4
5# 安裝核心套件
6pip install syntheseus

Core 安裝的依賴極少:rdkit, networkx, numpy, omegaconf, more_itertools, tqdm

3.2 Full 安裝(含所有模型)

適合需要使用內建 single-step model 的情況:

1# 建立完整環境(含 PyTorch + CUDA)
2conda env create -f environment_full.yml
3conda activate syntheseus-full
4
5# 安裝所有 extras
6pip install "syntheseus[all]"

注意:environment_full.yml 固定 CUDA 版本為 11.3,如需其他版本請自行修改。

3.3 選擇性安裝特定模型

只安裝需要的模型以減少依賴:

1# 只安裝 LocalRetro 和 RootAligned
2pip install "syntheseus[local-retro,root-aligned]"
3
4# 可選模型:chemformer, graph2edits, local-retro, megan, mhn-react, retro-knn, root-aligned
5# 附加:viz (視覺化), dev (開發工具)

3.4 預訓練 Checkpoint

所有 8 個模型都提供 USPTO-50K 預訓練 checkpoint,首次使用時自動下載,快取在 $HOME/.cache/torch/syntheseus。可透過環境變數 SYNTHESEUS_CACHE_DIR 自訂路徑。

4. 核心介面 (Interface Layer)

4.1 Molecule

Molecule 是不可變 (frozen) 的 dataclass,以 SMILES 字串為唯一識別:

1from syntheseus import Molecule
2
3mol = Molecule("CC(=O)Oc1ccccc1C(O)=O")  # aspirin
4print(mol.smiles)        # 正規化的 canonical SMILES
5print(mol.metadata)      # 可附加 is_purchasable, cost, supplier 等 metadata
6
7# 可存取 rdkit Mol 物件
8rdkit_mol = mol.rdkit_mol

重要特性:

  • 建構時預設自動做 SMILES canonicalization
  • frozen=True:建立後 SMILES 不可修改(保證 hash 一致性)
  • metadata 為 TypedDict,不參與 hash/compare,可自由增減欄位

4.2 Reaction 與 SingleProductReaction

 1from syntheseus.interface.reaction import Reaction, SingleProductReaction
 2from syntheseus.interface.bag import Bag
 3
 4# 從 reaction SMILES 建立
 5rxn = Reaction.from_reaction_smiles("CC.O>>CCO")
 6
 7# SingleProductReaction — 逆合成常用格式
 8retro_rxn = SingleProductReaction(
 9    reactants=Bag([Molecule("CC"), Molecule("O")]),
10    product=Molecule("CCO")
11)
12print(retro_rxn.product.smiles)       # "CCO"
13print(retro_rxn.reactants_str)        # "C.CC" (sorted)
14print(retro_rxn.reaction_smiles)      # "C.CC>>CCO"

Bag 是 frozen multiset(有序 tuple),保證相同反應物組合的 hash 一致。

4.3 Models 抽象介面

所有模型都繼承 BaseModel,提供 LRU 快取與呼叫次數追蹤:

 1# Backward model:product → reactants(逆合成核心)
 2class BackwardReactionModel(ReactionModel[Molecule, SingleProductReaction]):
 3    def _get_reactions(self, inputs: list[Molecule], num_results: int) -> list[Sequence[SingleProductReaction]]:
 4        ...
 5
 6# Forward model:reactants → products(可用於 round-trip 驗證)
 7class ForwardReactionModel(ReactionModel[Bag[Molecule], Reaction]):
 8    ...
 9
10# Scoring model:為反應打分
11class ReactionScoringModel(BaseModel[Reaction, float]):
12    ...
13
14# Filter model:過濾不合理反應(v0.7.2+ 新增抽象)
15class ReactionFilterModel(BaseModel[SingleProductReaction, bool]):
16    ...

4.4 MolInventory(分子可購買性清單)

 1from syntheseus.search.mol_inventory import SmilesListInventory
 2
 3# 從檔案載入 building block 清單(一行一個 SMILES)
 4inventory = SmilesListInventory.load_from_file("building_blocks.smi")
 5
 6# 查詢可購買性
 7mol = Molecule("CCO")
 8is_buyable = inventory.is_purchasable(mol)
 9print(f"Ethanol purchasable: {is_buyable}")
10
11# 取得清單大小
12print(f"Inventory size: {len(inventory)}")

實務建議:可從 Enamine REAL、eMolecules、MolPort 等供應商下載 building block SMILES 清單。

5. 搜尋演算法 (Search Layer)

5.1 內建演算法概覽

演算法Graph 類型特性適用場景
Retro*AND/ORBest-first search,使用 value function 預估合成難度預設推薦,綜合效能最佳
MCTSMolSetMonte Carlo Tree Search,UCT/P-UCB 選擇策略需要探索多樣路線
PDVNAND/ORDual value network MCTS 變體研究用途,可訓練 value/policy
BFSAND/OR 或 MolSet廣度優先搜尋,不需 value function找最短步驟路線
RandomAND/OR 或 MolSet隨機搜尋基線比較

5.2 AND/OR Graph vs MolSet Graph

AND/OR Graph(Retro*, PDVN 使用):

  • OrNode = 分子節點:「需要合成這個分子」
  • AndNode = 反應節點:「用這個反應來合成」
  • 一個 OrNode 找到任一 AndNode 的所有子 OrNode 可購買,即有解

MolSet Graph(MCTS 使用):

  • 每個節點是一組待合成分子的 frozenset
  • 根節點 = {target}
  • 展開一個分子後,用反應物替換它
  • 節點中所有分子都可購買時,即有解

5.3 搜尋停止條件

1# 常用的停止條件控制
2SearchAlgorithm(
3    time_limit_s=600,                    # 壁鐘時間限制(秒)
4    limit_reaction_model_calls=1_000_000, # 模型呼叫次數上限
5    limit_iterations=1_000_000,           # 迭代次數上限
6    max_expansion_depth=50,               # 最大搜尋深度
7    stop_on_first_solution=False,         # 找到第一個解就停?
8    prevent_repeat_mol_in_trees=True,     # 防止合成路線中分子重複
9)

Lead optimization 建議

  • 設定 max_expansion_depth=6~10(實際製藥合成通常 3-8 步)
  • 設定 time_limit_s=60~300(每個分子 1-5 分鐘)
  • 設定 stop_on_first_solution=False 以搜集多條路線

6. 內建 Single-Step Models

6.1 模型清單

Syntheseus 內建 8 個 SOTA backward reaction model 的推論 wrapper:

模型類型特性
ChemformerSequence-to-sequenceTransformer 架構,SMILES → SMILES
LocalRetroTemplate-based局部 atom mapping,高精度
MEGANGraph edit分子圖編輯預測
MHNreactTemplate-basedModern Hopfield Network
Graph2EditsGraph edit圖到編輯操作預測
RootAlignedSequence-to-sequenceRoot-aligned SMILES
RetroKNNTemplate + retrievalLocalRetro + kNN 增強
GLNTemplate-basedGraph Logic Network(需專用 Docker 環境)

6.2 使用預設 Checkpoint

所有模型提供 USPTO-50K 預訓練權重,首次使用自動下載:

 1from syntheseus.reaction_prediction.inference.local_retro import LocalRetroModel
 2
 3# 不指定 model_dir → 自動下載預設 checkpoint
 4model = LocalRetroModel()
 5
 6# 推論
 7from syntheseus import Molecule
 8target = Molecule("CC(=O)Oc1ccccc1C(O)=O")  # aspirin
 9results = model([target], num_results=10)
10
11for rxn in results[0]:
12    print(f"  {rxn.reactants_str} >> {rxn.product.smiles}")
13    if "probability" in rxn.metadata:
14        print(f"    probability: {rxn.metadata['probability']:.4f}")

6.3 反應過濾器 (Reaction Filters)

v0.7.2+ 新增的反應過濾抽象,可在搜尋前過濾不合理的預測:

 1from syntheseus.reaction_prediction.filters.forward import ForwardReactionFilterModel
 2from syntheseus.reaction_prediction.filters.scoring import ScoringReactionFilterModel
 3
 4# Round-trip filter:用 forward model 驗證逆合成預測
 5rt_filter = ForwardReactionFilterModel(
 6    forward_model=forward_model,
 7    top_k=10  # 檢查 forward 預測的 top-k 中是否包含原始 product
 8)
 9
10# Score-based filter:過濾低分反應
11score_filter = ScoringReactionFilterModel(
12    scoring_model=scoring_model,
13    min_score_threshold=0.5
14)

7. CLI 使用指南

7.1 搜尋(核心功能)

1syntheseus search \
2    search_target="NC1=Nc2ccc(F)cc2C2CCCC12" \
3    model_class=LocalRetro \
4    inventory_smiles_file=building_blocks.smi \
5    time_limit_s=60 \
6    search_algorithm=retro_star \
7    num_top_results=50 \
8    results_dir=./results

主要參數:

  • search_target:目標分子 SMILES(或 search_targets_file 批量處理)
  • model_class:Chemformer / LocalRetro / MEGAN / MHNreact / Graph2Edits / RootAligned / RetroKNN / GLN
  • inventory_smiles_file:可購買分子 SMILES 清單
  • search_algorithm:retro_star / mcts / pdvn
  • time_limit_s:搜尋時間限制
  • num_top_results:每次模型推論的候選數量
  • num_routes_to_plot:輸出視覺化路線數量

7.2 搜尋輸出結構

1results/LocalRetro_2026-06-05T10:00:00/
2├── stats.json           # 搜尋統計(是否找到解、模型呼叫次數、解答時間)
3├── graph.pkl            # 完整搜尋圖(pickle 格式)
4├── route_0.pkl          # 第一條路線
5├── route_0.pdf          # 第一條路線的視覺化(需 graphviz)
6├── route_1.pkl          # 第二條路線
7└── route_1.pdf          # ...

7.3 單步模型評估

1syntheseus eval-single-step \
2    model_class=LocalRetro \
3    data_dir=./data/USPTO_50k \
4    results_dir=./eval_results

8. Python API 實戰範例

8.1 完整搜尋流程

 1from syntheseus import Molecule
 2from syntheseus.reaction_prediction.inference.local_retro import LocalRetroModel
 3from syntheseus.search.algorithms.best_first.retro_star import RetroStarSearch
 4from syntheseus.search.mol_inventory import SmilesListInventory
 5from syntheseus.search.node_evaluation.common import ConstantNodeEvaluator
 6
 7# 1. 載入模型
 8model = LocalRetroModel(use_cache=True)
 9
10# 2. 載入 building block 清單
11inventory = SmilesListInventory.load_from_file("building_blocks.smi")
12
13# 3. 設定搜尋演算法
14alg = RetroStarSearch(
15    reaction_model=model,
16    mol_inventory=inventory,
17    value_function=ConstantNodeEvaluator(constant=0.5),
18    and_node_cost_fn=ConstantNodeEvaluator(constant=0.1),
19    time_limit_s=120,
20    max_expansion_depth=8,
21    limit_iterations=10_000,
22    stop_on_first_solution=False,
23)
24
25# 4. 執行搜尋
26target = Molecule("c1ccc2c(c1)CC1CCCCC1N2")  # 範例目標分子
27graph, num_steps = alg.run_from_mol(target)
28
29# 5. 檢查結果
30print(f"Graph nodes: {len(graph)}")
31print(f"Root has solution: {graph.root_node.has_solution}")
32print(f"Model calls: {model.num_calls()}")

8.2 路線提取與分析

 1from syntheseus.search.analysis.route_extraction import (
 2    iter_routes_time_order,
 3    iter_routes_cost_order,
 4)
 5from syntheseus.search.analysis.solution_time import get_first_solution_time
 6
 7# 按時間順序提取路線
 8routes = list(iter_routes_time_order(graph, max_routes=5))
 9print(f"Found {len(routes)} routes")
10
11# 分析每條路線
12for i, route_nodes in enumerate(routes):
13    # 提取路線中的分子與反應
14    from syntheseus.search.graph.and_or import OrNode, AndNode
15    mols = [n for n in route_nodes if isinstance(n, OrNode)]
16    rxns = [n for n in route_nodes if isinstance(n, AndNode)]
17    
18    purchasable = [m for m in mols if m.mol.metadata.get("is_purchasable")]
19    
20    print(f"\nRoute {i+1}:")
21    print(f"  Steps: {len(rxns)}")
22    print(f"  Molecules: {len(mols)}")
23    print(f"  Purchasable building blocks: {len(purchasable)}")
24    for m in purchasable:
25        print(f"    - {m.mol.smiles}")
26
27# 取得首次找到解答的時間
28for node in graph.nodes():
29    node.data["analysis_time"] = node.data.get("num_calls_rxn_model", 0)
30first_soln_time = get_first_solution_time(graph)
31print(f"First solution at model call #{first_soln_time}")

8.3 自訂 Backward Model

 1from syntheseus.interface.models import BackwardReactionModel
 2from syntheseus.interface.molecule import Molecule
 3from syntheseus.interface.reaction import SingleProductReaction
 4from syntheseus.interface.bag import Bag
 5
 6class MyCustomModel(BackwardReactionModel):
 7    """自訂逆合成模型 wrapper"""
 8    
 9    def __init__(self, my_model, **kwargs):
10        super().__init__(**kwargs)
11        self.my_model = my_model
12    
13    def _get_reactions(
14        self, inputs: list[Molecule], num_results: int
15    ) -> list[list[SingleProductReaction]]:
16        all_results = []
17        for mol in inputs:
18            # 呼叫你的模型
19            predictions = self.my_model.predict(mol.smiles, top_k=num_results)
20            
21            reactions = []
22            for pred in predictions:
23                reactants = Bag([Molecule(smi) for smi in pred["reactants"]])
24                rxn = SingleProductReaction(
25                    reactants=reactants,
26                    product=mol,
27                    metadata={"probability": pred.get("score", 0.0)}
28                )
29                reactions.append(rxn)
30            all_results.append(reactions)
31        
32        return all_results
33
34# 使用自訂模型進行搜尋
35custom_model = MyCustomModel(my_model, use_cache=True)
36alg = RetroStarSearch(
37    reaction_model=custom_model,
38    mol_inventory=inventory,
39    ...
40)

9. 與 Lead Optimization 工作流整合

9.1 批量評估 Analog 的合成可行性

 1import json
 2from pathlib import Path
 3from syntheseus import Molecule
 4from syntheseus.search.algorithms.best_first.retro_star import RetroStarSearch
 5from syntheseus.search.analysis.route_extraction import iter_routes_time_order
 6
 7def evaluate_synthesizability(
 8    smiles_list: list[str],
 9    model,
10    inventory,
11    time_limit_per_mol: float = 60,
12    max_depth: int = 8,
13) -> list[dict]:
14    """批量評估分子的合成可行性"""
15    
16    alg = RetroStarSearch(
17        reaction_model=model,
18        mol_inventory=inventory,
19        value_function=ConstantNodeEvaluator(constant=0.5),
20        and_node_cost_fn=ConstantNodeEvaluator(constant=0.1),
21        time_limit_s=time_limit_per_mol,
22        max_expansion_depth=max_depth,
23        stop_on_first_solution=False,
24    )
25    
26    results = []
27    for smi in smiles_list:
28        alg.reset()
29        mol = Molecule(smi)
30        graph, _ = alg.run_from_mol(mol)
31        
32        routes = list(iter_routes_time_order(graph, max_routes=3))
33        
34        results.append({
35            "smiles": smi,
36            "is_synthesizable": graph.root_node.has_solution,
37            "num_routes_found": len(routes),
38            "model_calls": model.num_calls(),
39            "graph_size": len(graph),
40        })
41    
42    return results
43
44# 使用範例
45analogs = ["CCO", "c1ccccc1", "CC(=O)Oc1ccccc1C(O)=O"]
46report = evaluate_synthesizability(analogs, model, inventory)
47for r in report:
48    status = "PASS" if r["is_synthesizable"] else "FAIL"
49    print(f"[{status}] {r['smiles']}{r['num_routes_found']} routes")

9.2 Building Block 清單管理

 1from syntheseus.search.mol_inventory import SmilesListInventory
 2
 3# 方法 1:從檔案載入
 4inventory = SmilesListInventory.load_from_file("enamine_bb.smi")
 5
 6# 方法 2:從 Python list 建立
 7bb_smiles = ["CCO", "CC(=O)O", "c1ccccc1", "CC(N)C(O)=O"]
 8inventory = SmilesListInventory(bb_smiles, canonicalize=True)
 9
10# 方法 3:合併多個供應商清單
11import itertools
12enamine = open("enamine_bb.smi").read().splitlines()
13molport = open("molport_bb.smi").read().splitlines()
14combined = list(set(itertools.chain(enamine, molport)))
15inventory = SmilesListInventory(combined, canonicalize=True)
16
17print(f"Total building blocks: {len(inventory)}")

9.3 短步驟優先策略

 1# 策略 1:限制搜尋深度
 2alg = RetroStarSearch(
 3    max_expansion_depth=5,  # 最多 5 步
 4    ...
 5)
 6
 7# 策略 2:使用 BFS 找最短路線
 8from syntheseus.search.algorithms.breadth_first import AndOr_BreadthFirstSearch
 9
10bfs_alg = AndOr_BreadthFirstSearch(
11    reaction_model=model,
12    mol_inventory=inventory,
13    max_expansion_depth=6,
14    time_limit_s=120,
15)
16
17# 策略 3:Retro* 搭配高 and_node_cost 偏好短路線
18from syntheseus.search.node_evaluation.common import ConstantNodeEvaluator
19
20alg = RetroStarSearch(
21    reaction_model=model,
22    mol_inventory=inventory,
23    value_function=ConstantNodeEvaluator(constant=0.5),
24    and_node_cost_fn=ConstantNodeEvaluator(constant=1.0),  # 每一步成本 = 1
25    # 這會讓 Retro* 偏好步驟數少的路線
26    ...
27)

10. 進階主題

10.1 視覺化合成路線

 1# 需安裝 viz extras: pip install "syntheseus[viz]"
 2from syntheseus.search.visualization import visualize_andor
 3
 4# 視覺化 AND/OR graph 中的特定路線
 5routes = list(iter_routes_time_order(graph, max_routes=1))
 6if routes:
 7    visualize_andor(
 8        graph=graph,
 9        filename="route_0.pdf",
10        nodes=routes[0],
11        draw_mols=True  # 繪製分子結構圖
12    )

輸出 PDF 中:

  • 綠色邊框 = 可購買分子
  • 紅色邊框 = 不可購買分子
  • 橢圓 = 分子節點 (OrNode)
  • 方塊 = 反應節點 (AndNode)

10.2 搜尋演算法比較

 1from syntheseus.search.algorithms.best_first.retro_star import RetroStarSearch
 2from syntheseus.search.algorithms.mcts.molset import MolSetMCTS
 3from syntheseus.search.algorithms.breadth_first import AndOr_BreadthFirstSearch
 4
 5algorithms = {
 6    "Retro*": RetroStarSearch,
 7    "MCTS": MolSetMCTS,
 8    "BFS": AndOr_BreadthFirstSearch,
 9}
10
11# 用相同模型與 inventory 比較
12for name, AlgClass in algorithms.items():
13    alg = AlgClass(
14        reaction_model=model,
15        mol_inventory=inventory,
16        time_limit_s=60,
17        max_expansion_depth=10,
18        # 各演算法特有參數...
19    )
20    graph, _ = alg.run_from_mol(target)
21    routes = list(iter_routes_time_order(graph, max_routes=5))
22    print(f"{name}: solved={graph.root_node.has_solution}, routes={len(routes)}, calls={model.num_calls()}")
23    alg.reset()

10.3 配置檔驅動搜尋

CLI 搜尋支援 YAML 配置檔,透過 OmegaConf 管理:

 1# search_config.yml
 2search_target: "CC(=O)Oc1ccccc1C(O)=O"
 3model_class: LocalRetro
 4inventory_smiles_file: building_blocks.smi
 5search_algorithm: retro_star
 6time_limit_s: 120
 7num_top_results: 50
 8retro_star_config:
 9  max_expansion_depth: 8
10  value_function_class: ConstantNodeEvaluator
11  value_function_kwargs:
12    constant: 0.5
13  and_node_cost_fn_class: ReactionModelLogProbCost
1syntheseus search --config search_config.yml

10.4 Resumable 評估(v0.7.2+)

v0.5.0+ 支援搜尋結果複用,v0.7.2 後的 single-step evaluation 也支援 resumability:

1# 如果上一次 eval 中斷,再次執行會跳過已完成的部分
2syntheseus eval-single-step \
3    model_class=LocalRetro \
4    data_dir=./data/USPTO_50k \
5    results_dir=./eval_results

11. 疑難排解與最佳實踐

11.1 常見問題

問題解決方案
ModuleNotFoundError: graphvizpip install "syntheseus[viz]" 或設 num_routes_to_plot=0
搜尋永不停止確認設定了 time_limit_slimit_iterations
找不到合成路線增加 time_limit_smax_expansion_depthnum_top_results;檢查 inventory 是否涵蓋足夠 building blocks
GPU 記憶體不足use_gpu=False 或減少 num_top_results
Checkpoint 下載失敗設定 SYNTHESEUS_CACHE_DIR 環境變數,手動下載 checkpoint
eval() in LocalRetro上游模型行為,輸入來自模型推論非使用者輸入,風險可控

11.2 效能調優建議

  1. 啟用模型快取use_cache=True(預設),避免重複推論相同分子
  2. 合理設定 num_top_results:50 通常足夠,過大會增加搜尋空間
  3. 使用 GPU:所有 neural model 都支援 GPU 推論
  4. LRU cache eviction:v0.6.0+ 支援 max_cache_size 限制記憶體使用
  5. Batch size:CLI 預設 batch_size=1,若需批量可調整

11.3 引用

如在學術工作中使用 Syntheseus,請引用:

1@article{maziarz2024re,
2  title={Re-evaluating retrosynthesis algorithms with syntheseus},
3  author={Maziarz, Krzysztof and Tripp, Austin and Liu, Guoqing and Stanley, Megan and Xie, Shufang and Gainski, Piotr and Seidl, Philipp and Segler, Marwin},
4  journal={Faraday Discussions},
5  year={2024},
6  publisher={Royal Society of Chemistry}
7}

本教學基於 syntheseus v0.7.2(2026-01-30),MIT License。