Image Segmentation
Transformers
Safetensors
English
prima
text-generation
computer-vision
multi-image-reasoning
pixel-grounding
vision-language
custom-code
custom_code
Instructions to use kanguyen-vn/PRIMA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use kanguyen-vn/PRIMA with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-segmentation", model="kanguyen-vn/PRIMA", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("kanguyen-vn/PRIMA", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download code/tests/test_multimodal.py from kanguyen-vn/PRIMA: direct link, hf CLI and curl.
- Browser
- Download file 5.65 kB
-
https://huggingface.co/kanguyen-vn/PRIMA/resolve/main/code/tests/test_multimodal.py
- Command line
-
hf download hf://kanguyen-vn/PRIMA/code/tests/test_multimodal.py
-
curl -L -o test_multimodal.py https://huggingface.co/kanguyen-vn/PRIMA/resolve/main/code/tests/test_multimodal.py
5.65 kB
| import unittest | |
| from types import SimpleNamespace | |
| import torch | |
| from torch import nn | |
| from model.llava.prima_arch import LlavaMetaForCausalLM | |
| from tools.utils import IGNORE_INDEX, IMAGE_TOKEN_INDEX | |
| class TinyMultimodalModel(nn.Module, LlavaMetaForCausalLM): | |
| def __init__(self, hidden_size=4, image_tokens=3): | |
| super().__init__() | |
| self.config = SimpleNamespace(with_region=False, mm_use_im_start_end=False, | |
| tune_mm_mlp_adapter=False) | |
| self.model = nn.Module() | |
| self.model.embed_tokens = nn.Embedding(32, hidden_size) | |
| self.model.mm_projector = nn.Linear(hidden_size, hidden_size) | |
| self.model.vision_tower = nn.Identity() | |
| self.model.get_vision_tower = lambda: self.model.vision_tower | |
| self.model.use_qformer = True | |
| self.model.Qformer = SimpleNamespace(config=SimpleNamespace(hidden_size=hidden_size)) | |
| self.model.device = torch.device('cpu') | |
| self.model.dtype = torch.float32 | |
| self.image_features = nn.Parameter(torch.arange(image_tokens * hidden_size).reshape( | |
| image_tokens, hidden_size).float() / 10) | |
| self.encoder_calls = 0 | |
| def device(self): | |
| return self.model.embed_tokens.weight.device | |
| def get_model(self): | |
| return self.model | |
| def encode_images_qformer(self, images, *args): | |
| self.encoder_calls += 1 | |
| values = images.flatten(1).mean(1)[:, None, None] | |
| return self.image_features.unsqueeze(0) + values, images | |
| def prepare(model, ids, *, mask=None, labels=None, images=None, past=None): | |
| offsets = torch.arange(len(ids) + 1) | |
| return model.prepare_inputs_labels_for_multimodal( | |
| ids, mask, past, labels, images, offsets, offsets, None, None) | |
| class MultimodalTests(unittest.TestCase): | |
| def test_image_features_replace_only_the_image_token(self): | |
| model = TinyMultimodalModel() | |
| ids = torch.tensor([[1, IMAGE_TOKEN_INDEX, 2, 3]]) | |
| labels = ids.clone() | |
| result = prepare(model, ids, mask=torch.ones_like(ids, dtype=torch.bool), | |
| labels=labels, images=torch.zeros(1, 3, 2, 2)) | |
| self.assertEqual(result[3].shape, (1, 6, 4)) | |
| self.assertTrue(torch.equal(result[3][0, 1:4], model.image_features)) | |
| self.assertTrue(torch.equal(result[3][0, [0, 4, 5]], model.model.embed_tokens(ids[0, [0, 2, 3]]))) | |
| self.assertEqual(result[4].tolist(), [[1, IGNORE_INDEX, IGNORE_INDEX, IGNORE_INDEX, 2, 3]]) | |
| self.assertEqual(result[5], [[slice(1, 4)]]) | |
| self.assertTrue(result[1].all()) | |
| result[3].sum().backward() | |
| self.assertTrue(torch.equal(model.image_features.grad, torch.ones_like(model.image_features))) | |
| def test_ragged_batch_preserves_left_padding_and_masks_new_right_padding(self): | |
| model = TinyMultimodalModel() | |
| ids = torch.tensor([[0, 1, IMAGE_TOKEN_INDEX, 2], [0, 0, 3, 4]]) | |
| mask = ids.ne(0) | |
| labels = ids.masked_fill(~mask, IGNORE_INDEX) | |
| for include_labels in (True, False): | |
| with self.subTest(labels=include_labels): | |
| result = prepare(model, ids, mask=mask, | |
| labels=labels if include_labels else None, | |
| images=torch.zeros(1, 3, 2, 2)) | |
| self.assertEqual(result[1].tolist(), [[False, True, True, True, True, True], | |
| [False, False, True, True, False, False]]) | |
| self.assertTrue(torch.equal(result[3][1, -2:], torch.zeros(2, 4))) | |
| if include_labels: | |
| self.assertEqual(result[4][1, -2:].tolist(), [IGNORE_INDEX, IGNORE_INDEX]) | |
| else: | |
| self.assertIsNone(result[4]) | |
| def test_cached_generation_extends_attention_without_encoding_images(self): | |
| model = TinyMultimodalModel() | |
| ids = torch.tensor([[5]]) | |
| past = ((torch.zeros(1, 2, 7, 4), torch.zeros(1, 2, 7, 4)),) | |
| result = prepare(model, ids, mask=torch.ones(1, 7, dtype=torch.bool), | |
| images=torch.zeros(1, 3, 2, 2), past=past) | |
| self.assertIs(result[0], ids) | |
| self.assertIs(result[2], past) | |
| self.assertIsNone(result[3]) | |
| self.assertEqual(result[1].shape, (1, 8)) | |
| self.assertTrue(result[1].all()) | |
| self.assertEqual(model.encoder_calls, 0) | |
| def test_ragged_embeddings_preserve_dtype_promotion(self): | |
| model = TinyMultimodalModel() | |
| model.model.embed_tokens.to(dtype=torch.bfloat16) | |
| ids = torch.tensor([[1, 2, 3, 4], [1, IMAGE_TOKEN_INDEX, 2, 3]]) | |
| result = prepare(model, ids, mask=torch.ones_like(ids, dtype=torch.bool), | |
| images=torch.zeros(1, 3, 2, 2)) | |
| self.assertEqual(result[3].dtype, torch.float32) | |
| self.assertTrue(torch.equal(result[3][1, 1:4], model.image_features)) | |
| def test_grouped_images_preserve_feature_order(self): | |
| model = TinyMultimodalModel() | |
| ids = torch.tensor([[1, IMAGE_TOKEN_INDEX, 2], [3, IMAGE_TOKEN_INDEX, 4]]) | |
| groups = [torch.stack((torch.zeros(3, 2, 2), torch.ones(3, 2, 2))), | |
| torch.full((1, 3, 2, 2), 2.0)] | |
| result = prepare(model, ids, mask=torch.ones_like(ids, dtype=torch.bool), images=groups) | |
| self.assertEqual(result[3].shape, (2, 8, 4)) | |
| self.assertTrue(torch.equal(result[3][0, 1:4], model.image_features)) | |
| self.assertTrue(torch.equal(result[3][0, 4:7], model.image_features + 1)) | |
| self.assertTrue(torch.equal(result[3][1, 1:4], model.image_features + 2)) | |
| if __name__ == '__main__': | |
| unittest.main() | |