loading
loading
Protein design is a search problem. Choose amino acids for an eight-residue protein sequence and more than 25 billion combinations are possible. Choose amino acids for a 100-residue protein sequence and the number of possibilities exceeds the number of atoms in the observable universe. Somewhere in that space is a protein that opens a path to a new therapy. There are too many combinations to search exhaustively, so finding it depends on knowing where to look.
RFD4-Proteina, an NVIDIA BioNeMo open model co-developed with the Institute for Protein Design at the University of Washington’s School of Medicine, navigates that space using patterns learned from nature. It co-designs protein sequences and all-atom structures, and uses reward-guided inference-time search to focus compute on the most promising candidates.
This tutorial shows computational biologists, ML engineers and drug discovery researchers how to design protein binder candidates against PD-L1, an oncology target, using reward-guided inference-time search and introduces experimental validation results across design tasks.
You can access RFD4-Proteina in two ways:
- Choose the open model for training, inference, method development, and direct control over sampling code or
- Choose the NIM microservice for rapid inference deployment with an HTTP interface
Building on Proteina-Complexa’s partially latent approach, RFD4-Proteina combines explicit backbone coordinates with latent representation, learned sequence and atomistic variables. Its autoencoder decoder produces the sequence and all-atom structure together, removing the separate inverse-folding handoff to a model such as ProteinMPNN.
Prerequisites
- Open model
- Supported Linux GPU host and Python 3.12; follow the repository setup guide and use a supported NVIDIA GPU.
- Model cache: Setup downloads the Hugging Face bundle automatically; set HF_HOME only if you want a different cache directory.
- NIM
- Self-host: x86_64 or arm64 Linux meeting the NIM prerequisites, Docker, NVIDIA Driver, NVIDIA Container Toolkit, and an NGC API key.
- NIM API endpoint (not recommended for production runs): HTTP access through NVIDIA build.nvidia.com via Shell and Python scripts, no local GPU or model installation required.
About RFD4-Proteina
The search loop shown in Figure 1, above, is where RFD4-Proteina focuses its compute.
During inference-time reasoning search, the model denoises generation trajectories to obtain structures, scores these designs, retains and branches promising partial states, and continues until the generation criteria are reached.
Rewards can measure geometry, interactions, or independent prediction confidence. This kind of extra search optimizes designs against a specified objective to yield higher-scoring designs. Later in this tutorial, you will see how a user can enable this functionality through the open model and the NIM.
RFD4-Proteina is faster and uses less memory than RFD3 for several reasons:
- It works on a residue-level latent representation instead of atom-level, which avoids memory blow-up.
- Engineering of the diffusion process cuts sampling from about 400 steps in Proteina-Complexa to 60, and computation is concentrated on the parts of the process that matter most thanks to reasoning capabilities in the model.
- Inference-time search is also faster, since the oracles (OF3 and physics methods like tmol) are CUDA-accelerated.
- The model and kernels were co-designed with the cuEquivariance and BioNeMo Inference Runtime (BIR) teams for speed and scalability.
From a molecular design idea to candidate designs
The workflow in Figure 3, above, demonstrates how to use RFD4-Proteina to go from a scientific objective to candidates for experimental testing. An agent can coordinate these tools and track results, while scientists define the objectives and use experimental evidence to guide the next round.
Preparing the molecular inputs and environment
Begin by defining the criteria and requirements for generation. For example, RFD4-Proteina expects users to define what may change, what must remain fixed, and computational and experimental success criteria.
Use AtomWorks to generate /manipulate the input data. AtomWorks is the molecular data layer used to prepare structures and design annotations for RFD4-Proteina. Its Python and PyMOL workflows prepare fixed atoms, designable residues, hotspots, and molecular context. Preserve the supplied ligand or motif chemistry when designing surrounding protein.
Both the open model and NIM accept annotated CIFs or a condition specification plus its source structure. The specification below fixes the target and defines the new binder.
The repository’s cropped PD-L1 structure from PDB 5O45 serves as the target. Fix the target’s sequence and backbone coordinates, allow its side chains to repack, and direct binder generation toward hotspot atoms on Tyr56, Met115, and Tyr123. The new binder has 100–150 residues, with free sequence and coordinates.
Clone the repository, then run the examples from its root. This writes pdl1.json; both paths use the same target CIF and conditions.
git clone https://github.com/RosettaCommons/RFD4-Proteina.git
cd RFD4-Proteina
cat > pdl1.json <<'JSON'
{
"pdl1_binder": {
"input": "docs/examples/inputs/5o45_cropped.cif",
"contig": "100-150, /0, A17-131",
"conditions": {
"C_CRD": {"true": [{"select": "sel('A') and is_protein_backbone"}]},
"C_SEQ": {"true": [{"select": "sel('A')"}]},
"C_HOT": {"true": [
{"select": "sel('A/*/56/[CG,OH]')"},
{"select": "sel('A/*/115/[CG,SD]')"},
{"select": "sel('A/*/123/[CD2,OH]')"}
]}
}
}
}
JSON
Open model setup
On a supported Linux/CUDA system, install the repository environment with a current uv release (validated with 0.12.24). If uv is already installed, update it first so it recognizes CUDA 13.2. Setup caches the Hugging Face model bundle, including the paired autoencoder. While the model repository is private, authenticate with hf auth login using an account with access.
bash setup.sh --native
source .venv/bin/activate
NIM environment setup
To host the NIM, run this block in Bash on a supported GPU host with Docker and NVIDIA Container Toolkit installed.
read -rsp 'NGC API key: ' NGC_API_KEY; echo
export NGC_API_KEY
printf '%s' "$NGC_API_KEY" | docker login nvcr.io \
-u '$oauthtoken' --password-stdin
image=nvcr.io/nim/ipd/rfd4-proteina:latest
docker pull "$image"
export RFD4_NIM_IMAGE="$(docker image inspect \
--format '{{index .RepoDigests 0}}' "$image")"
printf '%s\n' "$RFD4_NIM_IMAGE" > nim-image.txt
export LOCAL_NIM_CACHE="$HOME/.cache/nim"
mkdir -p "$LOCAL_NIM_CACHE"
docker run -d --rm --name rfd4-proteina \
--runtime=nvidia --gpus 'device=0' -p 8000:8000 \
-e NGC_API_KEY -v "$LOCAL_NIM_CACHE":/opt/nim/.cache \
--shm-size=16g "$RFD4_NIM_IMAGE"
Generate sequences and structures
Open-model generation
Save the following as design.py in the repository root. The same script supports generation and search. Proteina.from_pretrained("nvidia/RFD4-Proteina") loads the current Hugging Face model and paired autoencoder checkpoints.
import hydra
from rfd4_proteina import Proteina
from rfproteina.generate import run_generation
@hydra.main(config_path="configs", config_name="inference", version_base="1.3")
def main(cfg):
model = Proteina.from_pretrained("nvidia/RFD4-Proteina")
run_generation(cfg, model=model)
if __name__ == "__main__":
main()
Generate one candidate from the repository root:
python design.py inputs=pdl1.json out_dir=runs/pdl1-open seed=42 compile_lengths=null
Outputs are saved under runs/pdl1-open/inference_samples/. Add num_replicates=10 for ten candidates and choose a new out_dir for each run. Hugging Face caches downloads; add revision=”<commit>” to from_pretrained to reproduce a particular model version.
NIM generation
Save this as nim_client.py. It sends the PD-L1 condition spec and target CIF to the NIM, then saves generated structures and response metrics.
import json
from pathlib import Path
import requests
spec = json.loads(Path("pdl1.json").read_text())["pdl1_binder"]
target = Path(spec["input"])
spec["input"] = target.name
payload = {
"task": "motif_scaffolding",
"input": {"format": "condition_spec", "example_id": "pdl1_binder",
"spec": spec, "files": [{"filename": target.name, "content": target.read_text()}]},
"sampling": {"num_replicates": 1, "seed": 42},
"metrics": {"tags": ["design", "hotspot_conditioning"]},
}
def submit(payload, out):
out.mkdir(parents=True, exist_ok=True)
response = requests.post("http://localhost:8000/biology/ipd/rfd4-proteina/generative",
json=payload, timeout=1800)
response.raise_for_status()
result = response.json()
(out / "response.json").write_text(json.dumps(result, indent=2))
for i, design in enumerate(result["designs"]):
dest = out / f"design-{i}.cif"
dest.write_text(design["structure"]["content"])
print(design["design_id"], dest)
if __name__ == "__main__":
submit(payload, Path("runs/pdl1-nim"))
Install requests and run the client from the repository root. Keep pdl1.json beside the target CIF.
python -m pip install requests
python nim_client.py
Performance optimizations across open model and NIM
For faster design iteration, the BioIR backend accelerates RFD4-Proteina by 1.37–1.73× over the default compiled backend across six tested Hopper GPU configurations (see Figure 4, below). On H100 PCIe, total suite time drops from 161 to 111 seconds, about 31% less runtime. The benchmark uses batch size 1 and sums warm end-to-end timings across 15 sequence lengths (128–1,024 tokens).
Inference-time search with external oracles
Open-model search with OpenFold3
Install the optional OpenFold3 runtime and weights with ./scripts/download_example_data.sh ./data_path. Set OF3_IMAGE, OF3_MODEL_DIR, and OF3_JAX_CACHE_DIR to the paths it prints, then run mkdir -p "$OF3_JAX_CACHE_DIR". Apptainer must be available on the GPU host.
This example uses the AlphaFold3 codebase, which is released under the open-source Apache 2.0 license, and the OpenFold3 model weights, which are also released under the Apache 2.0 license.
Reuse design.py with the search preset:
python design.py inference_experiment=inference_beam_example \
metrics/refolding_oracles=of3 inputs=pdl1.json subset_to_examples=null \
num_replicates=1 out_dir=runs/pdl1-open-search seed=42 compile_lengths=null
The preset uses two branches, a beam width of three, and scoring at steps 20, 40, 50 and 60. It rewards the designed chain’s OpenFold3 pLDDT (oracle.plddt_coi), with a floor of 50, and saves qualifying rollouts at reward 80. This measures confidence in the binder, not evidence of binding; inspect interface and refolding metrics separately. Outputs are under runs/pdl1-open-search/.
NIM search with OpenFold3
Save this as nim_search_request.py. It reuses the PD-L1 input and submits a reward-guided OpenFold3 search.
from pathlib import Path
from nim_client import payload, submit
key = "oracle_of3_nvcf.overall_plddt"
payload["sampling"]["num_steps"] = 60
payload["search"] = {
"step_checkpoints": [0, 20, 40, 50, 60],
"n_branch": 2, "beam_width": 3,
"reward_metrics_tags": ["unconditional_refolding"],
"weights": {key: 1.0}, "clip_values": {key: {"min": 50.0}},
"intermediate_save_min_reward": 80.0,
}
payload["metrics"] = {"tags": ["design", "unconditional_refolding"]}
submit(payload, Path("runs/pdl1-nim-search"))
Enable the NIM oracle
Mount the OpenFold3 reward.py callback as described in the oracle guide. It reports oracle_of3_nvcf.overall_plddt for the whole complex; evaluate the binder interface separately.
Save the OpenFold3 NVCF callback from the oracle guide as reward.py and export OF3_NIM_API_KEY with an NVCF invoke credential. Relaunch the service with this callback:
docker stop rfd4-proteina
docker run -d --rm --name rfd4-proteina \
--gpdocument fetched 2026-10-24 11:20 · canonical https://developer.nvidia.com/blog/design-proteins-with-rfd4-proteina-using-reward-guided-inference-time-search