CoolFace
Modelpublic

satorean/jina-clip-v2-split-onnx

sourceHugging Facecc-by-nc-4.0updated 16d agoView on Hugging Face
0likes
Model Card

Jina CLIP v2 split ONNX

Independent text and vision ONNX encoders derived from `jinaai/jina-clip-v2`.

FilePrecisionSizeInput
jina-clip-v2-text-fp16.onnxFP161.12 GBinput_ids: int64 [batch, sequence]
jina-clip-v2-text-fp32.onnx (+.data)FP322.24 GBinput_ids: int64 [batch, sequence]
jina-clip-v2-text-int8.onnxDynamic INT8564 MBinput_ids: int64 [batch, sequence]
jina-clip-v2-vision-fp16.onnxFP16610 MBpixel_values: float32 [batch, 3, 512, 512]
jina-clip-v2-vision-fp32.onnx (+.data)FP321.22 GBpixel_values: float32 [batch, 3, 512, 512]
jina-clip-v2-vision-int8.onnxDynamic INT8313 MBpixel_values: float32 [batch, 3, 512, 512]

Every model is self-contained (FP32 uses an external-data companion file), supports dynamic batch sizes, and returns normalized float32 embeddings named embeddings with shape [batch, 1024]. The text models also support dynamic sequence lengths.

Which runtime should I use?

Measured on RTX 2070 (sm_75) unless noted. Full methodology: GitHub results.md.

scenariowhat to usemeasured
GPU, Turing (sm_75) or newer, fastestTensorRT engine built from the FP16 text graph via this repo's scripts/build_trt_engine.pyb1×1024 25 ms, b32×1024 0.80 s, flat ~3 GiB VRAM
GPU via ONNX RuntimeFP16 models (text: apply the Einsum→MatMul rewrite first — −25%)b1×1024 76–97 ms, b32×1024 2.4–2.6 s
GPU, portable PyTorch, long contextfp16 torch + `sdpa_patch.py`b32×1024 1.70 s, flat ~2.65 GB
CPUdynamic INT8 modelstext b8x128 tokens 0.74 s vs 3.14 s FP16 (i9-7980XE, ORT 1.29)

Notes:

  • TensorRT fuses each attention layer into a single flash-attention-style kernel (_gemm_mha_v2) with linear memory; engines are hardware-specific and bound to the built optimization profile (default [1,8]..[32,2048]; pad shorter sequences with pad-token id 1, which the internal mask makes semantically neutral). GTX 1080 Ti / Pascal cannot run TensorRT 10+ — use ONNX Runtime there.
  • FP16 ONNX is not recommended for CPU inference: CPU providers promote unsupported FP16 ops or insert casts, increasing latency and memory.

Preprocessing and inference

Use the tokenizer and image processor from the base model:

python
import onnxruntime as ort
from transformers import AutoImageProcessor, AutoTokenizer

base_model = "jinaai/jina-clip-v2"
tokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)
image_processor = AutoImageProcessor.from_pretrained(base_model, trust_remote_code=True)

text_session = ort.InferenceSession("jina-clip-v2-text-int8.onnx")
tokens = tokenizer(["A photo of a cat"], padding=True, truncation=True, return_tensors="np")
text_embeddings = text_session.run(["embeddings"], {"input_ids": tokens.input_ids})[0]

# `images` is a list of PIL images.
vision_session = ort.InferenceSession("jina-clip-v2-vision-int8.onnx")
pixels = image_processor(images=images, return_tensors="np").pixel_values
image_embeddings = vision_session.run(["embeddings"], {"pixel_values": pixels})[0]

Matryoshka dimensions

The trained dimensions are 32, 64, 128, 256, 512, 768, and 1024. To reproduce the base model's truncate_dim=N behavior, truncate the prefix and normalize it again:

python
import numpy as np

embedding = embedding[:, :dimension]
embedding /= np.linalg.norm(embedding, axis=1, keepdims=True)

Validation

Both INT8 graphs were re-quantized on 2026-09-01 with per-channel weight scales and ORT's reduce_range; the artifacts published before that date were per-tensor and are not faithful — a single caption embedded at mean cosine 0.70 to the base model. If you cached the earlier files, re-download them.

The text encoder is scored on 424 real captions against ground-truth PyTorch fp32, on two metrics, because neither catches the other's failure mode: per-vector cosine is absolute and per-document, retrieval ranking is relative and cross-document, and this export has shipped a build that passed each while failing the other.

DimensionMean cosineWorst captionRanking
640.99290.9699OK
1280.98990.9694OK
2560.98660.9639OK
5120.98460.9597OK
7680.98390.9589OK
10240.98380.9586OK

The FP16 and FP32 graphs score 1.0000 on the same check. Ranking is a 20-profile retrieval fixture in which the mean-pooled vectors of 4 relevant profiles must outrank 16 irrelevant ones; dim=32 ranks wrongly for every build including FP16 and is a property of that fixture, not of any encoder. Reproduce with jina-clip-verify --text-model <graph> from the GitHub repository.

Vision INT8 scores mean cosine 0.9874 (worst 0.9831) at 512 dimensions and 0.9855 (worst 0.9809) at 1024 against the FP16 vision graph on synthetic structured images; a real-image vision gate is still open.

INT8 CPU performance

ONNX Runtime 1.29, Intel i9-7980XE, ORT_ENABLE_BASIC, mean of 5 runs:

ShapeINT8FP16
b1x1280.13 s0.53 s
b8x1280.74 s3.14 s
b8x5123.53 s12.48 s

Peak resident memory: 2.6 GiB INT8 vs 5.0 GiB FP16. The text input remains dynamic up to 8192 tokens, although ordinary full attention still has quadratic memory use; the TensorRT path removes that quadratic term on supported GPUs.

License and attribution

This is a quantized and structurally split derivative of jinaai/jina-clip-v2. It retains the base model's CC BY-NC 4.0 license and non-commercial restriction. Refer to the base model card for intended use, limitations, training details, and complete attribution.