> ## 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.

# Beam Search Optimizer

> Beam search over an autoregressive language model: extends a single segment in fixed-length steps, scoring each candidate's full sequence against the constraints and keeping the top-scoring beams at every step.

<div class="page-hero">
  <div className="block dark:hidden">
    <svg viewBox="0 0 720 432" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Beam search optimizer: branch and prune beams at each generation step" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridbeamL" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arrbeamL" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#768b8e" /></marker></defs><rect x="12" y="12" width="696" height="408" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="696" height="408" rx="16" fill="url(#gridbeamL)" /><path d="M94,206 L202,108" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,140" fill="none" stroke="#046e7a" strokeWidth="2.6" /><path d="M94,206 L202,172" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,240" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,272" fill="none" stroke="#9eb4b2" strokeWidth="1.7" /><path d="M94,206 L202,304" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,140 L340,106" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,140 L340,132" fill="none" stroke="#046e7a" strokeWidth="2.6" /><path d="M218,140 L340,166" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,272 L340,244" fill="none" stroke="#9eb4b2" strokeWidth="1.7" /><path d="M218,272 L340,274" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,272 L340,302" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,132 L478,110" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,132 L478,146" fill="none" stroke="#046e7a" strokeWidth="2.6" /><path d="M356,132 L478,192" fill="none" stroke="#9eb4b2" strokeWidth="1.7" /><path d="M356,244 L478,250" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,244 L478,286" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,244 L478,320" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,146 L616,120" fill="none" stroke="#046e7a" strokeWidth="2.6" /><path d="M494,146 L616,150" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,146 L616,178" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,192 L616,208" fill="none" stroke="#9eb4b2" strokeWidth="1.7" /><path d="M494,192 L616,238" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,192 L616,266" fill="none" stroke="#b9c6c7" strokeWidth="1.3" strokeDasharray="3 3" /><circle cx="86" cy="206" r="8" fill="#046e7a" /><circle cx="210" cy="108" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="140" r="8" fill="#2f8f6b" /><circle cx="210" cy="172" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="240" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="272" r="8" fill="#2f8f6b" /><circle cx="210" cy="304" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="106" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="132" r="8" fill="#2f8f6b" /><circle cx="348" cy="166" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="244" r="8" fill="#2f8f6b" /><circle cx="348" cy="274" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="302" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="110" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="146" r="8" fill="#2f8f6b" /><circle cx="486" cy="192" r="8" fill="#2f8f6b" /><circle cx="486" cy="250" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="286" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="320" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="120" r="8" fill="#2f8f6b" /><circle cx="624" cy="150" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="178" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="208" r="8" fill="#2f8f6b" /><circle cx="624" cy="238" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="266" r="8" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><text x="210" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="middle">step 1</text><path d="M210,346 L210,354" fill="none" stroke="#9eb4b2" strokeWidth="1.2" /><text x="348" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="middle">step 2</text><path d="M348,346 L348,354" fill="none" stroke="#9eb4b2" strokeWidth="1.2" /><text x="486" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="middle">step 3</text><path d="M486,346 L486,354" fill="none" stroke="#9eb4b2" strokeWidth="1.2" /><text x="624" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="middle">step 4</text><path d="M624,346 L624,354" fill="none" stroke="#9eb4b2" strokeWidth="1.2" /><text x="86" y="176" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="middle">prompt</text><text x="360" y="56" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="13.5" fontWeight="600" fill="#1d2c2f" textAnchor="middle">each step:  extend +beam\_length tokens  →  score full sequence  →  keep top-K</text><circle cx="232" cy="392" r="5.5" fill="#2f8f6b" /><text x="248" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="start">kept</text><circle cx="338" cy="392" r="6" fill="#f9fcfc" stroke="#b9c6c7" strokeWidth="1.6" strokeDasharray="3 3" /><text x="354" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="start">pruned</text><path d="M441,392 l20,0" fill="none" stroke="#046e7a" strokeWidth="2.6" /><text x="468" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#768b8e" textAnchor="start">best path</text></svg>
  </div>

  <div className="hidden dark:block">
    <svg viewBox="0 0 720 432" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Beam search optimizer: branch and prune beams at each generation step" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridbeamD" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arrbeamD" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#7e9498" /></marker></defs><rect x="12" y="12" width="696" height="408" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="696" height="408" rx="16" fill="url(#gridbeamD)" /><path d="M94,206 L202,108" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,140" fill="none" stroke="#0a7e8c" strokeWidth="2.6" /><path d="M94,206 L202,172" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,240" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M94,206 L202,272" fill="none" stroke="#566b6e" strokeWidth="1.7" /><path d="M94,206 L202,304" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,140 L340,106" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,140 L340,132" fill="none" stroke="#0a7e8c" strokeWidth="2.6" /><path d="M218,140 L340,166" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,272 L340,244" fill="none" stroke="#566b6e" strokeWidth="1.7" /><path d="M218,272 L340,274" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M218,272 L340,302" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,132 L478,110" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,132 L478,146" fill="none" stroke="#0a7e8c" strokeWidth="2.6" /><path d="M356,132 L478,192" fill="none" stroke="#566b6e" strokeWidth="1.7" /><path d="M356,244 L478,250" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,244 L478,286" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M356,244 L478,320" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,146 L616,120" fill="none" stroke="#0a7e8c" strokeWidth="2.6" /><path d="M494,146 L616,150" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,146 L616,178" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,192 L616,208" fill="none" stroke="#566b6e" strokeWidth="1.7" /><path d="M494,192 L616,238" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><path d="M494,192 L616,266" fill="none" stroke="#3c4f51" strokeWidth="1.3" strokeDasharray="3 3" /><circle cx="86" cy="206" r="8" fill="#0a7e8c" /><circle cx="210" cy="108" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="140" r="8" fill="#2f8f6b" /><circle cx="210" cy="172" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="240" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="210" cy="272" r="8" fill="#2f8f6b" /><circle cx="210" cy="304" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="106" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="132" r="8" fill="#2f8f6b" /><circle cx="348" cy="166" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="244" r="8" fill="#2f8f6b" /><circle cx="348" cy="274" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="348" cy="302" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="110" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="146" r="8" fill="#2f8f6b" /><circle cx="486" cy="192" r="8" fill="#2f8f6b" /><circle cx="486" cy="250" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="286" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="486" cy="320" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="120" r="8" fill="#2f8f6b" /><circle cx="624" cy="150" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="178" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="208" r="8" fill="#2f8f6b" /><circle cx="624" cy="238" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><circle cx="624" cy="266" r="8" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><text x="210" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">step 1</text><path d="M210,346 L210,354" fill="none" stroke="#566b6e" strokeWidth="1.2" /><text x="348" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">step 2</text><path d="M348,346 L348,354" fill="none" stroke="#566b6e" strokeWidth="1.2" /><text x="486" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">step 3</text><path d="M486,346 L486,354" fill="none" stroke="#566b6e" strokeWidth="1.2" /><text x="624" y="364" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">step 4</text><path d="M624,346 L624,354" fill="none" stroke="#566b6e" strokeWidth="1.2" /><text x="86" y="176" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">prompt</text><text x="360" y="56" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="13.5" fontWeight="600" fill="#eef5f4" textAnchor="middle">each step:  extend +beam\_length tokens  →  score full sequence  →  keep top-K</text><circle cx="232" cy="392" r="5.5" fill="#2f8f6b" /><text x="248" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="start">kept</text><circle cx="338" cy="392" r="6" fill="#0e1718" stroke="#3c4f51" strokeWidth="1.6" strokeDasharray="3 3" /><text x="354" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="start">pruned</text><path d="M441,392 l20,0" fill="none" stroke="#0a7e8c" strokeWidth="2.6" /><text x="468" y="396" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="start">best path</text></svg>
  </div>
</div>

<p class="entity-disclaimer">This optimizer is open source. Any third-party models, product names, or trademarks referenced are the property of their respective owners, and Proto is not affiliated with them.</p>

<hr class="entity-rule" />

<div class="tool-tab-bar entity-source-bar"><span class="tool-tab-wrap"><span class="tool-tab badge-source entity-source-tab"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6" /><polyline points="8 6 2 12 8 18" /></svg> Source</span></span></div>

<a href="https://github.com/evo-design/proto-language/blob/d3b7822f74ea64747cc751a3b2ab1aa6b799ac47/proto_language/optimizer/beam_search_optimizer.py#L189" target="_blank" class="tab-panel source-panel entity-source-panel">
  <div class="source-info">
    <img noZoom src="https://github.com/evo-design.png?size=40" class="source-avatar" width="36" height="36" />

    <span class="source-path">evo-design/proto-language<span class="source-subpath">/proto\_language/optimizer/beam\_search\_optimizer.py</span></span>
  </div>

  <span class="panel-goto-btn source-goto-btn"><span><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" /></svg> View source</span></span>
</a>

<div class="entity-contributors"><span class="entity-contributors-label">Optimizer contributors</span><span class="entity-contributors-people"><a class="entity-contributor" href="https://github.com/dguo8412" target="_blank" rel="noopener" title="dguo8412: 7 commits"><img noZoom class="entity-contributor-avatar" src="https://avatars.githubusercontent.com/u/46211285?v=4&s=64" alt="" loading="lazy" /><span class="entity-contributor-login">dguo8412</span></a></span></div>
Beam search optimizer for sequence generation.

This optimizer implements beam search for sequence optimization where a single target
segment is generated with beam search. The optimizer maintains K beams (running sequences)
and generates K x N total proposals at each step by producing N variations per beam.
After constraint evaluation on the FULL accumulated sequence, only the top K sequences by
energy are retained for the next step.

The segment is split into ceil(sequence\_length / beam\_length) steps. Each step asks the single
autoregressive generator for beam\_length new tokens per proposal (the last step is truncated to
the remaining tokens), scores each proposal on its full accumulated sequence, and resamples any
beam left with fewer than proposals\_per\_result valid proposals (up to max\_resample\_attempts,
raising RuntimeError if a beam still falls short) before ranking. Within a beam, proposals are
kept by their most recent step energy; across beams, the top num\_results survivors are ranked by
score\_by ("mean" averages a beam's per-step energies, "last" uses only the most recent), become
the next step's parent beams, and seed the final result\_sequences. prepend\_prompt controls whether
the prompt is included in the output, and use\_kv\_caching reuses generator cache state across steps
(requires a KV-cache-capable generator). Use it for long autoregressive design under sequence-level
constraints; it targets a single segment and requires a protein/DNA language-model generator
(Evo1/Evo2/ProGen2), not a CPU generator.

## How It Works

Beam search extends a single segment step by step, pruning weak beams as it grows.

Beam search grows one segment left to right. The segment is split into `num_beams = ⌈ L / beam_length ⌉` steps; at each step every one of the `K = num_results` beams is extended by `beam_length` tokens in `proposals_per_result` variations, each candidate is scored on its **full accumulated sequence**, and only the top `K` beams survive:

```
num_beams = ⌈ L / beam_length ⌉
score_agg(beam) = mean(beam_scores)   if score_by = "mean"
                = beam_scores[-1]      if score_by = "last"
keep the K beams with smallest score_agg
```

Beams left with too few valid proposals are resampled (up to `max_resample_attempts`). Beam search starts from `prompt` and ignores upstream results; `use_kv_caching` reuses the generator's KV cache across steps.

## API Reference

<div class="api-model-section api-model-static api-config-section">
  <div class="api-model-header"><span class="api-model-badge api-config-badge">Config</span><span class="api-model-name">BeamSearchOptimizerConfig</span><a href="https://github.com/evo-design/proto-language/blob/d3b7822f74ea64747cc751a3b2ab1aa6b799ac47/proto_language/optimizer/beam_search_optimizer.py#L71" target="_blank" class="func-table-btn func-source-btn api-model-source"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6" /><polyline points="8 6 2 12 8 18" /></svg> Source</a></div>

  Configuration object for BeamSearchOptimizer.

  This class defines configuration parameters for the beam search optimizer, which
  generates a single long segment by splitting it into beams of `beam_length` tokens
  and performing beam search at each beam boundary.

  <ParamField path="prompt" type="string" required>
    Non-empty seed sequence that every beam begins from and extends (e.g. 'ATCG' for DNA).
  </ParamField>

  <ParamField path="num_results" type="integer">
    Number of beams (top-K by energy) retained at each beam boundary. Overrides program-level count.
  </ParamField>

  <ParamField path="proposals_per_result" type="integer" required>
    Number of proposals to generate per result sequence at each beam step.
  </ParamField>

  <ParamField path="beam_length" type="integer" required>
    Tokens per beam-search step before re-ranking; segment split into ceil(len/this) steps.
  </ParamField>

  <ParamField path="score_by" type="enum" default="mean">
    'mean' averages a beam's per-step energies across all steps; 'last' uses only the most recent.

    Options: `mean`, `last`
  </ParamField>

  <ParamField path="prepend_prompt" type="boolean" default="True">
    Whether to prepend the prompt to the generated sequence in the output.
  </ParamField>

  <ParamField path="use_kv_caching" type="boolean" default="False">
    Reuse cached KV state across beam steps to speed up generation; needs a KV-capable generator.
  </ParamField>

  <ParamField path="max_resample_attempts" type="integer" default="3">
    Maximum number of times to resample beams with invalid (inf/NaN) energies before giving up.
  </ParamField>

  <ParamField path="seed" type="integer">
    Random seed for reproducible optimization, generator, and constraint tool streams.
  </ParamField>

  <ParamField path="tracking_interval" type="integer" default="1">
    Save history and log progress every N steps. Step 0 and final step always saved.
  </ParamField>

  <ParamField path="track_proposals" type="boolean" default="False">
    Save granular per-proposal results (accept/reject) in history snapshots.
  </ParamField>

  <ParamField path="verbose" type="boolean" default="False">
    Emit per-step debug information about proposals, scores, and acceptance through the logger.
  </ParamField>
</div>

## Usage

```python python icon="python" theme={null}
>>> from proto_language.constraint import gc_content_constraint
>>> from proto_language.core import Constraint, Construct, Segment
>>> from proto_language.generator import Evo2Generator, Evo2GeneratorConfig
>>>
>>> segment = Segment(length=10000, sequence_type="dna")
>>> generator = Evo2Generator(Evo2GeneratorConfig(prompts="ATCG"))
>>> gc = Constraint(
...     inputs=[segment], function=gc_content_constraint, function_config={"min_gc": 40, "max_gc": 60}
... )
>>> beam_search = BeamSearchOptimizer(
...     target_segment=segment,
...     constructs=[Construct([segment])],
...     generators=[generator],
...     constraints=[gc],
...     config=BeamSearchOptimizerConfig(
...         prompt="ATCG", beam_length=2000, num_results=5, proposals_per_result=10
...     ),
... )
>>> # beam_search.run() drives the loop
```

## Metadata

| Property               | Value                     |
| ---------------------- | ------------------------- |
| Key                    | `beam-search`             |
| Class                  | `BeamSearchOptimizer`     |
| Targets Single Segment | `True`                    |
| Uses GPU               | `False`                   |
| Compatible Generators  | `evo1`, `evo2`, `progen2` |
