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

# ESM C SAE Features

> Sparse autoencoders (SAEs) decompose [Biohub](https://biohub.ai)'s ESM C activations into a large, sparsely-active feature space that is easier to interpret than raw embeddings. This toolkit loads an ESM C backbone, attaches the SAEs trained against the layers you request, and returns the active features at every residue.

<div class="page-hero"><img class="page-hero-banner" src="https://proto-bio.github.io/proto-assets/images/tool/esmc_sae/hero.png" alt="ESM C SAE Features" /><div class="tool-org-badges page-hero-badges"><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:** ESM C SAE Features is open source and free for academic and commercial use under an MIT license. Please refer to [the license](https://github.com/Biohub/esm/blob/main/LICENSE.md) for full terms.
</Note>

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

<hr class="entity-rule" />

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

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

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

<input type="radio" name="tab-esmc-sae" id="website-esmc-sae" class="tab-radio-input" />

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

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

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

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

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

<div class="tool-tab-bar">
  <span class="tool-tab-wrap"><label for="github-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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="website-esmc-sae" class="tool-tab tab-open badge-website"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg> Website</label><label for="none-esmc-sae" class="tool-tab tab-close badge-website"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg> Website</label></span> <span class="tool-tab-wrap"><label for="paper-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" 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-esmc-sae" class="tool-tab tab-open badge-local"><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="4 17 10 11 4 5" /><line x1="12" y1="19" x2="20" y2="19" /></svg> Run Locally</label><label for="none-esmc-sae" class="tool-tab tab-close badge-local"><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="4 17 10 11 4 5" /><line x1="12" y1="19" x2="20" y2="19" /></svg> Run Locally</label></span>
</div>

<a href="https://github.com/Biohub/esm" target="_blank" class="tab-panel github-panel" data-tab="github-esmc-sae">
  <div class="gh-card-wrap">
    <img src="https://opengraph.githubassets.com/1/Biohub/esm" class="gh-card-img img-fallback" alt="Biohub/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> Biohub/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>

<a href="https://huggingface.co/biohub/ESMC-SAE-Overview" target="_blank" class="tab-panel hf-panel" data-tab="hf-esmc-sae">
  <div class="hf-card-wrap">
    <img src="https://cdn-thumbnails.huggingface.co/social-thumbnails/models/biohub/ESMC-SAE-Overview.png" class="hf-card-img img-fallback" alt="biohub/ESMC-SAE-Overview" />

    <div class="hf-card-fallback">
      <div class="hf-fallback-org"><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> biohub/ESMC-SAE-Overview</div>
    </div>
  </div>

  <span class="panel-goto-btn hf-goto-btn"><span><img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" width="16" height="16" class="hf-logo" /> View model</span></span>
</a>

<a href="https://biohub.ai/" target="_blank" class="tab-panel website-panel" data-tab="website-esmc-sae">
  <div class="website-info">
    <img src="https://www.google.com/s2/favicons?domain=biohub.ai&sz=32" class="website-favicon" width="24" height="24" />

    <span class="website-url">biohub.ai</span>
  </div>

  <span class="panel-goto-btn website-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"><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg> Visit website</span></span>
</a>

<a href="https://doi.org/10.5281/zenodo.14219303" target="_blank" class="tab-panel paper-panel" data-tab="paper-esmc-sae">
  <div class="paper-info">
    <div class="paper-title">Language Modeling Materializes a World Model of Protein Biology</div>
    <div class="paper-meta">Salvatore Candido, Thomas Hayes, ... Alexander Rives</div>
    <div class="paper-meta paper-venue">2026</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-esmc-sae">
  <div class="cite-code-wrap">
    ```bibtex theme={null}
    @misc{candido2026language,
      title={Language Modeling Materializes a World Model of Protein Biology},
      author={Candido, Salvatore and Hayes, Thomas and Derry, Alexander and Rao, Roshan and Lin, Zeming and Verkuil, Robert and Wu, Bryan and Lee, Jin Sub and Bruguera, Elise S. and Keval, Jehan A. and Kopylov, Mykhailo and Pak, John E. and Wu, Wesley and Thomas, Neil and Mataraso, Samson and Hsu, Alvin and Trotman-Grant, Ashton C. and Fatras, Kilian and dos Santos Costa, Allan and Badkundri, Rohil and Ak{\i}n, Halil and Oktay, Deniz and Deaton, Jonathan and Montabana, Elizabeth and Sitwala, Hrishita and Yu, Yue and Wiggert, Marius and Carlin, Dylan Alexander and Goering, Anthony W. and Blazejewski, Tomasz and Sandora, McCullen and Hla, Michael and Jia, Tina Z. and Kloker, Leon H. and Sofroniew, Nicholas J. and Uehara, Masatoshi and Pannu, Jassi and Bachas, Sharrol and Liu, Daniel S. and Sercu, Tom and Rives, Alexander},
      year={2026},
      url={https://www.biorxiv.org/content/10.64898/2026.06.03.729735},
      note={Preprint}
    }

    @software{evolutionaryscale_2024,
      author={{EvolutionaryScale Team}},
      title={evolutionaryscale/esm},
      year={2024},
      publisher={Zenodo},
      doi={10.5281/zenodo.14219303},
      url={https://doi.org/10.5281/zenodo.14219303}
    }
    ```
  </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/esmc_sae" target="_blank" class="tab-panel source-panel" data-tab="source-esmc-sae">
  <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/esmc\_sae</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/esmc_sae/examples/example.ipynb" target="_blank" class="tab-panel notebook-panel" data-tab="notebook-esmc-sae">
  <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 run-local-panel" data-tab="proto-esmc-sae">
  <a href="https://github.com/evo-design/proto-tools" target="_blank" class="run-local-preview">
    <img noZoom src="https://opengraph.githubassets.com/1/evo-design/proto-tools" alt="proto-tools on GitHub" />
  </a>

  <div class="run-local-install">
    <span class="run-local-label">Run locally with proto-tools</span>

    <div class="run-local-code">
      ```bash theme={null}
      pip install git+https://github.com/evo-design/proto-tools.git
      ```
    </div>
  </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/adititm" target="_blank" rel="noopener" title="adititm: 1 commit"><img noZoom class="entity-contributor-avatar" src="https://avatars.githubusercontent.com/u/61667248?v=4&s=64" alt="" loading="lazy" /><span class="entity-contributor-login">adititm</span></a><a class="entity-contributor" href="https://github.com/bviggiano" target="_blank" rel="noopener" title="bviggiano: 1 commit"><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></span></div>

| Function                  | Description                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run_esmc_sae_features()` | Decompose ESM C activations into interpretable sparse autoencoder features (GPU) | <a href="#api-run-esmc-sae-features" 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/esmc_sae/esmc_sae_features.py#L367" 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

An SAE is trained to reconstruct a language model's internal activations through a bottleneck that permits only `k` active features per position out of a much larger codebook. The sparsity pressure pushes individual features toward single interpretable concepts, so a feature may correspond to a specific structural or functional property such as a zinc-binding site, a beta barrel, or a transmembrane helix. Biohub trained SAEs on ESM C using the TopK approach and used them to organize the ESM Atlas, a map of 6.8 billion proteins ([Biohub](https://www.biorxiv.org/content/10.64898/2026.06.03.729735)).

The SAEs were trained with two structural hyperparameters that set granularity. `k` fixes how many features are allowed to activate per residue, with lower values not able to reconstruct the activation as accurately — but higher values are harder to interpret, since a residue explained by 512 features is barely more legible than the dense embedding the SAE replaced. `k=64` is the balance Biohub trained across every layer. Additionally, the `codebook_size` of each SAE fixes how many features exist in total. Small codebooks group related concepts into one feature, for example a single metal-binding feature; large codebooks split that into dedicated zinc-finger, iron-sulfur, and calcium-binding features.

**Every combination of these is a separately trained model, not a runtime setting.** An SAE learns its dictionary against one backbone, one layer, one `k`, and one `codebook_size`, so those values are fixed in the weights. `model_checkpoint`, `sae_target`, `layers`, `k`, and `codebook_size` therefore act together as a selector: the tool composes them into a HuggingFace repo id and loads that SAE. Biohub published 97 such SAEs, and only some combinations exist, so the config rejects the ones that do not and names the valid alternatives.

## Tools

<a name="api-run-esmc-sae-features" />

<div class="tool-section-card">
  ### ESM C SAE Features (`esmc-sae-features`)

  Runs each sequence through the ESM C backbone once with SAEs attached to the requested layers, and returns the active codebook features at each residue, ordered by descending magnitude. Start and end tokens are stripped so positions align with the input sequence: `feature_indices[0]` holds the features for residue 1, and the `position` column of an exported CSV is 1-indexed, matching the rest of proto-tools.

  #### 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/shared_data_models.py#L29" 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: MaskedModelInput">
      <ParamField path="sequences" type="List[string]" required>
        Protein sequence(s) to process. Can be provided as:
      </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/esmc_sae/esmc_sae_features.py#L216" 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: ESMCSAEFeaturesConfig">
      <ParamField path="model_checkpoint" type="enum" default="esmc_300m">
        ESM C backbone whose activations are decomposed. The SAE must match the backbone it was trained on.

        Available options: `esmc_300m`, `esmc_600m`, `esmc_6b`
      </ParamField>

      <ParamField path="layers" type="array">
        Backbone layers to attach SAEs to. `None` uses the \~75%-depth layer Biohub sweeps (300M: 23, 600M: 27, 6B: 60). Each layer adds a download and GPU memory.
      </ParamField>

      <ParamField path="sae_target" type="enum" default="hidden_states">
        Which activations the SAE was trained on. Hidden states give a global view; MLP outputs isolate one layer's computation.

        Available options: `hidden_states`, `mlp_outputs`
      </ParamField>

      <ParamField path="k" type="enum" default="64">
        Active features per residue. Fixed in the SAE's weights, so this selects a model rather than a threshold; only `64` was trained against every layer, and other values exist solely at the sweep layer.

        Available options: `16`, `32`, `64`, `128`, `256`, `512`
      </ParamField>

      <ParamField path="codebook_size" type="enum" default="16384">
        Total features the SAE can represent, also fixed in its weights. Larger codebooks split concepts more finely; which sizes exist depends on `model_checkpoint` and `sae_target`.

        Available options: `8192`, `16384`, `32768`, `65536`, `131072`
      </ParamField>

      <ParamField path="backbone" type="enum" default="transformers">
        Which ESM C implementation supplies the activations the SAE reads. `"transformers"` matches the published SAE documentation. `"esm"` reads the `esmc` toolkit's weights instead, avoiding a second backbone download at the cost of \~1% disagreement in active features.

        Available options: `transformers`, `esm`
      </ParamField>

      <ParamField path="batch_size" type="integer" default="1">
        Sequences per forward pass.
      </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/esmc_sae/esmc_sae_features.py#L166" 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: ESMCSAEFeaturesOutput">
      <ResponseField name="results" type="List[SequenceSAEFeatures]" required>
        Per-sequence SAE features, index-parallel with the input sequences.

        <Expandable title="SequenceSAEFeatures">
          <ResponseField name="sequence" type="string" required>
            The input sequence these features were computed from, echoed so an exported row can name the residue a feature fired on.
          </ResponseField>

          <ResponseField name="layers" type="List[SAELayerFeatures]" required>
            One entry per requested layer, ascending.
          </ResponseField>
        </Expandable>
      </ResponseField>
    </Accordion>
  </div>

  #### Applications

  Feature activations show which concepts the model recognizes at each residue, which supports interpreting what drives an embedding, locating functional sites without supervision, and comparing how proteins are represented internally. Because features are sparse and indexed, activations are directly comparable across proteins: within one SAE, a feature index always denotes the same learned concept. Indices are not comparable between different SAEs, including different layers of the same backbone, since each is trained separately and orders its codebook arbitrarily. The `ESMC-6B-sae-layer60-k64-codebook16384` SAE additionally has agent-generated natural-language descriptions for its codebook, available through the ESM Atlas.

  #### Usage Tips

  * **`layers` selects which activations are decomposed.** The default is the \~75%-depth layer Biohub sweeps (300M: 23, 600M: 27, 6B: 60), where representations transfer best to downstream tasks. Each extra layer adds a download and GPU memory.
  * **`sae_target` picks what the SAE reads.** `hidden_states` (the default) decomposes the accumulated residual stream after a block, so features reflect everything the model has built up to that depth; it is what the ESM Atlas and the published feature descriptions use. `mlp_outputs` decomposes only that block's own MLP contribution before the residual add, which attributes a feature to one layer's computation. MLP-output SAEs are published only at `codebook_size=131072`.
  * **`k` and `codebook_size` are only free at the sweep layer.** All-layer SAEs exist at `k=64` and one codebook size, so varying either requires `layers` to be exactly the sweep layer. The config rejects unpublished combinations and names the valid alternatives.
  * **Only requested layers are downloaded, and layer size tracks `codebook_size`.** Each layer file holds an encoder and decoder of `d_model x codebook_size` weights, so a hidden-state layer is 0.13 GB on 300M and 0.34 GB on 6B, while an MLP-output layer (131072 codebook) is 1.0 GB and 2.7 GB respectively. Requesting every layer of the 6B MLP collection would pull roughly 217 GB; the tool logs a warning past 10 GB rather than refusing, since a deliberate multi-layer sweep is legitimate.
  * **Rank features by normalized activation, not raw magnitude.** The largest raw activations belong to features that fire on nearly every protein and say little. Biohub's published statistics correct for this: `(activation / uniref90_max_activation) * uniref90_idf` scales a feature to \[0, 1] and upweights rare ones. `describe_sae_features` in `helpers.py` returns both statistics alongside each feature's label, for the one SAE with published descriptions (`ESMC-6B-sae-layer60-k64-codebook16384`, which the 6B defaults resolve to).
  * **Output size scales with `k` times sequence length.** Each residue carries `k` indices and `k` magnitudes, so a 300-residue protein at `k=64` yields 19,200 pairs per layer.
</div>

## Toolkit Notes

These apply to every ESM C SAE tool in this toolkit (`esmc-sae-features`).

* **This toolkit shares the Biohub `esm` environment with ESM C and ESM3.** All three use the `biohub_esm` env; installing any one installs it for all.
* **The backbone is loaded through Transformers, not the `esm` package.** The SAE API is defined on the Transformers ESM C model, so this toolkit loads `biohub/ESMC-300M` and siblings rather than the `esm`-package weights the `esmc` toolkit uses. Both repos hold the same parameters in different serializations, so using both toolkits downloads the backbone twice: 1.3 GB for 300M, 2.3 GB for 600M, 25.4 GB for 6B. This is deliberate — the SAEs are published and documented against the Transformers model, and reading the `esm`-package activations instead agrees on only about 99% of active features, which is the wrong trade for an interpretability tool.
* **`batch_size` controls memory usage.** Lower it if you run out of GPU memory. For repeated calls, use `ToolInstance.persist_tool("esmc_sae")` to keep the backbone and SAEs loaded between calls.

<Tip>
  **Example notebook:** See the [full working example](https://github.com/evo-design/proto-tools/blob/47e34afa5ea240a3b406e323dc38aa5dc85f223e/proto_tools/tools/masked_models/esmc_sae/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>
