ESMC-LI
Fast, local protein retrieval with ESM-C residue embeddings and late interaction (MaxSim).
ESMC-LI is a pip-installable protein retrieval engine for local and offline
search. It encodes proteins with ESM-C 300M, projects every residue into a
128-dimensional vector, and ranks candidates with exact MaxSim late
interaction. The index is a single memory-mapped .esmci file; inference runs
through esmc.cpp.
Late interaction follows ColBERT; the protein-specific model idea was introduced by ProtoCol (arXiv:2605.29158). ESMC-LI focuses on the practical index, full-length evaluation, and a reproducible local package.
Paper: Scaling Late-Interaction Protein Retrieval · API: docs/api.md · Model: AnanyaPathak/esmc-li-300m-homology-v1 · Indexes: AnanyaPathak/esmc-li-indexes
At a glance
| Search | Exact MaxSim over residue vectors; no ANN approximation |
| Backbone | ESM-C 300M, 960-dimensional residue embeddings |
| Projection | 128-dimensional, L2-normalized rows |
| SCOPe ASTRAL40 cR@10 | 0.9065 (fine-tuned) vs 0.8933 reproduced ProtoCol |
| Full-length 100K cR@10 | 0.8974 vs 0.8304 MMseqs2 |
| Full-length 100K sensitivity | 0.6048 at superfamily level vs 0.4765 MMseqs2 |
| Exact search | ~1 s/query at 100K; 11.1 s/query at 1M on M4 Max Metal |
| Index size | 8.1 GB at 100K; 81 GB at 1M |
Install
pip install esmc-li
# optional, macOS: fused Metal search
pip install "esmc-li[metal]"
PyPI wheels target macOS arm64 and Linux x86_64 (glibc 2.34+), Python 3.10+. There is no Windows or Intel-macOS wheel in v1. Wheels bundle the native runtime and projection head; no compiler or separate esmc.cpp build is needed.
The fine-tuned GGUF is downloaded from Hugging Face on first use. The current
model is ~664 MB and is cached under ~/.cache/esmc-retrieval (the historical
cache path is kept for compatibility). Subsequent runs are local.
For a source install, libesmc is not bundled. Install from GitHub and set
ESMC_LIB or use the ESMC_EMBED CLI fallback; see
CONTRIBUTING.md.
Quickstart
esmc-li index pull scope-1k
esmc-li search scope-1k \
--sequence "GERRRSQLDRDQCAYCKEKGHWAKDCPKKPRGPRGPRPQT" \
--top-k 5
from esmc_li import ProteinIndex
index = ProteinIndex.load("scope-1k")
hits = index.search("GERRRSQLDRDQCAYCKEKGHWAKDCPKKPRGPRGPRPQT", k=5)
print(hits[0])
Build an index from your own FASTA:
esmc-li build proteins.fasta --output proteins.esmci
esmc-li search proteins.esmci \
--sequence "MKTIIALSYIFCLVFADYKDDDDK" \
--top-k 10
Batch FASTA queries:
esmc-li search proteins.esmci \
--query queries.fasta \
--output results.tsv
How it works
esmc.cppencodes a sequence into residue rows[L × 960]with BOS/EOS kept.- A frozen linear head projects each row to 128 dimensions and L2-normalizes it.
- Rows are packed into an
.esmcimmap index as f16. - Queries use the same encoder and head; exact MaxSim produces the top-k.
- Metal accelerates the max-and-reduce on macOS; numpy is the portable fallback.
Long chains are chunked at 2046 residues with 128-residue overlap. The index format is documented in docs/esmci.md.
How we compare
- ProtoCol: the released code is vendored at
vendor/ProtoColand run throughscripts/repro_protocol.py; only the device is changed. - MMseqs2:
-s 7.5 -e 1e10 --max-seqs 1000. - MinHash: 5-mers, 256 permutations.
- Pooled ESM-C: mean residue vector, cosine similarity.
- Frozen MaxSim: ESM-C residue vectors with no trained projection.
- ESMC-LI: fine-tuned ESM-C suffix, 128D head, exact MaxSim.
All reported values use the same frozen split; see the paper for the full protocol and limitations.
Results
| Method | SCOPe cR@10 | Full-length 100K cR@10 | Full-length sens superfamily |
|---|---|---|---|
| Pooled ESM-C | 0.4045 | 0.6870 | 0.2118 |
| MMseqs2 | 0.6179 | 0.8304 | 0.4765 |
| Frozen MaxSim 960D | 0.6304 | 0.8024 | 0.3914 |
| ProtoCol (reproduced) | 0.8933 | — | — |
| ESMC-LI fine-tuned | 0.9065 | 0.8974 | 0.6048 |
SCOPe cR@k curves and full-length 100K comparison. Values are from the committed evaluation CSVs; see the paper for protocol details.
SCOPe uses ASTRAL40, n=2314, leave-one-out superfamily retrieval, and a three-seed mean for the fine-tuned row. Full-length uses 100K single-clan Swiss-Prot chains and 500 test-clan queries; its ESMC-LI row is seed 0. See the paper for the full protocol, baselines, and limitations.
A useful negative result: frozen ESM-C is weaker than frozen ESM-2 35M under the same harness (0.6304 vs 0.8215 cR@10). The ESM-C gain appears after fine-tuning; the model is not a drop-in frozen upgrade.
ProtoCol reproduction and frozen-backbone control on our SCOPe split. The
ProtoCol rows use the vendored code in vendor/ProtoCol/.
Performance
| Database | Residues | Index | Build | Exact search |
|---|---|---|---|---|
| 10K | 3.15M | 0.81 GB | 0.17 h | 0.11 s/query |
| 100K | 31.8M | 8.14 GB | 1.79 h | ~1.0 s/query |
| 1M | 317M | 81.17 GB | 17.49 h | 11.13 s/query |
M4 Max, fused Metal, 50 queries. The 1M row is batch-mode; build and storage, not query latency at 100K, are the practical constraints. A 1K demo index searches in ~19 ms/query.
Exact search, coarse rerank, and index size versus database size on M4 Max.
Platform support
| Platform | Wheel | Notes |
|---|---|---|
| macOS 11+ arm64 | yes | Metal optional via esmc-li[metal] |
| Linux x86_64 glibc 2.34+ | yes | CPU search |
| Windows | no | not supported in v1 |
| Intel macOS | no | not supported in v1 |
Python 3.10+. Wheels include libesmc and ggml; macOS binaries are unsigned
and print a warning.
Model and indexes
| Artifact | Link | Contents |
|---|---|---|
| Fine-tuned model | esmc-li-300m-homology-v1 | GGUF encoder + 128×960 head |
| Demo index | scope-1k | 1K SCOPe domains |
| Benchmark index | swissprot-100k | 100K full-length chains |
The wheel contains no model weights. Model weights and GGUF derivatives are governed by the EvolutionaryScale Cambrian Open License; see NOTICE and CAMBRIAN-OPEN-LICENSE.md. ESMC-LI is not affiliated with EvolutionaryScale.
Python API
from esmc_li import ProteinIndex
# Build once
index = ProteinIndex.from_fasta("proteins.fasta", output="proteins.esmci")
# Load later
index = ProteinIndex.load("proteins.esmci")
hits = index.search("MKTIIALSYIFCLVFADYKDDDDK", k=20)
batch = index.search_batch(["MKT...", "MKT..."], k=20)
search() returns:
[{"id": "protein_123", "score": 0.87, "metadata": {...}}, ...]
See docs/api.md for signatures, device selection, and index compatibility.
CLI
esmc-li build proteins.fasta --output proteins.esmci
esmc-li search proteins.esmci --sequence "MKT..." --top-k 10
esmc-li search proteins.esmci --query queries.fasta --output results.tsv
esmc-li benchmark proteins.esmci
esmc-li index list
esmc-li index pull scope-1k
Limitations
- Exact search is interactive at 100K and batch-oriented at 1M.
- No Windows or Intel-macOS wheel in v1.
- No GPU retrieval; Metal is used for the fused max kernel on macOS.
- The model download is ~664 MB on first use.
- macOS runtime binaries are unsigned.
- The model weights and derivatives are Cambrian-licensed; the Python package itself is MIT.
Reproducibility and development
The paper and its tables are generated from a pinned results lock. The short version:
make audit # tests + paper claims + citation + lock checks
make tables # regenerate paper tables and figures
Development setup, the full paper audit, release steps, and benchmark commands are in CONTRIBUTING.md.
Citation
@software{pathak2026esmcli,
author = {Pathak, Ananya},
title = {ESMC-LI: Fast Local Protein Retrieval with ESM-C Residue Embeddings and Late Interaction},
version = {1.0.1},
year = {2026},
url = {https://github.com/AnanyaP-WDW/esmc-li}
}
See CITATION.cff for the machine-readable entry.
License and acknowledgements
Code is MIT-licensed. See LICENSE. ESM-C 300M weights and GGUF derivatives are governed by the Cambrian Open License; a copy is included in CAMBRIAN-OPEN-LICENSE.md.
Built with ESM. Thanks to the esmc.cpp, ESM-C, SCOPe, and UniProt teams.
Metadata
Release files for esmc-li 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| esmc_li-1.0.1-cp310-abi3-manylinux_2_34_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.34+ x86-64 | Details for esmc_li-1.0.1-cp310-abi3-manylinux_2_34_x86_64.whl |
| esmc_li-1.0.1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details for esmc_li-1.0.1-cp310-abi3-macosx_11_0_arm64.whl |
Total release size: 6.0 MB
Release files / esmc_li-1.0.1-cp310-abi3-manylinux_2_34_x86_64.whl
| Download URL | esmc_li-1.0.1-cp310-abi3-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.10 Linux glibc 2.34+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
45b21ba49a349f80f9a1002b5b4199c66364911b79d4b28813b12f99f24a347f
|
|
BLAKE2b-256 checksum How to use checksums |
e35a8df8083d772648861c12758075cb168ec8ec367acc58eab8c7b5cdb218a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logRelease files / esmc_li-1.0.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | esmc_li-1.0.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 3.1 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
6048d6846ca0cf5a8169a1739bb88af5e57dbf85b138e3f646186f5eeb02c84c
|
|
BLAKE2b-256 checksum How to use checksums |
1a4f6dd905ea07aa92fac76aafe0bcaa8cdc5c9dc587cbf263aa80311dc4fe82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logSecurity for esmc-li 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for esmc_li-1.0.1-cp310-abi3-manylinux_2_34_x86_64.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.