Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’¬ chatRDKit

Talk to RDKit in plain English. Cheminformatics without the boilerplate.

python RDKit LLM licence author

🌐 Websitemarcdeller.com βœ‰οΈ Contactmarc@marcdeller.com πŸ™ GitHubbellcheddar/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.


1. Prerequisites

1.1 Ollama + model

  1. Install Ollama:

  2. Make sure the server is running. The desktop app starts it automatically; otherwise:

    ollama serve
  3. 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.6b

    Then point chatRDKit at whichever tag you pulled (see Configuration) -- just make sure the model setting matches a tag from ollama list exactly.

  4. 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.content field.

1.2 Python + RDKit

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.txt

requirements.txt installs:

  • rdkit -- the latest release from PyPI (chemistry engine + drawing)
  • reportlab -- used for PDF report output (optional; PNG/HTML work without it)

2. Running chatRDKit

source .venv/bin/activate
python chatrdkit.py

On 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.

Three kinds of input

  • 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.

Multi-turn context

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

Rendering output

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 if reportlab isn'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).


3. Configuration

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

4. How it works

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
  1. Session. A single Python namespace (dict) is created at startup with Chem, AllChem, Draw, Descriptors, Lipinski, Crippen, QED, DataStructs, rdFingerprintGenerator, rdMolDescriptors, rdMolDraw2D, math, and a render() helper already in scope. Every molecule you create persists here for the rest of the session.

  2. Classifying input (router.classify):

    • looks_like_smiles() -- no spaces, only SMILES-valid characters, and Chem.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. typing mol).
    • Anything else is treated as English.
  3. 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.

  4. 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 normal print() output from the snippet appears directly. Errors are caught and reported without crashing the session.

  5. Rendering (render.render). Computes 2D coordinates if missing, builds a grid image with Draw.MolsToGridImage, asks for a format if not configured, and writes PNG/HTML/PDF to output_dir.


5. Safety notes

  • 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 direct os./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 on prints the model's raw output (including any stripped <think> blocks or code fences) so you can see exactly what was executed.

6. Troubleshooting

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.


7. Extending

  • More commands / better translations: extend rdkit_reference.RDKIT_CHEAT_SHEET with 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.

πŸ‘€ Author

Marc C. Deller, D.Phil.
Structural biologist & drug discovery scientist

🌐marcdeller.com βœ‰οΈmarc@marcdeller.com πŸ™github.com/bellcheddar/chatRDKit

About

Natural-language chat frontend for RDKit, powered by a local Ollama model

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages