Views
No views yet


jina-v5-omni-nano and jina-v5-omni-small define the open-weight frontier (Table 1 in the ArXiv report).
jina-embeddings-v5-omni-nano-classification is a multimodal embedding model that accepts text, images, video, and audio and produces embeddings in a shared vector space aligned with the text-only jinaai/jina-embeddings-v5-text-nano-classification — so you can index with text and query with any modality, no reindexing. For higher performance at a larger size, see jinaai/jina-embeddings-v5-omni-small-classification.jina-embeddings-v5-omni-nano family. The combined repo containing all task adapters is jinaai/jina-embeddings-v5-omni-nano.| Feature | Value |
|---|---|
| Parameters | ~0.95B |
| Embedding Dimension | 768 |
| Supported Tasks | classification |
| Max Sequence Length | 8192 |
| Pooling Strategy | Last-token |
| Supported Inputs | text, image, video, audio |
| Supported File Types | images: .jpg, .jpeg, .png, .gif, .webp, .bmp, .tif, .tiff, .avif, .heic, .svg; video: .mp4, .avi, .mov, .mkv, .webm, .flv, .wmv; audio: .wav, .mp3, .flac, .ogg, .m4a, .opus; documents: .pdf |
1# Retrieve the configuration of the preconfigured omni-nano inference endpoint
2GET /_inference/embedding/.jina-embeddings-v5-omni-nano
3
4# Generate an embedding for a single piece of text using the predefined endpoint
5POST _inference/embedding/.jina-embeddings-v5-omni-nano
6{
7 "input": [
8 "This is a test"
9 ]
10}
11
12# Fuse a text description and an image into a single embedding via a multimodal content block
13POST _inference/embedding/.jina-embeddings-v5-omni-nano
14{
15 "input": [
16 {
17 "content": [
18 { "type": "text", "value": "A small blue square" },
19 { "type": "image", "format": "base64", "value": "<BASE64_IMAGE_DATA>" }
20 ]
21 }
22 ]
23}
24
25# Create a custom endpoint that truncates omni-nano embeddings to 32 dimensions
26PUT _inference/embedding/jina-omni-nano-32d
27{
28 "service": "elastic",
29 "service_settings": {
30 "model_id": "jina-embeddings-v5-omni-nano",
31 "dimensions": 32
32 }
33}1# core
2pip install transformers torch pillow numpy
3
4# Optional — install only the extras for the modalities you actually use:
5pip install librosa soundfile # audio decoding
6pip install torchcodec # video decoding for proc(videos=path) (transformers default backend)
7pip install av # video decoding for SentenceTransformer model.encode("clip.mp4")
8pip install pdf2image pypdfium2 # PDF rendering
9pip install cairosvg pillow # SVG rendering
10pip install "vllm==0.20.1" # high-throughput serving (validated)
11pip install sentence-transformers # one-call multimodal API1from PIL import Image
2import librosa, torch
3from transformers import AutoModel, AutoProcessor, WhisperFeatureExtractor
4
5repo = "jinaai/jina-embeddings-v5-omni-nano-classification"
6model = AutoModel.from_pretrained(repo, trust_remote_code=True).eval()
7proc = AutoProcessor.from_pretrained(repo, trust_remote_code=True)
8
9# model.embed(**inputs) returns L2-normalized last-token embeddings.
10t_vec = model.embed(**proc(text="Document: A cute cat sitting on a mat.", return_tensors="pt").to(model.device))
11i_vec = model.embed(**proc(images=Image.open("photo.jpg"), text="<image>", return_tensors="pt").to(model.device))
12v_vec = model.embed(**proc(videos="clip.mp4", text="<image>", return_tensors="pt").to(model.device))
13# Needs torchcodec or torchvision. On Windows or envs without either, use model.encode("clip.mp4") from the sentence-transformers section below (av-only, no codec libs required).
14
15# Audio has no string placeholder — build the prompt from config. Size the
16# audio run from the REAL Whisper frame mask: the feature extractor pads every
17# clip out to the 30s window, so counting padded frames emits 750 audio tokens
18# for a 2s clip and a 30s clip alike, which is not how the model was trained.
19# (The sentence-transformers path below does all of this for you.)
20audio, _ = librosa.load("speech.wav", sr=16000)
21feats = WhisperFeatureExtractor(feature_size=128)(
22 audio, sampling_rate=16000, return_tensors="pt",
23 padding="max_length", return_attention_mask=True,
24)
25feat, feat_mask = feats["input_features"], feats["attention_mask"]
26real = int(feat_mask.sum()) # unpadded mel frames
27n = ((real - 1) // 2 + 1 - 2) // 2 + 1 # audio encoder output length
28cfg, tok = model.config, proc.tokenizer
29audio_run = (tok.convert_ids_to_tokens(cfg.audio_start_token_id)
30 + tok.convert_ids_to_tokens(cfg.audio_token_id) * n
31 + tok.convert_ids_to_tokens(cfg.audio_end_token_id))
32prompt = tok.apply_chat_template([{"role": "user", "content": audio_run}],
33 tokenize=False, add_generation_prompt=False)
34ids = torch.tensor([tok(prompt)["input_ids"]]) # keep the tokenizer's specials
35a_vec = model.embed(
36 input_ids=ids.to(model.device),
37 attention_mask=torch.ones_like(ids).to(model.device),
38 input_features=feat.to(model.device, dtype=next(model.parameters()).dtype),
39 feature_attention_mask=feat_mask.to(model.device),
40)Document: text prefix. The raw model.embed(...) path above explicitly prepends "Document: " to the text input, and via sentence-transformers (below) the same intent is expressed with the encode_document() helper. The vLLM path also expects the "Document: " prefix in the prompt string. Calling encode(text) (or embed(...)) on raw text without the prefix is off-distribution for this model.dtype, device, min_pixels, or custom pooling code needed — sensible defaults live in the model config (bf16 weights, 256–1280 vision tokens).transformers>=5.0 — the multimodal processor (image / video / audio) requires transformers 5.x; text-only also works on >=4.57torch>=2.5sentence-transformers — one-call API for all 4 modalitieslibrosa — audio decodingtorchcodec (or torchvision) — video decoding when calling proc(videos=…) directly (transformers' video processor selects torchcodec by default, falling back to torchvision)av — video decoding via model.encode("clip.mp4") (SentenceTransformer path); in-memory np.ndarray frames need no decodervllm==0.20.1 — high-throughput serving; H100 deployments may also need DeepGEMM installed for vLLM FP8 kernels1from transformers import AutoModel
2
3AutoModel.from_pretrained("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True, modality="omni") # all (default)
4AutoModel.from_pretrained("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True, modality="vision") # vision + text
5AutoModel.from_pretrained("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True, modality="audio") # audio + text
6AutoModel.from_pretrained("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True, modality="text") # text onlysentence-transformers:SentenceTransformer("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True, model_kwargs={"modality": "vision"})1from sentence_transformers import SentenceTransformer
2
3model = SentenceTransformer("jinaai/jina-embeddings-v5-omni-nano-classification", trust_remote_code=True)
4
5# URLs, local paths (with or without extension), PIL.Image, np.ndarray,
6# torch.Tensor, bytes, and BytesIO are all accepted directly.
7t_vec = model.encode_document("A cute cat sitting on a mat.")
8i_vec = model.encode("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg")
9v_vec = model.encode("https://huggingface.co/datasets/raushan-testing-hf/videos-test/resolve/main/sample_demo_1.mp4") # needs `pip install av`
10a_vec = model.encode("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac") # needs `pip install librosa soundfile`
11
12# Fused multimodal — a tuple becomes ONE embedding in a single forward pass:
13emb = model.encode(("Winter boots, waterproof leather upper",
14 "https://.../boot.jpg"))dtype, device, min_pixels, or custom pooling code needed — sensible defaults live in the model config (bf16 weights, 256–1280 vision tokens).model.encode(("narration.wav", "clip.mp4"))..mp4 .avi .mov .mkv .webm .flv .wmv, or extensionless — content-sniffed), HTTP(S) URL, bytes/io.BytesIO, and in-memory np.ndarray / torch.Tensor of shape (T, H, W, 3|4) with dtype uint8. In-memory frames go straight to the processor — no MP4 round-trip, no extra decoder.1import numpy as np
2# (T, H, W, 3) uint8 — e.g. from decord, imageio, or an rgb frame buffer
3frames = np.zeros((16, 224, 224, 3), dtype=np.uint8)
4v_vec = model.encode(frames)vllm==0.20.1. The model card already provides the pooling config, so no custom PoolerConfig is needed.1from vllm import LLM
2llm = LLM(
3 model="jinaai/jina-embeddings-v5-omni-nano-classification",
4 runner="pooling",
5 trust_remote_code=True,
6)
7outs = llm.embed([{"prompt": "Document: A cute cat sitting on a mat."}])vllm serve jinaai/jina-embeddings-v5-omni-nano-classification --trust-remote-code.1# transformers
2vec = model.embed(truncate_dim=256, **proc(text="hello", return_tensors="pt"))
3# or
4vec = model.encode(["hello"], task="retrieval", truncate_dim=256)
5
6# sentence-transformers
7vec = model.encode("hello", truncate_dim=256)
8
9# vLLM — ask the pooler for a smaller embedding
10from vllm import PoolingParams
11outs = llm.embed(prompts, pooling_params=PoolingParams(dimensions=256))
12# or truncate + renormalize the full-dim output yourself:
13import numpy as np
14full = np.asarray(outs[0].outputs.embedding)
15vec = full[:256] / np.linalg.norm(full[:256])1# sentence-transformers — any modality
2t_vecs = model.encode(["query 1", "query 2"])
3i_vecs = model.encode([Image.open("a.jpg"), Image.open("b.jpg")])
4v_vecs = model.encode(["clip1.mp4", "clip2.mp4"])
5a_vecs = model.encode(["speech1.wav", "speech2.wav"])
6
7# raw transformers — text (native padded batch)
8inputs = proc(text=["query 1", "query 2"], padding=True, truncation=True, return_tensors="pt").to(model.device)
9vecs = model.embed(**inputs) # (2, dim)
10
11# vLLM — list of request dicts, any modality
12outs = llm.embed([
13 {"prompt": "query 1"},
14 {"prompt": "query 2"},
15])sentence-transformers, images / video / audio are forwarded per-sample (one forward pass each). Text is truly batched. For large-scale multimodal throughput, prefer vLLM.jinaai/jina-embeddings-v5-text-nano-classification — text-onlyjinaai/jina-embeddings-v5-text-nano (via matching adapter)v5-text-nano model and query it with image,
video, or audio embeddings from jina-embeddings-v5-omni-nano-classification — no reindexing.