Talk to RDKit in plain English. Cheminformatics without the boilerplate.
| π Website | marcdeller.com | βοΈ Contact | marc@marcdeller.com | π GitHub | bellcheddar/chatRDKit |
A natural-language chat frontend for RDKit (the open-source
cheminformatics toolkit), powered by a local Ollama model (default:
qwen3.6:27b).
Why it matters: RDKit is the backbone of open-source cheminformatics, but its API is broad and unforgiving, and every routine task (computing descriptors, drawing a molecule, running a similarity search) means recalling the exact module, class, and function names. chatRDKit removes that friction by letting you describe what you want in natural language and translating it into correct RDKit code on the fly, all running locally against an Ollama model so no structures ever leave your machine. It is useful for medicinal chemists, structural biologists, and anyone who wants RDKit's power at the speed of thought: rapid property triage, on-the-fly depiction, Lipinski checks, and fingerprint comparisons, without breaking flow to look up syntax.
Type plain English at the prompt:
chatRDKit> Load aspirin and tell me its molecular weight, LogP and TPSA
[chatRDKit] >>> aspirin = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O")
[chatRDKit] >>> print("MW:", Descriptors.MolWt(aspirin))
[chatRDKit] >>> print("LogP:", Descriptors.MolLogP(aspirin))
[chatRDKit] >>> print("TPSA:", Descriptors.TPSA(aspirin))
MW: 180.15899999999996
LogP: 1.3101
TPSA: 63.60000000000001
Or type a SMILES string directly to load a molecule, or Python/RDKit code to run it as-is. Everything runs locally in a persistent Python session -- no data leaves your machine.
-
Install Ollama:
- macOS: download the app from https://ollama.com/download, or
brew install ollama - Linux:
curl -fsSL https://ollama.com/install.sh | sh - Windows: download the installer from https://ollama.com/download
- macOS: download the app from https://ollama.com/download, or
-
Make sure the server is running. The desktop app starts it automatically; otherwise:
ollama serve
-
Pull a Qwen3.6 model:
ollama pull qwen3.6:27b
This is the default chatRDKit uses (a ~27.8B-parameter model, ~17 GB on disk) and gives the best translation quality. It needs roughly 20 GB+ of free RAM/VRAM to run comfortably. If your machine can't handle that:
# Much smaller/faster, good for trying chatRDKit out, lower translation quality: ollama pull qwen3:0.6bThen point chatRDKit at whichever tag you pulled (see Configuration) -- just make sure the
modelsetting matches a tag fromollama listexactly. -
Sanity check the server is reachable and the model responds:
curl http://localhost:11434/api/chat -d '{ "model": "qwen3.6:27b", "messages": [{"role": "user", "content": "say hi"}], "stream": false }'
You should get back a JSON response with a
message.contentfield.
chatRDKit needs Python 3.10+ and the latest RDKit. A virtual environment is recommended:
cd chatRDKit
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtrequirements.txt installs:
rdkit-- the latest release from PyPI (chemistry engine + drawing)reportlab-- used for PDF report output (optional; PNG/HTML work without it)
source .venv/bin/activate
python chatrdkit.pyOn launch you'll see a welcome banner with 5 numbered example prompts:
========================================================================
chatRDKit -- chat with RDKit (2026.03.3) using natural language
========================================================================
Try one of these to get started (type the number, or your own request):
1. Enter a SMILES string to load a molecule (e.g. CC(=O)Oc1ccccc1C(=O)O for aspirin)
2. What is the molecular weight, LogP and TPSA of caffeine?
3. Draw ibuprofen and save it as an image
4. Generate a 3D structure of ethanol and optimise its geometry
5. Compare the similarity between aspirin and paracetamol using Morgan fingerprints
Type /help for commands, /exit to quit.
chatRDKit>
Type a number to run that example. Picking 1 prompts you to enter a
SMILES string, loads it as a molecule (mol, mol2, ... in the session),
and then shows a structured follow-up menu of suggested next steps for
that molecule (compute properties, draw it, generate 3D, find rings, check
Lipinski's Rule of Five) -- type a number to run one, or just type your own
request.
- A SMILES string (e.g.
CCO,c1ccccc1,CC(=O)Oc1ccccc1C(=O)O) is loaded directly as a new molecule (mol,mol2,mol3, ...) -- no LLM call needed. - Python/RDKit code (e.g.
Descriptors.MolWt(mol),mol.GetNumAtoms(),for atom in mol.GetAtoms(): print(atom.GetSymbol())) is executed directly in the session. A bare expression's value is printed, REPL-style. - Plain English (anything else) is sent to Ollama, translated into RDKit
code using the current session state as context, echoed as
[chatRDKit] >>> ..., and executed.
chatRDKit keeps a rolling history of your requests and the code it generated, plus a live snapshot of every molecule currently in the session (so "it", "the molecule", or a compound name you already loaded resolve correctly). Clear the history with:
chatRDKit> /reset
Whenever a request involves drawing/visualising a molecule or generating a
report, chatRDKit calls a built-in render(mol, name="...") helper, which
prompts you for the output format:
[chatRDKit] Output format? (1) PNG (2) HTML (3) PDF [1]:
- PNG -- a depiction image (single molecule or a grid for several)
- HTML -- a standalone report with the image, SMILES, and formula
- PDF -- the same report as a PDF (via
reportlab; falls back to PNG with a warning ifreportlabisn't installed)
Files are written to the current directory by default. Set output_dir to
a path to always use that directory, or to ask to be prompted for a
directory each time (configurable, see below).
All settings are stored in ~/.chatrdkit/config.json and can be viewed/
changed with /config:
chatRDKit> /config # list everything
chatRDKit> /config model # show one value
chatRDKit> /config model qwen3:0.6b # change the model
chatRDKit> /config host http://localhost:11434
chatRDKit> /config temperature 0.1
chatRDKit> /config output_format png # always PNG, never ask
chatRDKit> /config output_dir ~/Desktop/chatrdkit_out
chatRDKit> /config debug on # print raw LLM output (troubleshooting)
| Setting | Default | Meaning |
|---|---|---|
host |
http://localhost:11434 |
Ollama server URL |
model |
qwen3.6:27b |
Ollama model tag (must be pulled, must match ollama list) |
temperature |
0.2 |
LLM sampling temperature |
timeout |
180 |
Request timeout (seconds) |
echo |
True |
Print each translated line before running it |
debug |
False |
Print the raw LLM response (before cleanup) to the console |
max_history |
6 |
Number of past request/response turns kept for follow-ups |
output_dir |
. (current directory) |
Where render() saves files -- a path, or ask to prompt each time |
output_format |
ask |
ask, png, html, or pdf -- set to skip the format prompt |
chatRDKit is a single file, chatrdkit.py, organised into sections:
chatrdkit.py
βββ config JSON-backed settings (~/.chatrdkit/config.json)
βββ ollama_client minimal urllib client for POST /api/chat
βββ rdkit_reference system prompt + curated RDKit cheat-sheet + session context
βββ render PNG/HTML/PDF output via Draw.MolsToGridImage
βββ session persistent exec namespace (RDKit imports + render())
βββ router SMILES/code/English classification, translation, execution
βββ cli welcome banner, REPL loop, slash commands
-
Session. A single Python namespace (dict) is created at startup with
Chem,AllChem,Draw,Descriptors,Lipinski,Crippen,QED,DataStructs,rdFingerprintGenerator,rdMolDescriptors,rdMolDraw2D,math, and arender()helper already in scope. Every molecule you create persists here for the rest of the session. -
Classifying input (
router.classify):looks_like_smiles()-- no spaces, only SMILES-valid characters, andChem.MolFromSmiles()parses it successfully.looks_like_code()-- valid Python (ast.parse) that contains an assignment, call, attribute access, control flow, etc., or is a bare name that already exists in the session (e.g. typingmol).- Anything else is treated as English.
-
Translation (
router.translate). English requests are sent to Ollama with:- a system prompt describing the exec environment, the
render()helper, and a curated RDKit cheat-sheet (rdkit_reference.py, drawn from the Getting Started with RDKit in Python guide), rdkit_reference.build_context()-- a live list of every molecule currently in the session and its variable name, so "it"/"the molecule"/a compound name resolves correctly,- the last few turns of conversation for follow-ups.
The model is instructed to return only a Python/RDKit snippet (no markdown, no explanations), reuse existing session variables, create well-known compounds from SMILES using its own chemistry knowledge, and call
render()for anything visual. Generation is capped (num_predict) and any response that comes back too long or repetitive is discarded -- and not added to history -- rather than executed. - a system prompt describing the exec environment, the
-
Execution (
router.execute_code/session.run). Each snippet is echoed as[chatRDKit] >>> ...and run in the session namespace. A single bare expression's value is printed (REPL-style); otherwise normalprint()output from the snippet appears directly. Errors are caught and reported without crashing the session. -
Rendering (
render.render). Computes 2D coordinates if missing, builds a grid image withDraw.MolsToGridImage, asks for a format if not configured, and writes PNG/HTML/PDF tooutput_dir.
- chatRDKit executes whatever code the model returns, in-process, in the
same Python interpreter. A basic safety check refuses snippets containing
import os/sys/subprocess/shutil/socket/requests,open(,eval(,exec(,__import__, or directos./sys./etc. attribute access -- the system prompt also instructs the model not to use these. This is a best-effort net, not a sandbox: review echoed[chatRDKit] >>> ...lines for anything unexpected. - Everything runs locally against your Ollama server -- no data leaves your machine.
/config debug onprints the model's raw output (including any stripped<think>blocks or code fences) so you can see exactly what was executed.
Could not reach Ollama at http://localhost:11434 ...
Start Ollama (ollama serve or open the desktop app) and confirm the model
is pulled (ollama pull qwen3.6:27b, check with ollama list).
Ollama at ... did not respond to model '...' within 180s
The model took too long to respond. Common causes: the model is still
loading into memory (try again), the machine is under heavy load (e.g.
another ollama pull running), or the model is just slow for your
hardware. Increase /config timeout 300 or switch to a smaller/faster
model.
The model's response looked malformed or repetitive ... and was discarded
Small models occasionally loop or ramble instead of producing a short
snippet. chatRDKit detects this, discards the response, and does not add
it to conversation history (so it can't poison later requests). Try again,
rephrase, or switch to a larger model (/config model qwen3.6:27b).
Refusing to run this snippet -- it contains ...
The model's response touched something outside RDKit (file I/O, os,
subprocess, etc.). Rephrase the request -- chatRDKit's render() helper
already handles all file output.
AttributeError: module 'rdkit.Chem...' has no attribute '...'
Smaller models sometimes invent plausible-but-wrong RDKit function names.
This is reported as a normal Python error without crashing the session --
try rephrasing, or switch to qwen3.6:27b for better accuracy.
PDF output falls back to PNG
Install reportlab (pip install reportlab) for PDF report support.
- More commands / better translations: extend
rdkit_reference.RDKIT_CHEAT_SHEETwith examples for operations you use often. - Richer session context:
rdkit_reference.build_context()is the place to add more state (e.g. 3D conformers, reaction history). - New output formats: add a branch to
render.render()alongside_write_html/_write_pdf.
Marc C. Deller, D.Phil.
Structural biologist & drug discovery scientist
| π | marcdeller.com | βοΈ | marc@marcdeller.com | π | github.com/bellcheddar/chatRDKit |