unsloth/tests/python
Roland Tannous 68114fd223 Studio: multimodal RAG mode (Phase 3B-multimodal)
When a KB has mode = 'multimodal', ingestion extracts images alongside
text and embeds both into a shared 512-d vector space via BGE-VL-base.
Image hits become first-class search results — useful for slides,
reports, and diagrams where text-only retrieval loses ~30-50% of the
content.

Backend
- embeddings.py: new encode_images(image_bytes_list) — opens bytes via
  PIL and routes to the SentenceTransformer (BGE-VL accepts PIL images
  in the same encode call as text).
- ingestion.py: _subprocess_worker gains document_id arg and a new
  _stream_image_chunks() helper. For multimodal KBs the standard text
  chunking runs first, then images are saved to
  rag_uploads_root() / 'images' / <document_id> / img-NNNN.<ext> and
  embedded; for each image with an adjacent caption, both an
  'image'-kind chunk (vector = encoded image) and a 'caption'-kind
  chunk (vector = encoded caption text) are streamed back with a
  shared pair_group field.
- ingestion.py parent: _insert_chunks_and_collect_for_bm25 now reads
  kind / image_path / pair_group from the subprocess message,
  populates the new rag_chunks columns, and runs a second pass that
  sets linked_chunk_id for each image ↔ caption pair. BM25 indexes
  text + caption chunks only — image chunks have no tokenisable body.
- retrieval.py: Hit gains a `kind` field plumbed through bm25, dense,
  RRF, and rerank paths.
- reranker.py: image-kind hits skip CrossEncoder rerank (text-only
  model) but are appended back in their original relative position
  rather than dropped.
- routes/rag.py: new GET /api/rag/images/{document_id}/{filename}
  static-file route with realpath containment check. SearchHit gains
  `kind` and `image_url` fields so the chat UI can render image
  thumbnails alongside text hits. KB-doc upload threads kind/mode
  through to ingestion.

Frontend
- rag-api.ts: SearchHit gains optional `kind` and `image_url`.
- kb-create-dialog.tsx: new Mode select (Text / Multimodal) alongside
  the existing Chunking strategy select. The forbidden
  (multimodal + late) combo is enforced in the UI — each side
  disables the conflicting option on the other side with a tooltip
  explaining why. Embedding-model placeholder cycles through the
  three valid defaults (bge-small / nomic / BGE-VL).
- kb-list.tsx + chat-settings-sheet.tsx: 🖼️ MM badge alongside the
   Late one so multimodal KBs are obvious at a glance.

Tests
- test_rag_multimodal.py: parser returns images when want_images=True
  and skips them when False; _validate_mode_combo rejects the
  forbidden (multimodal, late) pair with 400; RAG_EMBEDDER_MATRIX
  contains the three valid combos and excludes the forbidden one;
  image URL construction shape is verified. A server-marked test
  loads BGE-VL-base end-to-end and confirms image + text vectors
  share the same dimension.

Phase 3 of the plan is now feature-complete on the backend; the
remaining items (re-ingest UX for changing strategy on existing KBs)
are tracked under "Backfill UX" and can land separately.
2026-05-24 12:33:08 +04:00
..
__init__.py Consolidate dual venvs and separate install from update (#4530) 2026-03-25 05:24:21 -07:00
conftest.py fix: add tokenizers to no-torch deps and TORCH_CONSTRAINT for arm64 macOS py313+ (#4748) 2026-04-01 06:12:17 -07:00
test_cross_platform_parity.py Add configurable PyTorch mirror via UNSLOTH_PYTORCH_MIRROR env var (#5024) 2026-04-15 11:39:11 +04:00
test_dpo_vision_processor_passthrough.py Fix DPO trainer multi process hang (#5199) 2026-04-29 04:15:34 -07:00
test_e2e_no_torch_sandbox.py tests: add no-torch / Intel Mac test suite (#4646) 2026-03-27 02:33:45 -07:00
test_fast_sentence_transformer_redirect_lifecycle.py Add Studio PR-time CI: pin enforcement, frontend, backend, wheel smoke (#5298) 2026-05-06 04:41:57 -07:00
test_flash_attn_install_python_stack.py studio: skip flash-attn install on Blackwell GPUs (sm_100+) (#5420) 2026-05-14 18:13:50 +04:00
test_gpu_init_ldconfig_guard.py feat(studio): MLX training tab on Apple Silicon (LoRA / full FT, VLM, export) (#5265) 2026-05-05 23:54:58 -07:00
test_install_python_stack.py Consolidate dual venvs and separate install from update (#4530) 2026-03-25 05:24:21 -07:00
test_no_torch_filtering.py [Studio] Install flash attn at setup time for linux (#4979) 2026-04-14 16:40:17 +04:00
test_orpo_processor_text_tokenizer.py Fix ORPO text-only tokenization with processors (#5501) 2026-05-18 00:40:30 -07:00
test_patch_trl_rl_trainers_defensive.py fix: unblock 4 tests deselected/skipped in #5312 (real bugs) (#5359) 2026-05-11 02:39:17 -07:00
test_rag_bm25.py Studio: add RAG with hybrid search, reranker, chat integration 2026-05-23 18:46:15 +04:00
test_rag_chunking.py Studio: layout-aware RAG parsers + heading-aware chunking (Phase 3A) 2026-05-24 11:10:13 +04:00
test_rag_late_chunking.py Studio: late chunking opt-in per KB (Phase 3B-late) 2026-05-24 12:18:09 +04:00
test_rag_multimodal.py Studio: multimodal RAG mode (Phase 3B-multimodal) 2026-05-24 12:33:08 +04:00
test_rag_parsers.py Studio: layout-aware RAG parsers + heading-aware chunking (Phase 3A) 2026-05-24 11:10:13 +04:00
test_rag_reranker.py Studio: add RAG with hybrid search, reranker, chat integration 2026-05-23 18:46:15 +04:00
test_rag_retrieval.py Studio: add RAG with hybrid search, reranker, chat integration 2026-05-23 18:46:15 +04:00
test_rag_vector_store.py Studio: add RAG with hybrid search, reranker, chat integration 2026-05-23 18:46:15 +04:00
test_studio_import_no_torch.py tests: add no-torch / Intel Mac test suite (#4646) 2026-03-27 02:33:45 -07:00
test_tokenizers_and_torch_constraint.py fix: add tokenizers to no-torch deps and TORCH_CONSTRAINT for arm64 macOS py313+ (#4748) 2026-04-01 06:12:17 -07:00
test_unsloth_run_tool_policy_resolver.py unsloth run: add --enable-tools/--disable-tools server-side tool policy (#5277) 2026-05-05 12:45:15 +04:00