Run the Latest Hugging Face Models on Your GPU Cluster Instantly

A new folding model shows up on Hugging Face and within a day someone on the science team has a notebook that works, at least for one sequence on one GPU. Getting that same model onto the rest of the table is a different job. You wrap it in FastAPI, write a Dockerfile, push an image, then sit down with a Kubernetes Deployment: GPU requests, health checks, retries, a Service, and a LynxKite box that maps rows onto that API. None of that is folding proteins. It is the work that sits between “the checkpoint is public” and “we can actually use it.”

NVIDIA already solved a lot of this with NIMs. A NIM is an optimized container from their catalog (BioNeMo and related models). You pull the image and run it on your GPU cluster, or you call their cloud API, and the production pieces are already there: a known HTTP interface, health checks, GPU packaging. The bio catalog covers the jobs you would expect, protein folding with ESMFold, AlphaFold2, and Boltz-2, protein design with RFdiffusion, plus small molecules and docking. LynxKite already talks to NIMs. If NVIDIA shipped the container you want, you should use it.

The trouble is timing. A NIM takes a while to release, and biology does not wait. Hugging Face has more than two million models. NVIDIA’s catalog has about 138 production-tuned images. We like NIMs, and we ship them. We still kept hitting the same gap: the checkpoint is already public, the Python example on the model card already runs, and the pipeline is stuck because nobody has packaged it yet. If you already have Python and a GPU cluster, that wait is hard to justify.

That is what a LynxKite Inference Microservice is for.

From a row function to a service

A LIM is a Python function that LynxKite runs as a Kubernetes service. You write the model code yourself, usually by copying the example from the Hugging Face card, put @lim on the row function, and LynxKite deploys it, scales it, and plugs it into the same kind of workspace box people already use. Sequences come in as table rows. Predictions come back as columns. You keep writing Python. LynxKite handles deploy and scale.

There is no extra container to build. LynxKite deploys its own worker image, and your function loads the checkpoint at runtime, usually from Hugging Face, the same way the model card already shows. The FastAPI wrapper, the Dockerfile, and the GPU Deployment stay out of the way.

Here is ESMFold2 as a LIM. The interesting line is @lim.

@op("Query ESMFold2", slow=True)
@elementwise(input_table="protein_table_column")
@lim
def query_esmfold2(record: Record, *, protein_table_column: TableColumn):
    sequence = record[protein_table_column]
    record.folded_protein = (
        _predict_esmfold2(sequence) if sequence else None
    )

_predict_esmfold2() is where the Hugging Face example code goes. It loads ESMFold2 from biohub/ESMFold2, runs the fold, and returns PDB text. One protein per table row goes in, and a folded_protein column comes out. LynxKite starts GPU workers, spreads rows across them, and shows progress while they come up.

The defaults are enough to try a model. If you need to pin CPU, GPU, or RAM, a settings.yaml next to the workspace does it per box:

lim:
  "LynxKite Bio > LIM Services > Query ESMFold2":
    cpu: "8"
    memory: "32Gi"

Replica count follows the workspace GPU setting. Workers share a Hugging Face cache, so the second sequence does not download the weights again.

This is easiest when the model is new and the Python API is clean. You can turn older models into LIMs as well (we looked at Boltz-2), but it takes more work if you do not have a short from_pretrained snippet to start from.

ESMFold2, this week

ESMFold2 is a good example of why the wait matters. It is newer than the ESMFold in the NIM catalog, and on the benchmark we looked at it is also more accurate. You can get it from Hugging Face today (biohub/ESMFold2). There is no NVIDIA container for it. We run it as a LIM.

  ESMFold2 LIM Boltz-2 NIM
Warm inference 1.30 s 1.43 s
Accuracy* 77% 70%

*From Figure 25 of the ESMFold2 preprint.

Warm inference is in the same range. Accuracy is better, and we did not wait for a catalog image. Both jobs still run on your cluster. The difference is only whether NVIDIA has already done the packaging.

We did not build LIMs to replace NIMs. A NIM is the right call when it exists: production-tuned, known API, already on the cluster. A LIM is the right call when the checkpoint is on Hugging Face and you need it in the pipeline this week, which is most of the catalog. Hugging Face has the models. NVIDIA has the ones they have packaged. LynxKite will run either.

If you have a model on the Hub, a table of sequences, and no interest in maintaining another microservice, get in touch. We can set you up with LIMs, NIMs, and the rest of LynxKite Enterprise.

Main platform: github.com/lynxkite/lynxkite-2000