NEWVectors or files. Pick a path.Start →
    Embeddings
    7 min read
    Updated 2026-11-11

    Why Are My SigLIP 2 Search Results So Bad? Text Padding and Lowercasing, Measured

    SigLIP 2 needs query text padded to 64 tokens and lowercased, as it was trained. Unpadded queries scored 0.74% recall@1 on Flickr30k in our run; padded, 73.86%; padded and lowercased, 79.32% against the paper's 80.7%. Why padding silently fails on fixed-resolution checkpoints, and how to fix it.

    Ethan Steininger
    By , Founder & CEO, Mixpeek
    SigLIP 2
    Embedding Models
    Text-to-Image Search
    Hugging Face
    Benchmark
    Troubleshooting

    Why are my SigLIP 2 text-to-image search results so bad?



    Almost always because the query text is not prepared the way SigLIP 2 was trained: padded to exactly 64 tokens and lowercased. SigLIP pools its text embedding from the last position, so an unpadded query is pooled from the wrong token and its vector points almost anywhere. In our benchmark on Flickr30k, unpadded queries scored 0.74% recall@1; padding them correctly gave 73.86%, and lowercasing them as well gave 79.32%, against 80.7% in the SigLIP 2 paper.

    Every number on this page comes from a run we measured on 2026-11-10 (text-to-image recall over all 5,000 Flickr30k test captions and 25,010 COCO 5k captions, with 95% bootstrap intervals), or from the source we link.

    What SigLIP 2 expects from your text



    Hugging Face's SigLIP 2 documentation lists the text preprocessing the model was trained with (Transformers docs):

  1. Fixed padding and truncation: padding="max_length", max_length=64, truncation=True.
  2. Lowercasing all input text.


  3. The processor (AutoProcessor) applies both for you. The problems start when a pipeline calls the tokenizer directly, or passes padding="max_length" without max_length.

    Why padding="max_length" can silently pad nothing



    The fixed-resolution SigLIP 2 checkpoints, such as google/siglip2-base-patch16-224 and google/siglip2-so400m-patch14-384, declare the model type siglip and ship a Gemma tokenizer that sets no model_max_length. With no length to pad to, padding="max_length" pads nothing and truncation=True truncates nothing, and no warning is raised. Two symptoms follow:

    1. Every query embedding is wrong. The model reads the last position of an unpadded sequence, which is a different token than the one it learned to pool. 2. Long captions fail. A caption over 64 tokens exceeds the text encoder's position count and is refused (1 of the 5,000 Flickr30k captions in our run).

    The fix is to pass the length explicitly, or to read it from the model's own config (text_config.max_position_embeddings is 64 for these checkpoints) rather than from the tokenizer.

    How much each fix is worth



    Measured with SigLIP 2 B/16 at 224 px, text-to-image recall@1:

    Query textFlickr30k 1kCOCO 5k
    Unpadded0.74%not run
    Padded to 64 tokens73.86%48.73%
    Padded and lowercased, punctuation removed79.32%53.09%
    SigLIP 2 paper, Table 1 (arXiv 2502.14786)80.7%52.1%


    SigLIP 2 So/14 at 384 px moved the same way on Flickr30k: 79.10% padded, 83.44% padded and lowercased, against the paper's 85.7%. As a control, OpenAI CLIP B/16 through the same pipeline landed within 0.1 point of its published scores on both sets (62.20% and 33.00%), since its tokenizer declares its 77-token length and lowercases on its own.

    How do I fix SigLIP 2 text embeddings?



    Use the processor, or pass the training settings yourself:

    from transformers import AutoModel, AutoProcessor model_id = "google/siglip2-base-patch16-224" model = AutoModel.from_pretrained(model_id).eval() processor = AutoProcessor.from_pretrained(model_id) texts = [t.lower() for t in ["A dog catching a frisbee", "Two people on a beach"]] inputs = processor(text=texts, padding="max_length", max_length=64, truncation=True, return_tensors="pt") text_vectors = model.get_text_features(**inputs) text_vectors = text_vectors / text_vectors.norm(dim=-1, keepdim=True)

    Then check three things in your own pipeline:

  4. Compare against a known number. Score a public set such as Flickr30k and compare with the paper before you trust your own data's results. A model that works shows up within a few points; one with a preprocessing bug is off by orders of magnitude.
  5. Clear cached query vectors after any fix. If your search layer caches query embeddings, a fix to tokenization does not reach queries that are already cached. In our run, cached vectors kept returning about 1% recall@1 until the cache was cleared.
  6. Embed images with the same preprocessing at index and query time. Resizing without antialiasing cost 0.4 points in our test, which is small next to text padding but worth keeping consistent.


  7. How Mixpeek runs SigLIP 2



    Mixpeek is a multimodal data warehouse: it embeds images and video frames where they sit in object storage and searches them through retrievers. SigLIP 2 models are in the model catalog, and a namespace can import other checkpoints from Hugging Face through the model registry.

    The 0.74% row above was measured through Mixpeek's own Hugging Face import, which padded only checkpoints that declare the model type siglip2. The loader fix, which pads and truncates every query to the text encoder's position count, was merged on 2026-11-10. With it, the platform's rankings matched an exhaustive offline cosine search over the same vectors to two decimals. Lowercasing queries is left to the caller today, as in the code above.

    Frequently Asked Questions



    Why does SigLIP 2 need text padded to 64 tokens?



    It was trained that way, and it pools its text embedding from the last position of the sequence. Hugging Face's documentation for SigLIP and SigLIP 2 says to pass padding="max_length" with max_length=64. An unpadded query is pooled from a different token, which in our test dropped Flickr30k recall@1 from 73.86% to 0.74%.

    Does SigLIP 2 need lowercase text?



    Yes. SigLIP 2 was trained on lowercased text, and its processor lowercases input by default. When we lowercased queries and removed punctuation ourselves, recall@1 rose by 4.4 to 5.5 points on Flickr30k and COCO for SigLIP 2 B/16.

    Why does padding="max_length" not pad my SigLIP 2 queries?



    The fixed-resolution SigLIP 2 checkpoints ship a tokenizer with no model_max_length, so there is no length to pad to. Pass max_length=64 explicitly, or read the length from the model config's text_config.max_position_embeddings.

    Is SigLIP 2 better than CLIP for text-to-image search?



    On the SigLIP 2 paper's benchmarks, yes: SigLIP 2 B/16 reports 80.7% recall@1 on Flickr30k against 62.1% for OpenAI CLIP B/16, and we measured 79.32% and 62.20% through one pipeline. The advantage holds only when SigLIP 2's text is padded and lowercased; unpadded, it scored far below CLIP in our run.

    How do I know if my embedding pipeline has a preprocessing bug?



    Score a public benchmark through it and compare with the model's paper. Recall within a few points means the pipeline is sound; a result near zero, or one that changes when you clear a cache, means queries are not being prepared the way the model was trained.
    Managed Mixpeek

    Put multimodal search to work

    Connect a bucket and Mixpeek runs the whole multimodal search pipeline for you: extraction, indexing, and search over your own objects. No models to wire up, nothing to host.

    Start with Managed
    MVS · bring your own

    Already have vectors?

    Keep your embeddings on your own cloud and run dense, sparse, and BM25 search directly on object storage. From $25/mo.

    Start with MVS

    Run this on your own data

    Point Mixpeek at the storage you already have and search your video, images, audio, and documents the way this guide describes. Build starts at $25/mo for up to 1M vectors.

    Search your own archiveRead Docs

    Related guides

    Embeddings

    Do E5 and BGE Embeddings Need Query and Passage Prefixes? We Measured It

    Yes for E5, and the wrong prefix is the expensive mistake. We scored e5-small-v2, bge-small-en-v1.5 and all-MiniLM-L6-v2 on SciFact, NFCorpus and FiQA with and without their prefixes. Dropping E5's prefixes cost up to 1.6 points of nDCG@10, most on FiQA. Writing passage: in front of E5 queries cost 22.1 points on FiQA. BGE v1.5's instruction is optional. Table, confidence intervals, code and raw results.

    Read guide →
    Embeddings

    Does Fine-Tuning an Embedding Model With LoRA Improve Search? We Measured It

    Yes, about as much as full fine-tuning, with a higher learning rate. We fine-tuned bge-small-en-v1.5 on 919 SciFact pairs and scored 300 held-out queries: LoRA on all linear layers at lr 1e-3 raised nDCG@10 from 0.706 to 0.744 and recall@10 from 0.830 to 0.894 with a 5.4 MB adapter. Full fine-tuning reached 0.751 with a 133 MB model. At lr 1e-4 the same adapter gained 1.3 points, within noise. Table, confidence intervals, code and raw results.

    Read guide →
    Embeddings

    How Does LoRA Fine-Tuning Work? (Adapters, QLoRA, DoRA, and Fine-Tuning Retrieval Models)

    LoRA fine-tunes a large model by freezing its weights and training a tiny low-rank adapter (a few hundred MB, under 1% of parameters): trainable on one GPU, swappable at inference. How LoRA, QLoRA, and DoRA work; the rank/alpha/target-module knobs that matter in 2026; and the retrieval-specific part most guides skip: fine-tuning embedding models, rerankers, and VLMs with LoRA, why you must re-embed your corpus afterward, and how swappable adapters enable multi-tenant retrieval. Vendor-neutral, with a comparison table and FAQs.

    Read guide →