Skip to content

fix: preserve ColModernVBERT image patch geometry - #760

Closed
hulkbig wants to merge 1 commit into
qdrant:colmodernvbert-fixesfrom
hulkbig:fix/colmodernvbert-patch-grid
Closed

hulkbig wants to merge 1 commit into
qdrant:colmodernvbert-fixesfrom
hulkbig:fix/colmodernvbert-patch-grid

Conversation

@hulkbig

@hulkbig hulkbig commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Summary

ColModernVBERT reconstructs an image's patch grid from its patch count, which loses the original rows and columns. For example, two local patches can be a 2×1 portrait or a 1×2 landscape grid, and four can be 1×4, 4×1, or 2×2. The current near-square guess supplies incorrect row/column tokens and row separators for some of these images.

This preserves the grid produced by ImageSplitter in per-call metadata and uses it when constructing the image prompt. The existing return types of ImageSplitter and Compose are unchanged. Unsplit images retain their global-image prompt, and geometry metadata is not passed to ONNX.

Regression coverage

Generated tiny RGB images exercise the real onnx_embed_image preprocessing path, including resizing, splitting, rescaling, normalization, nested-patch padding, prompt tokenization, and token padding. Tests cover portrait, landscape, wide, tall, square, unsplit, rounded/resized grids, mixed batches, both padding directions, and existing transform return shapes.

The tokenizer is a small real BPE model trained locally. Model construction/downloads are bypassed and the final ONNX run call is mocked to record its inputs. The initial unchanged-baseline tests produced 6 failures and 5 passing controls; the failures are actual prompt-token mismatches.

Validation

  • Targeted pytest: 42 passed (test_colmodernvbert_preprocessing.py, test_image_transform.py, test_common.py)
  • Same 42 tests passed after applying the exported patch to a pristine checkout
  • Standalone before/after reproduction: all 20 image pixel arrays are byte-identical; affected prompt tokens are corrected
  • Full repository mypy command: passed across 65 source files
  • CI pyright target: passed
  • Ruff 0.3.4 lint/format and git diff --check: passed
  • Prompt construction matches the standalone Transformers v4.57.1 reference prompt functions for the nine checked geometries

An earlier broader attempt including test_preprocessor_utils.py produced 32 passes and 31 fixture setup errors: the existing tokenizer fixture reaches a model-download path whose configured SOCKS proxy lacks socksio. Those tests never reached their assertions.

No pretrained model tokenizer, model weights, ONNX session, model inference, or retrieval-quality evaluation was used. The full model-download suite and multi-platform/Python-version CI matrix have not passed locally. This is an offline preprocessing fix, with no embedding-accuracy claim.

All Submissions

  • Read and followed the applicable contribution guidance
  • Checked existing PRs for the same change

The repository's complete CI suite remains to be run by CI. Pre-commit hooks were not installed locally; their pinned Ruff 0.3.4 checks were run directly.

@hulkbig
hulkbig marked this pull request as ready for review October 3, 2026 12:51
@hulkbig
hulkbig requested a review from joein as a code owner October 3, 2026 12:51
@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 28e8160d-fbc2-432a-beef-ef45f78c385f
📥 Commits

Reviewing files that changed from the base of the PR and between 7d36728 and 825414b.

📒 Files selected for processing (4)
  • fastembed/image/transform/operators.py
  • fastembed/late_interaction_multimodal/colmodernvbert.py
  • tests/test_colmodernvbert_preprocessing.py
  • tests/test_image_transform.py

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Image transforms now report per-image patch-grid dimensions through optional metadata. ColModernVBERT passes this metadata to image-input preprocessing, which validates each grid against the real patch count and uses it to build image prompts. New tests cover split and unsplit images, mixed batches, resizing, padding, and invalid grids.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 82541

The change makes image prompts use the actual patch grid instead of one inferred from patch count. No merge-blocking issue was identified in the supplied evidence.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to 82541

The reviewed change keeps image geometry associated with each request and checks its consistency before execution. Existing default outputs are preserved, and no material security risk was found in the changed path.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — Within the reviewed entrypoint, caller-provided images influence patches and generated tokens for an embedding batch. Metadata collection adds no new input-fetching path, identity transition, or privileged operation compared with the existing image-processing flow.

Trust Boundaries and Controls

  • observed — Missing or inconsistent geometry is rejected before model execution. Geometry is translated into token inputs; image_grid itself is not included in the ONNX input dictionary.

Resilience and Maintainability Implications

  • observed — Geometry metadata and intermediate arrays are local to each invocation rather than stored on the shared instance. Retries reconstruct geometry, and processing failures unwind owned image files through ExitStack before any output is returned. This isolates the new geometry state without establishing thread-safety guarantees for existing shared dependencies.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: preserving ColModernVBERT image patch geometry.
Description check ✅ Passed The description explains the patch-grid issue, the implementation, and the regression coverage. It is directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@joein
joein changed the base branch from main to colmodernvbert-fixes October 6, 2026 14:46
@joein

joein commented Oct 6, 2026

Copy link
Copy Markdown
Member

Hey @hulkbig

Thanks for your work!

Though, the pr requires some changes and I can't add those because you prohibited maintainers from adding changes to your branch.
I will close your PR and add you as a co-author to one of the commits on #784

@joein joein closed this Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants