Starlings.Models.EmbeddingGemma2
0.3.0
dotnet add package Starlings.Models.EmbeddingGemma2 --version 0.3.0
NuGet\Install-Package Starlings.Models.EmbeddingGemma2 -Version 0.3.0
<PackageReference Include="Starlings.Models.EmbeddingGemma2" Version="0.3.0" />
<PackageVersion Include="Starlings.Models.EmbeddingGemma2" Version="0.3.0" />
<PackageReference Include="Starlings.Models.EmbeddingGemma2" />
paket add Starlings.Models.EmbeddingGemma2 --version 0.3.0
#r "nuget: Starlings.Models.EmbeddingGemma2, 0.3.0"
#:package Starlings.Models.EmbeddingGemma2@0.3.0
#addin nuget:?package=Starlings.Models.EmbeddingGemma2&version=0.3.0
#tool nuget:?package=Starlings.Models.EmbeddingGemma2&version=0.3.0
Starlings.Models.EmbeddingGemma2
Embeddings from google/embeddinggemma-2 at revision 914f7f89142e33e77833254d9c9b90c3cef7303b, on ONNX Runtime 1.30.0, in-process and offline after an explicit download. The package is versioned 0.x, so the API may still change between minor versions; maturity is per profile (below).
- Text (
EmbeddingGemma2TextEmbedder,EmbeddingGemma2Encoder): owned tokenizer or token ids, on the released text graph. The text encoder rejects the ids of the media placeholder and boundary tokens (<|image|>,<|audio|>,<|video|>,<|image>,<image|>,<|audio>,<audio|>). - Images (
EmbeddingGemma2MultimodalEmbedder): an image alone, or text and images interleaved, from already-decoded RGB (EmbeddingGemma2Image), default budget of 280 soft tokens per image. See Images. - Videos (
EmbeddingGemma2MultimodalEmbedder,EmbeddingGemma2Video): a video alone, or text, images and videos interleaved, from already-decoded RGB frames, at the checkpoint's settings (1 frame per second, at most 32 frames, 140 soft tokens per frame, no timestamps). Audio is not supported. See Videos. - Right-padded batching, mean pooling over every attended token (prompt and image tokens included), L2 normalization: 768-dimensional unit vectors, or a Matryoshka size of 512, 256 or 128 (truncate, then normalize again, as sentence-transformers
truncate_dim). Other sizes are rejected. - Prompts are explicit and never added for you:
EmbeddingGemma2Prompt.Query("task: search result | query: ") for queries,EmbeddingGemma2Prompt.Document("title: none | text: ") for documents, any of the 20 names in the model'sconfig_sentence_transformers.jsonthroughEmbeddingGemma2Prompt.FromName, orNone(the default). The model card: "Prefixes apply to text only. Pass images, video, and audio without any prefix." - Inputs above 8,192 tokens (the card's context window; special tokens, prompt and image tokens included) are rejected with
EmbeddingGemma2InputTooLongException, never truncated. - CUDA runs with TF32 disabled (
use_tf32=0); with TF32 the text embeddings drift by up to 1.9e-4 and the image embeddings by up to 1.4e-3. - The package ships the asset locks (repository, commit, sizes and SHA-256), not the model files (1.1 GB for text, 2.9 GB with images). Acquisition is an explicit call; inference never downloads.
Maturity
Maturity is per profile, generated from the registry manifests by model-pipeline catalog (do not edit this table by hand). Gates, evidence and capabilities per profile: the model catalog.
| Profile | Maturity | Platforms |
|---|---|---|
embeddinggemma-2/image-fp32-cpu |
stable | linux-x64 cpu: supported; windows-x64 cpu: untested |
embeddinggemma-2/image-fp32-cuda |
stable | linux-x64 cuda: supported; windows-x64 cuda: untested |
embeddinggemma-2/onnx-fp32-cpu |
stable | linux-x64 cpu: supported; windows-x64 cpu: experimental |
embeddinggemma-2/onnx-fp32-cuda |
stable | linux-x64 cuda: supported; windows-x64 cuda: untested |
embeddinggemma-2/video-fp32-cpu |
stable | linux-x64 cpu: supported; windows-x64 cpu: untested |
embeddinggemma-2/video-fp32-cuda |
stable | linux-x64 cuda: supported; windows-x64 cuda: untested |
Tokenizer
Text goes through the owned tokenizer Starlings.Tokenizers (profile gemma-bpe-embeddinggemma2, exact against huggingface/tokenizers on the published fixtures): EmbeddingGemma2Tokenizer adds <bos> and <eos> and never truncates. No Microsoft.ML.Tokenizers and no native tokenizer library. Any other IEmbeddingGemma2Tokenizer must reproduce the pinned tokenizer.json exactly.
Install
dotnet add package Starlings.Models.EmbeddingGemma2
dotnet add package Microsoft.ML.OnnxRuntime --version 1.30.0 # CPU natives
# or, for CUDA on Linux x64: Microsoft.ML.OnnxRuntime.Gpu.Linux 1.30.0 (reference exactly one)
# optional, to decode image files: Starlings.Models.EmbeddingGemma2.Imaging.SkiaSharp
# optional, to decode video files on your own FFmpeg 8.x: Starlings.Models.EmbeddingGemma2.Video.FFmpeg
# (or on FFmpeg 9.x: Starlings.Models.EmbeddingGemma2.Video.FFmpeg9)
Use
using Starlings.Models.EmbeddingGemma2;
using Starlings.Runtime.Onnx;
await EmbeddingGemma2ModelAssets.DownloadAsync(); // once, explicit; verifies SHA-256
EmbeddingGemma2ModelFiles files = EmbeddingGemma2ModelAssets.OpenLocal(); // offline, verified, never downloads
using var encoder = EmbeddingGemma2Encoder.Create(files.ModelPath, new EmbeddingGemma2EncoderOptions
{
Session = new OnnxSessionOptions { ExpectedModelSha256 = EmbeddingGemma2ModelAssets.ModelSha256 },
Dimension = 768, // or 512, 256, 128
});
var tokenizer = EmbeddingGemma2Tokenizer.FromFile(files.TokenizerPath); // verifies the pinned SHA-256
var embedder = new EmbeddingGemma2TextEmbedder(tokenizer, encoder);
float[] q = embedder.Embed("how much protein should a female eat", EmbeddingGemma2Prompt.Query);
float[][] docs = embedder.EmbedBatch(["As a general guideline, ..."], EmbeddingGemma2Prompt.Document);
Vectors are normalized, so cosine similarity is the dot product.
Batching options
EmbedBatch splits a batch into ONNX Runtime calls, each right-padded to its longest row. EmbeddingGemma2EncoderOptions controls the split:
| Option | Default | Effect |
|---|---|---|
MaxBatchSize |
16 | Rows per call at most. |
MaxBatchTokens |
8,192 | Padded cells (rows x longest row) per call at most; a row longer than the budget runs alone. |
SortByLength |
false |
Chunks rows in ascending token length (ties in input order) so each call pads less, and writes each result back to its input position. Experimental (batch.sort_by_length). EmbeddingGemma2MultimodalOptions.SortByLength applies it to text-only inputs of the multimodal embedder; inputs with images or videos keep input order. |
The defaults are the qualified behavior: chunks are consecutive rows in input order, with outputs unchanged bit for bit. With SortByLength, which rows share a call depends on the whole batch, so a row's embedding can differ from the default by up to the profile's padded-batch-vs-single bound (CPU tests: at most 1.5e-7 against 5e-6 on 46 fixture rows of 2 to 1,743 tokens in random orders). If a call is cancelled, the Span<float> overload may already hold the rows of the chunks that completed: a prefix of the rows by default, the shortest rows with SortByLength.
DownloadAsync fetches the tokenizer and prompt configuration from google/embeddinggemma-2 and the text graph from the public Hugging Face repository Starlinghq/embeddinggemma-2-onnx at a pinned commit (EmbeddingGemma2ModelAssets.ModelSource), with no token. To use a graph you produced yourself with model-pipeline/reference/embeddinggemma2/release_embeddinggemma2_onnx.py (the digest must match), use OpenDirectory.
Images
await EmbeddingGemma2ModelAssets.DownloadImageAssetsAsync(); // text files + vision graph + multimodal text graph
var imageFiles = EmbeddingGemma2ModelAssets.OpenLocalImageAssets();
using var images = EmbeddingGemma2MultimodalEmbedder.Create(imageFiles); // SHA-256 of each graph checked while loading
// Decoded RGB from your own stack (3 bytes per pixel, rows top to bottom, no padding), or the SkiaSharp adapter:
EmbeddingGemma2Image photo = EmbeddingGemma2Image.FromRgb24(width, height, rgbBytes);
float[] e = images.Embed(photo); // an image alone, no prompt (the card)
float[] mixed = images.Embed(EmbeddingGemma2MultimodalInput.Create("A cat resting on a blanket. ", photo));
float[] text = images.Embed(EmbeddingGemma2MultimodalInput.FromText("a photo of a cat"), EmbeddingGemma2Prompt.Query);
- Pipeline (upstream, restated from decoded RGB). Aspect-preserving target size with sides that are multiples of 48 and at most 2,520 patches; PyTorch's uint8 antialiased bicubic resize, ported bit for bit (
EmbeddingGemma2ImageProcessor);x float32(1/255); 16x16 patches with (x, y) positions; the vision graph (16 layers, 3x3 pooling, projection to 512); the soft tokens replace the token embeddings of<|image>+ n x<|image|>+<image|>in the multimodal text graph; mean pooling over every token. - Interleaving.
EmbeddingGemma2MultimodalInput.Create(parts)takes strings and images in order; the text parts are concatenated with no separator and each image is expanded at its position. Text parts must not contain media placeholders. sentence-transformers'{"text": "... <|image|>", "image": img}becomesCreate("... ", img); text without a placeholder followed by images becomesCreate(text, img). - Graphs. Inputs with images run on the vision graph and the multimodal text graph (release
embeddinggemma-2-vision-onnx-r1); text-only inputs run on the released text graph and equalEmbeddingGemma2TextEmbedderbit for bit (it loads on the first text-only input). The multimodal graph also reproduces the released graph bit for bit on text-only input. - Limits. Images above 50 megapixels (
MaxImagePixels) throwEmbeddingGemma2ImageTooLargeException; inputs above 8,192 tokens after image expansion (about 29 images at 280 tokens) throwEmbeddingGemma2InputTooLongException. Both are checked before any inference. - Upstream conversion rules apply to whatever decoder you use: alpha dropped (not composited), grayscale replicated, palettes looked up, EXIF orientation not applied, 8 bits per channel (16-bit images are rejected by the SkiaSharp adapter; upstream turns them white).
- Budget. 280 soft tokens per image (the checkpoint's default);
MaxImageSoftTokensalso accepts 70, 140, 560 and 1,120 (experimental: proposed rows from sentence-transformers, within the protected bounds). - Memory and batching. One image per vision-graph call by default (
MaxVisionBatchSize = 1): on ONNX Runtime CUDA one 2,520-patch image needs about 610 MB of attention buffer per layer, and two did not fit in 5.5 GB. On CPU, vision batches equal single images bit for bit; raiseMaxVisionBatchSizeandMaxVisionBatchPatchesto trade memory for throughput. Each call is padded to its longest image (PadImagesToMaxPatches = false; upstream pads every image to 2,520 patches, which gives the same soft tokens on CPU and within 3.4e-5 on CUDA). - CUDA. The vision graph needs cuDNN 9 on the loader path (its
ReduceMaxruns through cuDNN); the three graphs take about 2.9 GB of GPU memory. - Speed (indicative, i7-5820K 12 threads; RTX 4060 Ti). Vision about 4.5 s per full-budget image on CPU, 0.23 s on CUDA; preprocessing about 1.5 to 2 ms for a photo and 5 ms for 4000x3000. The resize and the patch values run on AVX2 when the CPU has it and split the rows of large images over the thread pool; the bytes and values are the same on every path (integer resize, one float32 product per value).
Videos
var imageFiles = EmbeddingGemma2ModelAssets.OpenLocalImageAssets(); // same graphs as images
using var embedder = EmbeddingGemma2MultimodalEmbedder.Create(imageFiles);
// Every decoded frame (RGB24) plus the average frame rate and duration: the package samples as upstream.
EmbeddingGemma2Video video = EmbeddingGemma2Video.FromDecodedFrames(frames, framesPerSecond: 30, durationSeconds: 5);
float[] e = embedder.Embed(video); // a video alone, no prompt (the card)
float[] mixed = embedder.Embed(EmbeddingGemma2MultimodalInput.Create("The clip ", video, " shows moving shapes."));
// Or decode with the optional adapter on your own FFmpeg 8.x (Starlings.Models.EmbeddingGemma2.Video.FFmpeg):
// var clip = new EmbeddingGemma2VideoDecoder().DecodeFile("clip.mp4"); embedder.Embed(clip.Video);
- Frames in, three forms.
FromDecodedFrames(frames, fps, duration): every decoded frame with the timing torchcodec reports (packet count,max(pts + duration) - min(pts), frames / duration); only the sampled frames are read, soframesmay be a lazy list.FromSampledFrames(frames): 1 to 32 frames you sampled yourself, used as given (equal to the file only when they are upstream's frames).FromFramesWithoutTiming(frames): rejected by default withEmbeddingGemma2VideoTimingRequiredException;AllowVideosWithoutTiming = trueopts in to upstream's behaviour for an array without metadata (every frame, thinned to 32), which gives a different embedding than the same file (cosine 0.965 on a 5 s fixture clip). - Sampling (upstream, exact).
EmbeddingGemma2VideoSampling.SampleIndices:max(1, int(duration))candidates at 1 frame per second, candidatei= framemin(total - 1, int(i * fps)), more than 32 thinned likenp.linspace(..., dtype=int). Quirks kept for parity: a clip under 2 s gives one frame; sampling is by frame index from the average rate (variable frame rate samples frames, not seconds). - Per frame. The image preprocessing at 140 soft tokens (1,260 patches; same resize kernel; up to 8 frames preprocessed in parallel ahead of their vision calls,
EmbeddingGemma2ImageProcessor.Preprocess(frames, 140)for your own pipeline), the vision graph in calls of at mostMaxVideoFramesPerVisionCallframes (default 2, GPU-safe; on CPU frame batches equal single frames bit for bit), and<|image>+ n x<|video|>+<image|>per frame with no separator and no timestamps. A video costsframes x (n + 2)tokens, at most 4,544; inputs above 8,192 tokens are rejected before inference (two maximal videos do not fit). - Decoding. FFmpeg's default conversion is what upstream embeds (10-bit and odd sizes included); other converters move the embedding by up to 1.7e-2. Use the FFmpeg adapter (exact against torchcodec on the fixtures) or an equivalent FFmpeg call (
ffmpeg -i in.mp4 -f rawvideo -pix_fmt rgb24 -plus torchcodec-style metadata). - Speed (indicative). Vision about 2.7 s per frame on CPU (i7-5820K, 12 threads: a 32-frame video takes about 70 to 100 s) and about 0.07 s on CUDA (RTX 4060 Ti); prefer CUDA for video.
Memory on Linux
These apply to every profile on Linux.
- Heap trim on release (on by default). When a session's native memory is released (after
Disposeand the last in-flight run),Starlings.Runtime.Onnxcalls glibc'smalloc_trim(0), so a process that loads and unloads the model returns the freed memory instead of keeping it resident (text on the hosted runner: about 1,480 MiB after unloading without it, 400 to 500 MiB with it). It changes no allocator setting. Opt out per session withOnnxSessionOptions.TrimNativeHeapOnRelease = false, or for the whole process with theAppContextswitchStarlings.Runtime.Onnx.DisableNativeHeapTrim(details in theStarlings.Runtime.OnnxREADME). - No CPU memory arena on CPU (default). The package creates its CPU sessions with ONNX Runtime's CPU memory arena off (
OnnxSessionOptions.CpuMemoryArena,nullby default, means off here; set it totrueto restore the arena). With the arena, the loaded video embedder's resident memory rose by about 2.2 GB in 15 minutes on the hosted runner with one session kept loaded, and the arena's freed regions stayed resident in glibc's per-thread heaps after unloading; without it, the loaded footprint is about a third smaller (video about 2.7 GB instead of 3.9 GB, text 1.8 GB instead of 2.1 GB) and the one-hour hosted soaks of text and video passed in three qualification runs out of three (they failed before). Embeddings are bit-identical with and without the arena (a test checks it); warm latency changed by 1 to 2% on text and not measurably on video (development runs). Evidence: EmbeddingGemma 2 hosted soak. - Dedicated run threads on CPU (default). The package's CPU sessions run on the runtime's dedicated run threads (
OnnxSessionOptions.DedicatedRunThreads,nullby default, means on here; set it tofalseto run on the calling thread). Without the arena, each run's buffers are freed into the calling thread's glibc heap, which keeps up to 64 MiB of them resident; callers from the .NET thread pool rotate, and the hosted one-hour soaks of text and images failed intermittently as more and more heaps kept that memory (text: 3 to 7 heaps of about 19 MiB; images: 2 to 8 heaps of up to 59 MiB). On a fixed set of threads (at most one per processor, started only when all are busy) the same heaps are reused. Embeddings are bit-identical either way (a test checks it). Evidence: EmbeddingGemma 2 soak reliability. - Heap trims after load and after each run on the image and video path (CPU, default).
EmbeddingGemma2MultimodalEmbeddercreates its CPU sessions withOnnxSessionOptions.TrimNativeHeapAfterLoadandTrimNativeHeapAfterRunon (nullby default means on here; set them tofalseto turn them off). The text encoder does not use them. Without them, the loaded image embedder kept about 400 MiB freed during session creation in the main glibc heap, and 60 to 190 MiB of freed run buffers per run thread, varying from load to load and rising in steps over an hour. With them, the loaded footprint on the hosted runner is about 2.05 GB instead of 2.7 GB. Embeddings are bit-identical either way (a test checks it), and image request latency was unchanged on the hosted runner (p50 18.0 to 18.1 s with them, 18.0 to 18.3 s without, EPYC 7763). Evidence: EmbeddingGemma 2 image loaded soak. - Reused request buffers on the image and video path.
EmbeddingGemma2MultimodalEmbedderkeeps the large buffers of a request (resized pixels, patch values, the vision and multimodal graph inputs and outputs, soft tokens, resampler weight tables) in a pool it owns and reuses them for the next request; it releases them onDispose. Each request rents its buffers for its own use, so concurrent callers never share one, and the pool keeps only what concurrent requests used at the same time. Before, every image request allocated and freed several arrays on the .NET large object heap, which is not compacted, and its fragmentation moved the process's committed memory by 60 to 130 MiB over an hour. Managed allocation per request fell from about 11 MiB to 0.4 MiB, and peak resident memory for one caller was lower (2,871 MiB instead of 3,099 MiB in the same measurement). Embeddings are bit-identical (tests compare single, batched and concurrent requests with and without the pool, and the outputs with the code before the pool). Evidence: EmbeddingGemma 2 image loaded soak. - Transparent huge pages. The qualification soaks ran with
/sys/kernel/mm/transparent_hugepage/enabledset tomadvise(the Ubuntu default). On hosts set toalways, the kernel's khugepaged fills in partly used 2 MiB heap ranges, so resident memory can look larger and rise over time without any leak. Evidence: scheduled regression fix. - The Stable CPU profiles (
onnx-fp32-cpu,image-fp32-cpu,video-fp32-cpu) and the Stable CUDA text profile (onnx-fp32-cuda) need noMALLOC_*setting; their one-hour soaks ran with the defaults. The CUDA video profile (video-fp32-cuda) requiresMALLOC_MMAP_THRESHOLD_=65536(below).
Image and video on CUDA
Deployment requirement for embeddinggemma-2/video-fp32-cuda: set MALLOC_MMAP_THRESHOLD_=65536 in the environment of a Linux process that runs it. It is recommended for image-fp32-cuda too.
With default glibc settings, a process that loads and unloads the multimodal embedder repeatedly keeps about 0.7 to 0.8 GiB of freed native memory resident in glibc's main heap between loads, and that high-water mark creeps upward with each new peak (allocator retention, not a leak: malloc_trim returns it and the trimmed series is flat). In 12-minute CUDA soaks with the thread fix below, the default video run failed the soak's growth rule on the loaded series (316 MiB/h fitted); with MALLOC_MMAP_THRESHOLD_=65536 the image and video footprints were about half as large and flat. Device memory is returned at every unload, and the cuDNN, cuBLAS and driver mappings do not grow.
In a container whose CPU quota is below the host's CPU count, the session now uses .NET's container-aware processor count for its intra-op threads when none is set (ONNX Runtime's own default started one thread, and one malloc arena, per physical core of the host). Evidence: CUDA soak growth.
Status
Every profile of this package is Stable. On Linux x64 CPU: text (embeddinggemma-2/onnx-fp32-cpu) since 2026-10-15, images (image-fp32-cpu) since 2026-10-16 and videos (video-fp32-cpu) since 2026-10-17. On Linux x64 CUDA with an NVIDIA GeForce RTX 3090: text (onnx-fp32-cuda) and images (image-fp32-cuda) since 2026-10-16 and videos (video-fp32-cuda) since 2026-10-17. Each passed every qualification gate, G0 to G7. The weekly qualification workflow reruns the CPU profiles' G1 to G3 on the release sets and a one-hour soak. For text, G2 reads the reference embeddings committed under model-pipeline/protected/. For images and videos, G2 reads the accepted reference tensors hosted at Starlinghq/starling-release-references. Those are pinned by commit and SHA-256 in the release set's protected hosted-reference.json, and every array is checked against the set's tensors.json. GPU regression runs for every release (an ai-v* tag) and on demand, on an RTX 3090 only, in the qualification workflow's cuda (runpod) job: it reruns the CUDA tests, G1 to G3 on the release sets and a soak smoke test.
Videos were the last profiles promoted. Two blockers were fixed first. The hosted one-hour CPU video soak failed the growth rule in every run up to 2026-10-16 (about 280 MB/h). It has passed in every run since the library changes described under Memory on Linux: no CPU arena, dedicated run threads, heap trims after load and after each run, and reused request buffers (evidence). The release-set G2 failed on AVX-512 runners (token embeddings 1.83e-3 against 1e-3). The cause is the vision graph's Softmax kernels in ONNX Runtime (#89), and the PyTorch reference itself moves by up to 2.09e-3 between CPUs. The maintainer recalibrated that one intermediate bound to 4e-3 from the reference's own cross-CPU spread (#90); the final-embedding bound is unchanged. On CUDA, the first per-release run landed on an RTX 4090, outside the contract, and failed video G2 on the final embedding (1.009e-5 against 1e-5). The RTX 3090 runs pass (runs 39012176735 and 39023915026; evidence). Gate evidence: the catalog.
Text (onnx-fp32-cpu): release sets of 232 tokenizer rows (ids exact) and 696 embedding rows (no prompt, query and document; within 5.1e-7 of the PyTorch reference, binding bound 5e-6), MIRACL nDCG@10 0.8325; development fixtures of 138 rows up to 1,750 tokens (within 3.7e-7).
Images (image-fp32-cpu and image-fp32-cuda stable), Linux x64, from decoded RGB (42 protected rows: 28 images alone, 6 interleaved or prompted, 8 text queries): rendered ids exact; resized bytes, pixel values and positions bit-exact on the 28 supported images; embeddings within 2.3e-6 (CPU) and 1.0e-6 (CUDA) of the PyTorch reference, binding bound 1e-5, min cosine 0.9999995. Audio: unsupported. EmbeddingGemma2Capabilities.All lists every capability with its status.
Videos (video-fp32-cpu and video-fp32-cuda stable), Linux x64, from decoded RGB frames (35 protected rows: 22 videos alone, 6 interleaved or prompted, 2 input forms, 5 text queries; synthetic H.264, HEVC, VP9 and AV1 clips of 0.5 to 40 s): sampled indices exact (and on 20,849 upstream cases), rendered ids exact; decoded frames (FFmpeg adapter), resized frames, pixel values and positions bit-exact on all 32 video inputs; embeddings within 1.7e-6 (CPU) and 3.3e-6 (CUDA) of the PyTorch reference, binding bound 1e-5, min cosine 0.9999995. Frames without timing: rejected by default (upstream behaviour on opt-in reproduces its row within 1.2e-7). Timestamps, other sampling settings and audio tracks: unsupported.
Stable contract
This is the contract of profile embeddinggemma-2/onnx-fp32-cpu (text embeddings). Its Stable label (since 2026-10-15) commits to it under the support policy. The statuses are the registry manifest's and EmbeddingGemma2Capabilities.Profiles, which a test keeps equal key for key. Images and videos are the profiles of the contracts that follow.
| Item | Contract |
|---|---|
| Profile | embeddinggemma-2/onnx-fp32-cpu (registry manifest model-pipeline/registry/embeddinggemma-2/onnx-fp32-cpu/manifest.yaml). |
| Model | google/embeddinggemma-2 at 914f7f89142e33e77833254d9c9b90c3cef7303b. The text graph is Starling's float32 export (onnx/embeddinggemma2-text-fp32.onnx, digest in EmbeddingGemma2ModelAssets), downloaded with no token from the public repository Starlinghq/embeddinggemma-2-onnx at 92a02ae2. |
| Tokenizer | Starlings.Tokenizers 0.3.0, profile gemma-bpe-embeddinggemma2. <bos> and <eos> are added, and text is never truncated. |
| Runtime | ONNX Runtime 1.30.0 (the application adds Microsoft.ML.OnnxRuntime 1.30.0 CPU natives), fp32, .NET 10. |
| Supported platform | Linux x64, CPU. Gates G1 to G5 ran on an Intel Core i7-5820K (Haswell-E, 6 cores and 12 threads, AVX2 and FMA, no AVX-512), .NET 10.0.12. The weekly qualification reruns G1 to G3 on the release sets and a one-hour soak on GitHub-hosted ubuntu-latest x64 (4 logical CPUs; transparent huge pages madvise). No MALLOC_* environment setting is required for this profile. |
| Memory on Linux | The runtime calls malloc_trim(0) when a session is released, on by default. CPU sessions run without ONNX Runtime's CPU memory arena unless OnnxSessionOptions.CpuMemoryArena is set, and on the runtime's dedicated run threads unless OnnxSessionOptions.DedicatedRunThreads is set; outputs are the same. See Memory on Linux. |
| Input | Text or token ids. Prompts are explicit (EmbeddingGemma2Prompt: none, query or document) and never inserted. |
| Output | 768-dimensional float32 unit vectors (mean pooling over every attended token, then L2), or a Matryoshka size of 512, 256 or 128 (truncate, then normalize again). Other sizes are rejected. |
| Numerical bound | The protected tolerances of the profile (embedding max abs 5e-6, min cosine 0.9999999, against the PyTorch reference). Release set: 5.1e-7. The release set's reference embeddings are committed under model-pipeline/protected/ with the SHA-256 its reference.json records, so the weekly run evaluates G2 against the same file on any CPU. |
| Task quality | MIRACL dev, 8 languages: nDCG@10 at least 0.826 and MRR@10 at least 0.808 (budget); measured 0.8325 and 0.8136. |
| Supported | Embedding from text and from token ids; the owned tokenizer; no prompt and the query and document prompts; Matryoshka 512, 256 and 128; inputs up to 2,049 tokens; batch; cancellation; concurrent calls; explicit acquisition and anonymous graph download; Native AOT for the typed API and the Extensions.AI generator; Starlings.Models.EmbeddingGemma2.Extensions.AI (text generator, Matryoshka dimensions); Starlings.Models.EmbeddingGemma2.MLNet (text, row-wise and look-ahead batching). |
| Limits | 8,192 tokens, special and prompt tokens included; above that, EmbeddingGemma2InputTooLongException before inference. Inputs of 2,050 to 8,192 tokens run but are outside the Stable contract (below); temporary memory grows with the square of the length (one 8,192-token row took 80 s and a 5.9 GB process peak on the workstation). The text graph (1.08 GB) and tokenizer.json are acquired explicitly; inference never downloads. |
| Outside the Stable contract | Inputs of 2,050 to 8,192 tokens and the 18 other named task prompts: experimental (proposed rows, not yet accepted fixtures). CUDA: the onnx-fp32-cuda contract below. Images: the image-fp32-cpu contract below. Videos: the video-fp32-cpu contract below. Windows x64 CPU: experimental (CI builds, runs the weight-free tests and the clean-install drill without the model; no model run). macOS and ARM64: unsupported (no evidence). |
| Unsupported | inputs over 8,192 tokens, truncation, implicit prompt insertion, other Matryoshka sizes, audio, media placeholder tokens in text, pair input, ML.NET persistence and cancellation, the ML.NET adapter under Native AOT, streaming, TF32, bf16, fp16, quantized graphs, TensorRT, training. |
| Known issues | On hosts with transparent huge pages set to always, resident memory can grow over time with no leak behind it (Memory on Linux). The development tolerance file's export.token_embeddings bound (Python ONNX Runtime against PyTorch) reads differently judged per value (1.7e-2) and per case (6.2e-6, the reading the bound was set from); which reading binds is an open maintainer decision. Every .NET check passes either way, and the release set passed at 4.22e-6 relative. |
Stable contract: images
This is the contract of profile embeddinggemma-2/image-fp32-cpu (image and interleaved text-and-image embeddings). Its Stable label (since 2026-10-16) commits to it under the support policy. The statuses are the registry manifest's and EmbeddingGemma2Capabilities.Profiles, which a test keeps equal key for key.
| Item | Contract |
|---|---|
| Profile | embeddinggemma-2/image-fp32-cpu (registry manifest model-pipeline/registry/embeddinggemma-2/image-fp32-cpu/manifest.yaml). |
| Model | google/embeddinggemma-2 at 914f7f89142e33e77833254d9c9b90c3cef7303b. The vision graph and the multimodal text graph are Starling's float32 exports (digests in EmbeddingGemma2ModelAssets.ImageLock), downloaded with no token from the public repository Starlinghq/embeddinggemma-2-vision-onnx. Text-only inputs run on the text graph of the text contract. |
| Tokenizer | Starlings.Tokenizers 0.3.0, profile gemma-bpe-embeddinggemma2; each image is expanded to <|image> + 280 x <|image|> + <image|> at its position. |
| Runtime | ONNX Runtime 1.30.0 CPU natives, fp32, .NET 10. |
| Supported platform | Linux x64, CPU. Gates G1 to G5 ran on an Intel Core i7-5820K (Haswell-E, 6 cores and 12 threads, AVX2 and FMA, no AVX-512), .NET 10.0.12. The weekly qualification reruns G1 to G3 on the release sets and a one-hour soak on GitHub-hosted ubuntu-latest x64 (4 logical CPUs; transparent huge pages madvise). No MALLOC_* environment setting is required for this profile. |
| Memory on Linux | The runtime calls malloc_trim(0) when a session is released, on by default. CPU sessions run without ONNX Runtime's CPU memory arena unless OnnxSessionOptions.CpuMemoryArena is set, and on the runtime's dedicated run threads unless OnnxSessionOptions.DedicatedRunThreads is set. The image and video sessions also trim the native heap after load and after each run unless TrimNativeHeapAfterLoad or TrimNativeHeapAfterRun is set. Outputs are the same. See Memory on Linux. One full-budget image uses about 610 MB of attention buffer per vision layer; MaxVisionBatchSize is 1 by default. |
| Input | Decoded RGB images (EmbeddingGemma2Image.FromRgb24, or the SkiaSharp adapter for PNG and JPEG), alone or interleaved with text (EmbeddingGemma2MultimodalInput), several per input; text-only inputs; explicit prompts (none, query, document). Upstream's conversion rules apply: alpha dropped, grayscale replicated, palettes looked up, EXIF orientation not applied. |
| Output | 768-dimensional float32 unit vectors (mean pooling over every token, then L2), or a Matryoshka size of 512, 256 or 128. |
| Numerical bound | The protected tolerances of the profile: rendered ids, resized pixels, pixel values and positions exact; decoded RGB from the SkiaSharp adapter exact against PIL; embedding max abs 1e-5 and min cosine 0.9999995; soft tokens and token embeddings within 1e-3 row-relative; batches within 1e-5 of single inputs. Release set: embedding max abs 8.55e-7, soft tokens 8.68e-5 row-relative. The release set's reference tensors regenerate byte-identical only on the reference CPU, so the accepted arrays are hosted at Starlinghq/starling-release-references (commit and SHA-256 in the protected hosted-reference.json), and the evaluator checks every array against the protected tensors.json. |
| Task quality | image-retrieval-v1 (149 Commons images and their descriptions): nDCG@10 at least 0.916 and MRR@10 at least 0.893 (budget); measured 0.9222 and 0.9008, equal to the upstream reference. |
| Supported | Images alone and interleaved with text; several images per input; the query and document prompts; the default 280-token budget; batch; Matryoshka 512, 256 and 128; SkiaSharp decoding of PNG and JPEG; text-only inputs; cancellation; concurrent calls; anonymous graph download; Native AOT for the typed API from decoded RGB; Starlings.Models.EmbeddingGemma2.Extensions.AI (the multimodal generator). |
| Limits | 50,000,000 decoded pixels per image by default (MaxImagePixels, a memory bound; EmbeddingGemma2ImageTooLargeException) and 8,192 tokens after expansion (about 29 images; EmbeddingGemma2InputTooLongException), both checked before inference. The accepted release set has one 79 MP image; it passes G1 and G2 only with the limit raised, which is outside the contract (below). |
| Outside the Stable contract | Experimental: images above the default pixel limit with the limit raised; budgets of 70, 140, 560 and 1,120 soft tokens; GIF, BMP and WebP through the SkiaSharp adapter; EXIF orientation on opt-in; the SkiaSharp adapter under Native AOT. CUDA (image-fp32-cuda): the contract below. Windows x64: untested. macOS and ARM64: unsupported. |
| Unsupported | 16-bit-per-channel images (rejected; upstream renders them white), alpha compositing, GIFs with transparent pixels (rejected), other image formats in the adapter, inputs over 8,192 tokens, media placeholder tokens in text, audio, video (the video-fp32-cpu contract below), the ML.NET adapter (no image column), persistence, streaming, training. |
| Known issues | On hosts with transparent huge pages set to always, resident memory can grow over time with no leak behind it (Memory on Linux). One CPU architecture (AVX2) produced the reference; the C# resampler is integer arithmetic and machine-independent. |
Stable contract: videos
This is the contract of profile embeddinggemma-2/video-fp32-cpu (video and interleaved text, image and video embeddings). Its Stable label (since 2026-10-17) commits to it under the support policy. The statuses are the registry manifest's and EmbeddingGemma2Capabilities.Profiles, which a test keeps equal key for key.
| Item | Contract |
|---|---|
| Profile | embeddinggemma-2/video-fp32-cpu (registry manifest model-pipeline/registry/embeddinggemma-2/video-fp32-cpu/manifest.yaml). |
| Model | google/embeddinggemma-2 at 914f7f89142e33e77833254d9c9b90c3cef7303b, on the same graphs as the image contract (vision graph and multimodal text graph, digests in EmbeddingGemma2ModelAssets.ImageLock, public at Starlinghq/embeddinggemma-2-vision-onnx). Text-only inputs run on the text graph of the text contract. |
| Tokenizer | Starlings.Tokenizers 0.3.0, profile gemma-bpe-embeddinggemma2; each sampled frame becomes <\|image> + n x <\|video\|> + <image\|> (at most 140 soft tokens), frames concatenated with no separator and no timestamps. |
| Runtime | ONNX Runtime 1.30.0 CPU natives, fp32, .NET 10. |
| Supported platform | Linux x64 (x86-64), CPU. Gates G1 to G5 ran on an Intel Core i7-5820K (Haswell-E, AVX2 and FMA, no AVX-512), .NET 10.0.12. The weekly qualification reruns G1 to G3 on the release sets and a one-hour soak on GitHub-hosted ubuntu-latest x64 (4 logical CPUs; transparent huge pages madvise). Those runners are AVX2 (AMD EPYC 7763) or AVX-512 (Intel Xeon 8370C and 8573C, AMD EPYC 9V45/9V74) machines, and the contract covers both. On AVX-512, ONNX Runtime's Softmax kernels change the vision graph's soft tokens by about 2.6e-5 row-relative. The worst release row's token embeddings then reach 1.83e-3, within the 4e-3 bound the maintainer set from the reference's own cross-CPU spread (#89, #90). The final embedding stays within 5.72e-6 of the reference on every runner (bound 1e-5). No MALLOC_* environment setting is required for this profile. |
| Memory on Linux | As the image contract: malloc_trim(0) on session release, no CPU memory arena, dedicated run threads, and heap trims after load and after each run on the image and video path, each on by default with the same outputs either way (Memory on Linux). A video's frames run through the vision graph in calls of at most MaxVideoFramesPerVisionCall (default 2). |
| Input | Decoded 8-bit RGB frames with the average frame rate and duration (EmbeddingGemma2Video.FromDecodedFrames, or the FFmpeg adapters); the package then samples as upstream. Alone or interleaved with text and images (EmbeddingGemma2MultimodalInput), several videos per input; text-only inputs; explicit prompts (none, query, document). The checkpoint's settings only: 1 frame per second, at most 32 frames, 140 soft tokens per frame, no timestamps. |
| Decoding | Optional and user-supplied. Starlings.Models.EmbeddingGemma2.Video.FFmpeg loads your own FFmpeg 8.x shared libraries (libavcodec.so.62 and the others named in its README), and Starlings.Models.EmbeddingGemma2.Video.FFmpeg9 loads FFmpeg 9.x (libavcodec.so.63). Starling ships no FFmpeg. Use an LGPL build: GPL and nonfree builds are refused unless you opt in with AllowNonLgplBuild, and another FFmpeg major is a typed error. In the contract: FFmpeg n8.1.3 and n9.0.2 (BtbN LGPL shared builds, by SHA-256) on x86-64, whose metadata, sampled indices and every decoded frame equal torchcodec 0.17.0's on the fixture and release videos (G1 checks both majors). Other point releases are expected to decode the same but are not measured. Codec licensing (H.264, HEVC) is the deployer's responsibility; see the adapter READMEs. Any other decoder must reproduce FFmpeg's default RGB conversion, because other converters move the embedding by up to 1.7e-2. |
| Output | 768-dimensional float32 unit vectors (mean pooling over every token, then L2), or a Matryoshka size of 512, 256 or 128. |
| Numerical bound | The protected tolerances of the profile: sampled indices, rendered ids, decoded frames, resized frames, pixel values and positions exact; embedding max abs 1e-5 and min cosine 0.9999995; soft tokens within 1e-3 and token embeddings within 4e-3 row-relative (#90); batches within 1e-5 of single inputs. Release set: embedding max abs 1.29e-6, soft tokens 2.37e-4 row-relative (AVX2 reference machine); token embeddings 3.81e-4 on AVX2 and 1.83e-3 on AVX-512. The accepted reference tensors are hosted at Starlinghq/starling-release-references (commit and SHA-256 in the protected hosted-reference.json) and checked against the protected tensors.json. |
| Task quality | video-retrieval-v1 (50 Commons videos and their descriptions): nDCG@10 at least 0.797 and MRR@10 at least 0.751 (budget); measured 0.8126 and 0.7714, equal to the upstream reference. |
| Supported | Videos alone and interleaved with text and images; several videos per input; decoded frames with timing; the query and document prompts; batch; Matryoshka 512, 256 and 128; decoding through the FFmpeg 8 and FFmpeg 9 adapters (rotation 90 included); images and text-only inputs; cancellation; concurrent calls; anonymous graph download; Native AOT for the typed API from decoded frames; Starlings.Models.EmbeddingGemma2.Extensions.AI (the multimodal generator). |
| Limits | At most 32 frames per video and 8,192 tokens per input after expansion (one 32-frame video is 4,544 tokens; two do not fit; EmbeddingGemma2InputTooLongException); 50,000,000 decoded pixels per frame (EmbeddingGemma2ImageTooLargeException); both checked before inference. CPU video embedding is slow: about 2.7 s per frame on the i7-5820K (a 32-frame video takes 70 to 100 s); prefer CUDA for volume. |
| Outside the Stable contract | Experimental: pre-sampled frames (FromSampledFrames, up to 32 frames used as given; equal to the file only when they are upstream's frames); frames without timing on opt-in (AllowVideosWithoutTiming, upstream's behaviour, which differs from the file); variable frame rate, interlaced and HDR video and display rotations other than 90 (proposed edge-case rows); decoding from streams and memory (adapter tests only); the FFmpeg adapters under Native AOT. Untested: ARM64 and x86-64 CPUs without AVX2 (swscale's SIMD paths may differ by a level). CUDA (video-fp32-cuda): the contract below. Windows x64: untested. macOS: unsupported. |
| Unsupported | Frames without timing by default (EmbeddingGemma2VideoTimingRequiredException), timestamps and other sampling settings, audio tracks (ignored, as upstream), FFmpeg majors other than 8 and 9, inputs over 8,192 tokens, media placeholder tokens in text, audio, the ML.NET adapter (no video column), persistence, streaming, training. |
| Known issues | Sampled frames follow torchcodec's seek-based decoding, including the decoder state after a seek: on the Ogg Theora release video commons-video-02 the frame after a seek differs from a sequential decode, and it depends on FFmpeg frame threading (the adapter's DecoderThreads default equals upstream's). On hosts with transparent huge pages set to always, resident memory can grow over time with no leak behind it (Memory on Linux). |
Stable contract: CUDA
These are the contracts of profiles embeddinggemma-2/onnx-fp32-cuda (text) and embeddinggemma-2/image-fp32-cuda (images), Stable since 2026-10-16, and embeddinggemma-2/video-fp32-cuda (videos), Stable since 2026-10-17. Each is its CPU contract above, with these differences. The statuses are the registry manifests' and EmbeddingGemma2Capabilities.Profiles, which a test keeps equal key for key.
| Item | Contract |
|---|---|
| Profiles | embeddinggemma-2/onnx-fp32-cuda, embeddinggemma-2/image-fp32-cuda and embeddinggemma-2/video-fp32-cuda (registry manifests under model-pipeline/registry/embeddinggemma-2/). The same models, graphs and tokenizer as the CPU profiles. |
| Runtime | ONNX Runtime 1.30.0 with the CUDA execution provider (the application adds Microsoft.ML.OnnxRuntime.Gpu.Linux 1.30.0 instead of the CPU natives), use_tf32=0, fp32. The CUDA 13 runtime and cuDNN 9 must be on the loader path (the vision graph's ReduceMax runs through cuDNN); the package does not ship them. |
| Supported platform | Linux x64 with an NVIDIA GeForce RTX 3090 (Ampere), driver 580 or later. G1 to G3 on the release sets, the binding G4 one-hour soaks and G5 ran on RTX 3090s. Regression: the per-release GPU run (the qualification workflow's cuda (runpod) job, for every ai-v* tag and on demand) reruns the CUDA tests, G1 to G3 on the release sets and a soak smoke test, on an RTX 3090 only; the job refuses any other GPU. The RTX 4090 (Ada) is outside the contract: in run 38857860186 its video G2 failed on the final embedding (max abs 1.009e-5 against the unchanged 1e-5 bound, where the RTX 3090 measures 2.77e-6; its token embeddings, 3.34e-3, are within the 4e-3 bound of #90, so the final-embedding bound is the one it misses). Other GPUs are untested and outside the contract. |
| Memory on Linux | Text: no MALLOC_* setting is required. Images: MALLOC_MMAP_THRESHOLD_=65536 is recommended, not required (Image and video on CUDA); the G4 soak and the per-release soak smoke test ran without it. Videos: MALLOC_MMAP_THRESHOLD_=65536 is required in the environment of a Linux process that runs the profile; the G4 soak and the per-release soak smoke test ran with it (without it a process that loads and unloads the embedder failed the growth rule at 316 MiB/h). One full-budget image needs about 610 MB of GPU attention buffer per vision layer; the three graphs take about 2.9 GB of GPU memory. |
| Cancellation | A CUDA run is never terminated mid-graph: it completes, then the call throws OperationCanceledException (#61). Latency is one chunk (at most MaxBatchSize rows, default 16, and MaxBatchTokens padded tokens, default 8,192): up to about 1.2 s for text (lower MaxBatchSize or MaxBatchTokens for faster cancellation), and one vision or text run for images and videos (a video's frames run in calls of at most MaxVideoFramesPerVisionCall, default 2). |
| Numerical bound | Each CUDA profile's protected tolerances. Text release set: embedding max abs 8.6e-7 (bound 5e-6), C# against Python ONNX Runtime CUDA 2.5e-7. Image release set: embedding max abs 2.16e-6 (bound 1e-5), token embeddings 6.8e-5 row-relative (1e-3). Video release set (RTX 3090): embedding max abs 2.77e-6 (bound 1e-5), soft tokens 2.50e-4 (1e-3) and token embeddings 7.97e-4 row-relative (4e-3), in the binding round and again in per-release runs 39012176735 and 39023915026. |
| Task quality | Text, MIRACL: nDCG@10 0.8325, MRR@10 0.8136 (budget 0.826 and 0.808). Images, image-retrieval-v1: nDCG@10 0.9222, MRR@10 0.9008 (budget 0.916 and 0.893). Videos, video-retrieval-v1: nDCG@10 0.8126, MRR@10 0.7714 (budget 0.797 and 0.751). |
| Performance | G5 on an RTX 3090: text warm latency 0.414 to 1.095 of the Python ONNX Runtime CUDA run (budget 1.10); images 0.785 to 1.029, preprocessing 1.2 to 3.8% of the embedding time (budget 5%); videos 0.710 to 0.885, preprocessing 1.2 to 2.5% (budget 5%). |
| Supported | As in the CPU contracts, over CUDA sessions: text embedding from text and token ids, prompts none, query and document, Matryoshka, inputs up to 2,049 tokens, batch, cancellation, concurrent calls, Starlings.Models.EmbeddingGemma2.Extensions.AI (text generator) and Starlings.Models.EmbeddingGemma2.MLNet over CUDA; images alone and interleaved, several per input, prompts, the 280-token budget, batch, Matryoshka, PNG and JPEG decoding, text-only inputs, cancellation, concurrent calls; videos as in the video contract (decoding on the CPU through the FFmpeg 8 and 9 adapters). |
| Outside the Stable contract | Experimental: Native AOT with the CUDA natives (one local run, tools/aot-check-ai.sh --cuda, not in the per-release run); the multimodal IEmbeddingGenerator over CUDA, for images and videos (its test needs the video fixture set, which the per-release GPU pod does not have, so it is skipped there); and the rows that are experimental on CPU. Windows x64 CUDA: untested. |
| Per-release coverage of videos | The CUDA video parity tests (development fixtures) also need the video fixture set and are skipped on the per-release pod. The per-release regression of video-fp32-cuda is the release set's G1 (both FFmpeg decoder checks) and G2, G3 on video-retrieval-v1, and the soak smoke test with MALLOC_MMAP_THRESHOLD_=65536. |
Evidence: binding CUDA G4 and G5 round, per-release GPU regression, run 38857860186, per-release GPU regression for videos, runs 39012176735 and 39023915026, release-set gates for text, images and videos, CUDA cancellation.
Qualification evidence
- G0 provenance: the 2026-10-14 provenance check.
- G1, G2 and G3 on the P-030 release sets: text, images, videos.
- G4 one-hour soak: text, 2026-10-14; images and videos in the 2026-10-15 round below. G5 matched benchmark: 2026-10-15.
- G6 distribution and G7 integration: G6, G7.
- Regression support: the weekly qualification workflow (jobs
release-gatesandsoak): text green in run 38822625245; images and text green (release gates and soak) in run 38848321624; videos green (release gates, both FFmpeg decoder checks, and the one-hour soak) in run 39023915026 (evidence). CUDA: per-release GPU regression run 38857860186 (the qualification workflow'scuda (runpod)job).
License and usage policy
The package is MIT OR Apache-2.0; it includes a port of PyTorch's resize kernel (BSD-3-Clause, THIRD-PARTY-NOTICES.md). The model weights, and Starling's ONNX graphs derived from them, are licensed under the Apache License 2.0 by Google DeepMind (model card). The model card also states:
Deployments must adhere to the Gemma Prohibited Use Policy.
The text graph contains only the text path (embedding, per-layer embeddings, 24 layers, final norm, 512-to-768 projection); the vision graph only the vision tower, pooling and embed_vision; the multimodal text graph is the text graph with two inputs for soft tokens. All are converted to float32 and exported to ONNX; the release notices list the modifications.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Starlings.Acquisition (= 0.3.0)
- Starlings.Runtime.Onnx (= 0.3.0)
- Starlings.Tokenizers (= 0.3.0)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on Starlings.Models.EmbeddingGemma2:
| Package | Downloads |
|---|---|
|
Starlings.Models.EmbeddingGemma2.Extensions.AI
Microsoft.Extensions.AI IEmbeddingGenerator<string, Embedding<float>> over the EmbeddingGemma 2 text embedder (Starlings.Models.EmbeddingGemma2): explicit named prompts, Dimensions mapped to the Matryoshka sizes 768/512/256/128 (others rejected), batching, usage, node-boundary cancellation, model metadata and DI registration. Images and videos: IEmbeddingGenerator over DataContent and over content lists (text, image and video parts), with image and video decoder hooks (no decoder or native dependency of its own). Deployments must adhere to the Gemma Prohibited Use Policy. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry. |
|
|
Starlings.Models.EmbeddingGemma2.MLNet
ML.NET estimator and transformer for the EmbeddingGemma 2 text embedder (Starlings.Models.EmbeddingGemma2): a text column to a fixed-size Vector<Single, 768/512/256/128> embedding column and an optional token-count column, one inference per row however many getters are requested, explicit prompts and optional look-ahead batching. Text only. Pipeline composition only: saving the transformer is unsupported (it throws); the model is resolved from its asset lock at run time. Deployments must adhere to the Gemma Prohibited Use Policy. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry. |
|
|
Starlings.Models.EmbeddingGemma2.Imaging.SkiaSharp
Decodes image files and streams (PNG, JPEG, GIF, BMP and WebP experimental; GIF with transparency rejected) with SkiaSharp into Starlings.Models.EmbeddingGemma2 images, reproducing PIL's convert("RGB") as the upstream processor sees it: alpha dropped (not composited), grayscale and palettes expanded, CMYK converted, no colour management, EXIF orientation ignored unless explicitly applied (a documented deviation from upstream). Images with 16 bits per channel are rejected (upstream saturates them to white). Decoded size limit 50 megapixels by default. Brings SkiaSharp (MIT) and its Linux natives (SkiaSharp.NativeAssets.Linux.NoDependencies), whose bundled third-party notices include an MPL-1.1 GIF decoder and the Adobe DNG SDK license. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry. |
|
|
Starlings.Models.EmbeddingGemma2.Video.FFmpeg9
The FFmpeg 9 counterpart of Starlings.Models.EmbeddingGemma2.Video.FFmpeg: decodes video files and streams into Starlings.Models.EmbeddingGemma2 videos the way upstream does (torchcodec 0.17 on FFmpeg): torchcodec's packet-scan metadata, upstream's 1 frame per second sampling (at most 32 frames), the display matrix applied, and FFmpeg's default RGB conversion, so the decoded RGB equals torchcodec's bit for bit on the same FFmpeg major (tested on 22 fixture videos with FFmpeg 9.0.1, x86-64). Ships NO FFmpeg binaries: it loads the user's own FFmpeg 9.x shared libraries at run time through its own bindings, generated from the FFmpeg 9.0.1 headers; an LGPL build is expected and GPL or nonfree builds are rejected unless explicitly allowed. Codec licensing (H.264 and HEVC patent pools; VP9 and AV1 offered royalty-free) is the deployer's responsibility; see the README. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry. |
|
|
Starlings.Models.EmbeddingGemma2.Video.FFmpeg
Decodes video files and streams into Starlings.Models.EmbeddingGemma2 videos the way upstream does (torchcodec 0.17 on FFmpeg): torchcodec's packet-scan metadata, upstream's 1 frame per second sampling (at most 32 frames), the display matrix applied, and FFmpeg's default RGB conversion (swscale or filter graph, as torchcodec calls them), so the decoded RGB equals torchcodec's bit for bit on the same FFmpeg major (tested on 22 fixture videos with FFmpeg 8.1, x86-64). Ships NO FFmpeg binaries: it loads the user's own FFmpeg 8.x shared libraries at run time through its own bindings, generated from the FFmpeg 8.1 headers; an LGPL build is expected and GPL or nonfree builds are rejected unless explicitly allowed. Codec licensing (H.264 and HEVC patent pools; VP9 and AV1 offered royalty-free) is the deployer's responsibility; see the README. Maturity is per model profile (Stable, Preview or Experimental): see the README, generated from the model registry. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.0 | 141 | 10/19/2026 |
| 0.2.0 | 177 | 10/17/2026 |
| 0.1.0-preview.6 | 107 | 10/14/2026 |