Configuration Alternatives at Runtime
This section describes how to run the RFD4-Proteina NIM with different settings for
- serving your own model checkpoints
- deployment limits (request size, token count, step count, search cost)
- execution backend and compile tuning
- TMol metrics (refer to Oracles for the separate, mount-based refolding oracle)
- general service settings and admission control
These instructions assume you have installed and set up Prerequisite Software and pulled the container as described in Getting Started.
Start the NIM
Every environment variable that follows is passed the same way, with an
additional -e VARIABLE=value on the docker run command.
Using Your Own Model Checkpoints
RFD4-Proteina serves from two checkpoints: the latent-diffusion trunk (the
velocity model, sometimes called the “denoiser”) and a partial autoencoder
(encoder and decoder). Both are resolved from the manifest workspace at
NIM_WORKSPACE_PATH (default /opt/nim/workspace) unless named explicitly.
Serve your own weights (typically a fine-tune of the shipped architecture)
by mounting them into the container and naming them with two environment
variables:
Left unset, each is resolved by looking in NIM_WORKSPACE_PATH for the one
*.ckpt file that matches: autoencoder checkpoints are the ones whose name
contains _ae_, and the denoiser is whichever workspace checkpoint is not. That
only works when the workspace holds exactly one candidate of each kind, which
is true for the shipped image; set the variable explicitly whenever you mount
a different checkpoint, whether alongside the shipped one or in its place.
Confirm which checkpoints were loaded from the startup log:
What Is and Is Not Checked
A checkpoint you name must exist. Setting NIM_DENOISER_CKPT or
NIM_AUTOENCODER_CKPT to a path that is not a file fails the NIM at startup
rather than falling back to whatever the workspace would have resolved on its
own:
This is deliberate. Quietly serving the shipped checkpoint instead would look identical from the outside: the server starts, designs come back, metrics look ordinary. A fine-tune-and-re-serve workflow would then measure the model it was trying to replace. Leave both variables unset to use the shipped checkpoints.
The architecture is not checked up front. Each checkpoint is loaded with
strict=True, so the model is rebuilt from that checkpoint’s own saved
hyperparameters: any missing or unexpected weight key means the code has
drifted from whatever produced the checkpoint, and it is reported as a
PyTorch state-dict error at startup rather than a message from the NIM. This
also means a checkpoint trained with a materially different architecture (for
example, with the MSA module enabled, or a differently sized autoencoder)
fails loudly rather than loading partially initialized.
The Baker Laboratory’s public 2026_10_15_* checkpoints are one such case.
They widen the autoencoder’s residue vocabulary from 33 to 147 classes and
its latent from 16 to 32 dimensions. As a result, they cannot be served
through NIM_DENOISER_CKPT and NIM_AUTOENCODER_CKPT on this release.
No conversion is performed. Supply PyTorch .ckpt files in the same
format the NIM ships: either a raw training checkpoint (the EMA weights are
picked up automatically from the paired SimpleEMA state) or one already
named *-ema.ckpt. The NIM does not train or fine-tune; produce the weights
with your own training code and serve them here.
Accuracy and performance figures published for the RFD4-Proteina NIM describe the shipped checkpoints. Designs from your own weights are yours to validate.
Deployment Limits
These bound what a request can ask for, independent of the wide, static bounds enforced by the request schema itself: the schema stays wide so one client can talk to deployments of different capacity, and what a particular deployment accepts is a property of its GPU and its SLA.
Every response reports the limits actually in force for that deployment in
runtime.limits, so a client does not need to know these variable names to
discover them.
There is deliberately no ceiling on sampling.num_replicates. Replicates are
batched into one forward pass by default, so what a request can ask for is a
property of the GPU and the token count rather than a fixed number: a cap of
16 would refuse at 128 tokens a request the card would have served, and admit
at 1024 tokens one it cannot. The real detection is the out_of_memory (HTTP
413) answer, which names sampling.batch_size and sampling.num_replicates
as what the caller can change. Refer to Replicates and
Batching.
A request that exceeds one of these limits, or whose input turns out to
require more GPU memory than is available, is answered with the appropriate
error code (request_too_large or out_of_memory); refer to the
API Reference for the full error-code table.
Execution Backend and Compile Tuning
When switching a deployment from oss_torch_compile to bioir, make sure
NIM_COMPILE_LENGTHS is fully unset rather than set to an empty value: an
empty-but-set value is treated as an explicit (invalid) configuration rather
than “not configured.”
Oracle and TMol Metrics
The refolding oracle folds each design with an independent structure
predictor and scores it against eleven in-silico pass criteria
({criterion}.pass rows in the response’s aggregated_metrics). This NIM
ships with no refolding oracle built in: every image carries an inert
reward.py that declares none, and enabling one is a matter of mounting a
replacement. Refer to Oracles for the full
mount contract, the NIM_ORACLE_PLUGIN/NIM_ALLOW_ORACLE_PLUGIN variables,
and working reference implementations against hosted structure-prediction
NIMs.
A request tagging metrics or pass criteria that the mounted oracle does not
publish is rejected at request time with a clear error, rather than allowed
to run and silently score -inf mid-search. Refer to /v1/tasks and the
API Reference for which metric tags a running
deployment currently supports.
General Service Settings
NIM Telemetry
NIM Telemetry collects minimal host and NIM information to help improve performance, reliability, and compatibility across deployments. It is disabled by default and, when enabled, stays disabled on RTX GPUs unless explicitly opted in.
On an RTX GPU with telemetry requested but not opted in, the startup log reports it explicitly:
Refer to NIM Telemetry Settings for what is collected, retention, and advanced options, and to NVIDIA’s Privacy Policy.
Admission Control
By default, every request waits its turn for a free GPU, bounded only by
NIM_MAX_QUEUED_REQUESTS (10): beyond that, a request is rejected on
arrival with 503 rather than joining a queue it is unlikely to clear. In a
saturated deployment, nothing outside the process can see how deep that queue
is, so a client cannot distinguish a slow design from one that has not
started.
Setting NIM_ENABLE_QUEUE_METRICS to true hands queueing to nimlib’s own
admission-control middleware (nimlib >= 0.22.0) instead. It bounds
concurrency at NIM_MAX_CONCURRENT_REQUESTS, sheds requests with 503 and a
Retry-After header after NIM_QUEUE_TIMEOUT_SECONDS elapses or
NIM_MAX_QUEUE_DEPTH is exceeded, and publishes queue-depth metrics on
/v1/metrics. This NIM’s own queue gate (NIM_MAX_QUEUED_REQUESTS,
described earlier) stands down the moment admission control is enabled, so a
request is never waiting in two places that disagree about how many are
ahead of it.
Unlike some other bioNeMo NIMs, RFD4-Proteina does not accept
NIM_GPU_ACQUIRE_TIMEOUT_SECONDS. This NIM’s GPU worker pool waits
indefinitely for a free GPU after a request holds an admission-control permit,
rather than enforcing a second, shorter timeout of its own: a timed-out wait
would not stop the design in progress, since the worker keeps the GPU and
finishes anyway while the caller has already been told it failed.
The following table describes requirements admission control cannot infer for you.
While admission control is enabled, the following Prometheus series are
published on /v1/metrics:
Admission control is disabled unless NIM_ENABLE_QUEUE_METRICS is set. When
it is unset, this NIM’s own queue gate (NIM_MAX_QUEUED_REQUESTS) governs
request handling exactly as described in
Behavior Under Load, and none of the preceding queue
metric series are registered.
Behavior Under Load
A request arriving with every GPU worker busy and the queue full is answered
with HTTP 503 (service_busy), not 429: the NIM is not rate-limiting a
particular caller, it has no free capacity, so the caller should retry
elsewhere. Which queue governs this, this NIM’s own
(NIM_MAX_QUEUED_REQUESTS) or nimlib’s admission control
(NIM_MAX_QUEUE_DEPTH), depends on whether NIM_ENABLE_QUEUE_METRICS is set;
refer to Admission Control.
A request whose GPU memory is exhausted is answered with HTTP 413
(out_of_memory), a 4xx status: the same job on the same GPU will exhaust it
again, so retrying unchanged will not help. Memory grows with the batch size,
with the square of the token count, and with search width, so what can change
is sampling.batch_size (1 serves the replicates one at a time), the input
size, or the search width. The error names the batch size and token count it
failed at. Because batch_size defaults to num_replicates, a request that
raised its replicate count without setting a batch size raised its peak
memory with it; refer to Replicates and
Batching.
A client that disconnects before its response is ready is recorded as
HTTP 499 (client_gone) rather than a server error: since nobody
receives that status by definition, it exists only so the drop is not
counted against the NIM’s error rate. This matters more for RFD4-Proteina
than for a single forward pass: an abandoned beam search can hold a GPU for
minutes producing a response that nothing will read.