> ## Documentation Index
> Fetch the complete documentation index at: https://proto.evodesign.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# PD-L1 Antibody Design

> Run a Germinal-style PD-L1 antibody redesign pipeline.

This program redesigns a nanobody (VHH) against the PD-L1 target using a Germinal-style,
three-stage pipeline. A fixed `target` segment carries the PD-L1 structure, and a designable
`binder` segment is optimized through three stages that share the same construct: a gradient stage
over continuous logits, a gradient stage through a softmax schedule, and a discrete semigreedy MCMC
stage. Every stage scores candidates with AlphaFold2 binder objectives (interface pTM, pLDDT,
contact, radius-of-gyration losses) and an AbLang antibody language-model term that keeps the
sequence antibody-like.

Because the three stages, the stitched AF2 template, and the CDR/framework layout are involved to
assemble by hand, this walkthrough imports the program builder from the example script and runs it
with a small configuration: one seed, one final candidate, and a few steps per stage. The full
script sweeps many seeds and runs longer schedules to produce stronger binders. It requires a GPU
and the AlphaFold2 and AbLang weights.

<a href="https://github.com/evo-design/proto-language/blob/main/examples/notebooks/germinal-pdl1.ipynb" target="_blank" class="tutorial-notebook-btn">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />

    <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
  </svg>

  <span>Open as a runnable notebook</span>

  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M7 17L17 7M9 7h8v8" />
  </svg>
</a>

<a href="https://github.com/evo-design/proto-language/blob/main/examples/scripts/germinal_pdl1_sampling.py" target="_blank" class="tutorial-notebook-btn">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M16 18l6-6-6-6" />

    <path d="M8 6l-6 6 6 6" />
  </svg>

  <span>View as a Python script</span>

  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M7 17L17 7M9 7h8v8" />
  </svg>
</a>

<Note>
  **Runtime:** this walkthrough runs real models on a GPU and takes several minutes to complete. The first run is slower because it builds the tool environment and downloads model weights.
</Note>

## Building the three-stage program

`build_program` resolves the PD-L1 target and nanobody template into language-layer segments,
stitches the two-chain AF2 template, and wires the three optimizers with their AF2 and AbLang
constraints. The fixed `target` segment is built from the template PDB chain; the designable
`binder` segment is seeded from the scaffold sequence, and both are grouped into one `Construct`
shared across all three stages. The first two stages are `GradientOptimizer` instances configured
from `germinal_logit_preset` (the logit hallucination phase) and `germinal_softmax_preset` (the
softmax refinement phase); the third is an `MCMCOptimizer` running semigreedy mutation.

The arguments below scale every stage down. `--logit-steps`, `--softmax-steps`, and
`--mcmc-steps` override each stage's step count, `--num-seeds 1 --num-results 1` produces a single
trajectory and a single ranked candidate, `--proposals-per-result 1` sets the MCMC proposals per
trajectory per step, and `--num-recycles 1` sets the AlphaFold2 recycle iterations used for
multimer scoring. The printout reports the resolved binder and target lengths.

```python python icon="python" theme={null}
import sys
from pathlib import Path

# The PD-L1 pipeline composes three stages with stitched AF2 templates; reuse the script's builder.
sys.path.insert(0, str(Path.cwd().parents[1]))
from examples.scripts.germinal_pdl1_sampling import build_program, parse_args, summarize_candidates

sys.argv = [
    "germinal",
    "--num-seeds", "1",          # one design trajectory
    "--num-results", "1",        # keep the single best candidate
    "--logit-steps", "2",        # stage 1: gradient over logits
    "--softmax-steps", "1",      # stage 2: gradient through a softmax schedule
    "--mcmc-steps", "1",         # stage 3: discrete semigreedy MCMC
    "--proposals-per-result", "1",
    "--num-recycles", "1",       # AF2 recycles for multimer scoring
    "--seed", "0",
]
args = parse_args()
program, binder, target, binder_seed, template_pdb = build_program(args)

print(f"binder length: {binder.sequence_length} aa  |  target: PD-L1 ({target.sequence_length} aa)")
```

## Running the stages

The three optimizers run in sequence on the shared construct, so each stage's output becomes the
next stage's starting point. Stage one optimizes the per-position logits with gradient descent;
stage two continues those logits through Germinal's softmax annealing schedule, where the softmax
temperature ramps from 1.0 toward 0.01; and stage three runs discrete Metropolis-Hastings,
proposing single-point mutations with the `SemigreedyMutationGenerator` and accepting or rejecting
them under simulated annealing. Every stage scores candidates with the AlphaFold2 binder
objectives and the AbLang antibody-language-model term, which scores how natural the sequence is
under an antibody language model.

`DeviceManager.get_instance().configure(allow_multiple_per_device=True)` lets the AlphaFold2 and
AbLang persistent workers coexist on the same GPU. `program.run()` executes all three stages and
populates `program.energy_scores` with the final per-trajectory objective values.

```python python icon="python" theme={null}
from proto_tools.utils import DeviceManager

DeviceManager.get_instance().configure(allow_multiple_per_device=True)
program.run()
```

## Inspect the result

`summarize_candidates` ranks the final designs by their combined objective (lower energy is
better) and pulls the headline AlphaFold2 confidence metrics out of each result's constraint
metadata. The printout shows, per candidate: `energy` (the summed weighted constraint loss being
minimized), `avg_plddt` (the predicted local-distance-difference-test confidence), and `iptm` (the
predicted interface TM-score for the binder-target interface), followed by the designed binder
sequence.

```python python icon="python" theme={null}
summary = summarize_candidates(binder, program.energy_scores)
for row in summary:
    print(f"rank {row['rank']}: energy={row['energy']:.3f} "
          f"avg_plddt={row['avg_plddt']} iptm={row['iptm']}")
    print(f"  designed binder: {row['sequence']}")
```

```text theme={null}
rank 1: energy=3.850 avg_plddt=0.7996058464050293 iptm=0.11053422838449478
  designed binder: QVQLVESGGGLVQPGGSLRLSCAASGDKGAQHQTTSLGWFRQAPGQGAEAVAAWQTKQRYGYYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCRSRVPRLARVYQGWAFEMWGQGTLVTVSSRGR
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Binder Design" icon="magnet" href="/docs/language/guides/examples/binder-design">
    A single-stage binder design with RFdiffusion3 and ProteinMPNN.
  </Card>

  <Card title="Multi-Stage Optimization" icon="layers" href="/docs/language/guides/examples/multi-stage-optimization">
    How stages hand a shared construct forward.
  </Card>
</CardGroup>
