siglipSeqLen top-level constant
SigLIP2's fixed context width and pad id, both taken from the model's own
tokenizer.json, which bakes them in:
"padding": {"strategy": {"Fixed": 64}, "direction": "Right",
"pad_id": 0, "pad_token": "<pad>"}
The width has to live in the ids. The int8 export reads as DYNAMIC-shape
(OrtIoSpec.staticSeqLen == null), so the forward pass never pads, and the
graph carries NO attention_mask. Worse, the head does not pool over the
sequence at all — Siglip2TextModel takes last_hidden_state[:, -1, :]
("the last token's hidden state, which may be padding", upstream's own
comment). With right-padding the pooled vector therefore IS the pad
position, which is why the pad id is first-order: measured against a correct
vector, padding with 1 instead of 0 gives cosine 0.81-0.90 and reorders
retrieval; not padding at all gives 0.58-0.69.
SigLIP 2 only. SigLIP 1 is a different tokenizer entirely (T5 Unigram,
32k vocab, pad = </s> = 1); SigLIP 2 uses the Gemma BPE tokenizer (256k,
<pad> = 0, <eos> = 1). Pointing this profile at a SigLIP 1 file
silently produces wrong vectors.
Implementation
const int siglipSeqLen = 64;