C3LM

Chemistry Constraint–Consistent Language Model

Paper ChemCensor


CREED overview

Overview

C3LM is a chemistry-focused language model for Single-Step Retrosynthesis task. This checkpoint was initialized from LFM2-2.6B and trained with supervised fine-tuning (SFT) on a combined CREED + USPTO-full dataset.


Load model

from transformers import AutoModelForCausalLM, AutoTokenizer

# Load model and tokenizer
model_id = "insilicomedicine/C3LM"
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    torch_dtype="bfloat16",
#    attn_implementation="flash_attention_2" <- uncomment on compatible GPU
)
tokenizer = AutoTokenizer.from_pretrained(model_id)

Usage example

import re

ATOM_TOKENS = ["Ag","Al","As","Au","Bi","Br","Ca","Cl","Cr","Cu","Fe","Ga","Gd","Ge","Hg","Li","Mg","Mo","Na","Pt","Ru","Sb","Se","Si","Sn","Sc","B","C","F","H","I","K","M","N","O","P","S","V","W","Z","c","e","n","o","p","s"]

SMI_REGEX_PATTERN = (
    r"(\[|\]|\(|\)|\.|=|#|-|\+|\\|\/|:|~|@|\?|>>?|\*|\$|\%[0-9]{2}|[0-9]|"
    + "|".join(ATOM_TOKENS)
    + ")"
)
smi_regex = re.compile(SMI_REGEX_PATTERN)

def isolate_sequence(s):
    return "".join(["<sm_" + tok + ">" for tok in smi_regex.findall(s)])

def deisolate_sequence(s):
    s = re.sub("[<\s]?sm_[^>]+>", lambda matchobj: matchobj.group(0)[4:-1], s).strip()
    return s

# Prepare prompts
product_smiles = "N1C(=O)Cc2ccc(Nc3ccc(N[C@@H]4CN(C(c5cc(NCCO)ccc5)=O)C[C@@H]4c4scnc4)cc3)cc21"
prompt = f"What are the possible reactants that could have formed the following product <smiles>{isolate_sequence(product_smiles)}</smiles>? Wrap an answer in <smiles> tags/think"

input_ids = tokenizer.apply_chat_template(
    [
        {"role": "system", "content": "You are a helpful assistant in chemistry and biology."},
        {"role": "user", "content": prompt}
    ],
    add_generation_prompt=True,
    return_tensors="pt",
    tokenize=True,
)['input_ids'].to(model.device)

# Generate answer
output = model.generate(
    input_ids,
    do_sample=True,
    temperature=0.3,
    min_p=0.15,
    repetition_penalty=1.05,
    max_new_tokens=512,
)

for out in output:
    out = tokenizer.decode(out, skip_special_tokens=False)
    answer_part = out.split('</think>')[1].split('<smiles>')[1].split('</smiles>')[0]
    answer_part = deisolate_sequence(answer_part)
    print('Reactants: ', answer_part)

Citation

@misc{zagribelnyy2026singleanswerenoughrethinking,
      title={When Single Answer Is Not Enough: Rethinking Single-Step Retrosynthesis Benchmarks for LLMs}, 
      author={Bogdan Zagribelnyy and Ivan Ilin and Maksim Kuznetsov and Nikita Bondarev and Roman Schutski
                and Thomas MacDougall and Rim Shayakhmetov and Zulfat Miftakhutdinov
                and Mikolaj Mizera and Vladimir Aladinskiy and Alex Aliper and Alex Zhavoronkov},
      year={2026},
      eprint={2602.03554},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2602.03554}, 
}
Downloads last month
-
Safetensors
Model size
3B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for insilicomedicine/C3LM

Finetuned
(33)
this model

Paper for insilicomedicine/C3LM