BoghdadyJR commited on
Commit
ee1fa58
·
verified ·
1 Parent(s): 724389f

Add inference handler for HF Endpoints

Browse files
README.md CHANGED
@@ -1,22 +1,202 @@
1
  ---
2
- base_model: unsloth/qwen2-vl-2b-instruct-bnb-4bit
3
- tags:
4
- - text-generation-inference
5
- - transformers
6
- - unsloth
7
- - qwen2_vl
8
- - trl
9
- license: apache-2.0
10
- language:
11
- - en
12
  ---
13
 
14
- # Uploaded model
15
 
16
- - **Developed by:** BoghdadyJR
17
- - **License:** apache-2.0
18
- - **Finetuned from model :** unsloth/qwen2-vl-2b-instruct-bnb-4bit
19
 
20
- This qwen2_vl model was trained 2x faster with [Unsloth](https://github.com/unslothai/unsloth) and Huggingface's TRL library.
21
 
22
- [<img src="https://raw.githubusercontent.com/unslothai/unsloth/main/images/unsloth%20made%20with%20love.png" width="200"/>](https://github.com/unslothai/unsloth)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ base_model: unsloth/Qwen2-VL-2B-Instruct
3
+ library_name: peft
 
 
 
 
 
 
 
 
4
  ---
5
 
6
+ # Model Card for Model ID
7
 
8
+ <!-- Provide a quick summary of what the model is/does. -->
 
 
9
 
 
10
 
11
+
12
+ ## Model Details
13
+
14
+ ### Model Description
15
+
16
+ <!-- Provide a longer summary of what this model is. -->
17
+
18
+
19
+
20
+ - **Developed by:** [More Information Needed]
21
+ - **Funded by [optional]:** [More Information Needed]
22
+ - **Shared by [optional]:** [More Information Needed]
23
+ - **Model type:** [More Information Needed]
24
+ - **Language(s) (NLP):** [More Information Needed]
25
+ - **License:** [More Information Needed]
26
+ - **Finetuned from model [optional]:** [More Information Needed]
27
+
28
+ ### Model Sources [optional]
29
+
30
+ <!-- Provide the basic links for the model. -->
31
+
32
+ - **Repository:** [More Information Needed]
33
+ - **Paper [optional]:** [More Information Needed]
34
+ - **Demo [optional]:** [More Information Needed]
35
+
36
+ ## Uses
37
+
38
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
39
+
40
+ ### Direct Use
41
+
42
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
43
+
44
+ [More Information Needed]
45
+
46
+ ### Downstream Use [optional]
47
+
48
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
49
+
50
+ [More Information Needed]
51
+
52
+ ### Out-of-Scope Use
53
+
54
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
55
+
56
+ [More Information Needed]
57
+
58
+ ## Bias, Risks, and Limitations
59
+
60
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
61
+
62
+ [More Information Needed]
63
+
64
+ ### Recommendations
65
+
66
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
67
+
68
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
69
+
70
+ ## How to Get Started with the Model
71
+
72
+ Use the code below to get started with the model.
73
+
74
+ [More Information Needed]
75
+
76
+ ## Training Details
77
+
78
+ ### Training Data
79
+
80
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
81
+
82
+ [More Information Needed]
83
+
84
+ ### Training Procedure
85
+
86
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
87
+
88
+ #### Preprocessing [optional]
89
+
90
+ [More Information Needed]
91
+
92
+
93
+ #### Training Hyperparameters
94
+
95
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
96
+
97
+ #### Speeds, Sizes, Times [optional]
98
+
99
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
100
+
101
+ [More Information Needed]
102
+
103
+ ## Evaluation
104
+
105
+ <!-- This section describes the evaluation protocols and provides the results. -->
106
+
107
+ ### Testing Data, Factors & Metrics
108
+
109
+ #### Testing Data
110
+
111
+ <!-- This should link to a Dataset Card if possible. -->
112
+
113
+ [More Information Needed]
114
+
115
+ #### Factors
116
+
117
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
118
+
119
+ [More Information Needed]
120
+
121
+ #### Metrics
122
+
123
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
124
+
125
+ [More Information Needed]
126
+
127
+ ### Results
128
+
129
+ [More Information Needed]
130
+
131
+ #### Summary
132
+
133
+
134
+
135
+ ## Model Examination [optional]
136
+
137
+ <!-- Relevant interpretability work for the model goes here -->
138
+
139
+ [More Information Needed]
140
+
141
+ ## Environmental Impact
142
+
143
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
144
+
145
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
146
+
147
+ - **Hardware Type:** [More Information Needed]
148
+ - **Hours used:** [More Information Needed]
149
+ - **Cloud Provider:** [More Information Needed]
150
+ - **Compute Region:** [More Information Needed]
151
+ - **Carbon Emitted:** [More Information Needed]
152
+
153
+ ## Technical Specifications [optional]
154
+
155
+ ### Model Architecture and Objective
156
+
157
+ [More Information Needed]
158
+
159
+ ### Compute Infrastructure
160
+
161
+ [More Information Needed]
162
+
163
+ #### Hardware
164
+
165
+ [More Information Needed]
166
+
167
+ #### Software
168
+
169
+ [More Information Needed]
170
+
171
+ ## Citation [optional]
172
+
173
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
174
+
175
+ **BibTeX:**
176
+
177
+ [More Information Needed]
178
+
179
+ **APA:**
180
+
181
+ [More Information Needed]
182
+
183
+ ## Glossary [optional]
184
+
185
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
186
+
187
+ [More Information Needed]
188
+
189
+ ## More Information [optional]
190
+
191
+ [More Information Needed]
192
+
193
+ ## Model Card Authors [optional]
194
+
195
+ [More Information Needed]
196
+
197
+ ## Model Card Contact
198
+
199
+ [More Information Needed]
200
+ ### Framework versions
201
+
202
+ - PEFT 0.15.2
adapter_config.json CHANGED
@@ -24,13 +24,13 @@
24
  "rank_pattern": {},
25
  "revision": null,
26
  "target_modules": [
27
- "gate_proj",
28
- "k_proj",
29
  "o_proj",
30
  "down_proj",
31
- "q_proj",
32
- "up_proj",
33
- "v_proj"
34
  ],
35
  "task_type": "CAUSAL_LM",
36
  "trainable_token_indices": null,
 
24
  "rank_pattern": {},
25
  "revision": null,
26
  "target_modules": [
27
+ "v_proj",
28
+ "up_proj",
29
  "o_proj",
30
  "down_proj",
31
+ "gate_proj",
32
+ "k_proj",
33
+ "q_proj"
34
  ],
35
  "task_type": "CAUSAL_LM",
36
  "trainable_token_indices": null,
adapter_model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:7942ec41c2ac0084a6ecf27663ee3b7cff3f3d7ccc1c9d77b9a984835e9d0e79
3
- size 36981072
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d63b8e9eca3db32d6df66e661439564f2f3e6f76473bd8deb46d213a0467fc40
3
+ size 36986952
chat_template.jinja ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {% set image_count = namespace(value=0) %}{% set video_count = namespace(value=0) %}{% for message in messages %}{% if loop.first and message['role'] != 'system' %}<|im_start|>system
2
+ You are a helpful assistant.<|im_end|>
3
+ {% endif %}<|im_start|>{{ message['role'] }}
4
+ {% if message['content'] is string %}{{ message['content'] }}<|im_end|>
5
+ {% else %}{% for content in message['content'] %}{% if content['type'] == 'image' or 'image' in content or 'image_url' in content %}{% set image_count.value = image_count.value + 1 %}{% if add_vision_id %}Picture {{ image_count.value }}: {% endif %}<|vision_start|><|image_pad|><|vision_end|>{% elif content['type'] == 'video' or 'video' in content %}{% set video_count.value = video_count.value + 1 %}{% if add_vision_id %}Video {{ video_count.value }}: {% endif %}<|vision_start|><|video_pad|><|vision_end|>{% elif 'text' in content %}{{ content['text'] }}{% endif %}{% endfor %}<|im_end|>
6
+ {% endif %}{% endfor %}{% if add_generation_prompt %}<|im_start|>assistant
7
+ {% endif %}
handler.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, List, Any
2
+ from unsloth import FastVisionModel
3
+ from PIL import Image
4
+ import torch
5
+
6
+ class EndpointHandler():
7
+ def __init__(self, path=""):
8
+ # Load model and tokenizer
9
+ self.model, self.tokenizer = FastVisionModel.from_pretrained(
10
+ path,
11
+ device_map="auto",
12
+ load_in_4bit=False, # Use 4bit to reduce memory use. False for 16bit LoRA
13
+ use_gradient_checkpointing="unsloth", # True or "unsloth" for long context
14
+ )
15
+
16
+ # Enable for inference
17
+ FastVisionModel.for_inference(self.model)
18
+
19
+ # Store the instruction template
20
+ self.instruction = """
21
+ A conversation between a Healthcare Provider and an AI Medical Image Analysis Assistant. The provider shares a medical image, and the Assistant generates a clear description/report. The assistant first analyzes the image systematically, then provides a concise report. The analysis process and report are enclosed within <thinking> </thinking><answer> </answer>.
22
+
23
+ Always respond in this format:
24
+
25
+ <thinking>
26
+ 1. Initial Assessment:
27
+ - What type of image is this? (X-ray, CT, MRI, etc.)
28
+ - Which body part/region is shown?
29
+ - Is the image quality adequate?
30
+
31
+ 2. Key Findings:
32
+ - What are the normal structures visible?
33
+ - Are there any abnormalities?
34
+ - What are the important measurements?
35
+
36
+ 3. Clinical Significance:
37
+ - What are the main clinical findings?
38
+ - Are there any critical findings?
39
+ </thinking>
40
+
41
+ <answer>
42
+ Brief Structured Report:
43
+ 1. EXAM TYPE: [imaging type and body region]
44
+ 2. FINDINGS: [key observations and abnormalities]
45
+ 3. IMPRESSION: [summary and clinical significance]
46
+ </answer>
47
+ """
48
+
49
+ def __call__(self, data: Any) -> List[Dict[str, Any]]:
50
+ """
51
+ Args:
52
+ data (:obj:):
53
+ includes the input data and the parameters for the inference.
54
+ Expected format:
55
+ {
56
+ "inputs": {
57
+ "image": PIL.Image object,
58
+ "instruction": optional_custom_instruction
59
+ },
60
+ "parameters": {
61
+ "max_new_tokens": 512,
62
+ "temperature": 0.7,
63
+ "top_p": 0.9,
64
+ ...
65
+ }
66
+ }
67
+ Return:
68
+ A :obj:`list`:. The list contains a dictionary with:
69
+ - "generated_text": The model's response
70
+ """
71
+ inputs = data.pop("inputs", data)
72
+ parameters = data.pop("parameters", {})
73
+
74
+ # Extract image and instruction
75
+ image = inputs.get("image")
76
+ custom_instruction = inputs.get("instruction", self.instruction)
77
+
78
+ # Prepare messages
79
+ messages = [
80
+ {"role": "user", "content": [
81
+ {"type": "image"},
82
+ {"type": "text", "text": custom_instruction}
83
+ ]}
84
+ ]
85
+
86
+ # Apply chat template
87
+ input_text = self.tokenizer.apply_chat_template(messages, add_generation_prompt=True)
88
+
89
+ # Tokenize inputs
90
+ model_inputs = self.tokenizer(
91
+ image,
92
+ input_text,
93
+ add_special_tokens=False,
94
+ return_tensors="pt",
95
+ ).to(self.model.device)
96
+
97
+ # Set default parameters
98
+ generation_params = {
99
+ "max_new_tokens": parameters.get("max_new_tokens", 512),
100
+ "temperature": parameters.get("temperature", 0.7),
101
+ "top_p": parameters.get("top_p", 0.9),
102
+ "min_p": parameters.get("min_p", 0.1),
103
+ "use_cache": True,
104
+ "do_sample": parameters.get("do_sample", True),
105
+ "repetition_penalty": parameters.get("repetition_penalty", 1.1),
106
+ }
107
+
108
+ output_ids = self.model.generate(
109
+ **model_inputs,
110
+ **generation_params
111
+ )
112
+
113
+
114
+ # Decode output
115
+ generated_text = self.tokenizer.decode(output_ids[0], skip_special_tokens=True)
116
+
117
+ # Extract only the generated response (remove the prompt)
118
+ response = generated_text.split(custom_instruction)[-1].strip()
119
+
120
+ return [{
121
+ "generated_text": response
122
+ }]
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ torch>=2.0.0
2
+ transformers>=4.36.0
3
+ unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git
4
+ Pillow>=9.0.0
5
+ accelerate>=0.25.0
tokenizer.json CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:00ff1d43b119596534f778ecc067f5b457d2ce2fe2665ab12fe7a8705fda3437
3
- size 11420639
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:091aa7594dc2fcfbfa06b9e3c22a5f0562ac14f30375c13af7309407a0e67b8a
3
+ size 11420371
tokenizer_config.json CHANGED
@@ -130,22 +130,15 @@
130
  "<|video_pad|>"
131
  ],
132
  "bos_token": null,
133
- "chat_template": "{% set image_count = namespace(value=0) %}{% set video_count = namespace(value=0) %}{% for message in messages %}{% if loop.first and message['role'] != 'system' %}<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n{% endif %}<|im_start|>{{ message['role'] }}\n{% if message['content'] is string %}{{ message['content'] }}<|im_end|>\n{% else %}{% for content in message['content'] %}{% if content['type'] == 'image' or 'image' in content or 'image_url' in content %}{% set image_count.value = image_count.value + 1 %}{% if add_vision_id %}Picture {{ image_count.value }}: {% endif %}<|vision_start|><|image_pad|><|vision_end|>{% elif content['type'] == 'video' or 'video' in content %}{% set video_count.value = video_count.value + 1 %}{% if add_vision_id %}Video {{ video_count.value }}: {% endif %}<|vision_start|><|video_pad|><|vision_end|>{% elif 'text' in content %}{{ content['text'] }}{% endif %}{% endfor %}<|im_end|>\n{% endif %}{% endfor %}{% if add_generation_prompt %}<|im_start|>assistant\n{% endif %}",
134
  "clean_up_tokenization_spaces": false,
135
  "eos_token": "<|im_end|>",
136
  "errors": "replace",
137
  "extra_special_tokens": {},
138
- "max_length": 2048,
139
  "model_max_length": 32768,
140
- "pad_to_multiple_of": null,
141
  "pad_token": "<|vision_pad|>",
142
- "pad_token_type_id": 0,
143
  "padding_side": "right",
144
  "processor_class": "Qwen2VLProcessor",
145
  "split_special_tokens": false,
146
- "stride": 0,
147
  "tokenizer_class": "Qwen2Tokenizer",
148
- "truncation_side": "right",
149
- "truncation_strategy": "longest_first",
150
  "unk_token": null
151
  }
 
130
  "<|video_pad|>"
131
  ],
132
  "bos_token": null,
 
133
  "clean_up_tokenization_spaces": false,
134
  "eos_token": "<|im_end|>",
135
  "errors": "replace",
136
  "extra_special_tokens": {},
 
137
  "model_max_length": 32768,
 
138
  "pad_token": "<|vision_pad|>",
 
139
  "padding_side": "right",
140
  "processor_class": "Qwen2VLProcessor",
141
  "split_special_tokens": false,
 
142
  "tokenizer_class": "Qwen2Tokenizer",
 
 
143
  "unk_token": null
144
  }
video_preprocessor_config.json ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_valid_kwargs_names": [
3
+ "do_convert_rgb",
4
+ "do_resize",
5
+ "size",
6
+ "size_divisor",
7
+ "default_to_square",
8
+ "resample",
9
+ "do_rescale",
10
+ "rescale_factor",
11
+ "do_normalize",
12
+ "image_mean",
13
+ "image_std",
14
+ "do_pad",
15
+ "do_center_crop",
16
+ "crop_size",
17
+ "data_format",
18
+ "input_data_format",
19
+ "device",
20
+ "min_pixels",
21
+ "max_pixels",
22
+ "patch_size",
23
+ "temporal_patch_size",
24
+ "merge_size"
25
+ ],
26
+ "crop_size": null,
27
+ "data_format": "channels_first",
28
+ "default_to_square": true,
29
+ "device": null,
30
+ "do_center_crop": null,
31
+ "do_convert_rgb": true,
32
+ "do_normalize": true,
33
+ "do_pad": null,
34
+ "do_rescale": true,
35
+ "do_resize": true,
36
+ "image_mean": [
37
+ 0.48145466,
38
+ 0.4578275,
39
+ 0.40821073
40
+ ],
41
+ "image_processor_type": "Qwen2VLImageProcessor",
42
+ "image_std": [
43
+ 0.26862954,
44
+ 0.26130258,
45
+ 0.27577711
46
+ ],
47
+ "input_data_format": null,
48
+ "max_pixels": 12845056,
49
+ "merge_size": 2,
50
+ "min_pixels": 3136,
51
+ "model_valid_processing_keys": [
52
+ "do_convert_rgb",
53
+ "do_resize",
54
+ "size",
55
+ "size_divisor",
56
+ "default_to_square",
57
+ "resample",
58
+ "do_rescale",
59
+ "rescale_factor",
60
+ "do_normalize",
61
+ "image_mean",
62
+ "image_std",
63
+ "do_pad",
64
+ "do_center_crop",
65
+ "crop_size",
66
+ "data_format",
67
+ "input_data_format",
68
+ "device",
69
+ "min_pixels",
70
+ "max_pixels",
71
+ "patch_size",
72
+ "temporal_patch_size",
73
+ "merge_size"
74
+ ],
75
+ "patch_size": 14,
76
+ "processor_class": "Qwen2VLProcessor",
77
+ "resample": 3,
78
+ "rescale_factor": 0.00392156862745098,
79
+ "size": {
80
+ "longest_edge": 12845056,
81
+ "shortest_edge": 3136
82
+ },
83
+ "size_divisor": null,
84
+ "temporal_patch_size": 2,
85
+ "video_processor_type": "Qwen2VLVideoProcessor"
86
+ }