|
53 | 53 | Qwen3OmniMoeVisionProjector as JaxQwen3OmniMoeVisionProjector, |
54 | 54 | ) |
55 | 55 | from maxtext.multimodal import processor as mm_processor |
| 56 | +from maxtext.multimodal import utils as mm_utils |
56 | 57 | from tests.utils.multimodal_test_utils import ( |
57 | 58 | assert_all_close_jax_torch, |
58 | 59 | copy_attention_weights_to_maxtext, |
@@ -869,6 +870,67 @@ def test_padded_video_projected_outputs_match_unpadded_batched(self): |
869 | 870 | atol=1e-4, |
870 | 871 | ) |
871 | 872 |
|
| 873 | + # --- Test Merging into Text Sequence --- |
| 874 | + emb_dim = config.out_hidden_size_for_vit |
| 875 | + |
| 876 | + # Example 1: 2 placeholders at indices 5, 6. |
| 877 | + text_embeddings_1 = jnp.arange(1 * 20 * emb_dim, dtype=jnp.float32).reshape(1, 20, emb_dim) |
| 878 | + placeholder_mask_1 = jnp.zeros((1, 20), dtype=jnp.int32) |
| 879 | + placeholder_mask_1 = placeholder_mask_1.at[:, 5:7].set(1) |
| 880 | + |
| 881 | + # Example 2: 4 placeholders at indices 5, 6, 7, 8. |
| 882 | + text_embeddings_2 = jnp.arange(1 * 20 * emb_dim, dtype=jnp.float32).reshape(1, 20, emb_dim) + 1000.0 |
| 883 | + placeholder_mask_2 = jnp.zeros((1, 20), dtype=jnp.int32) |
| 884 | + placeholder_mask_2 = placeholder_mask_2.at[:, 5:9].set(1) |
| 885 | + |
| 886 | + # Batch text inputs |
| 887 | + batched_text_embeddings = jnp.concatenate([text_embeddings_1, text_embeddings_2], axis=0) |
| 888 | + batched_placeholder_mask = jnp.concatenate([placeholder_mask_1, placeholder_mask_2], axis=0) |
| 889 | + batched_projected_mask = jnp.concatenate([projected_mask_1, projected_mask_2], axis=0) |
| 890 | + |
| 891 | + # Run batched merge |
| 892 | + batched_merged = mm_utils.merge_mm_embeddings( |
| 893 | + text_embeddings=batched_text_embeddings, |
| 894 | + multimodal_embeddings=batched_padded_output, |
| 895 | + mask=batched_placeholder_mask, |
| 896 | + token_masks=batched_projected_mask, |
| 897 | + ) |
| 898 | + |
| 899 | + # Run individual unpadded merges |
| 900 | + token_mask_1 = jnp.ones((1, 2), dtype=jnp.int32) |
| 901 | + merged_1 = mm_utils.merge_mm_embeddings( |
| 902 | + text_embeddings=text_embeddings_1, |
| 903 | + multimodal_embeddings=raw_output_1, |
| 904 | + mask=placeholder_mask_1, |
| 905 | + token_masks=token_mask_1, |
| 906 | + ) |
| 907 | + |
| 908 | + # Example 2 has 4 valid blocks |
| 909 | + token_mask_2 = jnp.ones((1, 4), dtype=jnp.int32) |
| 910 | + merged_2 = mm_utils.merge_mm_embeddings( |
| 911 | + text_embeddings=text_embeddings_2, |
| 912 | + multimodal_embeddings=raw_output_2, |
| 913 | + mask=placeholder_mask_2, |
| 914 | + token_masks=token_mask_2, |
| 915 | + ) |
| 916 | + |
| 917 | + # Verify that batched merge matches individual unpadded merges |
| 918 | + # Batch item 0 |
| 919 | + np.testing.assert_allclose( |
| 920 | + np.asarray(batched_merged[0]), |
| 921 | + np.asarray(merged_1[0]), |
| 922 | + rtol=1e-4, |
| 923 | + atol=1e-4, |
| 924 | + ) |
| 925 | + |
| 926 | + # Batch item 1 |
| 927 | + np.testing.assert_allclose( |
| 928 | + np.asarray(batched_merged[1]), |
| 929 | + np.asarray(merged_2[0]), |
| 930 | + rtol=1e-4, |
| 931 | + atol=1e-4, |
| 932 | + ) |
| 933 | + |
872 | 934 |
|
873 | 935 | class TestDeepstackProcess(unittest.TestCase): |
874 | 936 | """Tests for deepstack_process. |
|
0 commit comments