SANATextEncode
The half of SANA that's secretly a 2B LLM (and why it stays off your GPU)
- class
If SANA won't fit on your GPU, your first instinct is to blame the diffusion transformer. Wrong culprit. SANA's text encoder is a Gemma-2 2B LLM - a genuine small language model - and on low-VRAM setups that's usually the part that tips you over the edge. SANATextEncode is the node that deals with it: it encodes your prompt on the CPU, in bfloat16, and hands the result to SANADiffuse. The GPU never sees the LLM. That split, more than anything in this pack, is what makes the "2GB VRAM" claim real.
How it works
Like its sibling node, this is a client for the bundled Flask server. You hit Queue, the node spawns the server, POSTs your prompt and negative prompt to the /encode endpoint, and the server loads the SANA pipeline with the transformer and VAE stripped out - transformer=None, vae=None - so only the text encoder is in memory. It runs a couple of quick steps in text-only mode, serializes the resulting embeddings to JSON, and hands them back. Your node just waits on localhost for the answer.
The inputs that matter
There are only three, and two of them are prompts:
- prompt and negative_prompt - both multiline, both real. SANA's Gemma encoder genuinely consumes negative guidance, so unlike some single-encoder architectures, leaving the negative box empty is leaving quality on the table.
- model_path - pick the SANA variant you're about to diffuse. The dropdown lists four built-in HuggingFace repo IDs (600M/1600M at 512px/1024px) plus anything sitting in your
ComfyUI/models/diffusersfolder. This one must match SANADiffuse. The embeddings are produced by one model and consumed by another; mismatch the text encoder and you're feeding the diffuser embeddings from a different language space, which reliably produces garbage.
The catch
The output is a class-typed blob, and it's opaque in the truest sense. You can't inspect it, you can't wire it into anything that isn't SANADiffuse, and there's no standard CLIP interface to lean on. It's a closed loop - SANATextEncode to SANADiffuse to image. That's fine for a workflow living entirely inside this pack, and a dead end if you wanted to reuse SANA embeddings or mix in native ComfyUI conditioning. Everything also round-trips as JSON through a server that gets spawned and killed on every run, so budget a few seconds of startup lag per generation.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/taabata/SANA_LOWVRAM.git
pip install diffusers flask
Drop the diffusers model folders from the Efficient-Large-Model SANA collection into ComfyUI/models/diffusers and restart ComfyUI - or find "SANA_LOWVRAM" in the Manager install dialog and let it do the clone. The README mentions only diffusers, but the bundled server imports Flask too, so if your first run errors on flask, that pip line is the missing piece.
If your hardware can spare the VRAM, SANA's native ComfyUI support is cleaner and gives you real tensors to work with. But if the entire point is squeezing SANA onto a machine that barely runs anything - LLM parked on CPU, diffuser on GPU - this is a genuinely clever way to do it.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | — | |
| negative_prompt | STRING | — | |
| model_path | COMBO | 4 options: Efficient-Large-Model/Sana_600M_512px_diffusers, Efficient-Large-Model/Sana_600M_1024px_diffusers, Efficient-Large-Model/Sana_1600M_512px_diffusers, Efficient-Large-Model/Sana_1600M_1024px_diffusers |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| class | class | — |