Gradient-guided adaptive beam search optimizer with Population Based Training
Project description
GrAdaBeam
Gradient-guided adaptive beam search optimizer with Population Based Training (PBT), for nucleic acid sequence design.
GrAdaBeam is the design algorithm introduced in "GrAdaBeam: Combining model gradients with evolutionary search for generalizable nucleic acid design". It unifies the broad exploration of evolutionary search with the precise guidance of model gradients, and statistically outperformed seven other design algorithms across the NucleoBench benchmark.
Overview
This package provides two sequence optimizers for designing biomolecular sequences:
| Optimizer | Gradient-guided | PBT | File |
|---|---|---|---|
| GradaBeam | Yes | Optional | gradabeam/gradabeam_optimizer.py |
| AdaBeam | No (random) | No | gradabeam/adabeam_optimizer.py |
Both use adaptive beam search with rollouts. Each round, the beam (a set of candidate sequences) is expanded by rolling out random or gradient-guided mutations, and the top-scoring candidates are kept.
GradaBeam additionally uses TISM (a sequence-level gradient) to bias mutations toward positions and characters that improve the model score, and can adapt its mutation rate on-the-fly via Population Based Training (PBT).
Scoring convention: the optimizers minimize the oracle output — lower is better. The bundled demo oracles negate their underlying quantity (e.g. a letter count) so that minimizing the score maximizes that quantity.
Installation
From PyPI:
pip install gradabeam
To run the built-in examples (e.g. BPNet), install the examples extra:
pip install "gradabeam[examples]"
From source:
git clone https://github.com/move37-labs/gradabeam.git
cd gradabeam
pip install -e .
# Or, to include the example oracles (e.g. BPNet):
# pip install -e ".[examples]"
Quick Start
The optimizers take a model_fn oracle: a callable mapping list[str] -> list[float] whose output is minimized
(lower is better). GradaBeam additionally requires the oracle to expose gradient information (see
Oracle interface).
GradaBeam (gradient-guided)
from gradabeam import GradaBeam
optimizer = GradaBeam(
model_fn=your_model, # callable: list[str] -> list[float], minimized
start_sequence="ACGTACGTACGT",
mutations_per_sequence=2.0,
beam_size=10,
n_rollouts_per_root=4,
exploration_alpha=0.05, # 0.0 = fully gradient-guided, 1.0 = uniform random
use_pbt=True, # adapt the mutation rate via Population Based Training
)
optimizer.run(n_steps=20)
top_sequences = optimizer.get_samples(n_samples=5)
print(top_sequences)
AdaBeam (gradient-free)
from gradabeam import AdaBeam
optimizer = AdaBeam(
model_fn=your_model,
start_sequence="ACGTACGTACGT",
mutations_per_sequence=2.0,
beam_size=10,
n_rollouts_per_root=4,
eval_batch_size=1,
skip_repeat_sequences=True,
)
optimizer.run(n_steps=20)
top_sequences = optimizer.get_samples(n_samples=5)
Command-Line Interface
The CLI runs either optimizer against an oracle that you supply via --oracle_script. The script must define a
make_oracle() function (see oracles/template.py for a starting point). Several ready-to-run
oracles ship in the oracles/ directory:
oracles/count_letter.py— maximizes the count of a target letter (tiny, no extra deps).oracles/substring_count.py— maximizes occurrences of a target substring.oracles/bpnet.py— a real BPNet transcription-factor-binding model (requires theexamplesextra).
You must pass --beam_size, --mutations_per_sequence, and --n_rollouts_per_root, plus exactly one of --n_steps
or --time_budget. For --optimizer gradabeam you must also pass --use_pbt. Any extra flags are forwarded to the
oracle's make_oracle().
# GradaBeam demo: maximize C-content with the count_letter oracle
python -m gradabeam \
--oracle_script oracles/count_letter.py \
--start_sequence AAAAAAAAAA \
--n_steps 10 \
--beam_size 5 \
--mutations_per_sequence 2.0 \
--n_rollouts_per_root 4 \
--exploration_alpha 0.05 \
--use_pbt True
# AdaBeam demo: maximize occurrences of a target substring (oracle arg passed through)
python -m gradabeam \
--optimizer adabeam \
--oracle_script oracles/substring_count.py \
--start_sequence AAAAAAAAAAAAAAAAAAAA \
--n_steps 10 \
--beam_size 2 \
--mutations_per_sequence 1.0 \
--n_rollouts_per_root 4 \
--substring ATGTC
# GradaBeam with the BPNet neural-network oracle on a real biological sequence
# (requires `pip install -e ".[examples]"`); --protein is forwarded to the oracle
python -m gradabeam \
--oracle_script oracles/bpnet.py \
--start_sequence local://ATAC_start_seq.txt \
--time_budget 300 \
--beam_size 2 \
--mutations_per_sequence 2.0 \
--n_rollouts_per_root 4 \
--use_pbt False \
--protein ATAC
The --start_sequence (and --positions_to_mutate) flags support two special prefixes:
# Load the sequence from a local file
python -m gradabeam --oracle_script oracles/count_letter.py \
--start_sequence local://path/to/seq.txt \
--n_steps 5 --beam_size 5 --mutations_per_sequence 2.0 --n_rollouts_per_root 4 --use_pbt True
See all options:
python -m gradabeam --help
Oracle interface
The model_fn oracle must be callable and return one score per sequence, lower is better:
def __call__(self, sequences: list[str]) -> list[float]:
"""Return a score per sequence. The optimizer minimizes this (lower is better)."""
...
GradaBeam additionally requires the oracle to provide gradient-based mutation information via get_tism
(internally it also relies on a tism_torch method):
def get_tism(
self, sequence: str, idxs: list[int] | None = None
) -> tuple[list[tuple[int, str]], np.ndarray]:
"""Return (pos_and_chars_to_mutate, logits) for the mutable positions."""
...
The easiest way to satisfy this is to inherit from gradabeam.tism.TISMModelClass, which implements get_tism and
tism_torch for you given a small set of model hooks (vocab, vocab_array, vocab_to_idx, and
inference_on_tensor). See oracles/bpnet.py and
oracles/substring_count.py for reference implementations.
Key Parameters
| Parameter | Applies to | Description |
|---|---|---|
start_sequence |
Both | Initial DNA string (alphabet ACGT). |
mutations_per_sequence |
Both | Expected number of edits applied per mutation step. |
beam_size |
Both | Number of candidate sequences carried between rounds. |
n_rollouts_per_root |
Both | Rollouts launched from each beam candidate per round. |
eval_batch_size |
Both | Sequences sent to the model per batch call. |
rng_seed |
Both | Seed for reproducibility. |
positions_to_mutate |
Both | Optional list of mutable positions (0-based). Defaults to all. |
max_rollout_len |
Both | Max rollout depth before stopping. |
exploration_alpha |
GradaBeam | Blend of gradient-guided (0.0) vs. uniform-random (1.0) mutations. |
use_pbt |
GradaBeam | Enable Population Based Training for an adaptive mutation rate. |
gradient_prob_cap |
GradaBeam | Per-action probability cap applied after softmax. |
max_logit |
GradaBeam | Dynamic temperature ceiling for TISM logit scaling. |
skip_repeat_sequences |
AdaBeam | Skip already-evaluated sequences during rollouts. |
Development
To contribute or run the tests locally, we recommend using micromamba (or mamba/conda) to set up the
development environment:
micromamba create -f environment.yml
micromamba activate gradabeam
pytest gradabeam/
Or with coverage:
pytest --cov=gradabeam gradabeam/
Citation
If you use GrAdaBeam, please cite:
@article{shor2025gradabeam,
author = {Shor, Joel and Strand, Erik and McLean, Cory Y.},
title = {{GrAdaBeam: Combining model gradients with evolutionary search for generalizable nucleic acid design}},
journal = {bioRxiv},
year = {2025},
doi = {10.1101/2025.06.20.660785},
url = {https://www.biorxiv.org/content/10.1101/2025.06.20.660785}
}
If you use the NucleoBench benchmark or the AdaBeam algorithm, please also cite:
@article{shor2025nucleobench,
author = {Shor, Joel and Strand, Erik and McLean, Cory Y.},
title = {{NucleoBench: A Large-Scale Benchmark of Neural Nucleic Acid Design Algorithms}},
journal = {bioRxiv},
year = {2025},
doi = {10.1101/2025.06.20.660785},
url = {https://www.biorxiv.org/content/10.1101/2025.06.20.660785}
}
License
Apache License 2.0, consistent with the upstream nucleobench project.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gradabeam-0.1.0.tar.gz.
File metadata
- Download URL: gradabeam-0.1.0.tar.gz
- Upload date:
- Size: 36.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59575f8ac57e08e5fd5c114888658e34f439a33f472162c234c871e9e8955a3c
|
|
| MD5 |
692742f6b4c568219adb0c56171356aa
|
|
| BLAKE2b-256 |
6e232d18d810eb15c5c148aba7c7c7094a905dbe3da7bd1ab22161412a164de8
|
Provenance
The following attestation bundles were made for gradabeam-0.1.0.tar.gz:
Publisher:
publish.yml on move37-labs/gradabeam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gradabeam-0.1.0.tar.gz -
Subject digest:
59575f8ac57e08e5fd5c114888658e34f439a33f472162c234c871e9e8955a3c - Sigstore transparency entry: 1694825372
- Sigstore integration time:
-
Permalink:
move37-labs/gradabeam@3e62f65622d3172684a54ca741fb3072f21c0c3f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/move37-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e62f65622d3172684a54ca741fb3072f21c0c3f -
Trigger Event:
push
-
Statement type:
File details
Details for the file gradabeam-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gradabeam-0.1.0-py3-none-any.whl
- Upload date:
- Size: 38.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35d1bedeb0d1b4772ae53c51e351614aabb5dbdc17ab93edf8801e2432134a7c
|
|
| MD5 |
cadac3d57f71fd3da2f468adb73bf57d
|
|
| BLAKE2b-256 |
8edc8ade9805895fc4a765118f40bf63e1d768c981549873fb32b797cb11bd72
|
Provenance
The following attestation bundles were made for gradabeam-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on move37-labs/gradabeam
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gradabeam-0.1.0-py3-none-any.whl -
Subject digest:
35d1bedeb0d1b4772ae53c51e351614aabb5dbdc17ab93edf8801e2432134a7c - Sigstore transparency entry: 1694825471
- Sigstore integration time:
-
Permalink:
move37-labs/gradabeam@3e62f65622d3172684a54ca741fb3072f21c0c3f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/move37-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e62f65622d3172684a54ca741fb3072f21c0c3f -
Trigger Event:
push
-
Statement type: