EmbeddingGemma 2 Encode Text
Turn a list of captions into vectors you can measure
- model
- embeddings
- report
Here's the workflow this node unlocks. You generated sixteen images from one prompt. Four of them are actually what you asked for. Instead of eyeballing the grid, you write out a handful of candidate captions, encode them here, encode the images, and let cosine similarity tell you which image belongs to which caption. This node is the text half of that.
It does the quieter jobs too - text-to-video search, sorting audio clips by description - but the image-labelling trick is why most people end up here.
What comes out
embeddings - the pack's EG2_EMBEDDINGS type, a bundle of unit-length vectors with a label attached to each one. Feed it into Similarity or Rank Images. It doesn't connect to anything outside this pack.
report - a JSON string with the model name, modalities, dtype, device, item count, vector length, the task used, and how many seconds the encode took. Like all of these nodes, it's a plain STRING, so a Show Text or a save-to-log node is all you need to see it. Handy for confirming you actually got 256-dimensional vectors and not the 768 you assumed.
The three fields that matter
text - multiline. With one_per_line on (the default), every non-empty line becomes its own item, trimmed. That's the mode you want: one caption per line, five embeddings out. Turn it off and the entire box is a single item, which is what you want for embedding a paragraph as one document. Empty input raises no text to encode rather than returning an empty bundle.
task - the one that separates this from a naive embedding node, and the one beginners ignore. EmbeddingGemma 2 was trained with instruction prefixes, and the model card is specific about pairings:
SearchQueryfor anything you're searching with - a text prompt hunting for the matching image, video or audio clip. This is the right choice when you're comparing text against images or video.Documentfor the texts you're searching through.QuestionAnswering,FactChecking,CodeRetrievalfor those specific jobs.Classification,Clustering,SentenceSimilaritywhen you're comparing like with like - and the same task on both sides.
Media-side encoders apply no prefix, so text-to-image ranking is SearchQuery on the text and nothing on the images. Getting the pairing wrong doesn't error; it just makes your scores worse and you'll never know. That's the actual trap here.
title - only does anything with task set to Document, where each item gets rewritten to the model card's title: {title} | text: {content} format. One title for the whole batch, so it's a limitation if your documents differ. Empty means title: none.
Then dimensions, default 768. This is Matryoshka truncation: the vector is cut to its leading 768, 512, 256 or 128 values and renormalised. 512 and 256 are close to lossless by the model card's account, and I'd just use them - a third of the storage, no meaningful quality drop, and cosine similarity on 256 floats is trivial. 128 is where images, video and audio start visibly degrading. Text survives it better, but 256 is the honest default.
The hard rule: only vectors of the same length can be compared. Mix a 768 text embedding with a 256 image embedding and Similarity throws a ValueError naming both lengths. It's a good error message, and it exists because this is the mistake everyone makes.
How it works, briefly
The node picks your items, maps task to a prompt name in the model's config_sentence_transformers.json, and calls SentenceTransformer.encode() with prompt_name set. Truncation goes through the library's own truncate_dim path with renormalisation on. Vectors come back float32 on the CPU, so downstream maths is deterministic.
One thing to keep in mind: the official processing does not truncate text. The model's context is 8,192 tokens, and a 12,000-word document will happily become 12,003 tokens and misbehave. The README's own number. If you're embedding long documents, split them yourself.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/hiroki-abe-58/ComfyUI-EmbeddingGemma2
python -m pip install -r ComfyUI-EmbeddingGemma2/requirements.txt
python ComfyUI-EmbeddingGemma2/tools/download_model.py --models-dir ../models/embeddinggemma
Or search EmbeddingGemma 2 for ComfyUI in ComfyUI Manager. Restart, load one of the shipped workflows in workflows/gui/ (image_captions labels input/example.png and is the fastest way to see the whole idea work), and note that the pack needs a reasonably current ComfyUI - it's written against the V3 node API and registers nothing on old builds.
Realistic expectations
On the author's RTX 5090 in bfloat16, six texts encode in 0.04 s once the model is resident; the first call after loading is slower. Loading itself is around 3 s and 2.5 GiB with all encoders. If you're on CPU it works, at float32, and you'll feel it.
This pack has almost no community footprint yet - EmbeddingGemma itself barely registers in discussion - so you're on your own for workflow patterns. The mechanism is boring and well-tested, which is what you want from a measuring tool.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| model | EG2_MODEL | — | |
| text | STRING | a red fox in the snow a sailboat at sunset an aerial view of a river | — |
| one_per_line | BOOLEAN | true | Each non-empty line is one item; off = the whole text is one item. |
| task | COMBO | SearchQuery | 9 options: SearchQuery, Document, QuestionAnswering, FactChecking, CodeRetrieval, Classification, +3 |
| title | STRING | Document task only: the documents' title (empty = 'title: none'). | |
| dimensions | COMBO | 768 | Matryoshka length: the leading dimensions, re-normalised. 768 = full; 512 / 256 are close to lossless; 128 loses noticeably on images, video and audio (model card). Only vectors of the same length can be compared. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| embeddings | EG2_EMBEDDINGS | — |
| report | STRING | — |