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

# ESM2

> Published in 2023, ESM-2 is Meta AI's second-generation of protein masked language models. Spanning six checkpoints ranging in scale from 8M to 15B parameters, the ESM-2 model family has become a widely used tool for protein embedding generation, and zero-shot variant-effect prediction via masked log-probabilities.

<div class="page-hero"><img class="page-hero-banner" src="https://proto-bio.github.io/proto-assets/images/tool/esm2/hero.png" alt="ESM2" /><div class="tool-org-badges page-hero-badges"><a href="/docs/tools/organizations/meta-ai" class="tool-org-badge" style={{background: "#0866FF"}} title="Meta AI"><img src="https://mintcdn.com/bio-pro/_UGa2jUMKeVPCbLk/assets/images/cached/122d88bc7259.png?fit=max&auto=format&n=_UGa2jUMKeVPCbLk&q=85&s=ca6fedad598bccf781a70ad3b02bf561" alt="" class="tool-org-badge-logo" width="200" height="200" data-path="assets/images/cached/122d88bc7259.png" /> Meta AI</a> <a href="/docs/tools/organizations/biohub" class="tool-org-badge" style={{background: "#111111"}} title="Biohub"><img src="https://mintcdn.com/bio-pro/_UGa2jUMKeVPCbLk/assets/images/cached/59f8c7606fb7.png?fit=max&auto=format&n=_UGa2jUMKeVPCbLk&q=85&s=e4891edc150dd75c0f1e262cfdb2d304" alt="" class="tool-org-badge-logo" width="192" height="192" data-path="assets/images/cached/59f8c7606fb7.png" /> Biohub</a></div></div>

<Note>
  **License:** ESM2 is open source and free for academic and commercial use under an MIT license. Please refer to [the license](https://github.com/facebookresearch/esm/blob/main/LICENSE) for full terms.
</Note>

<p class="entity-disclaimer">Proto is not affiliated with Meta AI and Biohub. This toolkit is open source and builds on the implementations produced by these organizations. Product names, logos, and trademarks are the property of their respective owners.</p>

<hr class="entity-rule" />

<input type="radio" name="tab-esm2" id="none-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="github-esm2" class="tab-radio-input" defaultChecked />

<input type="radio" name="tab-esm2" id="hf-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="paper-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="cite-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="source-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="notebook-esm2" class="tab-radio-input" />

<input type="radio" name="tab-esm2" id="proto-esm2" class="tab-radio-input" />

<div class="tool-tab-bar">
  <span class="tool-tab-wrap"><label for="github-esm2" class="tool-tab tab-open badge-github"><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> GitHub</label><label for="none-esm2" class="tool-tab tab-close badge-github"><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> GitHub</label></span> <span class="tool-tab-wrap"><label for="hf-esm2" class="tool-tab tab-open badge-hf"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> HuggingFace</label><label for="none-esm2" class="tool-tab tab-close badge-hf"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> HuggingFace</label></span> <span class="tool-tab-wrap"><label for="paper-esm2" class="tool-tab tab-open badge-paper"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" /></svg> Publication</label><label for="none-esm2" class="tool-tab tab-close badge-paper"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" /></svg> Publication</label></span> <span class="tool-tab-wrap"><label for="cite-esm2" class="tool-tab tab-open badge-cite"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z" /><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" /></svg> Cite</label><label for="none-esm2" class="tool-tab tab-close badge-cite"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z" /><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" /></svg> Cite</label></span> <span class="tool-tab-wrap"><label for="source-esm2" class="tool-tab tab-open badge-source"><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> Tool Source</label><label for="none-esm2" class="tool-tab tab-close badge-source"><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> Tool Source</label></span> <span class="tool-tab-wrap"><label for="notebook-esm2" class="tool-tab tab-open badge-notebook"><svg width="14" height="14" 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> Open as Notebook</label><label for="none-esm2" class="tool-tab tab-close badge-notebook"><svg width="14" height="14" 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> Open as Notebook</label></span> <span class="tool-tab-wrap"><label for="proto-esm2" class="tool-tab tab-open badge-proto"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" /></svg> Open on Proto</label><label for="none-esm2" class="tool-tab tab-close badge-proto"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" /></svg> Open on Proto</label></span>
</div>

<a href="https://github.com/facebookresearch/esm" target="_blank" class="tab-panel github-panel" data-tab="github-esm2">
  <div class="gh-card-wrap">
    <img src="https://opengraph.githubassets.com/1/facebookresearch/esm" class="gh-card-img img-fallback" alt="facebookresearch/esm" />

    <div class="gh-card-fallback">
      <div class="gh-fallback-org"><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> facebookresearch/esm</div>
    </div>
  </div>

  <span class="panel-goto-btn gh-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 repo</span></span>
</a>

<div class="tab-panel hf-panel hf-multi-panel" data-tab="hf-esm2">
  <div class="hf-model-list">
    <a href="https://huggingface.co/facebook/esm2_t6_8M_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t6_8M_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t6_8M_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t6\_8M\_UR50D</span>
    </a>

    <a href="https://huggingface.co/facebook/esm2_t12_35M_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t12_35M_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t12_35M_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t12\_35M\_UR50D</span>
    </a>

    <a href="https://huggingface.co/facebook/esm2_t30_150M_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t30_150M_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t30_150M_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t30\_150M\_UR50D</span>
    </a>

    <a href="https://huggingface.co/facebook/esm2_t33_650M_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t33_650M_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t33_650M_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t33\_650M\_UR50D</span>
    </a>

    <a href="https://huggingface.co/facebook/esm2_t36_3B_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t36_3B_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t36_3B_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t36\_3B\_UR50D</span>
    </a>

    <a href="https://huggingface.co/facebook/esm2_t48_15B_UR50D" target="_blank" class="hf-model-card">
      <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/facebook/esm2_t48_15B_UR50D.png" class="hf-model-card-bg img-fallback" alt="esm2_t48_15B_UR50D" />

      <span class="hf-model-card-label"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> esm2\_t48\_15B\_UR50D</span>
    </a>
  </div>
</div>

<a href="https://doi.org/10.1126/science.ade2574" target="_blank" class="tab-panel paper-panel" data-tab="paper-esm2">
  <div class="paper-info">
    <div class="paper-title">Evolutionary-scale prediction of atomic-level protein structure with a language model</div>
    <div class="paper-meta">Zeming Lin, Halil Akin, ... Yaniv Shmueli</div>
    <div class="paper-meta paper-venue">Science (2023)</div>
  </div>

  <span class="panel-goto-btn pub-goto-btn"><span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" /></svg> Read paper</span></span>
</a>

<div class="tab-panel cite-panel" data-tab="cite-esm2">
  <div class="cite-code-wrap">
    ```bibtex theme={null}
    @article{lin2023esm2,
      title={Evolutionary-scale prediction of atomic-level protein structure with a language model},
      author={Lin, Zeming and Akin, Halil and Rao, Roshan and Hie, Brian and Zhu, Zhongkai and Lu, Wenting and Smetanin, Nikita and Verkuil, Robert and Kabeli, Ori and Shmueli, Yaniv and others},
      journal={Science},
      volume={379},
      number={6637},
      pages={1123--1130},
      year={2023},
      publisher={American Association for the Advancement of Science},
      doi={10.1126/science.ade2574}
    }
    ```
  </div>

  <span class="panel-goto-btn cite-copy-btn"><span><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z" /><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" /></svg> Copy citation</span></span>
</div>

<a href="https://github.com/evo-design/proto-tools/tree/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2" target="_blank" class="tab-panel source-panel" data-tab="source-esm2">
  <div class="source-info">
    <img src="https://github.com/evo-design.png?size=40" class="source-avatar" width="36" height="36" />

    <span class="source-path">evo-design/proto-tools<span class="source-subpath">/proto\_tools/tools/masked\_models/esm2</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>

<a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/examples/example.ipynb" target="_blank" class="tab-panel notebook-panel" data-tab="notebook-esm2">
  <div class="notebook-info">
    <span class="notebook-icon">
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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>

    <span class="notebook-label">Open Notebook</span>
  </div>

  <span class="panel-goto-btn notebook-goto-btn"><span><svg width="14" height="14" 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> Open notebook</span></span>
</a>

<div class="tab-panel proto-panel" data-tab="proto-esm2">
  <div class="proto-info">
    <div class="proto-cloud">
      <svg class="proto-cloud-bg" viewBox="0 0 640 512" xmlns="http://www.w3.org/2000/svg">
        <path d="M0 336c0 79.5 64.5 144 144 144H512c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z" />
      </svg>

      <img noZoom src="https://mintcdn.com/bio-pro/KVh0EKV-IKblvXR8/assets/logo/evo-logo-light.svg?fit=max&auto=format&n=KVh0EKV-IKblvXR8&q=85&s=0cb66034ba45618505501aee6ea5f5c1" class="proto-panel-logo block dark:hidden" alt="Proto" width="198" height="151" data-path="assets/logo/evo-logo-light.svg" />

      <img noZoom src="https://mintcdn.com/bio-pro/KVh0EKV-IKblvXR8/assets/logo/evo-logo-dark.svg?fit=max&auto=format&n=KVh0EKV-IKblvXR8&q=85&s=2c9e23a14635e60384a434e220788f54" class="proto-panel-logo hidden dark:block" alt="Proto" width="198" height="151" data-path="assets/logo/evo-logo-dark.svg" />
    </div>
  </div>

  <div class="proto-actions">
    <a href="https://proto.evodesign.org/tools/esm2-embedding" target="_blank" class="proto-action-btn"><span>ESM2 Embeddings</span><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7" /><polyline points="7 7 17 7 17 17" /></svg></a>
    <a href="https://proto.evodesign.org/tools/esm2-gradient" target="_blank" class="proto-action-btn"><span>ESM2 Gradient</span><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7" /><polyline points="7 7 17 7 17 17" /></svg></a>
    <a href="https://proto.evodesign.org/tools/esm2-sample" target="_blank" class="proto-action-btn"><span>ESM2 Sampling</span><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7" /><polyline points="7 7 17 7 17 17" /></svg></a>
    <a href="https://proto.evodesign.org/tools/esm2-score" target="_blank" class="proto-action-btn"><span>ESM2 Scoring</span><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7" /><polyline points="7 7 17 7 17 17" /></svg></a>
  </div>
</div>

<div class="entity-contributors"><span class="entity-contributors-label">Toolkit contributors</span><span class="entity-contributors-people"><a class="entity-contributor" href="https://github.com/bviggiano" target="_blank" rel="noopener" title="bviggiano: 32 commits"><img noZoom class="entity-contributor-avatar" src="https://avatars.githubusercontent.com/u/21143637?v=4&s=64" alt="" loading="lazy" /><span class="entity-contributor-login">bviggiano</span></a><a class="entity-contributor" href="https://github.com/dguo8412" target="_blank" rel="noopener" title="dguo8412: 22 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><a class="entity-contributor" href="https://github.com/leba01" target="_blank" rel="noopener" title="leba01: 4 commits"><img noZoom class="entity-contributor-avatar" src="https://avatars.githubusercontent.com/u/124846286?v=4&s=64" alt="" loading="lazy" /><span class="entity-contributor-login">leba01</span></a><a class="entity-contributor" href="https://github.com/brianhie" target="_blank" rel="noopener" title="brianhie: 2 commits"><img noZoom class="entity-contributor-avatar" src="https://avatars.githubusercontent.com/u/6365340?v=4&s=64" alt="" loading="lazy" /><span class="entity-contributor-login">brianhie</span></a></span></div>

| Function                | Description                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run_esm2_embeddings()` | Extract protein sequence embeddings and logits using ESM2 (GPU)                        | <a href="#api-run-esm2-embeddings" class="func-table-btn func-api-btn"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" /></svg> Docs</a> <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_embeddings.py#L162" target="_blank" class="func-table-btn func-source-btn"><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> |
| `run_esm2_gradient()`   | Compute ESM2 masked pseudo-log-likelihood gradient for relaxed protein sequences (GPU) | <a href="#api-run-esm2-gradient" class="func-table-btn func-api-btn"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" /></svg> Docs</a> <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_gradient.py#L162" target="_blank" class="func-table-btn func-source-btn"><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>     |
| `run_esm2_sample()`     | Sample masked positions in protein sequences using ESM2 language model (GPU)           | <a href="#api-run-esm2-sample" class="func-table-btn func-api-btn"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" /></svg> Docs</a> <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_sample.py#L201" target="_blank" class="func-table-btn func-source-btn"><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>         |
| `run_esm2_score()`      | Score protein sequences using ESM2 language model (GPU)                                | <a href="#api-run-esm2-score" class="func-table-btn func-api-btn"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20" /></svg> Docs</a> <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_score.py#L126" target="_blank" class="func-table-btn func-source-btn"><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>           |

## Background

In 2023, [Lin et al.](https://doi.org/10.1126/science.ade2574) introduced ESM-2, a family of Transformer encoders trained with a BERT-style masked-language-modeling objective. Training used [UniRef50](https://www.uniprot.org/help/uniref), a clustered subset of UniProt covering roughly 65 million unique protein sequences. A central focus of the paper was the impact of scale, which was treated as the experimental variable across six model checkpoints spanning more than three orders of magnitude (8M, 35M, 150M, 650M, 3B, and 15B parameters). ESM-2 models were trained using a simple masked language modeling (MLM) objective adapted from BERT. Unlike autoregressive language models, which predict each token from preceding context only, MLM lets every residue attend to its full sequence context in both directions. At each training step a randomly generated mask covers 15% of input residues and replaces those tokens with a `<mask>` symbol. The model is then trained to predict the original amino acid from the surrounding bidirectional context. No structural, functional, or alignment supervision is used.

ESM-2 has since become a de facto sequence representation model for protein engineering. Its direct successor, ESM3 ([Hayes et al., 2025](https://doi.org/10.1126/science.ads0018)), extends the recipe at [EvolutionaryScale](https://www.evolutionaryscale.ai) into a multimodal generative model that jointly handles sequence, structure, and function tracks via discrete diffusion. ESM-2 still remains the lightest and most widely deployed protein language model. Within this toolkit, the 650M checkpoint (`esm2_t33_650M_UR50D`) is a standard quality/speed tradeoff and is the default for every tool.

## Tools

<a name="api-run-esm2-embeddings" />

<div class="tool-section-card tool-section-card--embedding">
  ### ESM2 Embeddings (`esm2-embedding`)

  Runs a single forward pass over ESM-2 to extract contextualized per-residue hidden states. The hidden states are mean-pooled across valid positions to produce a fixed-length sequence descriptor. Per-position 20-way amino-acid logits over the canonical order `ACDEFGHIKLMNPQRSTVWY` are also returned on request.

  #### API Reference

  <div class="api-model-section api-input-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_embeddings.py#L40" 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>

    <Accordion title="Input: ESM2EmbeddingsInput">
      <ParamField path="sequences" type="List[string]" required>
        Protein sequence(s) to process. Each must be ≤ 1022 residues (ESM-2's positional-encoding cap); over-length inputs raise `ValueError`.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-config-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_embeddings.py#L86" 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>

    <Accordion title="Config: ESM2EmbeddingsConfig">
      <ParamField path="model_checkpoint" type="enum" default="esm2_t33_650M_UR50D">
        ESM2 weights variant. Sizes range from 8M (320-dim, fastest) to 15B (5120-dim, highest quality). The 650M variant offers a good speed/quality trade-off.

        Available options: `esm2_t6_8M_UR50D`, `esm2_t12_35M_UR50D`, `esm2_t30_150M_UR50D`, `esm2_t33_650M_UR50D`, `esm2_t36_3B_UR50D`, `esm2_t48_15B_UR50D`
      </ParamField>

      <ParamField path="return_logits" type="boolean" default="False">
        Include per-position logits in the output (large; disable to save memory).
      </ParamField>

      <ParamField path="repr_layer" type="integer" default="-1">
        Transformer layer index for embeddings. `-1` selects the last (top) layer; uses HuggingFace `hidden_states` indexing where `0` is the embedding-layer output and `N` is transformer layer N.
      </ParamField>

      <ParamField path="verbose" type="integer" default="0">
        Print status messages during model execution.
      </ParamField>

      <ParamField path="device" type="string" default="cuda">
        Device to run the model on.
      </ParamField>

      <ParamField path="timeout" type="integer" default="3600">
        Maximum execution time in seconds. `None` waits indefinitely.
      </ParamField>

      <ParamField path="seed" type="integer">
        Random seed. When set, tools run reproducibly up to small GPU float noise (see `BaseToolOutput.approx_equal`), and the seed participates in cache keys. When None, cacheable seed-sensitive tools skip cache until seeded.
      </ParamField>

      <ParamField path="batch_size" type="integer" default="8">
        Number of sequences to process in parallel. Larger batches improve throughput but require more GPU memory.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-output-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_embeddings.py#L61" 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>

    <Accordion title="Output: ESM2EmbeddingsOutput">
      <ResponseField name="results" type="List[SequenceEmbedding]" required>
        Per-sequence embedding results. Each `SequenceEmbedding` contains:

        <Expandable title="SequenceEmbedding">
          <ResponseField name="mean_embedding" type="List[number]" required>
            Mean-pooled embedding vector for one sequence.
          </ResponseField>

          <ResponseField name="attention_mask" type="List[integer]" required>
            Binary mask indicating valid positions (1) vs padding (0).
          </ResponseField>

          <ResponseField name="logits" type="array">
            Optional per-position amino acid logits for one sequence.
          </ResponseField>

          <ResponseField name="projection" type="Projection2D">
            Optional 2D coordinate from a UMAP projection of all embeddings in the same call. Populated when `n_sequences >= 4`; `None` otherwise (single-point or 2-3-point UMAP is meaningless).
          </ResponseField>
        </Expandable>
      </ResponseField>
    </Accordion>
  </div>

  #### Applications

  The mean-pooled embedding is a standard learned protein representation for downstream supervised tasks like clustering, classification, and regression on protein properties. The same embeddings also power similarity search through cosine similarity on the mean vector. The per-position logits support variant-effect screening by comparing wild-type and mutant log-probabilities at each position. The underlying attention maps are themselves rich enough to recover residue-residue contacts without explicit supervision.

  #### Usage Tips

  * **The last transformer layer carries the richest bidirectional context.** `repr_layer` chooses which layer to read for the mean-pooled embedding; the default `-1` selects the last layer and is the standard pick for downstream classification, regression, and variant-effect work. Earlier layers can outperform the top on certain probes (contact prediction is the canonical example).
  * **Per-position logits are large and slow to materialize.** Enabling `return_logits` adds a `seq_len × 20` float tensor per sequence to the output, dominating wall time on long inputs. Leave it `False` unless you actually need the per-position distribution.

  <a name="api-run-esm2-sample" />
</div>

<div class="tool-section-card tool-section-card--sample">
  ### ESM2 Sampling (`esm2-sample`)

  Selects positions to mutate via a specifiable masking strategy, replaces them with `<mask>`, and resamples from ESM-2's predicted distribution. Two decoding modes are available. The `single_pass` mode fills every masked position in one forward pass with independent draws. The `iterative_refinement` mode instead runs a [MaskGIT](https://arxiv.org/abs/2202.04200)-style multi-round commit loop. Each round of that loop uses a cosine or linear unmask schedule with optional temperature annealing. To target specific positions directly, pre-mask them yourself with `_` in the input string. The tool will then fill exactly those positions and skip the masking strategy entirely.

  #### API Reference

  <div class="api-model-section api-input-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_sample.py#L48" 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>

    <Accordion title="Input: ESM2SampleInput">
      <ParamField path="sequences" type="List[string]" required>
        Protein sequence(s) with `_` at positions to sample. Each must be ≤ 1022 residues (ESM-2's positional-encoding cap); over-length inputs raise `ValueError`.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-config-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_sample.py#L82" 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>

    <Accordion title="Config: ESM2SampleConfig">
      <ParamField path="masking_strategy" type="MaskingStrategy">
        Positions to mask before sampling.

        <Expandable title="MaskingStrategy">
          <ParamField path="temperature" type="number" default="1.0">
            Temperature for position selection. \< 1.0 is greedy, 1.0 uses scores as-is, > 1.0 is more uniform. Only affects model-based methods.
          </ParamField>

          <ParamField path="method" type="enum" default="random">
            Scoring method for position selection. `"random"`: uniform random, `"entropy"`: highest model uncertainty, `"max-logit"`: lowest model confidence.

            Available options: `random`, `entropy`, `max-logit`
          </ParamField>

          <ParamField path="num_mutations" type="integer">
            Exact number of positions to mask per sequence.
          </ParamField>

          <ParamField path="mask_fraction" type="number">
            Fraction of designable positions to mask (e.g. 0.15 for \~15%).
          </ParamField>

          <ParamField path="fixed_positions" type="array">
            1-indexed positions that must NOT be masked. Applied uniformly to all sequences.
          </ParamField>
        </Expandable>
      </ParamField>

      <ParamField path="model_checkpoint" type="enum" default="esm2_t33_650M_UR50D">
        ESM2 weights variant.

        Available options: `esm2_t6_8M_UR50D`, `esm2_t12_35M_UR50D`, `esm2_t30_150M_UR50D`, `esm2_t33_650M_UR50D`, `esm2_t36_3B_UR50D`, `esm2_t48_15B_UR50D`
      </ParamField>

      <ParamField path="sampling_method" type="enum" default="single_pass">
        "single\_pass" fills every mask in one forward; "iterative\_refinement" runs an iterative MaskGIT-style loop driven by the five settings below.

        Available options: `single_pass`, `iterative_refinement`
      </ParamField>

      <ParamField path="temperature" type="number" default="1.0">
        Softmax temperature.
      </ParamField>

      <ParamField path="top_p" type="number" default="1.0">
        Nucleus threshold (iterative only).
      </ParamField>

      <ParamField path="num_steps" type="integer" default="20">
        Refinement steps (iterative only).
      </ParamField>

      <ParamField path="schedule" type="enum" default="cosine">
        Unmask schedule (iterative only).

        Available options: `cosine`, `linear`
      </ParamField>

      <ParamField path="strategy" type="enum" default="random">
        Per-round commit selection (iterative only).

        Available options: `random`, `entropy`
      </ParamField>

      <ParamField path="temperature_annealing" type="boolean" default="True">
        Anneal toward 0 across rounds (iterative only).
      </ParamField>

      <ParamField path="return_logits" type="boolean" default="False">
        Include per-position logits.
      </ParamField>

      <ParamField path="verbose" type="integer" default="0">
        Verbosity level (0=quiet, 1=info, 2=debug, 3=raw subprocess stderr). `True` is coerced to `1` and `False` to `0`.
      </ParamField>

      <ParamField path="device" type="string" default="cuda">
        Device to run on.
      </ParamField>

      <ParamField path="timeout" type="integer" default="3600">
        Maximum execution time in seconds. `None` waits indefinitely.
      </ParamField>

      <ParamField path="seed" type="integer">
        Random seed. When set, tools run reproducibly up to small GPU float noise (see `BaseToolOutput.approx_equal`), and the seed participates in cache keys. When None, cacheable seed-sensitive tools skip cache until seeded.
      </ParamField>

      <ParamField path="batch_size" type="integer" default="8">
        Sequences per GPU forward pass.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-output-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_sample.py#L69" 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>

    <Accordion title="Output: ESM2SampleOutput">
      <ResponseField name="results" type="List[MaskedModelSample]" required>
        One entry per input sequence, in input order. Each holds the sampled sequence (the input with masked positions replaced by model-predicted alternatives) and its optional per-position logits.

        <Expandable title="MaskedModelSample">
          <ResponseField name="sequence" type="string" required>
            The sampled or restored protein sequence.
          </ResponseField>

          <ResponseField name="logits" type="array">
            Per-position amino acid logits for this sequence, shape `[seq_len, 20]`. Present only when the tool's config sets `return_logits=True`.
          </ResponseField>
        </Expandable>
      </ResponseField>
    </Accordion>
  </div>

  #### Applications

  This tool drives guided point mutation, variant generation, and infilling at designable sites for protein engineering work. Resampling masked positions from a protein language model is the core operation behind directed-evolution proposals and antibody affinity maturation, which was demonstrated at experimental scale in [Hie et al., 2024](https://www.nature.com/articles/s41587-023-01763-2). It is also the inner loop of MaskGIT-style iterative refinement schemes adapted from image generation ([Chang et al., 2022](https://arxiv.org/abs/2202.04200)) for biological sequences.

  #### Usage Tips

  * **`iterative_refinement` produces more coherent joint samples than `single_pass`.** It is a multi-round MaskGIT-style commit loop (each round uses a cosine or linear unmask schedule) and is roughly `num_steps×` slower than the one-shot `single_pass` mode. Default to it whenever you mask more than a handful of sites.
  * **`masking_strategy` controls which positions get masked before sampling.** See the [masking strategy README](https://github.com/evo-design/proto-tools/blob/main/proto_tools/transforms/masking/README.md) for the available selection methods and tuning parameters. As an alternative to passing a strategy, pre-mask exact positions yourself with `_` directly in the input string and the masking strategy is skipped entirely.
  * **`temperature` scales the per-position logits before sampling.** Values of 0.5 to 0.7 yield conservative mutations close to the input; values above 1.0 broaden exploration of the model's distribution.
  * **Long-range coherence is weak.** ESM-2 has no global coherence beyond its local context window, so very long-range dependencies between distant residues are not well captured even in iterative mode.
  * **ESM-2 was trained as a masked language model, not with a generative objective.** Resampling masked positions works for local edits, but the model was optimized for representation rather than de novo generation. For generative workloads (large-scale infilling, sequence design), [ESM3](https://bio-pro.mintlify.app/tools/masked-models/esm3) adds an explicit generative training objective and is the better fit.

  <a name="api-run-esm2-score" />
</div>

<div class="tool-section-card tool-section-card--score">
  ### ESM2 Scoring (`esm2-score`)

  Computes the masked-language-model pseudo-perplexity for each input sequence. Each position is masked individually, and the model's log-probability of the true amino acid under bidirectional context is recorded. The per-position scores are then aggregated into per-sequence log-likelihood, average log-likelihood, and perplexity metrics.

  #### API Reference

  <div class="api-model-section api-input-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_score.py#L39" 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>

    <Accordion title="Input: ESM2ScoringInput">
      <ParamField path="sequences" type="List[string]" required>
        Protein sequence(s) to score. Each must be ≤ 1022 residues (ESM-2's positional-encoding cap); over-length inputs raise `ValueError`.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-config-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_score.py#L64" 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>

    <Accordion title="Config: ESM2ScoringConfig">
      <ParamField path="model_checkpoint" type="enum" default="esm2_t33_650M_UR50D">
        ESM2 weights variant.

        Available options: `esm2_t6_8M_UR50D`, `esm2_t12_35M_UR50D`, `esm2_t30_150M_UR50D`, `esm2_t33_650M_UR50D`, `esm2_t36_3B_UR50D`, `esm2_t48_15B_UR50D`
      </ParamField>

      <ParamField path="verbose" type="integer" default="0">
        Print status messages during scoring.
      </ParamField>

      <ParamField path="device" type="string" default="cuda">
        Device to run the model on.
      </ParamField>

      <ParamField path="timeout" type="integer" default="3600">
        Maximum execution time in seconds. `None` waits indefinitely.
      </ParamField>

      <ParamField path="seed" type="integer">
        Random seed. When set, tools run reproducibly up to small GPU float noise (see `BaseToolOutput.approx_equal`), and the seed participates in cache keys. When None, cacheable seed-sensitive tools skip cache until seeded.
      </ParamField>

      <ParamField path="batch_size" type="integer" default="8">
        Masked variants per forward pass, pooled across all input sequences. Larger batches improve throughput but use more memory.
      </ParamField>

      <ParamField path="return_logits" type="boolean" default="False">
        Include per-position logits in the output (large; disable to save memory).
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-output-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/shared_data_models.py#L401" 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>

    <Accordion title="Output: MaskedModelScoringOutput">
      <ResponseField name="scores" type="List[MaskedModelScoringMetrics]" required>
        List of scoring outputs, one per input sequence. Each entry is a `Metrics` subclass with scalar metrics (accessed via `score.perplexity` or `score["perplexity"]`) plus declared `logits` / `vocab` fields that carry raw model outputs when requested.

        <Expandable title="MaskedModelScoringMetrics">
          <ResponseField name="logits" type="array">
            Per-position logits array `(seq_len, vocab_size)`. `None` unless `return_logits=True`.
          </ResponseField>

          <ResponseField name="vocab" type="array">
            Token ordering for `logits`.
          </ResponseField>

          <ResponseField name="primary_metric" type="string">
            Name of the metric that best summarizes the result overall (e.g. `"avg_plddt"` for AlphaFold2). Used by downstream UI and reporting to pick a headline value.
          </ResponseField>

          <ResponseField name="metric_type" type="string">
            Concrete Metrics subclass tag; enables typed reconstruction after a serialization round-trip.
          </ResponseField>
        </Expandable>
      </ResponseField>

      **Metrics** (one set per `scores` item)

      | Metric               | Type  | Range | Availability |
      | -------------------- | ----- | ----- | ------------ |
      | `log_likelihood`     | float | ≤ 0.0 | always       |
      | `avg_log_likelihood` | float | ≤ 0.0 | always       |
      | `perplexity`         | float | ≥ 1.0 | always       |
    </Accordion>
  </div>

  #### Applications

  ESM2 pseudo-perplexity is a standard fitness proxy when ranking variants, filtering generated sequences for naturalness, or comparing engineered constructs against wild type. The same masked log-likelihood difference between wild-type and mutant residues is a canonical zero-shot baseline for variant-effect prediction.

  #### Usage Tips

  * **Pseudo-perplexity is a relative score, not an absolute fitness.** It is measured against ESM-2's training distribution, which is UniRef50 (the natural proteins it saw during pretraining), which can bias it to proteins that are more heavily represented. The metric is also sensitive to length, so it is most useful for comparing closely related sequences of similar length.
  * **Ambiguous residues are excluded.** Perplexity is computed only over the 20 canonical amino acids; `X`, `B`, `Z`, and similar are dropped from both the log-likelihood sum and the position count.

  <a name="api-run-esm2-gradient" />
</div>

<div class="tool-section-card tool-section-card--gradient">
  ### ESM2 Gradient (`esm2-gradient`)

  Computes the gradient of the mean masked negative log-likelihood with respect to a relaxed `(L, 20)` input distribution over the canonical amino-acid order `ACDEFGHIKLMNPQRSTVWY`. The ESM-2 weights are kept frozen throughout. The relaxed distribution is mixed against ESM-2's per-residue token embeddings to form a soft input. Each amino-acid position is then masked in turn, and a per-chunk backward pass accumulates the gradient. An optional Straight-Through Estimator runs the forward on hard one-hot tokens while still routing gradients through the soft probabilities.

  #### API Reference

  <div class="api-model-section api-input-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_gradient.py#L27" 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>

    <Accordion title="Input: ESM2GradientInput">
      <ParamField path="logits" type="List[array]" required>
        Relaxed protein sequence state with shape `(L, 20)` in canonical amino-acid order `ACDEFGHIKLMNPQRSTVWY`. `L` must be ≤ 1022 (ESM-2's positional-encoding cap); over-length inputs raise `ValueError`.
      </ParamField>

      <ParamField path="temperature" type="number">
        Optional softmax temperature. When set, applies `softmax(input / temperature)` before computing the gradient. When `None` (default), the input is used as-is.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-config-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_gradient.py#L89" 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>

    <Accordion title="Config: ESM2GradientConfig">
      <ParamField path="model_checkpoint" type="enum" default="esm2_t33_650M_UR50D">
        ESM2 weights variant.

        Available options: `esm2_t6_8M_UR50D`, `esm2_t12_35M_UR50D`, `esm2_t30_150M_UR50D`, `esm2_t33_650M_UR50D`, `esm2_t36_3B_UR50D`, `esm2_t48_15B_UR50D`
      </ParamField>

      <ParamField path="use_ste" type="boolean" default="False">
        Straight-Through Estimator: hard one-hot in the forward pass with gradients flowing through soft probabilities. When `False`, uses soft blended embeddings directly.
      </ParamField>

      <ParamField path="compute_gradient" type="boolean" default="True">
        Run backward pass and return gradient. Set `False` for forward-only log-likelihood scoring.
      </ParamField>

      <ParamField path="batch_size" type="integer">
        AA positions per forward pass for batched PLL. `None` selects the backend default.
      </ParamField>

      <ParamField path="verbose" type="integer" default="0">
        Verbosity level (0=quiet, 1=info, 2=debug, 3=raw subprocess stderr). `True` is coerced to `1` and `False` to `0`.
      </ParamField>

      <ParamField path="device" type="string" default="cuda">
        Device to run the model on.
      </ParamField>

      <ParamField path="timeout" type="integer" default="3600">
        Maximum execution time in seconds. `None` waits indefinitely.
      </ParamField>

      <ParamField path="seed" type="integer">
        Random seed. When set, tools run reproducibly up to small GPU float noise (see `BaseToolOutput.approx_equal`), and the seed participates in cache keys. When None, cacheable seed-sensitive tools skip cache until seeded.
      </ParamField>
    </Accordion>
  </div>

  <div class="api-model-section api-output-section">
    <a href="https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/esm2_gradient.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>

    <Accordion title="Output: ESM2GradientOutput">
      <ResponseField name="gradient" type="array">
        Gradient w\.r.t. input logits, or `None` when `compute_gradient=False`.
      </ResponseField>

      <ResponseField name="loss" type="number" required>
        Mean negative log-likelihood over AA positions.
      </ResponseField>

      <ResponseField name="metrics" type="Dict[string, any]">
        Log-likelihood, perplexity, sequence length, and objective details.
      </ResponseField>

      <ResponseField name="vocab" type="List[string]" required>
        Amino-acid column ordering for the input logits.
      </ResponseField>
    </Accordion>
  </div>

  #### Applications

  This tool exposes ESM-2 as a differentiable, structure-free protein-language-model loss for use inside MCMC, gradient descent, or any other optimization loop over relaxed protein sequences. It is most often used as a naturalness prior in continuous design pipelines, including latent Bayesian optimization frameworks and discrete walk-jump sampling approaches for de novo protein design.

  #### Usage Tips

  * **`temperature` controls how the raw input is converted into a distribution.** With a value set, the tool applies `softmax(logits / T)` before the forward pass; leave it `None` (the default) if the input already sums to 1 per position.
  * **`use_ste` enables the Straight-Through Estimator.** The forward then runs on hard one-hot tokens while gradients still route through the soft probabilities, giving stronger guidance toward discrete sequences. Leave it off for smooth optimization over the relaxed simplex.
  * **`compute_gradient` toggles whether the backward pass runs.** When set to `False`, the `gradient` field is `None`, but `loss` and `metrics` (log-likelihood, perplexity, and so on) are still populated. Useful for ranking MCMC proposals without paying the backward cost.
</div>

## Toolkit Notes

These apply to every ESM-2 tool in this toolkit (`esm2-embedding`, `esm2-sample`, `esm2-score`, `esm2-gradient`).

* **Different ESM-2 checkpoints produce different embedding sizes.** Downstream tasks built on one checkpoint will not transfer to another without re-fitting; pick one and stick with it for an analysis.
* **Smaller checkpoints run faster.** The 150M and 35M variants are significantly faster than the 650M default, with drops in representation quality.
* **Max sequence length is 1022 residues.** ESM-2's positional encoding caps inputs at 1022 residues, and will raise `ValueError` on longer inputs rather than truncating.
* **`batch_size` controls memory usage across the toolkit.** Lower it if you OOM; raise it for short-sequence throughput. One nuance: for `esm2-score`, `batch_size` counts masked variants pooled across all input sequences rather than sequences themselves (each input contributes `L` masked variants).

<Tip>
  **Example notebook:** See the [full working example](https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esm2/examples/example.ipynb) for a copy-paste-ready walkthrough.
</Tip>

## Infrastructure Guides

The following guides cover how to run tools efficiently and at scale.

<CardGroup cols={2}>
  <Card title="Tool Persistence" icon="repeat" href="/docs/tools/guides/tool-persistence">Keep a tool's model warm across calls instead of reloading it every invocation.</Card>
  <Card title="Device Management" icon="cpu" href="/docs/tools/guides/device-management">How GPUs are allocated to tools and how to target specific devices.</Card>
  <Card title="Parallel Execution" icon="layers" href="/docs/tools/guides/parallel-execution">Fan a batch of inputs out across multiple GPUs.</Card>
</CardGroup>
