Download export/eg2_text_mm.py from EverPaper/embeddinggemma-2-coreai: direct link, hf CLI and curl.
- Browser
- Download file 3.12 kB
-
https://huggingface.co/EverPaper/embeddinggemma-2-coreai/resolve/main/export/eg2_text_mm.py
- Command line
-
hf download hf://EverPaper/embeddinggemma-2-coreai/export/eg2_text_mm.py
-
curl -L -o eg2_text_mm.py https://huggingface.co/EverPaper/embeddinggemma-2-coreai/resolve/main/export/eg2_text_mm.py
3.12 kB
| # Copyright 2026 Everpaper. Licensed under the Apache License, Version 2.0 (see ../LICENSE). | |
| """The EmbeddingGemma 2 text encoder with multimodal (soft-token) inputs: `eg2_text.EmbeddingGemma2Text` plus a | |
| mix of token embeddings and externally computed soft tokens at the start of the graph. | |
| input_ids [1, S] int32 token ids; placeholder slots (<|image|> = 258880) are looked up like any id | |
| attention_mask [1, S] fp16 1 = token, 0 = right padding | |
| mm_embeds [1, S, 512] fp16 soft tokens placed at their slots (zeros elsewhere); NOT scaled by sqrt(512) | |
| mm_mask [1, S] fp16 1 at a soft-token slot, 0 elsewhere | |
| -> x = embed(input_ids) * (1 - mm_mask) + mm_embeds * mm_mask, then exactly the text graph (per-layer | |
| embeddings, 24 layers, final norm, projection, masked mean pooling over ALL tokens, L2 normalization) | |
| -> embedding [1, 768] fp16 | |
| With mm_mask all zero this is the text encoder (x * 1 + 0 is exact in fp16). eg2_text.py is unchanged (it is the | |
| file that produced the text-only bundle); this module only re-states its forward with the mix. | |
| """ | |
| from __future__ import annotations | |
| import torch | |
| import eg2_text | |
| class EmbeddingGemma2TextMM(eg2_text.EmbeddingGemma2Text): | |
| def forward(self, input_ids, attention_mask, mm_embeds, mm_mask): # noqa: D102 | |
| S = input_ids.shape[1] | |
| keep = (self.one - mm_mask)[:, :, None] | |
| x = self.embed_tokens(input_ids) * keep + mm_embeds * mm_mask[:, :, None] # [1, S, 512] | |
| ple = self.per_layer_projection_norm( | |
| self.per_layer_model_projection(x).view(1, S, self.cfg.n_layers, self.cfg.ple_dim)) | |
| full, sliding = self._biases(attention_mask, S) | |
| cs = {} | |
| for lt in ("sliding_attention", "full_attention"): | |
| cs[lt] = (getattr(self, f"cos_{lt}")[:S].to(x.dtype)[None, None], getattr(self, f"sin_{lt}")[:S].to(x.dtype)[None, None]) | |
| for i, layer in enumerate(self.layers): | |
| lt = self.cfg.layer_types[i] | |
| x = layer(x, ple[:, :, i, :], cs[lt][0], cs[lt][1], sliding if lt == "sliding_attention" else full) | |
| x = self.embedding_projection(self.norm(x)) | |
| if eg2_text.PRECISION_MODE == "ane": | |
| w = attention_mask * eg2_text._recip(attention_mask.sum(-1, keepdim=True)) | |
| pooled = torch.matmul(w[:, None, :], x)[:, 0, :] | |
| u = pooled * eg2_text._recip(torch.maximum(pooled.abs().amax(-1, keepdim=True), self.floor16)) | |
| return u * torch.rsqrt((u * u).sum(-1, keepdim=True)) | |
| xf = x.float() | |
| wf = attention_mask.float() | |
| pooled = (xf * wf[:, :, None]).sum(1) / wf.sum(-1, keepdim=True) | |
| return (pooled / pooled.norm(dim=-1, keepdim=True)).to(x.dtype) | |
| def load_model(model_dir: str, dtype: torch.dtype, max_seq: int = 2048) -> EmbeddingGemma2TextMM: | |
| """Same weights and folding as eg2_text.load_model, mm forward.""" | |
| cfg = eg2_text.Cfg(model_dir) | |
| m = EmbeddingGemma2TextMM(cfg, max_seq) | |
| base = eg2_text.load_model(model_dir, dtype, max_seq) | |
| m.load_state_dict(base.state_dict(), strict=True) | |
| return m.to(dtype).eval() | |