Skip to main content
The optimize() function implements a genetic-like optimization algorithm that iteratively generates and refines molecules based on oracle feedback.

The optimize() Function

Located in chemlactica/mol_opt/optimization.py, this is the main entry point:

Parameters

AutoModelForCausalLM
required
The ChemLactica model (125M, 1.3B, or Chemma-2B)
AutoTokenizer
required
Tokenizer corresponding to the model
Oracle
required
Your custom oracle implementing the oracle interface
dict
required
Hyperparameter configuration dictionary (from YAML)
dict
default:"{}"
Optional additional properties to include in prompts (e.g., molecular weight, logP)
callable
default:"lambda x: True"
Optional function to validate generated SMILES before scoring

Algorithm Workflow

The optimization process follows these steps:
1

Initialize Pool

Create an empty pool to store the top-performing molecules
The pool maintains:
  • Top pool_size molecules sorted by score
  • Training/validation split for fine-tuning
  • Diversity filtering to avoid duplicates
2

Generation Loop

Generate num_gens_per_iter new molecules per iteration:a) Create prompts from pool molecules:
Each prompt includes:
  • Similar molecules with Tanimoto similarities
  • Desired oracle score (random between max_score and max_possible_oracle_score)
  • Additional properties if specified
b) Generate molecules:
c) Parse and validate:
Extract SMILES between [START_SMILES] and [END_SMILES] tags
3

Oracle Evaluation

Score unique molecules with the oracle:
Track best score and log results:
4

Update Pool

Add new molecules to the pool:
The pool:
  • Sorts molecules by score (descending)
  • Removes duplicates and highly similar molecules
  • Keeps only top pool_size molecules
  • Maintains train/validation split
5

Adaptive Fine-tuning (Optional)

If using rej-sample-v2 strategy and no improvement for train_tol_level iterations:a) Prepare datasets:
b) Fine-tune model:
The model learns to generate molecules that match the oracle’s preferences.
6

Adjust Temperature

Increase sampling temperature over time for exploration:
Starts at generation_temperature[0] and increases to generation_temperature[1]
7

Check Stopping Condition

Stop when oracle budget is exhausted:

Key Components

Pool Management

The Pool class (mol_opt/utils.py:88) maintains top molecules:

Prompt Construction

The OptimEntry.to_prompt() method creates prompts for generation: During generation (is_generation=True):
During training (is_generation=False):

Molecule Entry

The MoleculeEntry class represents a molecule:

Tolerance Mechanism

The algorithm tracks iterations without improvement:
This adaptive mechanism ensures:
  • Continued exploration when making progress
  • Model adaptation when stuck
  • Efficient use of oracle budget

Generation Temperature Schedule

Temperature increases linearly to encourage exploration:
Why increase temperature?
  • Early: Low temperature (1.0) focuses on likely, high-quality molecules
  • Late: High temperature (1.5) explores diverse, creative solutions
  • This schedule balances exploitation and exploration

Diversity Filtering

The pool removes molecules that are too similar:
By default, only exact duplicates are removed. You can increase diversity_score in the pool to filter more aggressively.

Algorithm Pseudocode

Here’s the complete algorithm in pseudocode:

Comparison with Other Approaches

Similarities:
  • Maintains a pool of top candidates
  • Iterative generation and selection
  • Fitness-based ranking
Differences:
  • Uses LLM generation instead of crossover/mutation
  • Prompts guide generation with similarity constraints
  • Optional model fine-tuning for adaptation
Similarities:
  • Oracle acts as reward function
  • Model learns to maximize rewards
  • Exploration-exploitation tradeoff
Differences:
  • No RL training loop (uses supervised fine-tuning)
  • Simpler implementation
  • Faster convergence on many benchmarks
Similarities:
  • Efficient use of oracle budget
  • Balances exploration and exploitation
Differences:
  • No surrogate model
  • LLM directly generates candidates
  • Better handles discrete molecular space

Performance Characteristics

Memory Usage

  • Pool: ~10-100 molecules (negligible)
  • Model: 125M (~0.5GB), 1.3B (~5GB), 2B (~8GB)
  • Fine-tuning: +2x model size during training

Oracle Calls

  • Typical budget: 1K - 10K calls
  • Batch size: 200 molecules/iteration
  • PMO benchmark: ~5K calls to SOTA

Runtime

  • Generation: ~1-2 sec/batch (200 molecules)
  • Fine-tuning: ~30 sec - 2 min per round
  • Total: Minutes to hours depending on oracle complexity

Success Rate

  • QED optimization: 99% success (10K calls)
  • PMO benchmark: 17.5 avg score
  • Docking: 3-4x fewer calls than SOTA

Next Steps

Configure Hyperparameters

Learn how to tune pool size, temperature, and fine-tuning settings

Complete Examples

See full working examples with different oracles