chen459664 commited on
Commit
bc2e152
·
verified ·
1 Parent(s): 480c63b

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. .python_history +18 -0
  2. llm-awq/awq.egg-info/PKG-INFO +319 -0
  3. llm-awq/awq.egg-info/SOURCES.txt +81 -0
  4. llm-awq/awq.egg-info/dependency_links.txt +1 -0
  5. llm-awq/awq.egg-info/requires.txt +16 -0
  6. llm-awq/awq/kernels/csrc/w8a8/reduction_utils.cuh +170 -0
  7. llm-awq/awq/quantize/__pycache__/__init__.cpython-311.pyc +0 -0
  8. llm-awq/awq/utils/calib_data.py +32 -0
  9. llm-awq/examples/README.md +10 -0
  10. llm-awq/examples/chat_demo.ipynb +272 -0
  11. llm-awq/examples/convert_to_hf.py +69 -0
  12. llm-awq/examples/llava_demo.ipynb +0 -0
  13. llm-awq/figures/vila-logo.jpg +0 -0
  14. llm-awq/scripts/DeepSeek_R1_Distill_example.sh +25 -0
  15. llm-awq/scripts/llama_example.sh +25 -0
  16. llm-awq/scripts/llava_example.sh +12 -0
  17. llm-awq/scripts/nvila_example.sh +12 -0
  18. llm-awq/scripts/opt_example.sh +25 -0
  19. llm-awq/scripts/qwen_example.sh +25 -0
  20. llm-awq/scripts/starcoder_example.sh +25 -0
  21. llm-awq/scripts/vicuna_example.sh +25 -0
  22. llm-awq/scripts/vila15_example.sh +14 -0
  23. llm-awq/scripts/vila_example.sh +12 -0
  24. llm-awq/tinychat/README.md +526 -0
  25. llm-awq/tinychat/benchmark.py +379 -0
  26. llm-awq/tinychat/demo.py +283 -0
  27. llm-awq/tinychat/internvl_benchmark.py +167 -0
  28. llm-awq/tinychat/internvl_demo.py +270 -0
  29. llm-awq/tinychat/models/__init__.py +10 -0
  30. llm-awq/tinychat/models/internvl/configuration_internvl.py +204 -0
  31. llm-awq/tinychat/models/internvl/conversation.py +391 -0
  32. llm-awq/tinychat/models/internvl/internvit.py +425 -0
  33. llm-awq/tinychat/models/internvl/media.py +113 -0
  34. llm-awq/tinychat/models/llama.py +413 -0
  35. llm-awq/tinychat/models/llava_base/llava_arch.py +412 -0
  36. llm-awq/tinychat/models/llava_base/multimodal_encoder/builder.py +21 -0
  37. llm-awq/tinychat/models/llava_base/multimodal_encoder/clip_encoder.py +97 -0
  38. llm-awq/tinychat/models/llava_base/multimodal_projector/builder.py +72 -0
  39. llm-awq/tinychat/models/llava_llama.py +282 -0
  40. llm-awq/tinychat/models/mpt.py +304 -0
  41. llm-awq/tinychat/models/nvila/configuration_llava.py +89 -0
  42. llm-awq/tinychat/models/nvila_qwen2.py +157 -0
  43. llm-awq/tinychat/modules/__init__.py +9 -0
  44. llm-awq/tinychat/modules/fused_mlp.py +101 -0
  45. llm-awq/tinychat/nvila_benchmark.py +163 -0
  46. llm-awq/tinychat/nvila_demo.py +272 -0
  47. llm-awq/tinychat/offline-weight-repacker.py +157 -0
  48. llm-awq/tinychat/scripts/llama2_demo.sh +31 -0
  49. llm-awq/tinychat/split_ckpt.py +51 -0
  50. llm-awq/tinychat/vila15_demo.py +264 -0
.python_history ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ a=[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2]
2
+ len(a)
3
+ a= " 1 "
4
+ int(a)
5
+ b=int(a)
6
+ b
7
+ type(b)
8
+ type(b)
9
+ type(b)
10
+ b
11
+ 3584*3584*2+3584+51282
12
+ 3584*18944*3
13
+ 203685888/25744978
14
+ 4096*4096*2+ 4096*1024*2
15
+ 4096*14336*3
16
+ 176160768/41943040
17
+ a=[29, 23, 24, 30, 18, 28, 26, 20, 16, 27, 25, 17, 19, 21]
18
+ len(a)
llm-awq/awq.egg-info/PKG-INFO ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: awq
3
+ Version: 0.1.0
4
+ Summary: An efficient and accurate low-bit weight quantization(INT3/4) method for LLMs.
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: accelerate==0.34.2
11
+ Requires-Dist: sentencepiece
12
+ Requires-Dist: tokenizers>=0.12.1
13
+ Requires-Dist: torch==2.3.0
14
+ Requires-Dist: torchvision==0.18.0
15
+ Requires-Dist: transformers==4.46.0
16
+ Requires-Dist: lm_eval==0.3.0
17
+ Requires-Dist: texttable
18
+ Requires-Dist: toml
19
+ Requires-Dist: attributedict
20
+ Requires-Dist: protobuf
21
+ Requires-Dist: gradio==3.35.2
22
+ Requires-Dist: gradio_client==0.2.9
23
+ Requires-Dist: fastapi
24
+ Requires-Dist: uvicorn
25
+ Requires-Dist: pydantic==1.10.19
26
+ Dynamic: license-file
27
+
28
+ # AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
29
+ [[Paper](https://arxiv.org/abs/2306.00978)][[Website](https://hanlab.mit.edu/projects/awq)]
30
+
31
+ **Efficient and accurate** low-bit weight quantization (INT3/4) for LLMs, supporting **instruction-tuned** models and **multi-modal** LMs.
32
+
33
+ ![overview](figures/overview.png)
34
+
35
+ The current release supports:
36
+
37
+ - AWQ search for accurate quantization.
38
+ - Pre-computed AWQ model zoo for LLMs (Llama-1/2/3, OPT, CodeLlama, StarCoder, Vicuna, VILA, LLaVA; load to generate quantized weights).
39
+ - Memory-efficient 4-bit Linear in PyTorch.
40
+ - Efficient CUDA kernel implementation for fast inference (support context and decoding stage).
41
+ - Examples on 4-bit inference of an instruction-tuned model (Vicuna) and **multi-modal LM** (VILA).
42
+ - Chunk prefilling for faster prefilling in multi-round Q&A setting.
43
+ - State-of-the-art prefilling speed of LLMs/VLMs on edge devices: [TinyChat 2.0](./tinychat).
44
+
45
+ **Thanks to AWQ, TinyChat can deliver more efficient responses with LLM/VLM chatbots through 4-bit inference.**
46
+
47
+ * TinyChat with LLaMA-3-8b on RTX 4090 (2.7x faster than FP16):
48
+
49
+ ![TinyChat with LLaMA-3-8b on RTX 4090: W4A16 is 2.7x faster than FP16](./tinychat/figures/4090_example_new.gif)
50
+
51
+ * TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
52
+
53
+ ![TinyChat with LLaMA-3-8b on Jetson Orin: W4A16 is 2.9x faster than FP16](./tinychat/figures/orin_example_new.gif)
54
+
55
+
56
+ **TinyChat also supports inference with vision language models (e.g., VILA, LLaVA). In the following examples, W4A16 quantized models from VILA family are launched with TinyChat.**
57
+
58
+ * TinyChat with NVILA-8B on RTX 4090 (single-image inputs):
59
+
60
+ ![TinyChat with NVILA on 4090 single image](./tinychat/figures/4090_nvila_single.gif)
61
+
62
+ * TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
63
+
64
+ ![TinyChat with NVILA on 4090 multiple images](./tinychat/figures/4090_nvila_multi.gif)
65
+
66
+ <!-- Check out [TinyChat](tinychat), which delievers **30 tokens/second** inference performance (**3.2x faster** than FP16) for the **Llama2** chatbot on the resource-constrained NVIDIA Jetson Orin! -->
67
+
68
+ * TinyChat with video reasoning:
69
+
70
+ https://github.com/user-attachments/assets/b68a7a0d-5175-4030-985b-5ae0ae94f874
71
+
72
+ **Prompt:** What might be the next step according to the video?
73
+
74
+ **Answer:** The next step in the video could be to place the shaped dough onto a baking sheet and let it rise before baking.
75
+
76
+ **Online demo:** https://vila.hanlab.ai
77
+
78
+ Check out [TinyChat](tinychat), which offers a turn-key solution for **on-device inference** of LLMs and VLMs on **resource-constrained edge platforms**. With TinyChat, it is now possible to efficiently run **large** models on **small** and **low-power** devices even without Internet connection!
79
+
80
+
81
+ ## News
82
+ - [2025/04] 🔥 AWQ now supports DeepSeek-R1-Distilled models. Try our example [here](https://github.com/mit-han-lab/llm-awq/blob/main/scripts/DeepSeek_R1_Distill_example.sh)!
83
+ - [2025/02] AWQ now supports BF16 precision. See example [here](https://github.com/mit-han-lab/llm-awq/blob/main/scripts/qwen_example.sh).
84
+ - [2024/10] 🔥⚡ Explore advancements in [TinyChat 2.0](./tinychat), the latest version with significant advancements in prefilling speed of Edge LLMs and VLMs, **1.5-1.7x** faster than the previous version of TinyChat. Please refer to the [README](./tinychat/README.md) and [blog](https://hanlab.mit.edu/blog/tinychat20) for more details.
85
+ - [2024/05] 🏆 AWQ receives the **Best Paper Award** at **MLSys 2024**. 🎉
86
+ - [2024/05] 🔥 The **VILA-1.5** model family which features **video understanding** is now supported in AWQ and TinyChat. Check out out online demo powered by TinyChat [here](https://vila.hanlab.ai). Example is [here](scripts/vila15_example.sh).
87
+ - [2024/05] 🔥 [AMD](https://community.amd.com/t5/ai/reduce-memory-footprint-and-improve-performance-running-llms-on/ba-p/686157) adopts AWQ to improve LLM serving efficiency.
88
+ - [2024/04] 🔥 We released AWQ and TinyChat support for The **Llama-3** model family! Check out our example [here](scripts/llama3_example.sh).
89
+ - [2024/02] 🔥 AWQ has been accepted to **MLSys 2024**!
90
+ - [2024/02] 🔥 We supported [VILA Vision Languague Models](https://arxiv.org/abs/2312.07533) in AWQ & TinyChat! Check our latest demos with multi-image inputs!
91
+ - [2024/02] 🔥 We released new version of quantized GEMM/GEMV kernels in [**TinyChat**](tinychat), leading to **38 tokens/second** inference speed on NVIDIA Jetson Orin!
92
+ - [2024/01] 🔥 AWQ has been integrated by [Google Vertex AI](https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama-2-quantized)!
93
+ - [2023/11] 🔥 AWQ has been integrated by [Amazon Sagemaker Containers](https://aws.amazon.com/blogs/machine-learning/boost-inference-performance-for-llms-with-new-amazon-sagemaker-containers/)!
94
+ - [2023/11] 🔥 We added AWQ support and pre-computed search results for CodeLlama, StarCoder, StableCode models. Checkout our model zoo [here](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo)!
95
+ - [2023/11] 🔥 AWQ is now integrated natively in Hugging Face transformers through `from_pretrained`. You can either load quantized models from the Hub or your own HF quantized models.
96
+ - [2023/10] AWQ is integrated into NVIDIA [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM/)
97
+ - [2023/09] AWQ is integrated into [Intel Neural Compressor](https://github.com/intel/neural-compressor), [FastChat](https://github.com/lm-sys/FastChat/blob/main/docs/awq.md), [vLLM](https://github.com/vllm-project/vllm/blob/main/vllm/model_executor/layers/quantization/awq.py), [HuggingFace TGI](https://github.com/huggingface/text-generation-inference/pull/1054), and [LMDeploy](https://github.com/InternLM/lmdeploy).
98
+ - [2023/09] ⚡ Check out our latest [**TinyChat**](tinychat), which is ~2x faster than the first release on Orin!
99
+ - [2023/09] ⚡ Check out [**AutoAWQ**](https://github.com/casper-hansen/AutoAWQ), a third-party implementation to make AWQ easier to expand to new models, improve inference speed, and integrate into Huggingface.
100
+ - [2023/07] 🔥 We released **TinyChat**, an efficient and lightweight chatbot interface based on AWQ. TinyChat enables efficient LLM inference on both cloud and edge GPUs. Llama-2-chat models are supported! Check out our implementation [here](tinychat).
101
+ - [2023/07] 🔥 We added AWQ support and pre-computed search results for Llama-2 models (7B & 13B). Checkout our model zoo [here](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo)!
102
+ - [2023/07] We extended the support for more LLM models including MPT, Falcon, and BLOOM.
103
+
104
+ ## Contents
105
+
106
+ - [AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration](#awq-activation-aware-weight-quantization-for-llm-compression-and-acceleration)
107
+ - [News](#news)
108
+ - [Contents](#contents)
109
+ - [Helpful Links](#helpful-links)
110
+ - [Install](#install)
111
+ - [AWQ Model Zoo](#awq-model-zoo)
112
+ - [Examples](#examples)
113
+ - [Usage](#usage)
114
+ - [Results on Visual Language Models](#results-on-visual-language-models)
115
+ - [Reference](#reference)
116
+ - [Related Projects](#related-projects)
117
+
118
+ ## Helpful Links
119
+
120
+ - [VILA online demo](vila.hanlab.ai): Visual Language Models efficiently supported by AWQ & TinyChat.
121
+ - [LLM on the Edge](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop?tab=readme-ov-file#install): AWQ and TinyChat support edge GPUs such as NVIDIA Jetson Orin.
122
+ - [VLMs on Laptop](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop?tab=readme-ov-file#run-vila-on-laptop): Follow the instructions to deploy VLMs on NVIDIA Laptops with TinyChat.
123
+ - [Gradio Server](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop/tinychat/serve#gradio-demo-vila-with-tinychat): Try to build your own VLM online demo with AWQ and TinyChat!
124
+ - [QServe](https://github.com/mit-han-lab/qserve): 🔥 **[New]** Efficient and accurate serving system for large-scale LLM inference.
125
+
126
+ ## Install
127
+
128
+ 1. Clone this repository and navigate to AWQ folder
129
+ ```
130
+ git clone https://github.com/mit-han-lab/llm-awq
131
+ cd llm-awq
132
+ ```
133
+
134
+ 2. Install Package
135
+ ```
136
+ conda create -n awq python=3.10 -y
137
+ conda activate awq
138
+ pip install --upgrade pip # enable PEP 660 support
139
+ pip install -e .
140
+ ```
141
+
142
+ * For **edge devices** like Orin, before running the commands above, please:
143
+
144
+ 1. Modify [pyproject.toml](pyproject.toml) by commenting out [this line](https://github.com/mit-han-lab/llm-awq/blob/3fce69061682fdd528824e5da3d03a8a8b545f2a/pyproject.toml#L17).
145
+ 2. Manually install precompiled PyTorch binaries (>=2.0.0) from [NVIDIA](https://forums.developer.nvidia.com/t/pytorch-for-jetson/72048). You also need to install torchvision from this website when running NVILA.
146
+ 3. Set the appropriate Python version for conda environment (e.g., `conda create -n awq python=3.8 -y` for JetPack 5).
147
+
148
+ 3. Install efficient W4A16 (4-bit weight, 16-bit activation) CUDA kernel and optimized FP16 kernels (e.g. layernorm, positional encodings).
149
+ ```
150
+ cd awq/kernels
151
+ python setup.py install
152
+ ```
153
+
154
+ 4. Install Flash Attention
155
+ ```
156
+ pip install flash-attn --no-build-isolation
157
+ ```
158
+
159
+ We recommend starting an interactive python CLI interface and run `import flash_attn` to check whether FlashAttention-2 is installed successfully. If not, we recommend downloading pre-built wheels from [here](https://github.com/Dao-AILab/flash-attention/releases/tag/v2.5.8). Please notice:
160
+
161
+ - PyTorch version needs to exactly match with the version specified in the `.whl` name;
162
+ - Check out both `cxx11abiTRUE` and `cxx11abiFALSE` wheels if one of them does not work;
163
+ - It's recommended to match CUDA version specified in the `.whl` filename, but minor mismatches (e.g. 12.1 vs 12.2, or even 11.8 vs 12.2) usually do not matter.
164
+
165
+
166
+ 5. [Optional] In order to run AWQ and TinyChat with NVILA model family, please install VILA:
167
+
168
+ ```bash
169
+ git clone https://github.com/NVlabs/VILA.git
170
+ cd VILA
171
+ pip install -e .
172
+ ```
173
+
174
+ ## AWQ Model Zoo
175
+
176
+ We provide pre-computed AWQ search results for multiple model families, including LLaMA, OPT, Vicuna, and LLaVA. To get the pre-computed AWQ search results, run:
177
+
178
+ ```bash
179
+ # git lfs install # install git lfs if not already
180
+ git clone https://huggingface.co/datasets/mit-han-lab/awq-model-zoo awq_cache
181
+ ```
182
+
183
+ The detailed support list:
184
+
185
+ | Models | Sizes | INT4-g128 | INT3-g128 |
186
+ | ------ | --------------------------- | --------- | --------- |
187
+ | [DeepSeek-R1-Distill](/scripts/DeepSeek_R1_Distill_example.sh) | 1.5B/7B/8B | ✅ | |
188
+ | [Qwen-2.5](/scripts/qwen_example.sh) | 7B/72B | ✅ | |
189
+ | [NVILA](/scripts/nvila_example.sh) | 3B/8B | ✅ | |
190
+ | [VILA-1.5](/scripts/vila15_example.sh) | 3B/8B/13B/40B | ✅ | ✅ |
191
+ | [Llama3](/scripts/llama_example.sh) | 8B/70B | ✅ | ✅ |
192
+ | [VILA](/scripts/vila_example.sh) | 7B/13B | ✅ | |
193
+ | [Llama2](/scripts/llama_example.sh) | 7B/13B/70B | ✅ | ✅ |
194
+ | [LLaMA](/scripts/llama2_example.sh) | 7B/13B/30B/65B | ✅ | ✅ |
195
+ | [OPT](/scripts/opt_example.sh) | 125m/1.3B/2.7B/6.7B/13B/30B | ✅ | ✅ |
196
+ | [CodeLlama](/scripts/codellama_example.sh) | 7B/13B/34B | ✅ | ✅ |
197
+ | [StarCoder](/scripts/starcoder_example.sh) | 15.5B | ✅ | ✅ |
198
+ | [Vicuna-v1.1](/scripts/vicuna_example.sh) | 7B/13B | ✅ | |
199
+ | [LLaVA-v0](/scripts/llava_example.sh) | 13B | ✅ | |
200
+
201
+ Note: We only list models that we have prepare the [AWQ searching results](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo/tree/main) in the table above. AWQ also supports models such as LLaVA-v1.5 7B, and you may need to run the [AWQ search](#usage) on your own to quantize these models. For our latest VLM NVILA, quantized weights are available [here](https://huggingface.co/Efficient-Large-Model/NVILA-AWQ).
202
+
203
+ ## Examples
204
+
205
+ AWQ can be easily applied to various LMs thanks to its good generalization, including instruction-tuned models and multi-modal LMs. It provides an easy-to-use tool to reduce the serving cost of LLMs.
206
+
207
+ Here we provide two examples of AWQ application: Vicuna-7B (chatbot) and LLaVA-13B (visual reasoning) under `./examples` directory. AWQ can easily reduce the GPU memory of model serving and speed up token generation. It provides accurate quantization, providing reasoning outputs. You should be able to observe **memory savings** when running the models with 4-bit weights.
208
+
209
+ Note that we perform AWQ using only textual calibration data, depsite we are running on multi-modal input. Please refer to `./examples` for details.
210
+
211
+ ![overview](figures/example_vis.jpg)
212
+
213
+ ## Usage
214
+
215
+ We provide several sample script to run AWQ (please refer to `./scripts`). We use Llama3-8B as an example.
216
+
217
+ 1. Perform AWQ search and save search results (we already did it for you):
218
+ ```bash
219
+ python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
220
+ --w_bit 4 --q_group_size 128 \
221
+ --run_awq --dump_awq awq_cache/llama3-8b-w4-g128.pt
222
+ ```
223
+
224
+ 2. Evaluate the AWQ quantized model on WikiText-2 (simulated pseudo quantization)
225
+ ```bash
226
+ python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
227
+ --tasks wikitext \
228
+ --w_bit 4 --q_group_size 128 \
229
+ --load_awq awq_cache/llama3-8b-w4-g128.pt \
230
+ --q_backend fake
231
+ ```
232
+
233
+ 3. Generate real quantized weights (INT4)
234
+ ```bash
235
+ mkdir quant_cache
236
+ python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
237
+ --w_bit 4 --q_group_size 128 \
238
+ --load_awq awq_cache/llama3-8b-w4-g128.pt \
239
+ --q_backend real --dump_quant quant_cache/llama3-8b-w4-g128-awq.pt
240
+ ```
241
+
242
+ 4. Load and evaluate the real quantized model (now you can see smaller gpu memory usage)
243
+ ```bash
244
+ python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
245
+ --tasks wikitext \
246
+ --w_bit 4 --q_group_size 128 \
247
+ --load_quant quant_cache/llama3-8b-w4-g128-awq.pt
248
+ ```
249
+ ## Results on Visual Language Models
250
+
251
+ AWQ also seamlessly supports large multi-modal models (LMMs). Please refer to [TinyChat](./tinychat/README.md) for more details.
252
+
253
+
254
+ <!-- AWQ also seamlessly supports large multi-modal models (LMMs). We demonstrate the results on the recent [VILA-1.5](https://github.com/Efficient-Large-Model/VILA) model family. -->
255
+
256
+ <!--
257
+ | VILA-1.5-3B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
258
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
259
+ | FP16 | 80.4 | 61.5 | 53.5 | 69.0 | 60.4 | 85.9 | 1442.4 | 63.4 | 52.7 | 60.9 |
260
+ | AWQ-INT4 | 80.0 | 61.1 | 53.8 | 67.8 | 60.4 | 85.9 | 1437.3 | 63.3 | 51.4 | 59.8 |
261
+
262
+ | VILA-1.5-8B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
263
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
264
+ | FP16 | 80.9 | 61.9 | 58.7 | 79.9 | 66.3 | 84.4 | 1577.01 | 72.3 | 66.2 | 64.2 |
265
+ | AWQ-INT4 | 80.3 | 61.7 | 59.3 | 79.0 | 65.4 | 82.9 | 1593.65 | 71.0 | 64.9 | 64.0 |
266
+
267
+ | VILA-1.5-13B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
268
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
269
+ | FP16 | 82.8 | 64.3 | 62.6 | 80.1 | 65.0 | 86.3 | 1569.55 | 74.9 | 66.3 | 65.1 |
270
+ | AWQ-INT4 | 82.7 | 64.5 | 63.3 | 79.7 | 64.7 | 86.7 | 1531.35 | 74.7 | 66.7 | 65.1 |
271
+
272
+
273
+ | VILA-1.5-40B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
274
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
275
+ | FP16 | 84.3 | 64.6 | 62.2 | 87.2 | 73.6 | 87.3 | 1726.82 | 82.4 | 80.2 | 69.1 |
276
+ | AWQ-INT4 | 84.1 | 64.4 | 61.3 | 86.7 | 73.2 | 88.2 | 1714.79 | 83.2 | 79.6 | 68.9 |
277
+
278
+
279
+ ## Inference speed ( Token/sec )
280
+
281
+ | $~~~~~~$ | Precision | A100 | 4090 | Orin |
282
+ | ---------------------- | --------- | ----- | ----- | ---- |
283
+ | VILA1.5-3B | fp16 | 104.6 | 137.6 | 25.4 |
284
+ | VILA1.5-3B-AWQ | int4 | 182.8 | 215.5 | 42.5 |
285
+ | VILA1.5-3B-S2 | fp16 | 104.3 | 137.2 | 24.6 |
286
+ | VILA1.5-3B-S2-AWQ | int4 | 180.2 | 219.3 | 40.1 |
287
+ | Llama-3-VILA1.5-8B | fp16 | 74.9 | 57.4 | 10.2 |
288
+ | Llama-3-VILA1.5-8B-AWQ | int4 | 168.9 | 150.2 | 28.7 |
289
+ | VILA1.5-13B | fp16 | 50.9 | OOM | 6.1 |
290
+ | VILA1.5-13B-AWQ | int4 | 115.9 | 105.7 | 20.6 |
291
+ | VILA1.5-40B | fp16 | OOM | OOM | -- |
292
+ | VILA1.5-40B-AWQ | int4 | 57.0 | OOM | -- | -->
293
+
294
+
295
+ ## Reference
296
+
297
+ If you find AWQ useful or relevant to your research, please kindly cite our paper:
298
+
299
+ ```
300
+ @inproceedings{lin2023awq,
301
+ title={AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration},
302
+ author={Lin, Ji and Tang, Jiaming and Tang, Haotian and Yang, Shang and Chen, Wei-Ming and Wang, Wei-Chen and Xiao, Guangxuan and Dang, Xingyu and Gan, Chuang and Han, Song},
303
+ booktitle={MLSys},
304
+ year={2024}
305
+ }
306
+ ```
307
+
308
+ ## Related Projects
309
+
310
+ [SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models](https://github.com/mit-han-lab/smoothquant)
311
+
312
+ [GPTQ: Accurate Post-training Compression for Generative Pretrained Transformers](https://arxiv.org/abs/2210.17323)
313
+
314
+ [Vicuna and FastChat](https://github.com/lm-sys/FastChat#readme)
315
+
316
+ [LLaVA: Large Language and Vision Assistant](https://github.com/haotian-liu/LLaVA)
317
+
318
+ [VILA: On Pre-training for Visual Language Models](https://github.com/Efficient-Large-Model/VILA)
319
+
llm-awq/awq.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ awq/entry.py
5
+ awq.egg-info/PKG-INFO
6
+ awq.egg-info/SOURCES.txt
7
+ awq.egg-info/dependency_links.txt
8
+ awq.egg-info/requires.txt
9
+ awq.egg-info/top_level.txt
10
+ awq/kernels/setup.py
11
+ awq/kernels/csrc/attention/setup.py
12
+ awq/quantize/__init__.py
13
+ awq/quantize/auto_clip.py
14
+ awq/quantize/auto_scale.py
15
+ awq/quantize/pre_quant.py
16
+ awq/quantize/qmodule.py
17
+ awq/quantize/quantizer.py
18
+ awq/quantize/smooth.py
19
+ awq/quantize/w8a8_linear.py
20
+ awq/utils/__init__.py
21
+ awq/utils/calib_data.py
22
+ awq/utils/lm_eval_adaptor.py
23
+ awq/utils/module.py
24
+ awq/utils/parallel.py
25
+ awq/utils/utils.py
26
+ tinychat/benchmark.py
27
+ tinychat/demo.py
28
+ tinychat/internvl_benchmark.py
29
+ tinychat/internvl_demo.py
30
+ tinychat/nvila_benchmark.py
31
+ tinychat/nvila_demo.py
32
+ tinychat/offline-weight-repacker.py
33
+ tinychat/split_ckpt.py
34
+ tinychat/vila10_demo.py
35
+ tinychat/vila15_demo.py
36
+ tinychat/models/__init__.py
37
+ tinychat/models/falcon.py
38
+ tinychat/models/internvl3.py
39
+ tinychat/models/llama.py
40
+ tinychat/models/llava_llama.py
41
+ tinychat/models/mpt.py
42
+ tinychat/models/nvila_qwen2.py
43
+ tinychat/models/qwen2.py
44
+ tinychat/models/vila_llama.py
45
+ tinychat/models/internvl/configuration_internvl.py
46
+ tinychat/models/internvl/conversation.py
47
+ tinychat/models/internvl/internvit.py
48
+ tinychat/models/internvl/media.py
49
+ tinychat/models/llava_base/llava_arch.py
50
+ tinychat/models/llava_base/multimodal_encoder/builder.py
51
+ tinychat/models/llava_base/multimodal_encoder/clip_encoder.py
52
+ tinychat/models/llava_base/multimodal_projector/builder.py
53
+ tinychat/models/nvila/builder.py
54
+ tinychat/models/nvila/configuration_llava.py
55
+ tinychat/models/nvila/llava_arch.py
56
+ tinychat/modules/__init__.py
57
+ tinychat/modules/fused_attn.py
58
+ tinychat/modules/fused_internencoder.py
59
+ tinychat/modules/fused_mlp.py
60
+ tinychat/modules/fused_norm.py
61
+ tinychat/modules/fused_siglipdecoder.py
62
+ tinychat/modules/fused_vision_attn.py
63
+ tinychat/serve/controller.py
64
+ tinychat/serve/gradio_web_server.py
65
+ tinychat/serve/llava_conv.py
66
+ tinychat/serve/model_worker.py
67
+ tinychat/serve/model_worker_new.py
68
+ tinychat/stream_generators/NVILA_stream_gen.py
69
+ tinychat/stream_generators/__init__.py
70
+ tinychat/stream_generators/internvl_stream_gen.py
71
+ tinychat/stream_generators/llava_stream_gen.py
72
+ tinychat/stream_generators/stream_gen.py
73
+ tinychat/utils/__init__.py
74
+ tinychat/utils/constants.py
75
+ tinychat/utils/conversation_utils.py
76
+ tinychat/utils/input_metadata.py
77
+ tinychat/utils/llava_image_processing.py
78
+ tinychat/utils/load_quant.py
79
+ tinychat/utils/log_utils.py
80
+ tinychat/utils/prompt_templates.py
81
+ tinychat/utils/tune.py
llm-awq/awq.egg-info/dependency_links.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
llm-awq/awq.egg-info/requires.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ accelerate==0.34.2
2
+ sentencepiece
3
+ tokenizers>=0.12.1
4
+ torch==2.3.0
5
+ torchvision==0.18.0
6
+ transformers==4.46.0
7
+ lm_eval==0.3.0
8
+ texttable
9
+ toml
10
+ attributedict
11
+ protobuf
12
+ gradio==3.35.2
13
+ gradio_client==0.2.9
14
+ fastapi
15
+ uvicorn
16
+ pydantic==1.10.19
llm-awq/awq/kernels/csrc/w8a8/reduction_utils.cuh ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Adapted from https://github.com/NVIDIA/FasterTransformer/blob/release/v5.3_tag/src/fastertransformer/kernels/reduce_kernel_utils.cuh
3
+ * Copyright (c) 2023, The vLLM team.
4
+ * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ #pragma once
19
+ #define FINAL_MASK 0xffffffff
20
+
21
+
22
+ namespace vllm {
23
+
24
+ template<typename T>
25
+ __inline__ __device__ T warpReduceSum(T val) {
26
+ #pragma unroll
27
+ for (int mask = 16; mask > 0; mask >>= 1)
28
+ val += __shfl_xor_sync(0xffffffff, val, mask, 32);
29
+ return val;
30
+ }
31
+
32
+ template <typename T, int NUM>
33
+ __inline__ __device__ T warpReduceSumV2(T* val)
34
+ {
35
+ #pragma unroll
36
+ for (int i = 0; i < NUM; i++)
37
+ {
38
+ #pragma unroll
39
+ for (int mask = 16; mask > 0; mask >>= 1)
40
+ val[i] += __shfl_xor_sync(FINAL_MASK, val[i], mask, 32);
41
+ }
42
+ return (T) (0.0f);
43
+ }
44
+
45
+ /* Calculate the sum of all elements in a block */
46
+ template<typename T>
47
+ __inline__ __device__ T blockReduceSum(T val) {
48
+ static __shared__ T shared[32];
49
+ int lane = threadIdx.x & 0x1f;
50
+ int wid = threadIdx.x >> 5;
51
+
52
+ val = warpReduceSum<T>(val);
53
+
54
+ if (lane == 0)
55
+ shared[wid] = val;
56
+
57
+ __syncthreads();
58
+
59
+ // Modify from blockDim.x << 5 to blockDim.x / 32. to prevent
60
+ // blockDim.x is not divided by 32
61
+ val = (threadIdx.x < (blockDim.x / 32.f)) ? shared[lane] : (T)(0.0f);
62
+ val = warpReduceSum<T>(val);
63
+ return val;
64
+ }
65
+
66
+ /* Calculate the sum of all elements in a block */
67
+ template<typename T>
68
+ __inline__ __device__ T blockAllReduceSum(T val) {
69
+ static __shared__ T shared[32];
70
+ int lane = threadIdx.x & 0x1f;
71
+ int wid = threadIdx.x >> 5;
72
+
73
+ val = warpReduceSum<T>(val);
74
+
75
+ if (lane == 0)
76
+ shared[wid] = val;
77
+
78
+ __syncthreads();
79
+
80
+ // Modify from blockDim.x << 5 to blockDim.x / 32. to prevent
81
+ // blockDim.x is not divided by 32
82
+ val = (lane < (blockDim.x / 32.f)) ? shared[lane] : (T)(0.0f);
83
+ val = warpReduceSum<T>(val);
84
+ return val;
85
+ }
86
+
87
+ template <typename T, int NUM>
88
+ __inline__ __device__ T blockReduceSumV2(T* val)
89
+ {
90
+ static __shared__ T shared[NUM][33];
91
+ int lane = threadIdx.x & 0x1f;
92
+ int wid = threadIdx.x >> 5;
93
+
94
+ warpReduceSumV2<T, NUM>(val);
95
+
96
+ if (lane == 0)
97
+ {
98
+ #pragma unroll
99
+ for (int i = 0; i < NUM; i++)
100
+ {
101
+ shared[i][wid] = val[i];
102
+ }
103
+ }
104
+
105
+ __syncthreads();
106
+
107
+ bool is_mask = threadIdx.x < (blockDim.x / 32.f);
108
+ #pragma unroll
109
+ for (int i = 0; i < NUM; i++)
110
+ {
111
+ val[i] = is_mask ? shared[i][lane] : (T) (0.0f);
112
+ }
113
+ warpReduceSumV2<T, NUM>(val);
114
+ return (T) 0.0f;
115
+ }
116
+
117
+ template<typename T>
118
+ __inline__ __device__ T warpReduceMax(T val)
119
+ {
120
+ #pragma unroll
121
+ for (int mask = 16; mask > 0; mask >>= 1)
122
+ val = max(val, __shfl_xor_sync(0xffffffff, val, mask, 32));
123
+ return val;
124
+ }
125
+ /* Calculate the maximum of all elements in a block */
126
+ template<typename T>
127
+ __inline__ __device__ T blockReduceMax(T val)
128
+ {
129
+ static __shared__ T shared[32];
130
+ int lane = threadIdx.x & 0x1f; // in-warp idx
131
+ int wid = threadIdx.x >> 5; // warp idx
132
+ val = warpReduceMax(val); // get maxx in each warp
133
+ if (lane == 0) // record in-warp maxx by warp Idx
134
+ shared[wid] = val;
135
+ __syncthreads();
136
+ // Modify from blockDim.x << 5 to blockDim.x / 32. to prevent
137
+ // blockDim.x is not divided by 32
138
+ val = (threadIdx.x < (blockDim.x / 32.f)) ? shared[lane] : -1e20f;
139
+ val = warpReduceMax(val);
140
+ return val;
141
+ }
142
+
143
+ /* Calculate the maximum of all elements in a block */
144
+ template <typename T>
145
+ __inline__ __device__ T blockAllReduceMax(T val)
146
+ {
147
+ static __shared__ T shared[32];
148
+ int lane = threadIdx.x & 0x1f; // in-warp idx
149
+ int wid = threadIdx.x >> 5; // warp idx
150
+
151
+ val = warpReduceMax(val); // get maxx in each warp
152
+
153
+ if (lane == 0) // record in-warp maxx by warp Idx
154
+ shared[wid] = val;
155
+
156
+ __syncthreads();
157
+
158
+ // Modify from blockDim.x << 5 to blockDim.x / 32. to prevent
159
+ // blockDim.x is not divided by 32
160
+ val = (lane < (blockDim.x / 32.f)) ? shared[lane] : -1e20f;
161
+ val = warpReduceMax(val);
162
+
163
+ return val;
164
+ }
165
+
166
+
167
+
168
+
169
+
170
+ } // namespace vllm
llm-awq/awq/quantize/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (246 Bytes). View file
 
llm-awq/awq/utils/calib_data.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from datasets import load_dataset
3
+
4
+
5
+ def get_calib_dataset(data="pileval", tokenizer=None, n_samples=512, block_size=512):
6
+ if data == "pileval":
7
+ dataset = load_dataset("mit-han-lab/pile-val-backup", split="validation")
8
+ else:
9
+ raise NotImplementedError
10
+ dataset = dataset.shuffle(seed=42)
11
+ samples = []
12
+ n_run = 0
13
+ for data in dataset:
14
+ line = data["text"]
15
+ line = line.strip()
16
+ line_encoded = tokenizer.encode(line)
17
+ if len(line_encoded) > 512:
18
+ continue
19
+ sample = torch.tensor([line_encoded])
20
+ if sample.numel() == 0:
21
+ continue
22
+ samples.append(sample)
23
+ n_run += 1
24
+ if n_run == n_samples:
25
+ break
26
+ # now concatenate all samples and split according to block size
27
+ cat_samples = torch.cat(samples, dim=1)
28
+ n_split = cat_samples.shape[1] // block_size
29
+ print(f" * Split into {n_split} blocks")
30
+ return [
31
+ cat_samples[:, i * block_size : (i + 1) * block_size] for i in range(n_split)
32
+ ]
llm-awq/examples/README.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # AWQ Examples
2
+
3
+ Here we provide two AWQ examples, applying to:
4
+ - [Vicuna-7B](https://github.com/lm-sys/FastChat), a chatbot with instruction-tuning
5
+ - [LLaVA-13B](https://github.com/lm-sys/FastChat), a visual LM for multi-modal applications like visual reasoning.
6
+ - [A simple conversion script](https://github.com/mit-han-lab/llm-awq/tree/main/examples/convert_to_hf.py) to convert llm-awq weights into HF format.
7
+
8
+ Here are some example output from the two demos. You should able to observe memory saving when running the demos in 4-bit. Please check the notebooks for details.
9
+
10
+ ![overview](../figures/example_vis.jpg)
llm-awq/examples/chat_demo.ipynb ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# AWQ on Vicuna"
8
+ ]
9
+ },
10
+ {
11
+ "cell_type": "markdown",
12
+ "metadata": {},
13
+ "source": [
14
+ "In this notebook, we use Vicuna model to demonstrate the performance of AWQ on instruction-tuned models. We implement AWQ real-INT4 inference kernels, which are wrapped as Pytorch modules and can be easily used by existing models. We also provide a simple example to show how to use AWQ to quantize a model and save/load the quantized model checkpoint."
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "markdown",
19
+ "metadata": {},
20
+ "source": [
21
+ "In order to run this notebook, you need to install the following packages:\n",
22
+ "- [AWQ](https://github.com/mit-han-lab/llm-awq)\n",
23
+ "- [Pytorch](https://pytorch.org/)\n",
24
+ "- [Accelerate](https://github.com/huggingface/accelerate)\n",
25
+ "- [Transformers](https://github.com/huggingface/transformers)"
26
+ ]
27
+ },
28
+ {
29
+ "cell_type": "code",
30
+ "execution_count": 1,
31
+ "metadata": {},
32
+ "outputs": [],
33
+ "source": [
34
+ "import torch\n",
35
+ "from accelerate import init_empty_weights, load_checkpoint_and_dispatch\n",
36
+ "from awq.quantize.quantizer import real_quantize_model_weight\n",
37
+ "from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfig\n",
38
+ "from tinychat.demo import gen_params, stream_output\n",
39
+ "from tinychat.stream_generators import StreamGenerator\n",
40
+ "from tinychat.modules import make_quant_norm, make_quant_attn, make_fused_mlp\n",
41
+ "from tinychat.utils.prompt_templates import get_prompter\n",
42
+ "import os\n",
43
+ "# This demo only support single GPU for now\n",
44
+ "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\""
45
+ ]
46
+ },
47
+ {
48
+ "cell_type": "markdown",
49
+ "metadata": {},
50
+ "source": [
51
+ "Please get the Vicuna model from [FastChat](https://github.com/lm-sys/FastChat) and run the following command to generate a quantized model checkpoint first.\n",
52
+ "\n",
53
+ "```bash\n",
54
+ "mkdir quant_cache\n",
55
+ "python -m awq.entry --model_path [vicuna-7b_model_path] \\\n",
56
+ " --w_bit 4 --q_group_size 128 \\\n",
57
+ " --load_awq awq_cache/vicuna-7b-w4-g128.pt \\\n",
58
+ " --q_backend real --dump_quant quant_cache/vicuna-7b-w4-g128-awq.pt\n",
59
+ "```"
60
+ ]
61
+ },
62
+ {
63
+ "cell_type": "code",
64
+ "execution_count": 2,
65
+ "metadata": {},
66
+ "outputs": [],
67
+ "source": [
68
+ "# model_path = \"\" # the path of vicuna-7b model\n",
69
+ "# load_quant_path = \"quant_cache/vicuna-7b-w4-g128-awq.pt\"\n",
70
+ "model_path = \"/data/llm/checkpoints/vicuna-hf/vicuna-7b\"\n",
71
+ "load_quant_path = \"/data/llm/checkpoints/vicuna-hf/vicuna-7b-awq-w4g128.pt\""
72
+ ]
73
+ },
74
+ {
75
+ "cell_type": "markdown",
76
+ "metadata": {},
77
+ "source": [
78
+ "We first load a empty model and replace all the linear layers with WQLinear layers. Then we load the quantized weights from the checkpoint. "
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": 3,
84
+ "metadata": {},
85
+ "outputs": [
86
+ {
87
+ "data": {
88
+ "application/vnd.jupyter.widget-view+json": {
89
+ "model_id": "8b79a82b73ab4d9191ba54f5d0f8cb86",
90
+ "version_major": 2,
91
+ "version_minor": 0
92
+ },
93
+ "text/plain": [
94
+ "Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]"
95
+ ]
96
+ },
97
+ "metadata": {},
98
+ "output_type": "display_data"
99
+ },
100
+ {
101
+ "name": "stderr",
102
+ "output_type": "stream",
103
+ "text": [
104
+ "real weight quantization...(init only): 100%|███████████████████| 32/32 [00:11<00:00, 2.69it/s]\n",
105
+ "The model weights are not tied. Please use the `tie_weights` method before using the `infer_auto_device` function.\n",
106
+ "The model weights are not tied. Please use the `tie_weights` method before using the `infer_auto_device` function.\n"
107
+ ]
108
+ }
109
+ ],
110
+ "source": [
111
+ "config = AutoConfig.from_pretrained(model_path)\n",
112
+ "tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)\n",
113
+ "with init_empty_weights():\n",
114
+ " model = AutoModelForCausalLM.from_pretrained(model_path, config=config,\n",
115
+ " torch_dtype=torch.float16)\n",
116
+ "q_config = {\"zero_point\": True, \"q_group_size\": 128}\n",
117
+ "real_quantize_model_weight(\n",
118
+ " model, w_bit=4, q_config=q_config, init_only=True)\n",
119
+ "\n",
120
+ "model = load_checkpoint_and_dispatch(\n",
121
+ " model, load_quant_path,\n",
122
+ " device_map=\"auto\",\n",
123
+ " no_split_module_classes=[\"LlamaDecoderLayer\"]\n",
124
+ ")"
125
+ ]
126
+ },
127
+ {
128
+ "cell_type": "code",
129
+ "execution_count": 4,
130
+ "metadata": {},
131
+ "outputs": [
132
+ {
133
+ "name": "stdout",
134
+ "output_type": "stream",
135
+ "text": [
136
+ "[Warning] Calling a fake MLP fusion. But still faster than Huggingface Implimentation.\n"
137
+ ]
138
+ },
139
+ {
140
+ "data": {
141
+ "text/plain": [
142
+ "LlamaForCausalLM(\n",
143
+ " (model): LlamaModel(\n",
144
+ " (embed_tokens): Embedding(32000, 4096, padding_idx=0)\n",
145
+ " (layers): ModuleList(\n",
146
+ " (0-31): 32 x LlamaDecoderLayer(\n",
147
+ " (self_attn): QuantLlamaAttention(\n",
148
+ " (qkv_proj): WQLinear(in_features=4096, out_features=12288, bias=False, w_bit=4, group_size=128)\n",
149
+ " (o_proj): WQLinear(in_features=4096, out_features=4096, bias=False, w_bit=4, group_size=128)\n",
150
+ " (rotary_emb): QuantLlamaRotaryEmbedding()\n",
151
+ " )\n",
152
+ " (mlp): QuantLlamaMLP(\n",
153
+ " (down_proj): WQLinear(in_features=11008, out_features=4096, bias=False, w_bit=4, group_size=128)\n",
154
+ " )\n",
155
+ " (input_layernorm): FTLlamaRMSNorm()\n",
156
+ " (post_attention_layernorm): FTLlamaRMSNorm()\n",
157
+ " )\n",
158
+ " )\n",
159
+ " (norm): FTLlamaRMSNorm()\n",
160
+ " )\n",
161
+ " (lm_head): Linear(in_features=4096, out_features=32000, bias=False)\n",
162
+ ")"
163
+ ]
164
+ },
165
+ "execution_count": 4,
166
+ "metadata": {},
167
+ "output_type": "execute_result"
168
+ }
169
+ ],
170
+ "source": [
171
+ "make_quant_attn(model, \"cuda:0\")\n",
172
+ "make_quant_norm(model)\n",
173
+ "make_fused_mlp(model)"
174
+ ]
175
+ },
176
+ {
177
+ "cell_type": "code",
178
+ "execution_count": 5,
179
+ "metadata": {},
180
+ "outputs": [
181
+ {
182
+ "name": "stdin",
183
+ "output_type": "stream",
184
+ "text": [
185
+ "USER: Show me some attractions in Boston.\n"
186
+ ]
187
+ },
188
+ {
189
+ "name": "stdout",
190
+ "output_type": "stream",
191
+ "text": [
192
+ "ASSISTANT: 1. Boston Public Library\n",
193
+ "2. Fenway Park\n",
194
+ "3. Harvard Square\n",
195
+ "4. Boston Common\n",
196
+ "5. Freedom Trail\n",
197
+ "6. Museum of Fine Arts\n",
198
+ "7. Isabella Stewart Gardner Museum\n",
199
+ "8. Paul Revere House\n",
200
+ "9. New England Aquarium\n",
201
+ "10. Museum of Science\n",
202
+ "==================================================\n",
203
+ "Speed of Inference\n",
204
+ "--------------------------------------------------\n",
205
+ "Context Stage : 7.18 ms/token\n",
206
+ "Generation Stage : 9.49 ms/token\n",
207
+ "Average Speed : 8.53 ms/token\n",
208
+ "==================================================\n"
209
+ ]
210
+ },
211
+ {
212
+ "name": "stdin",
213
+ "output_type": "stream",
214
+ "text": [
215
+ "USER: \n"
216
+ ]
217
+ },
218
+ {
219
+ "name": "stdout",
220
+ "output_type": "stream",
221
+ "text": [
222
+ "EXIT...\n"
223
+ ]
224
+ }
225
+ ],
226
+ "source": [
227
+ "model_prompter = get_prompter(\"llama\", model_path)\n",
228
+ "stream_generator = StreamGenerator\n",
229
+ "count = 0\n",
230
+ "while True:\n",
231
+ " # Get input from the user\n",
232
+ " input_prompt = input(\"USER: \")\n",
233
+ " if input_prompt == \"\":\n",
234
+ " print(\"EXIT...\")\n",
235
+ " break\n",
236
+ " model_prompter.insert_prompt(input_prompt)\n",
237
+ " output_stream = stream_generator(model, tokenizer, model_prompter.model_input, gen_params, device=\"cuda:0\")\n",
238
+ " outputs = stream_output(output_stream) \n",
239
+ " model_prompter.update_template(outputs)\n",
240
+ " count += 1"
241
+ ]
242
+ },
243
+ {
244
+ "cell_type": "code",
245
+ "execution_count": null,
246
+ "metadata": {},
247
+ "outputs": [],
248
+ "source": []
249
+ }
250
+ ],
251
+ "metadata": {
252
+ "kernelspec": {
253
+ "display_name": "Python (awq)",
254
+ "language": "python",
255
+ "name": "awq"
256
+ },
257
+ "language_info": {
258
+ "codemirror_mode": {
259
+ "name": "ipython",
260
+ "version": 3
261
+ },
262
+ "file_extension": ".py",
263
+ "mimetype": "text/x-python",
264
+ "name": "python",
265
+ "nbconvert_exporter": "python",
266
+ "pygments_lexer": "ipython3",
267
+ "version": "3.10.11"
268
+ }
269
+ },
270
+ "nbformat": 4,
271
+ "nbformat_minor": 4
272
+ }
llm-awq/examples/convert_to_hf.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This script demonstrates how you can convert your model into HF format
2
+ # easily and push the quantized weights on the Hub using simple tools.
3
+ # Make sure to have transformers > 4.34 and that you have ran
4
+ # `huggingface-cli login` on your terminal before running this
5
+ # script
6
+ import os
7
+ import argparse
8
+
9
+ # This demo only support single GPU for now
10
+ os.environ["CUDA_VISIBLE_DEVICES"] = "0"
11
+
12
+ from transformers import AutoConfig, AwqConfig, AutoTokenizer
13
+ from huggingface_hub import HfApi
14
+
15
+ api = HfApi()
16
+
17
+ parser = argparse.ArgumentParser()
18
+ parser.add_argument(
19
+ "--model_path", type=str, help="path of the original hf model", required=True
20
+ )
21
+ parser.add_argument(
22
+ "--quantized_model_path",
23
+ type=str,
24
+ help="path of the quantized AWQ model",
25
+ required=True,
26
+ )
27
+ parser.add_argument(
28
+ "--quantized_model_hub_path",
29
+ type=str,
30
+ help="path of the quantized AWQ model to push on the Hub",
31
+ required=True,
32
+ )
33
+ parser.add_argument("--w_bit", type=int, default=4, help="")
34
+ parser.add_argument("--q_group_size", default=128, type=int)
35
+ parser.add_argument("--no_zero_point", action="store_true")
36
+
37
+ args = parser.parse_args()
38
+
39
+ original_model_path = args.model_path
40
+ quantized_model_path = args.quantized_model_path
41
+ quantized_model_hub_path = args.quantized_model_hub_path
42
+
43
+ # Load the corresponding AWQConfig
44
+ quantization_config = AwqConfig(
45
+ bits=args.w_bit,
46
+ group_size=args.q_group_size,
47
+ zero_point=not args.no_zero_point,
48
+ backend="llm-awq",
49
+ version="gemv",
50
+ )
51
+
52
+ # Set the attribute `quantization_config` in model's config
53
+ config = AutoConfig.from_pretrained(original_model_path)
54
+ config.quantization_config = quantization_config
55
+
56
+ # Load tokenizer
57
+ tok = AutoTokenizer.from_pretrained(original_model_path)
58
+
59
+ # Push config and tokenizer
60
+ config.push_to_hub(quantized_model_hub_path)
61
+ tok.push_to_hub(quantized_model_hub_path)
62
+
63
+ # Upload model weights
64
+ api.upload_file(
65
+ path_or_fileobj=quantized_model_path,
66
+ path_in_repo="pytorch_model.bin",
67
+ repo_id=quantized_model_hub_path,
68
+ repo_type="model",
69
+ )
llm-awq/examples/llava_demo.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
llm-awq/figures/vila-logo.jpg ADDED
llm-awq/scripts/DeepSeek_R1_Distill_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=DeepSeek-R1-Distill-Llama-8B
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/models/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/models/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/models/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/models/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/llama_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=llama-7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/llava_example.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=llava-13b-v0
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/llava-hf/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # generate real quantized weights (w4)
9
+ python -m awq.entry --model_path /dataset/llava-hf/$MODEL \
10
+ --w_bit 4 --q_group_size 128 \
11
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
12
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/nvila_example.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # run AWQ search
2
+ python -m awq.entry --model_path PATH/TO/NVILA \
3
+ --smooth_scale --media_path https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen2-VL/space_woaudio.mp4 \
4
+ --act_scale_path awq_cache/NVILA-VT-smooth-scale.pt --vila-20 \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/NVILA.pt
7
+
8
+ # generate real quantized weights (w4)
9
+ python -m awq.entry --model_path PATH/TO/NVILA/llm \
10
+ --w_bit 4 --q_group_size 128 \
11
+ --load_awq awq_cache/NVILA.pt \
12
+ --q_backend real --dump_quant quant_cache/NVILA-w4-g128-awq.pt --vila-20
llm-awq/scripts/opt_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=opt-6.7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/opt/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/opt/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/opt/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/opt/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/qwen_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=qwen2.5-7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/models/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/models/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/models/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/models/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/starcoder_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=starcoder
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/starcoder-hf/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/starcoder-hf/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/starcoder-hf/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/starcoder-hf/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/vicuna_example.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=vicuna-7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/vicuna-hf/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # evaluate the AWQ quantize model (simulated pseudo quantization)
9
+ python -m awq.entry --model_path /dataset/vicuna-hf/$MODEL \
10
+ --tasks wikitext \
11
+ --w_bit 4 --q_group_size 128 \
12
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
13
+ --q_backend fake
14
+
15
+ # generate real quantized weights (w4)
16
+ python -m awq.entry --model_path /dataset/vicuna-hf/$MODEL \
17
+ --w_bit 4 --q_group_size 128 \
18
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
19
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
20
+
21
+ # load and evaluate the real quantized model (smaller gpu memory usage)
22
+ python -m awq.entry --model_path /dataset/vicuna-hf/$MODEL \
23
+ --tasks wikitext \
24
+ --w_bit 4 --q_group_size 128 \
25
+ --load_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/scripts/vila15_example.sh ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=VILA1.5-7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ # Note: vila checkpoints are now stored in 3 parts.
5
+ # only llm folder will be quantized
6
+ python -m awq.entry --model_path /dataset/vila-hf/$MODEL/llm \
7
+ --w_bit 4 --q_group_size 128 --vila-15 \
8
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
9
+
10
+ # generate real quantized weights (w4)
11
+ python -m awq.entry --model_path /dataset/vila-hf/$MODEL/llm \
12
+ --w_bit 4 --q_group_size 128 --vila-15 \
13
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
14
+ --q_backend real --dump_quant /dataset/vila-hf/$MODEL-awq/llm/$MODEL-w4-g128-awq.pt
llm-awq/scripts/vila_example.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL=vila-7b
2
+
3
+ # run AWQ search (optional; we provided the pre-computed results)
4
+ python -m awq.entry --model_path /dataset/vila-hf/$MODEL \
5
+ --w_bit 4 --q_group_size 128 \
6
+ --run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
7
+
8
+ # generate real quantized weights (w4)
9
+ python -m awq.entry --model_path /dataset/vila-hf/$MODEL \
10
+ --w_bit 4 --q_group_size 128 \
11
+ --load_awq awq_cache/$MODEL-w4-g128.pt \
12
+ --q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
llm-awq/tinychat/README.md ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TinyChat 2.0: Efficient and Lightweight Chatbot with AWQ
2
+
3
+ We introduce TinyChat, a cutting-edge chatbot interface designed for lightweight resource consumption and fast inference speed on GPU platforms. It allows for seamless deployment on consumer-level GPUs such as 3090/4090 and low-power edge devices like the NVIDIA Jetson Orin, empowering users with a responsive conversational experience like never before.
4
+
5
+ The current release supports:
6
+
7
+ - DeepSeek-R1-Distill-Qwen-1.5B/7B
8
+
9
+ - DeepSeek-R1-Distill-Llama-8B
10
+
11
+ - Llama-3-8B/70B-instruct;
12
+
13
+ - NVILA-3B/8B;
14
+
15
+ - VILA-1.5-3B/8B/13B/40B;
16
+
17
+ - VILA-7B/13B;
18
+
19
+ - LLaVA-7B/13B;
20
+
21
+ - Llama-2-7B/13B-chat;
22
+
23
+ - Vicuna;
24
+
25
+ ## Contents
26
+
27
+ - [Examples](#examples)
28
+
29
+ - [Benchmarks](#benchmarks)
30
+
31
+ - [Usage](#usage)
32
+
33
+ - [Reference](#reference)
34
+
35
+ ## Examples
36
+
37
+ **Thanks to AWQ, TinyChat can now deliver more prompt responses through 4-bit inference. The following examples showcase that TinyChat's W4A16 generation is up to 2.7x faster on RTX 4090 and 2.9x faster on Jetson Orin, compared to the FP16 baselines. (Tested with LLaMA-3-8b model.)**
38
+
39
+
40
+ * TinyChat with LLaMA-3-8b on RTX 4090 (2.7x faster than FP16):
41
+
42
+ ![TinyChat with LLaMA-3-8b on RTX 4090: W4A16 is 2.7x faster than FP16](./figures/4090_example_new.gif)
43
+
44
+ * TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
45
+
46
+ ![TinyChat with LLaMA-3-8b on Jetson Orin: W4A16 is 2.9x faster than FP16](./figures/orin_example_new.gif)
47
+
48
+ **TinyChat also supports inference with visual language models (e.g., VILA, LLaVA, NVILA). In the following examples, W4A16 quantized models from VILA family are launched with TinyChat.**
49
+
50
+ * TinyChat with NVILA-8B on RTX 4090 (single-image inputs):
51
+
52
+ ![TinyChat with NVILA on 4090 single image](./figures/4090_nvila_single.gif)
53
+
54
+ * TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
55
+
56
+ ![TinyChat with NVILA on 4090 multiple images](./figures/4090_nvila_multi.gif)
57
+
58
+ * TinyChat with video reasoning:
59
+
60
+ https://github.com/user-attachments/assets/b68a7a0d-5175-4030-985b-5ae0ae94f874
61
+
62
+ **Prompt:** What might be the next step according to the video?
63
+
64
+ **Answer:** The next step in the video could be to place the shaped dough onto a baking sheet and let it rise before baking.
65
+
66
+ **Online demo:** https://vila.hanlab.ai
67
+
68
+ ## Speed Benchmarks
69
+
70
+ We benchmark TinyChat on NVIDIA RTX 4090 (desktop GPU), Orin (edge GPU), and A100 (server-class GPU).
71
+
72
+ We use the default implementation from Huggingface for the FP16 baseline. The INT4 implementation applies AWQ and utilizes our fast W4A16 GPU kernel. We also apply additional optimization techniques in the latest release. For example, we fuse all the operations in MHA/GQA/MQA into a single kernel, and fuse positional embedding kernels into the attention kernel. We also pre-allocate key-value caches to avoid the online memory allocation overhead from Huggingface. For W4A16 GEMM, we introduce FP16 accumulation when applicable for higher throughputs.
73
+
74
+
75
+ ### Decoding Speed
76
+
77
+ We benchmarked the per-token generation latency for the decoding stage in the following tables.
78
+
79
+
80
+ #### RTX 4090 Results
81
+
82
+ | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
83
+ | ----------- |:-----------------:|:-----------------:|:-------:|
84
+ | LLaMA-3-8B | 17.07 | 6.39 | 2.69x |
85
+ | LLaMA-2-7B | 15.50 | 5.28 | 2.94x |
86
+ | LLaMA-2-13B | OOM | 9.19 | -- |
87
+ | Vicuna-7B | 15.81 | 5.33 | 2.97x |
88
+ | VILA-7B | 17.09 | 5.95 | 2.87x |
89
+ | VILA-13B | OOM | 10.01 | -- |
90
+ | NVILA-2B | 5.26 | 4.27 | 1.23x |
91
+ | NVILA-8B | 16.12 | 5.97 | 2.70x |
92
+
93
+ *: For the decoding speed of language models, we follow the benchmarking setting from exLLaMA (i.e. only 4 context tokens) for the sake of simplicity and fairness. For multi-modal LMs (VILA and [NVILA](https://arxiv.org/abs/2412.04468)), we benchmark the decoding speed with single image inputs. Specifically, for NVILA, we activate the lite mode during the benchmarking, where each image is correspond to 128 input tokens.
94
+
95
+ <!-- | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
96
+ | ----------- |:-----------------:|:-----------------:|:-------:|
97
+ | LLaMA-3-8B | 17.07 | 6.66 | 2.56x |
98
+ | LLaMA-2-7B | 16.17 | 6.02* | 2.68x |
99
+ | LLaMA-2-13B | OOM | 10.35 | -- |
100
+ | Vicuna-7B | 15.81 | 5.33 | 2.97x |
101
+ | Vicuna-13B | OOM | 9.17 | -- |
102
+ | MPT-7B | 17.09 | 6.18 | 2.77x |
103
+ | MPT-30B | OOM | 20.60 | -- |
104
+ | Falcon-7B | 29.91 | 8.02 | 3.73x |
105
+ | VILA-7B | 17.09 | 5.95 | 2.87x |
106
+ | VILA-13B | OOM | 10.01 | -- | -->
107
+
108
+ <!-- *: The reason why LLaMA-2-7B is slower than Vicuna-7B is because we need a longer prompt (with > 500 tokens) to prevent the model from talking with itself. If we use the benchmarking strategy from exLLaMA (i.e. only 4 context tokens), our speed is around 195 tokens / second. -->
109
+
110
+ <!-- ### A6000 Results
111
+ | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
112
+ | ----------- |:-----------------:|:-----------------:|:-------:|
113
+ | LLaMA-3-8B | 24.95 | 10.68 | 2.34x |
114
+ | LLaMA-2-7B | 22.75 | 8.71 | 2.61x |
115
+ | LLaMA-2-13B | 41.72 | 14.64 | 2.85x |
116
+ | Vicuna-7B | 22.03 | 8.39 | 2.63x |
117
+ | Vicuna-13B | 38.97 | 13.46 | 2.90x |
118
+ | MPT-7B | 22.79 | 7.99 | 2.85x |
119
+ | MPT-30B | OOM | 28.15 | -- |
120
+ | Falcon-7B | 39.44 | 11.71 | 3.37x |
121
+ | VILA-7B | 23.60 | 8.14 | 2.90x |
122
+ | VILA-13B | 46.58 | 13.74 | 3.39x | -->
123
+
124
+
125
+ #### Jetson Orin Results
126
+
127
+ | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
128
+ | ----------- |:-----------------:|:-----------------:|:-------:|
129
+ | LLaMA-3-8B | 96.00 | 32.53 | 2.95x |
130
+ | LLaMA-2-7B | 83.95 | 25.94 | 3.24x |
131
+ | LLaMA-2-13B | 162.33 | 47.67 | 3.41x |
132
+ | Vicuna-7B | 84.77 | 26.34 | 3.22x |
133
+ | VILA-7B | 86.95 | 28.09 | 3.10x |
134
+ | VILA-13B | OOM | 57.14 | -- |
135
+ | NVILA-2B | 24.22 | 22.25 | 1.09x |
136
+ | NVILA-8B | 86.24 | 30.48 | 2.83x |
137
+
138
+ <!-- | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
139
+ | ----------- |:-----------------:|:-----------------:|:-------:|
140
+ | LLaMA-3-8B | 96.24 | 32.55 | 2.96x |
141
+ | LLaMA-2-7B | 86.80 | 32.14* | 2.70x |
142
+ | LLaMA-2-13B | OOM | 58.20 | -- |
143
+ | Vicuna-7B | 84.77 | 30.73 | 2.76x |
144
+ | Vicuna-13B | OOM | 54.98 | -- |
145
+ | MPT-7B | 89.85 | 31.22 | 2.88x |
146
+ | Falcon-7B | 147.84 | 45.10 | 3.28x |
147
+ | VILA-7B | 86.95 | 28.09 | 3.10x |
148
+ | VILA-13B | OOM | 57.14 | -- |
149
+
150
+ *: We can similarly achieve 33 tokens / second on Orin if we use the benchmarking strategy from exLLaMA. -->
151
+
152
+ #### A100 Results
153
+
154
+ | Model | FP16 latency (ms) | INT4 latency (ms) | Speedup |
155
+ | ----------- |:-----------------:|:-----------------:|:-------:|
156
+ | LLaMA-3-8B | 12.37 | 6.29 | 1.96x |
157
+ | LLaMA-2-7B | 10.77 | 5.71 | 1.89x |
158
+ | LLaMA-2-13B | 19.08 | 7.90 | 2.41x |
159
+ | Vicuna-7B | 10.54 | 5.87 | 1.80x |
160
+ | VILA-7B | 13.35 | 5.92 | 2.26x |
161
+ | VILA-13B | 19.64 | 8.63 | 2.28x |
162
+ | NVILA-2B | 7.03 | 5.38 | 1.31x |
163
+ | NVILA-8B | 11.90 | 5.50 | 2.16x |
164
+
165
+
166
+ ### Prefilling Speed
167
+
168
+ In TinyChat 2.0, we also introduce significant prefilling speed optimizations for Large Language Models (LLMs) and Visual Language Models (VLMs). Specifically, with the integration of latest flash attention and FP16 accumulation in GEMM kernels, TinyChat now achieves state-of-the-art prefilling speed on edge devices.
169
+
170
+ #### RTX 4090 Results
171
+
172
+ Time-To-First-Token (TTFT) of Llama-3-8B (Unit: Seconds):
173
+
174
+ | Seq Len | 256 | 512 | 1024 | 2048 | 3072 | 4096 |
175
+ | ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
176
+ | FP16 | 0.031 | 0.055 | 0.109 | 0.211 | 0.336 | 0.446 |
177
+ | TinyChat | 0.021 | 0.033 | 0.064 | 0.131 | 0.200 | 0.275 |
178
+ | Speedup | 1.52x | 1.68x | 1.69x | 1.61x | 1.68x | 1.62x |
179
+
180
+
181
+ Time-To-First-Token (TTFT) of Llama-2-7B (Unit: Seconds):
182
+
183
+ | Seq Len | 256 | 512 | 1024 | 2048 | 3072 | 4096 |
184
+ | ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
185
+ | FP16 | 0.029 | 0.058 | 0.100 | 0.211 | 0.329 | 0.441 |
186
+ | TinyChat | 0.018 | 0.031 | 0.060 | 0.124 | 0.193 | 0.265 |
187
+ | Speedup | 1.57x | 1.83x | 1.66x | 1.70x | 1.70x | 1.66x |
188
+
189
+
190
+ #### Jetson Orin Results
191
+
192
+ Time-To-First-Token (TTFT) of Llama-3-8B (Unit: Seconds):
193
+
194
+ | Seq Len | 256 | 512 | 1024 | 2048 | 3072 | 4096 |
195
+ | ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
196
+ | FP16 | 0.206 | 0.399 | 0.566 | 1.519 | 2.308 | 3.114 |
197
+ | TinyChat | 0.166 | 0.315 | 0.623 | 1.248 | 1.907 | 2.573 |
198
+ | Speedup | 1.24x | 1.26x | 0.91x | 1.22x | 1.21x | 1.21x |
199
+
200
+
201
+ #### Comparison with Other Systems
202
+
203
+ Time-To-First-Token (TTFT) of 4-bit weight-only quantized Llama3-8B on RTX 4090 across various systems (Unit: Seconds):
204
+
205
+
206
+ | Seq Len | 256 | 512 | 1024 | 2048 | 4096 |
207
+ |:-------------------:|:-----:|:-----:|:-----:|:-----:|:------:|
208
+ | TensorRT-LLM | 0.027 | 0.051 | 0.100 | 0.204 | 0.421 |
209
+ | MLC | 0.028 | 0.042 | 0.081 | 0.166 | 0.350 |
210
+ | llama.cpp | 0.026 | 0.045 | 0.086 | 0.175 | 0.375 |
211
+ | ExLlama v2 | 0.040 | 0.051 | 0.077 | 0.139 | 0.294 |
212
+ | TinyChat (Legacy) | 0.031 | 0.051 | 0.101 | 0.219 | 0.461 |
213
+ | TinyChat 2.0 | 0.021 | 0.033 | 0.065 | 0.132 | 0.278 |
214
+
215
+ Our approach outperforms all existing projects, achieving state-of-the-art speed.
216
+
217
+ ### Context Streaming: Efficient Multi-round Dialogues
218
+
219
+ In TinyChat 2.0, we introduce chunk-prefilling optimization for multi-round dialogues. For multi-turn inputs, TinyChat will reuse the KV Cache from previous conversations without recomputing them. This optimization eliminates redundant computations and significantly reduce the Time To First Token (TTFT) for subsequent interaction rounds.
220
+
221
+ #### RTX 4090 Results
222
+
223
+ To evaluate Context Streaming, we measure the TTFT in multi-round conversations with a fixed question length of 32 tokens, and varying history lengths from 16 to 1024 tokens. Specifically, in TinyChat 2.0, all history tokens are already prefilled to the existing KV Cache when processing the current query, while baseline systems recompute the history tokens for each query.
224
+
225
+ <!-- To demonstrate the effectiveness of Context Streaming, we measure the TTFT in multi-round conversation with a fixed question length of 32 and varying history lengths ranging from 16 to 1024 tokens. This setup means that a number of history tokens (based on the specified history length) are already input into the model. In this round, the question tokens (32 tokens) are also input, and the model takes TTFT to process these question tokens, prefill the KV cache, and generate the first token. All the tables below follows this setting. The speedup ratio in all the tables below refer to the acceleration achieved by the new method compared to FP16 inference. -->
226
+
227
+ Time-To-First-Token (TTFT) of Llama-3-8B (Unit: ms):
228
+
229
+ | History length | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
230
+ |---------------------------|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:------:|
231
+ | FP16 | 21.49 | 21.38 | 23.51 | 40.82 | 47.15 | 75.41 | 162.27 |
232
+ | TinyChat (Legacy) | 15.20 | 14.89 | 17.61 | 29.66 | 44.11 | 72.50 | 163.90 |
233
+ | TinyChat 2.0 | 14.30 | 14.05 | 14.05 | 14.43 | 14.38 | 14.35 | 14.49 |
234
+ | Speedup | 1.54x | 1.54x | 1.69x | 2.84x | 3.33x | 5.27x | 11.45x |
235
+
236
+ <!-- Time-To-First-Token (TTFT) of VILA-1.5-8B (Unit: ms):
237
+
238
+ | History length | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
239
+ |---------------------------|:-----:|:-----:|:-----:|:-----:|:-----:|:------:|:------:|
240
+ | FP16 TTFT (ms) | 22.20 | 22.00 | 24.17 | 41.85 | 62.97 | 101.84 | 217.57 |
241
+ | Legacy TinyChat TTFT (ms) | 16.14 | 15.98 | 18.28 | 30.72 | 59.67 | 98.52 | 219.19 |
242
+ | New TinyChat TTFT (ms) | 14.86 | 14.69 | 14.64 | 14.90 | 14.91 | 14.95 | 14.90 |
243
+ | New TinyChat Speedup | 1.49x | 1.50x | 1.65x | 2.81x | 4.22x | 6.81x | 14.60x |
244
+
245
+ NOTE: [TODO] @Yuming. The current setting is too complicated. Let's consider the case: each round, there is an image input. Baseline need to re-encode every image, while tinychat only need to encode 1 image.
246
+
247
+ *: For Visual Language Models, the speedup of Context Streaming is more significant, since the model only decodes images during the first round. In the experiment, We assume that approximately 75% of the history tokens represent images, leading to the number of images in the table being 0, 0, 0, 0, 1, 2, 4. This assumption is reasonable to some extent, considering that a single image is decoded into 196 tokens. -->
248
+
249
+
250
+
251
+ <!-- We have optimized the speed of the context stage and updated our code with several enhancements, including the adoption of FlashAttention and the elimination of redundant computations. The key optimizations include:
252
+ 1. Adopting the FlashAttention kernel. (Currently we only support single-batch operations to achieve better results)
253
+ 2. Computing only the last tokens in the final logits layer. (This method is used by default.)
254
+ 3. Utilizing history KV caches in the context stage to speed up. (chunk prefilling) -->
255
+
256
+ <!-- These optimizations are orthogonal, enabling their combined application to achieve significant speedups. Under specific conditions, these enhancements can lead to up to an 14x speedup on 4090 GPUs and an 8x speedup on Orin GPUs in Time To First Token (TTFT) compared to the previous version of TinyChat and FP16. We conducted experiments using both Orin and 4090 GPUs, and detailed results are presented below. -->
257
+
258
+
259
+ <!-- ### Orin Results
260
+ We follow the setup above and the results are as below.
261
+ #### Llama-3-8B
262
+ | History length | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
263
+ |---------------------------|:------:|:------:|:------:|:------:|:------:|:------:|:-------:|
264
+ | FP16 TTFT (ms) | 107.10 | 108.81 | 114.07 | 224.78 | 343.95 | 582.54 | 1048.11 |
265
+ | Legacy TinyChat TTFT (ms) | 92.04 | 111.31 | 106.60 | 160.78 | 278.47 | 528.70 | 1145.35 |
266
+ | New TinyChat TTFT (ms) | 65.57 | 65.40 | 66.49 | 67.15 | 73.29 | 84.67 | 118.53 |
267
+ | New TinyChat Speedup | 1.52x | 1.65x | 1.70x | 3.30x | 4.51x | 6.75x | 8.65x | -->
268
+
269
+
270
+ ## Accuracy Evaluation
271
+
272
+
273
+ AWQ also achieves decent performance on the Visual Language Models. We evaluate AWQ on VILA and the lastest NVILA models.
274
+
275
+ | NVILA-8B | AI2D | ChartQA | DocVQA | MMMU_val | SEED | TextVQA | VideoMME |
276
+ | ---------- |:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|
277
+ | FP16 | 91.0 | 84.8 | 91.7 | 50.7 | 76.3 | 78.1 | 63.9 |
278
+ | AWQ-INT4 | 90.9 | 83.3 | 89.2 | 49.3 | 76.2 | 78.2 | 62.1 |
279
+
280
+ <!--
281
+ | NVILA-8B | AI2D | ChartQA | DocVQA | MMMU_val | SEED | TextVQA | VideoMME-Short | VideoMME-Medium | VideoMME-Long | VideoMME-Overall |
282
+ | ---------- |:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|:----------:|
283
+ | FP16 | 91.0 | 84.8 | 91.7 | 50.7 | 76.3 | 78.1 | 74.9 | 62.1 | 54.7 | 63.9 |
284
+ | AWQ-INT4 | 90.9 | 83.3 | 89.2 | 49.3 | 76.2 | 78.2 | 73.2 | 61.3 | 51.6 | 62.1 | -->
285
+
286
+
287
+
288
+ | VILA-1.5-3B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
289
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
290
+ | FP16 | 80.4 | 61.5 | 53.5 | 69.0 | 60.4 | 85.9 | 1442.4 | 63.4 | 52.7 | 60.9 |
291
+ | AWQ-INT4 | 80.0 | 61.1 | 53.8 | 67.8 | 60.4 | 85.9 | 1437.3 | 63.3 | 51.4 | 59.8 |
292
+
293
+ | VILA-1.5-8B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
294
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
295
+ | FP16 | 80.9 | 61.9 | 58.7 | 79.9 | 66.3 | 84.4 | 1577.01 | 72.3 | 66.2 | 64.2 |
296
+ | AWQ-INT4 | 80.3 | 61.7 | 59.3 | 79.0 | 65.4 | 82.9 | 1593.65 | 71.0 | 64.9 | 64.0 |
297
+
298
+ | VILA-1.5-13B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
299
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
300
+ | FP16 | 82.8 | 64.3 | 62.6 | 80.1 | 65.0 | 86.3 | 1569.55 | 74.9 | 66.3 | 65.1 |
301
+ | AWQ-INT4 | 82.7 | 64.5 | 63.3 | 79.7 | 64.7 | 86.7 | 1531.35 | 74.7 | 66.7 | 65.1 |
302
+
303
+
304
+ | VILA-1.5-40B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
305
+ | ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
306
+ | FP16 | 84.3 | 64.6 | 62.2 | 87.2 | 73.6 | 87.3 | 1726.82 | 82.4 | 80.2 | 69.1 |
307
+ | AWQ-INT4 | 84.1 | 64.4 | 61.3 | 86.7 | 73.2 | 88.2 | 1714.79 | 83.2 | 79.6 | 68.9 |
308
+
309
+ AWQ has also demonstrated impressive performance on inference benchmarks, maintaining strong accuracy across a range of reasoning tasks.
310
+
311
+ | DeepSeek-R1-Distill-Llama-8B | WikiText perplexity | AIME 2024 | Math-500 |
312
+ | ---------------------------- |:-------------------:|:-------------------:|:-------------------:|
313
+ | FP16 | 13.13 | 43.33% | 83.00% |
314
+ | AWQ-INT4 | 13.84 | 43.33% | 84.40% |
315
+
316
+ | DeepSeek-R1-Distill-Qwen-7B | WikiText perplexity | AIME 2024 | Math-500 |
317
+ | --------------------------- |:-------------------:|:-------------------:|:-------------------:|
318
+ | FP16 | 25.06 | 53.33% | 91.40% |
319
+ | AWQ-INT4 | 27.45 | 53.33% | 89.60% |
320
+
321
+ ## Usage
322
+
323
+ 1. Please follow the [AWQ installation guidance](https://github.com/mit-han-lab/llm-awq#readme) to install AWQ and its dependencies. If you want to use FlashAttention, start by installing it with: ```pip install flash-attn --no-build-isolation```. However, for some GPUs such as Jetson Orin, there is no pre-built version available. You will need to build it from source. Follow these commands:
324
+ ```bash
325
+ git clone https://github.com/Dao-AILab/flash-attention.git
326
+ cd flash-attention
327
+ sed -i '168 a\ cc_flag.append("-gencode")\n\ cc_flag.append("arch=compute_87,code=sm_87")' setup.py
328
+ python setup.py install
329
+ ```
330
+ This process may take some time as it involves compiling the code. Additionally, please note that these commands are just for Jetson Orin GPUs, whose CUDA compute capability is 87. For other GPUs, you may use ```nvidia-smi --query-gpu=compute_cap --format=csv``` to get the compute capability and merely change '87' to that.
331
+
332
+ 2. Download the pretrained instruction-tuned LLMs:
333
+
334
+ - For LLaMA-2-chat, please refer to [this link](https://huggingface.co/meta-llama/Llama-2-7b-chat-hf);
335
+
336
+ - For Vicuna, please refer to [this link](https://huggingface.co/lmsys/);
337
+
338
+ - For MPT-chat, please refer to [this link](https://huggingface.co/mosaicml/mpt-7b-chat);
339
+
340
+ - For Falcon-instruct, please refer to [this link](https://huggingface.co/tiiuae/falcon-7b-instruct).
341
+
342
+ 3. Quantize instruction-tuned LLMs with AWQ:
343
+ - We provide pre-computed AWQ search results for multiple model families, including LLaMA, OPT, Vicuna, VILA, and LLaVA. To get the pre-computed AWQ search results, run:
344
+
345
+ ```bash
346
+ # git lfs install # install git lfs if not already
347
+ git clone https://huggingface.co/datasets/mit-han-lab/awq-model-zoo awq_cache
348
+ ```
349
+
350
+ - You may run a one-line starter below:
351
+
352
+ ```bash
353
+ ./scripts/llama2_demo.sh
354
+ ```
355
+
356
+ Alternatively, you may go through the process step by step. We will demonstrate the quantization process with LLaMA-2. For all other models except Falcon, one only needs to change the `model_path` and saving locations. For Falcon-7B, we also need to change `q_group_size` from 128 to 64.
357
+
358
+ - Perform AWQ search and save search results (we already did it for you):
359
+
360
+ ```bash
361
+ mkdir awq_cache
362
+ python -m awq.entry --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
363
+ --w_bit 4 --q_group_size 128 \
364
+ --run_awq --dump_awq awq_cache/llama-2-7b-chat-w4-g128.pt
365
+ ```
366
+
367
+ - Generate real quantized weights (INT4):
368
+
369
+ ```bash
370
+ mkdir quant_cache
371
+ python -m awq.entry --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
372
+ --w_bit 4 --q_group_size 128 \
373
+ --load_awq awq_cache/llama-2-7b-chat-w4-g128.pt \
374
+ --q_backend real --dump_quant quant_cache/llama-2-7b-chat-w4-g128-awq.pt
375
+ ```
376
+
377
+ 4. Run the TinyChat demo:
378
+
379
+ ```bash
380
+ cd tinychat
381
+ python demo.py --model_type llama \
382
+ --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
383
+ --q_group_size 128 --load_quant quant_cache/llama-2-7b-chat-w4-g128-awq.pt \
384
+     --precision W4A16
385
+ ```
386
+
387
+ Note: if you use Falcon-7B-instruct, please remember to also change `q_group_size` to 64. You may also run the following command to execute the chatbot in FP16 to compare the speed and quality of language generation:
388
+
389
+ ```bash
390
+ python demo.py --model_type llama \
391
+ --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
392
+ --precision W16A16
393
+ ```
394
+ You can now try using FlashAttention along with chunk prefilling. Use the following two arguments when running demo: ```
395
+ --flash --chunk_prefilling```.
396
+
397
+ The above command works well for most cloud and desktop GPUs, since their CPU and GPU memory space are separated. However, for edge GPUs with shared host and device memory, in order to run larger models (e.g. LLaMA-2-70B on 64GB Orin), it is necessary to break down the pretrained checkpoints into small pieces:
398
+
399
+ ```bash
400
+ python split_ckpt.py --input_path quant_cache/llama-2-7b-chat-w4-g128-awq.pt \
401
+ --output_path quant_cache/llama-2-7b-chat-w4-g128-awq
402
+ ```
403
+
404
+ Then, to run the demo, one can use the following command. The only changes compared with the demo command above are:
405
+
406
+ - We modify the `load_quant` argument;
407
+
408
+ - We introduce another flag `mem_efficient_load`.
409
+
410
+ ```bash
411
+ cd tinychat
412
+ python demo.py --model_type llama \
413
+ --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
414
+ --q_group_size 128 --load_quant quant_cache/llama-2-7b-chat-w4-g128-awq \
415
+     --precision W4A16 --mem_efficient_load
416
+ ```
417
+
418
+ 5. (Optional) Run the benchmark script to get TTFT and decoding throughput:
419
+
420
+ ```bash
421
+ cd tinychat
422
+ python benchmark.py --flash \
423
+ --context_length 16 32 64 128 256 512 1024 2048 \
424
+ --model_path /PATH/TO/LLAMA2/llama-2-7b-chat --precision W4A16
425
+ ```
426
+ To benchmark chunk prefilling, use:
427
+ ```bash
428
+ python benchmark.py --chunk_prefilling \
429
+ --model_path /PATH/TO/LLAMA2/llama-2-7b-chat \
430
+ --question_length 32 --context_length 16 32 64 128 256 512 1024 --precision W4A16
431
+ ```
432
+ Note: The kv caches in the current implementation are pre-allocated. So if you run out of memory, it might be the case that the kv cache is too large. To solve the problem, you may pass in `--max_seq_len [a smaller number]`.
433
+ ### Support Visual Language Models (VILA-1.5, VILA, LLaVA, NVILA)
434
+
435
+ Our TinyChat also supports visual language models. Follow the instructions below to run VLMs on your own devices!
436
+
437
+ Step 1-3 are same as the deployment for Language-only models.
438
+
439
+ 1. Follow the [AWQ installation guidance](https://github.com/mit-han-lab/llm-awq#readme) to install AWQ and its dependencies.
440
+
441
+ 2. Download the pretrained VLMs (VILA).
442
+
443
+ 3. Quantize the VLMs with AWQ and get the quantized checkpoint in `quant_cache`. We also provide a [sample script](../scripts/vila_example.sh) for this step.
444
+
445
+ 4. Run the TinyChat demo for VLMs (with vila15_demo.py for VILA-1.5, vila10_demo.py for VILA and LLaVA):
446
+
447
+ ```bash
448
+ cd tinychat
449
+ python vila15_demo.py \
450
+ --model-path /PATH/TO/VILA/VILA-1.5-13B \
451
+ --quant-path quant_cache/vila-1.5-13b-w4-g128-awq.pt \
452
+     --precision W4A16 \
453
+ --image-file /PATH/TO/INPUT/IMAGE \
454
+ --vis-image #Optional
455
+ ```
456
+
457
+ Alternatively, one may also skip the quantization process and directy download the quantized VILA-1.5 checkpoints from [here](https://huggingface.co/Efficient-Large-Model). Take VILA-1.5-13B as an example, after running:
458
+
459
+ ```bash
460
+ cd tinychat
461
+ git clone https://huggingface.co/Efficient-Large-Model/VILA1.5-13b-AWQ
462
+ ```
463
+
464
+ One may run:
465
+ ```bash
466
+ python vila15_demo.py \
467
+ --model-path VILA1.5-13b-AWQ \
468
+ --quant-path VILA1.5-13b-AWQ/llm \
469
+     --precision W4A16 \
470
+ --image-file /PATH/TO/INPUT/IMAGE \
471
+ --vis-image #Optional
472
+ ```
473
+
474
+ to run the terminal demo directly. You can also use``` --flash --chunk_prefilling``` to accelerate. We also support context stage benckmarking for VILA.
475
+ ```bash
476
+ python benchmark_context.py --flash --chunk_prefilling \
477
+ --model_path PATH/TO/Llama-3-VILA1.5-8B \
478
+ --question_length 32 --context_length 16 32 64 128 256 512 1024 \
479
+ --model_type vila --quant
480
+ ```
481
+ Note: if you enable `--vis-image` mode, TinyChat will print input images directly in your terminal. You may need to install [termvisage](https://github.com/AnonymouX47/termvisage) to enable this mode. A [terminal emulator](https://github.com/AnonymouX47/termvisage?tab=readme-ov-file#requirements) is also required.
482
+
483
+ Note: VILA model family supports multi-image inputs. You can input multiple images in `/PATH/TO/INPUT/IMAGE` above, each image should be seperated by `,`.
484
+
485
+ 5. TinyChat support NVILA now! We adopt W8A8 SmoothQuant for VisionTower and W4A16 quantization for LLM, achieving 1.3x -3.3x speedup for prefiling satge and nearly 1.5x higher throughput. You can use the commands below to prepare the your model and try four basic tasks of NVILA-video model.
486
+ To prepared the needed act scale for awq and smoothquant, please run:
487
+ ```bash
488
+ python -m awq.entry --model_path PATH/TO/NVILA \
489
+ --smooth_scale --media_path https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen2-VL/space_woaudio.mp4 \
490
+ --act_scale_path awq_cache/NVILA-VT-smooth-scale.pt --vila-20 \
491
+ --w_bit 4 --q_group_size 128 \
492
+ --run_awq --dump_awq awq_cache/NVILA.pt
493
+ ```
494
+ Then, please generate real quantized LLM with:
495
+ ```bash
496
+ python -m awq.entry --model_path PATH/TO/NVILA/llm \
497
+ --w_bit 4 --q_group_size 128 \
498
+ --load_awq awq_cache/NVILA.pt \
499
+ --q_backend real --dump_quant quant_cache/NVILA-w4-g128-awq.pt --vila-20
500
+ ```
501
+ Next, try chatting with it using the command below to experience shorter Time To First Token (TTFT) and higher decoding throughput.
502
+ ```bash
503
+ python nvila_demo.py --model-path EPATH/TO/NVILA \
504
+ --quant_path PATH/TO/NVILA-w4-g128-v2.pt \
505
+ --media PATH/TO/MEDIA \
506
+ --act_scale_path PATH/TO/NVILA-smooth-scale.pt \
507
+ --quant_llm --chunk --model_type nvila
508
+ ```
509
+
510
+
511
+ ## Team
512
+
513
+ TinyChat is developed by the following wonderful team:
514
+
515
+ - [Shang Yang](https://ys-2020.github.io/): Project Lead, TinyChat v1 and v2 Lead;
516
+ - [Haotian Tang](http://kentang.net): Project Lead, TinyChat v1 Lead, v2 Mentor;
517
+ - [Yuming Lou](<>): TinyChat v2 Lead;
518
+ - [Junxian Guo](<>): TinyChat v2 Contributor;
519
+ - [Song Han](https://hanlab.mit.edu/songhan): Project Advisor.
520
+
521
+ Credits also go to AWQ algorithm leads: [Ji Lin](https://www.linji.me/) and [Jiaming Tang](https://jiamingtang.me/).
522
+
523
+ ## Reference
524
+
525
+ TinyChat is inspired by the following open-source projects: [FasterTransformer](https://github.com/NVIDIA/FasterTransformer), [FlashAttention](https://github.com/Dao-AILab/flash-attention), [vLLM](https://github.com/vllm-project/vllm), [FastChat](https://github.com/lm-sys/FastChat), [llama_cu_awq](https://github.com/ankan-ban/llama_cu_awq), [LLaVA](https://github.com/haotian-liu/LLaVA), [termvisage](https://github.com/AnonymouX47/termvisage).
526
+
llm-awq/tinychat/benchmark.py ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Usage:
2
+ # Please first install awq/kernels
3
+ # then directly run CUDA_VISIBLE_DEVICES=0 python benchmark.py
4
+ import argparse
5
+ import torch
6
+ import time
7
+ import numpy as np
8
+ from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig, modeling_utils
9
+ import tinychat.utils.constants
10
+ from tinychat.utils.load_quant import load_awq_model
11
+ from awq.quantize.quantizer import real_quantize_model_weight
12
+ from tinychat.utils.tune import (
13
+ tune_all_wqlinears,
14
+ device_warmup,
15
+ tune_llava_patch_embedding,
16
+ )
17
+ from tinychat.modules import make_quant_norm, make_quant_attn, make_fused_mlp
18
+
19
+
20
+ def skip(*args, **kwargs):
21
+ pass
22
+
23
+
24
+ def main():
25
+ parser = argparse.ArgumentParser()
26
+ parser.add_argument(
27
+ "--model_type", type=str, default="LLaMa", help="type of the model"
28
+ )
29
+ parser.add_argument(
30
+ "--model_path",
31
+ type=str,
32
+ default="/data/llm/checkpoints/vicuna-hf/vicuna-7b",
33
+ help="path to the model",
34
+ )
35
+ parser.add_argument("--q_group_size", type=int, default=128)
36
+ parser.add_argument(
37
+ "--verbose",
38
+ default=False,
39
+ action="store_true",
40
+ help="Wheter to print more information.",
41
+ )
42
+ parser.add_argument(
43
+ "--max_seq_len",
44
+ type=int,
45
+ default=8192,
46
+ help="maximum sequence length for kv cache",
47
+ )
48
+ parser.add_argument(
49
+ "--max_batch_size", type=int, default=1, help="maximum batch size for kv cache"
50
+ )
51
+ parser.add_argument(
52
+ "--flash_attn",
53
+ action="store_true",
54
+ help="whether to use flash attention",
55
+ )
56
+ parser.add_argument(
57
+ "--chunk_prefilling",
58
+ action="store_true",
59
+ help="If used, in context stage, the history tokens will not be recalculated, greatly speeding up the calculation",
60
+ )
61
+ parser.add_argument(
62
+ "--context_length",
63
+ type=list,
64
+ nargs="+",
65
+ help="The length of input. And if chunk_prefilling used, this serves as the length of tokens from history rounds.",
66
+ )
67
+ parser.add_argument(
68
+ "--question_length",
69
+ type=list,
70
+ nargs="+",
71
+ help="The length of new input. Only useful and necessary when benchmarking chunk_prefilling method",
72
+ )
73
+ parser.add_argument(
74
+ "--precision", type=str, default="W4A16", help="compute precision"
75
+ )
76
+ args = parser.parse_args()
77
+ # some checks
78
+ assert (args.question_length is not None and args.chunk_prefilling) or (
79
+ not args.chunk_prefilling
80
+ ), "If you want to benchmark chunk prefilling, you need specify the question length and context length"
81
+ assert args.precision in ["W4A16", "W16A16"], "We only support W4A16/W16A16 now"
82
+ token_num = 256
83
+ # We support fixing a certain kind of length
84
+ if args.chunk_prefilling:
85
+ if len(args.context_length) == 1 and len(args.question_length) > 1:
86
+ args.context_length = [
87
+ args.context_length[0] for _ in range(len(args.question_length))
88
+ ]
89
+ elif len(args.question_length) == 1 and len(args.context_length) > 1:
90
+ args.question_length = [
91
+ args.question_length[0] for _ in range(len(args.context_length))
92
+ ]
93
+ elif len(args.question_length) != len(args.context_length):
94
+ raise ValueError(
95
+ "The number of items in the question_length and context_length is expected to be either one or equal!"
96
+ )
97
+ tinychat.utils.constants.max_batch_size = args.max_batch_size
98
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
99
+ from tinychat.models import FalconForCausalLM, LlamaForCausalLM, MPTForCausalLM
100
+ from tinychat.models.vila_llama import VilaLlamaForCausalLM
101
+
102
+ modeling_utils._init_weights = False
103
+ torch.nn.init.kaiming_uniform_ = skip
104
+ torch.nn.init.kaiming_normal_ = skip
105
+ torch.nn.init.uniform_ = skip
106
+ torch.nn.init.normal_ = skip
107
+
108
+ device = "cuda:0"
109
+ model_type_dict = {
110
+ "llama": LlamaForCausalLM,
111
+ "falcon": FalconForCausalLM,
112
+ "mpt": MPTForCausalLM,
113
+ }
114
+
115
+ config = AutoConfig.from_pretrained(args.model_path, trust_remote_code=True)
116
+ assert args.model_type.lower() in [
117
+ "llama",
118
+ "falcon",
119
+ "mpt",
120
+ "vila",
121
+ ], "We only support llama & falcon & mpt & vila now"
122
+ if "vila" in args.model_type.lower():
123
+ model = VilaLlamaForCausalLM(config).half()
124
+ print(model)
125
+ if args.precision in ["W4A16"]:
126
+ real_quantize_model_weight(
127
+ model.llm,
128
+ w_bit=4,
129
+ q_config=dict(q_group_size=args.q_group_size, zero_point=True),
130
+ init_only=True,
131
+ )
132
+ make_quant_attn(model.llm, device, args.flash_attn)
133
+ make_quant_norm(model.llm)
134
+ make_fused_mlp(model.llm)
135
+ model = model.to(device)
136
+ device_warmup(device)
137
+ tune_llava_patch_embedding(model.get_vision_tower(), device=device)
138
+ if not args.chunk_prefilling:
139
+ image_num = [
140
+ int(int("".join(i)) * 1 / 196) for i in args.context_length
141
+ ] # consider about three thirds of the history tokens are images
142
+ if sum(image_num) > 0:
143
+ image_tensor = 2 * torch.rand((max(image_num), 3, 384, 384)) - 1
144
+ image_tensor = image_tensor.half().to(device)
145
+ else:
146
+ image_tensor = None
147
+
148
+ print("huggingface ckpt loaded")
149
+
150
+ # warming up
151
+ input_ids = [1 for _ in range(2048)]
152
+ inputs = torch.as_tensor([input_ids], device=device)
153
+ out = model(
154
+ inputs, start_pos=0, chunk_prefilling=args.chunk_prefilling
155
+ ) # warmup
156
+
157
+ if not args.chunk_prefilling:
158
+ for i, context_length in enumerate(args.context_length):
159
+ context_length = int("".join(context_length))
160
+ time_lis = []
161
+ if image_num[i]:
162
+ images = image_tensor[0 : image_num[i], :, :, :]
163
+ input_ids = [-200 for _ in range(image_num[i])] + [
164
+ 1 for _ in range(context_length - 196 * image_num[i])
165
+ ]
166
+ else:
167
+ images = None
168
+ input_ids = [1 for _ in range(context_length)]
169
+ print("-" * 80)
170
+ print(
171
+ "Context length: {} with {} pictures".format(
172
+ context_length, image_num[i]
173
+ )
174
+ )
175
+ with torch.inference_mode():
176
+ for i in range(10): # Run ten times and get the average value
177
+ start_pos = 0
178
+ torch.cuda.synchronize()
179
+ t_st = time.time()
180
+ inputs = torch.as_tensor([input_ids], device=device)
181
+ out = model(
182
+ inputs,
183
+ start_pos=start_pos,
184
+ chunk_prefilling=args.chunk_prefilling,
185
+ images=images,
186
+ )
187
+ start_pos += inputs.shape[1]
188
+ torch.cuda.synchronize()
189
+ t_ed = time.time()
190
+ token = out[:, -1].max(1)[1].unsqueeze(1)
191
+ time_lis.append(t_ed - t_st)
192
+ if args.verbose:
193
+ print(i, t_ed - t_st)
194
+ print(f"Time To First Token: {np.mean(time_lis):.5f} s.")
195
+ print("-" * 80)
196
+ else:
197
+ for i, (context_length, question_length) in enumerate(
198
+ zip(args.context_length, args.question_length)
199
+ ):
200
+ context_length = int("".join(context_length))
201
+ question_length = int("".join(question_length))
202
+ input_ids_old = [1 for _ in range(context_length)]
203
+ images = None
204
+ input_ids_new = [1 for _ in range(question_length)]
205
+ time_lis = []
206
+ print("-" * 80)
207
+ print(
208
+ "History length: {} ; Question length: {}".format(
209
+ context_length, question_length
210
+ )
211
+ )
212
+ with torch.inference_mode():
213
+ for i in range(10): # Run ten times and get the average value
214
+ # history rounds
215
+ start_pos = 0
216
+ if context_length > question_length:
217
+ inputs = torch.as_tensor([input_ids_old], device=device)
218
+ out = model(
219
+ inputs,
220
+ start_pos=start_pos,
221
+ chunk_prefilling=args.chunk_prefilling,
222
+ images=None,
223
+ )
224
+ start_pos += context_length
225
+
226
+ # the present round
227
+ torch.cuda.synchronize()
228
+ t_st = time.time()
229
+ inputs = torch.as_tensor([input_ids_new], device=device)
230
+ out = model(
231
+ inputs,
232
+ start_pos=start_pos,
233
+ chunk_prefilling=args.chunk_prefilling,
234
+ )
235
+ start_pos += inputs.shape[1]
236
+ torch.cuda.synchronize()
237
+ t_ed = time.time()
238
+
239
+ token = out[:, -1].max(1)[1].unsqueeze(1)
240
+ time_lis.append(t_ed - t_st)
241
+ if args.verbose:
242
+ print(i, t_ed - t_st)
243
+ print(
244
+ f"Time To First Token of this round: {np.mean(time_lis):.5f} s."
245
+ )
246
+ print("-" * 80)
247
+ else:
248
+ model = model_type_dict[args.model_type.lower()](config).half()
249
+ if args.precision in ["W4A16"]:
250
+ real_quantize_model_weight(
251
+ model,
252
+ w_bit=4,
253
+ q_config=dict(q_group_size=args.q_group_size, zero_point=True),
254
+ init_only=True,
255
+ )
256
+ model = model.to(device)
257
+
258
+ if args.precision in ["W4A16"]:
259
+ # tune_all_wqlinears(model)
260
+ make_quant_attn(model, device, args.flash_attn)
261
+ make_quant_norm(model)
262
+ make_fused_mlp(model)
263
+ device_warmup(device)
264
+
265
+ print("huggingface ckpt loaded")
266
+
267
+ # warming up
268
+ input_ids = [1 for _ in range(2048)]
269
+ inputs = torch.as_tensor([input_ids], device=device)
270
+ out = model(
271
+ inputs,
272
+ start_pos=0,
273
+ chunk_prefilling=args.chunk_prefilling,
274
+ quant=args.precision in ["W4A16"],
275
+ ) # warmup
276
+
277
+ if not args.chunk_prefilling:
278
+ for context_length in args.context_length:
279
+ context_length = int("".join(context_length))
280
+ input_ids = [1 for _ in range(context_length)]
281
+ time_lis = []
282
+ print("-" * 80)
283
+ print("Context length: {}".format(context_length))
284
+ with torch.inference_mode():
285
+ for i in range(10): # Run ten times and get the average value
286
+ start_pos = 0
287
+ torch.cuda.synchronize()
288
+ t_st = time.time()
289
+ inputs = torch.as_tensor([input_ids], device=device)
290
+ out = model(
291
+ inputs,
292
+ start_pos=start_pos,
293
+ chunk_prefilling=args.chunk_prefilling,
294
+ quant=args.precision in ["W4A16"],
295
+ )
296
+ start_pos += inputs.shape[1]
297
+ torch.cuda.synchronize()
298
+ t_ed = time.time()
299
+ token = torch.argmax(out, keepdim=True)[0]
300
+ time_lis.append(t_ed - t_st)
301
+ if args.verbose:
302
+ print(i, t_ed - t_st)
303
+ print(f"Time To First Token: {np.mean(time_lis):.5f} s.")
304
+ # decoing throughput
305
+ time_lis = []
306
+ start_pos = context_length
307
+ torch.cuda.synchronize()
308
+ t_st = time.time()
309
+ for i in range(token_num):
310
+ token = model(
311
+ token,
312
+ start_pos=start_pos,
313
+ chunk_prefilling=args.chunk_prefilling,
314
+ quant=args.precision in ["W4A16"],
315
+ )
316
+ start_pos += 1
317
+ token = torch.argmax(token, keepdim=True)[0]
318
+ torch.cuda.synchronize()
319
+ t_ed = time.time()
320
+ time_lis.append(t_ed - t_st)
321
+ print(
322
+ f"Decoding throughput: {token_num/sum(time_lis):.5f} token/s."
323
+ )
324
+ print("-" * 80)
325
+ else:
326
+ for context_length, question_length in zip(
327
+ args.context_length, args.question_length
328
+ ):
329
+ context_length = int("".join(context_length))
330
+ question_length = int("".join(question_length))
331
+ input_ids_old = [1 for _ in range(context_length)]
332
+ input_ids_new = [1 for _ in range(question_length)]
333
+ time_lis = []
334
+ print("-" * 80)
335
+ print(
336
+ "History length: {} ; Question length: {}".format(
337
+ context_length, question_length
338
+ )
339
+ )
340
+ with torch.inference_mode():
341
+ for i in range(10): # Run ten times and get the average value
342
+ # history rounds
343
+ start_pos = 0
344
+ if context_length > question_length:
345
+ inputs = torch.as_tensor([input_ids_old], device=device)
346
+ out = model(
347
+ inputs,
348
+ start_pos=start_pos,
349
+ chunk_prefilling=args.chunk_prefilling,
350
+ quant=args.precision in ["W4A16"],
351
+ )
352
+ start_pos += inputs.shape[1]
353
+
354
+ # the present round
355
+ torch.cuda.synchronize()
356
+ t_st = time.time()
357
+ inputs = torch.as_tensor([input_ids_new], device=device)
358
+ out = model(
359
+ inputs,
360
+ start_pos=start_pos,
361
+ chunk_prefilling=args.chunk_prefilling,
362
+ quant=args.precision in ["W4A16"],
363
+ )
364
+ start_pos += inputs.shape[1]
365
+ torch.cuda.synchronize()
366
+ t_ed = time.time()
367
+
368
+ token = out[:, -1].max(1)[1].unsqueeze(1)
369
+ time_lis.append(t_ed - t_st)
370
+ if args.verbose:
371
+ print(i, t_ed - t_st)
372
+ print(
373
+ f"Time To First Token of this round: {np.mean(time_lis):.5f} s."
374
+ )
375
+ print("-" * 80)
376
+
377
+
378
+ if __name__ == "__main__":
379
+ main()
llm-awq/tinychat/demo.py ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import time
3
+ import numpy as np
4
+ import torch
5
+ import torch.nn as nn
6
+ from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig, modeling_utils
7
+ from attributedict.collections import AttributeDict
8
+ from tinychat.stream_generators import StreamGenerator
9
+ import tinychat.utils.constants
10
+ from tinychat.utils.load_quant import load_awq_model, load_awq_llama_fast
11
+ from tinychat.utils.prompt_templates import get_prompter, get_stop_token_ids
12
+ from tinychat.utils.tune import device_warmup, tune_all_wqlinears
13
+
14
+ import os
15
+
16
+ os.environ["CUDA_VISIBLE_DEVICES"] = "0"
17
+
18
+ # opt_params in TinyLLMEngine
19
+ gen_params = AttributeDict(
20
+ [
21
+ ("seed", -1), # RNG seed
22
+ ("n_threads", 1), # TODO: fix this
23
+ ("n_predict", 512), # new tokens to predict
24
+ ("n_parts", -1), # amount of model parts (-1: determine from model dimensions)
25
+ ("n_ctx", 512), # context size
26
+ ("n_batch", 512), # batch size for prompt processing (must be >=32 to use BLAS)
27
+ ("n_keep", 0), # number of tokens to keep from initial prompt
28
+ ("n_vocab", 50272), # vocabulary size
29
+ # sampling parameters
30
+ ("logit_bias", dict()), # logit bias for specific tokens: <int, float>
31
+ ("top_k", 40), # <= 0 to use vocab size
32
+ ("top_p", 0.95), # 1.0 = disabled
33
+ ("tfs_z", 1.00), # 1.0 = disabled
34
+ ("typical_p", 1.00), # 1.0 = disabled
35
+ ("temp", 0.70), # 1.0 = disabled
36
+ ("repeat_penalty", 1.10), # 1.0 = disabled
37
+ (
38
+ "repeat_last_n",
39
+ 64,
40
+ ), # last n tokens to penalize (0 = disable penalty, -1 = context size)
41
+ ("frequency_penalty", 0.00), # 0.0 = disabled
42
+ ("presence_penalty", 0.00), # 0.0 = disabled
43
+ ("mirostat", 0), # 0 = disabled, 1 = mirostat, 2 = mirostat 2.0
44
+ ("mirostat_tau", 5.00), # target entropy
45
+ ("mirostat_eta", 0.10), # learning rate
46
+ ]
47
+ )
48
+
49
+
50
+ def stream_output(output_stream):
51
+ print(f"ASSISTANT: ", end="", flush=True)
52
+ pre = 0
53
+ for outputs in output_stream:
54
+ output_text = outputs["text"]
55
+ output_text = output_text.strip().split(" ")
56
+ now = len(output_text) - 1
57
+ if now > pre:
58
+ print(" ".join(output_text[pre:now]), end=" ", flush=True)
59
+ pre = now
60
+ print(" ".join(output_text[pre:]), flush=True)
61
+ if "timing" in outputs and outputs["timing"] is not None:
62
+ timing = outputs["timing"]
63
+ context_tokens = timing["context_tokens"]
64
+ context_time = timing["context_time"]
65
+ total_tokens = timing["total_tokens"]
66
+ generation_time_list = timing["generation_time_list"]
67
+ generation_tokens = len(generation_time_list)
68
+ average_speed = (context_time + np.sum(generation_time_list)) / (
69
+ context_tokens + generation_tokens
70
+ )
71
+ print("=" * 50)
72
+ print("Speed of Inference")
73
+ print("-" * 50)
74
+ print(f"TTFT : { context_time:.3f} s for {context_tokens} tokens")
75
+ print(
76
+ f"Speed of Generation : {np.average(generation_time_list)*1000:.2f} ms/token"
77
+ )
78
+ print("=" * 50)
79
+ return " ".join(output_text), total_tokens
80
+
81
+
82
+ if __name__ == "__main__":
83
+ parser = argparse.ArgumentParser()
84
+ parser.add_argument(
85
+ "--model_type", type=str, default="LLaMa", help="type of the model"
86
+ )
87
+ parser.add_argument(
88
+ "--dtype", type=str, default="float16", choices=["float16", "bfloat16"]
89
+ )
90
+ parser.add_argument(
91
+ "--model_path",
92
+ type=str,
93
+ help="path to the model",
94
+ )
95
+ parser.add_argument(
96
+ "--precision", type=str, default="W4A16", help="compute precision"
97
+ )
98
+ parser.add_argument("--device", type=str, default="cuda:0")
99
+ parser.add_argument("--q_group_size", type=int, default=128)
100
+ parser.add_argument(
101
+ "--load_quant",
102
+ type=str,
103
+ help="path to the pre-quanted 4-bit weights",
104
+ )
105
+ parser.add_argument(
106
+ "--max_seq_len",
107
+ type=int,
108
+ default=2048,
109
+ help="maximum sequence length for kv cache",
110
+ )
111
+ parser.add_argument(
112
+ "--max_batch_size", type=int, default=1, help="maximum batch size for kv cache"
113
+ )
114
+ parser.add_argument(
115
+ "--mem_efficient_load",
116
+ action="store_true",
117
+ help="enable mem_efficient_load mod",
118
+ )
119
+ parser.add_argument(
120
+ "--single_round",
121
+ action="store_true",
122
+ help="whether to memorize previous conversations",
123
+ )
124
+ parser.add_argument(
125
+ "--flash_attn",
126
+ action="store_true",
127
+ help="whether to use flash attention",
128
+ )
129
+ parser.add_argument(
130
+ "--chunk_prefilling",
131
+ action="store_true",
132
+ help="If used, in context stage, the history tokens will not be recalculated, greatly speeding up the calculation",
133
+ )
134
+
135
+ args = parser.parse_args()
136
+ assert args.model_type.lower() in [
137
+ "llama",
138
+ "falcon",
139
+ "mpt",
140
+ "qwen",
141
+ ], "We only support llama & falcon & mpt now"
142
+ assert args.precision in ["W4A16", "W16A16"], "We only support W4A16/W16A16 now"
143
+
144
+ gen_params.n_predict = 1024
145
+ gen_params.n_vocab = 32000
146
+ tinychat.utils.constants.max_batch_size = args.max_batch_size
147
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
148
+ tinychat.utils.constants.mem_efficient_load = args.mem_efficient_load
149
+ if tinychat.utils.constants.mem_efficient_load:
150
+ print("=" * 80)
151
+ print(
152
+ "[Info] You have activated mem_efficient_load mode.\n Less on-chip memory will be consumed when loading the model.\n However, the loading process will take more time."
153
+ )
154
+ print("=" * 80)
155
+ # TODO (Haotian): a more elegant implementation here.
156
+ # We need to update these global variables before models use them.
157
+ from tinychat.models import (
158
+ FalconForCausalLM,
159
+ LlamaForCausalLM,
160
+ MPTForCausalLM,
161
+ Qwen2ForCausalLM,
162
+ )
163
+
164
+ def skip(*args, **kwargs):
165
+ pass
166
+
167
+ torch.nn.init.kaiming_uniform_ = skip
168
+ torch.nn.init.kaiming_normal_ = skip
169
+ torch.nn.init.uniform_ = skip
170
+ torch.nn.init.normal_ = skip
171
+
172
+ config = AutoConfig.from_pretrained(args.model_path, trust_remote_code=True)
173
+ if "mpt" in config.__class__.__name__.lower():
174
+ # config.init_device="meta"
175
+ tokenizer = AutoTokenizer.from_pretrained(
176
+ config.tokenizer_name, trust_remote_code=True
177
+ )
178
+ else:
179
+ tokenizer = AutoTokenizer.from_pretrained(
180
+ args.model_path, use_fast=False, trust_remote_code=True
181
+ )
182
+ torch_dtype = torch.float16 if args.dtype == "float16" else torch.bfloat16
183
+ modeling_utils._init_weights = False
184
+ torch.set_default_dtype(torch_dtype)
185
+
186
+ model_type_dict = {
187
+ "llama": LlamaForCausalLM,
188
+ "falcon": FalconForCausalLM,
189
+ "mpt": MPTForCausalLM,
190
+ "qwen": Qwen2ForCausalLM,
191
+ }
192
+
193
+ if args.precision == "W4A16":
194
+ if args.model_type.lower() == "llama":
195
+ model = model_type_dict["llama"](config).to(torch_dtype)
196
+ model = load_awq_llama_fast(
197
+ model, args.load_quant, 4, args.q_group_size, args.device
198
+ )
199
+ elif args.model_type.lower() == "qwen":
200
+ model = model_type_dict["qwen"](config).to(torch_dtype)
201
+ model = load_awq_llama_fast(
202
+ model, args.load_quant, 4, args.q_group_size, args.device
203
+ )
204
+ else:
205
+ model = model_type_dict[args.model_type.lower()](config).to(torch_dtype)
206
+ model = load_awq_model(
207
+ model, args.load_quant, 4, args.q_group_size, args.device
208
+ )
209
+ else:
210
+ loaded_model = AutoModelForCausalLM.from_pretrained(
211
+ args.model_path,
212
+ config=config,
213
+ torch_dtype=torch_dtype,
214
+ trust_remote_code=True,
215
+ )
216
+ model = (
217
+ model_type_dict[args.model_type.lower()](config)
218
+ .to(torch_dtype)
219
+ .to(args.device)
220
+ )
221
+ model.load_state_dict(loaded_model.state_dict())
222
+ # device warm up
223
+ device_warmup(args.device)
224
+
225
+ # autotune split_k_iters
226
+ # tune_all_wqlinears(model)
227
+
228
+ # TODO (Haotian): Verify if the StreamGenerator still works for the unmodified falcon impl.
229
+ stream_generator = StreamGenerator
230
+
231
+ # Optimize AWQ quantized model
232
+ if args.precision == "W4A16" and (
233
+ args.model_type.lower() == "llama" or args.model_type.lower() == "qwen"
234
+ ):
235
+ from tinychat.modules import make_quant_norm, make_quant_attn
236
+
237
+ if args.flash_attn:
238
+ make_quant_attn(model, args.device, args.flash_attn)
239
+ else:
240
+ make_quant_attn(model, args.device)
241
+ make_quant_norm(model)
242
+ model(
243
+ torch.randint(0, 1000, (1, 512), dtype=torch.int, device="cuda:0"),
244
+ 0,
245
+ quant=args.precision == "W4A16",
246
+ )
247
+ if args.max_seq_len <= 1024:
248
+ short_prompt = True
249
+ else:
250
+ short_prompt = False
251
+ model_prompter = get_prompter(args.model_type, args.model_path, short_prompt)
252
+ stop_token_ids = get_stop_token_ids(args.model_type, args.model_path)
253
+ count = 0
254
+ start_pos = 0
255
+ print("=" * 50)
256
+ while True:
257
+ # Get input from the user
258
+ input_prompt = input("USER: ")
259
+ if input_prompt == "":
260
+ print("EXIT...")
261
+ break
262
+ model_prompter.insert_prompt(input_prompt)
263
+ output_stream = stream_generator(
264
+ model,
265
+ tokenizer,
266
+ model_prompter.model_input,
267
+ start_pos,
268
+ gen_params,
269
+ device=args.device,
270
+ stop_token_ids=stop_token_ids,
271
+ chunk_prefilling=args.chunk_prefilling,
272
+ quant_llm=args.precision == "W4A16",
273
+ )
274
+ outputs, total_tokens = stream_output(output_stream)
275
+ if args.chunk_prefilling:
276
+ start_pos += total_tokens
277
+ else:
278
+ start_pos = 0
279
+ if (
280
+ args.single_round is not True and args.max_seq_len > 512
281
+ ): # Only memorize previous conversations when kv_cache_size > 512
282
+ model_prompter.update_template(outputs, args.chunk_prefilling)
283
+ count += 1
llm-awq/tinychat/internvl_benchmark.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from termcolor import colored
4
+
5
+ import llava
6
+ from llava import conversation as clib
7
+ from llava.media import Image, Video
8
+ import torch
9
+ from awq.quantize import fake_quant
10
+ from awq.quantize.quantizer import real_quantize_model_weight
11
+ from transformers import AutoConfig
12
+ import tinychat
13
+
14
+ from torchao.quantization import quantize_, Int4WeightOnlyConfig
15
+
16
+ import os
17
+
18
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
19
+
20
+ def skip(*args, **kwargs):
21
+ pass
22
+
23
+
24
+ def main() -> None:
25
+ parser = argparse.ArgumentParser()
26
+ parser.add_argument(
27
+ "--model-path",
28
+ "-m",
29
+ type=str,
30
+ default="/home/yuming/workspace/qwen/models/nvila-internal-8b-v1",
31
+ )
32
+ parser.add_argument(
33
+ "--quant_path",
34
+ type=str,
35
+ default="/PATH/TO/QUANT",
36
+ )
37
+ # parser.add_argument("--model-path", "-m", type=str, default="Efficient-Large-Model/J65")
38
+ # parser.add_argument("--quant_path", type=str, default="/home/yuming/workspace/qwen/models/J65/llm/vila2-J65-w4-g128-awq-v2.pt")
39
+ parser.add_argument("--conv-mode", "-c", type=str, default="auto")
40
+ # parser.add_argument("--media", type=str, default="/home/yuming/workspace/space_woaudio.mp4")
41
+ parser.add_argument("--device", type=str, default="cuda:0")
42
+ parser.add_argument(
43
+ "--act_scale_path",
44
+ type=str,
45
+ default="/PATH/TO/SCALE",
46
+ )
47
+ # quantization options
48
+ parser.add_argument("--quant_llm", action="store_true")
49
+ parser.add_argument("--quant_VT", action="store_true")
50
+ # Four basic tasks
51
+ parser.add_argument("--video_caption", action="store_true")
52
+ parser.add_argument("--video_QA", action="store_true")
53
+ parser.add_argument("--image_caption", action="store_true")
54
+ parser.add_argument("--image_QA", action="store_true")
55
+
56
+ parser.add_argument(
57
+ "--all",
58
+ action="store_true",
59
+ help="Whether to quantize visiontower and llm, and test all 4 tasks",
60
+ )
61
+ parser.add_argument(
62
+ "--fakequant_VT",
63
+ action="store_true",
64
+ help="Use fake quant or real quant for VisionTower",
65
+ )
66
+ parser.add_argument(
67
+ "--all_task", action="store_true", help="Whether to test all 4 tasks"
68
+ )
69
+ parser.add_argument(
70
+ "--video_path", type=str, default="../figures/nvila_demo_video.mp4"
71
+ )
72
+ parser.add_argument("--image_path", type=str, default="../figures/vila-logo.jpg")
73
+ parser.add_argument("--max_seq_len", type=int, default=8192)
74
+ args = parser.parse_args()
75
+
76
+ torch.nn.init.kaiming_uniform_ = skip
77
+ torch.nn.init.kaiming_normal_ = skip
78
+ torch.nn.init.uniform_ = skip
79
+ torch.nn.init.normal_ = skip
80
+ import tinychat.utils.constants
81
+
82
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
83
+ from transformers import modeling_utils
84
+
85
+ modeling_utils._init_weights = False
86
+
87
+ # Load model
88
+ from tinychat.models import InternVL3
89
+
90
+ config = AutoConfig.from_pretrained(args.model_path, trust_remote_code=True)
91
+ config.resume_path = args.model_path
92
+ model = InternVL3(config).half()
93
+ model.language_model = model.language_model.eval()
94
+ if args.quant_llm or args.all:
95
+ from tinychat.modules import (
96
+ make_quant_norm,
97
+ make_quant_attn,
98
+ make_fused_mlp,
99
+ make_fused_vision_attn,
100
+ )
101
+
102
+ real_quantize_model_weight(
103
+ model.language_model,
104
+ w_bit=4,
105
+ q_config=dict(q_group_size=128, zero_point=True),
106
+ init_only=True,
107
+ )
108
+ make_quant_attn(model.language_model, "cuda", True)
109
+ make_quant_norm(model.language_model)
110
+ make_fused_mlp(model.language_model)
111
+ model = model.to("cuda")
112
+ model = model.to(args.device)
113
+ if args.quant_VT or args.all:
114
+ from tinychat.modules import QuantInternVisionEncoder
115
+ model.vision_model.encoder = QuantInternVisionEncoder(model.vision_model.encoder)
116
+ model.vision_model.encoder = torch.compile(model.vision_model.encoder)
117
+
118
+ model = model.cuda().eval()
119
+
120
+ if args.video_caption or args.all or args.all_task:
121
+ print("-" * 80)
122
+ print("Video_Caption")
123
+ # Set conversation mode
124
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
125
+ media = Video(args.video_path)
126
+ text = "Elaborate on the visual and narrative elements of the video in detail." # + "1"+" 1"*3069
127
+ prompt = [media, text]
128
+ # Generate response
129
+ with torch.no_grad():
130
+ response = model.benchmark(prompt, args.quant_llm)
131
+ if args.video_QA or args.all or args.all_task:
132
+ print("-" * 80)
133
+ print("Video_QA")
134
+ # Set conversation mode
135
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
136
+ media = Video(args.video_path)
137
+ text = "What is the person in the video doing? Select the option that best describes their action: A. Folding paper B. Playing computer games C. Sleeping." # + "1"+" 1"*3069
138
+ prompt = [media, text]
139
+ # Generate response
140
+ with torch.no_grad():
141
+ response = model.benchmark(prompt, args.quant_llm)
142
+ if args.image_caption or args.all or args.all_task:
143
+ print("-" * 80)
144
+ print("Image_Caption")
145
+ # Set conversation mode
146
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
147
+ media = Image(args.image_path)
148
+ text = "Describe the image in detail."
149
+ prompt = [media, text]
150
+ # Generate response
151
+ with torch.no_grad():
152
+ response = model.benchmark(prompt, args.quant_llm)
153
+ if args.image_QA or args.all or args.all_task:
154
+ print("-" * 80)
155
+ print("Image_QA")
156
+ # Set conversation mode
157
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
158
+ media = Image(args.image_path)
159
+ text = "What does the text in the image say? Choose the option that best matches: A. VILA B. AIIV C. ALIV."
160
+ prompt = [media, text]
161
+ # Generate response
162
+ with torch.no_grad():
163
+ response = model.benchmark(prompt, args.quant_llm)
164
+
165
+
166
+ if __name__ == "__main__":
167
+ main()
llm-awq/tinychat/internvl_demo.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from termcolor import colored
4
+
5
+ import llava
6
+ from llava.media import Image, Video
7
+ import torch
8
+ from awq.quantize import fake_quant
9
+ from transformers import AutoConfig, AutoTokenizer
10
+ from tinychat.utils.load_quant import load_awq_model
11
+ from tinychat.utils.llava_image_processing import (
12
+ load_images,
13
+ vis_images,
14
+ )
15
+
16
+
17
+ def skip(*args, **kwargs):
18
+ pass
19
+
20
+
21
+ from tinychat.utils.tune import (
22
+ device_warmup,
23
+ tune_all_wqlinears,
24
+ tune_llava_patch_embedding,
25
+ )
26
+ from tinychat.utils.prompt_templates import (
27
+ get_prompter,
28
+ get_stop_token_ids,
29
+ get_image_token,
30
+ )
31
+ from llava.utils.media import extract_media
32
+ import tinychat.utils.constants
33
+ from tinychat.stream_generators.internvl_stream_gen import InternVLStreamGenerator
34
+ from tinychat.utils.conversation_utils import gen_params, stream_output, TimeStats
35
+
36
+ import os
37
+
38
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
39
+
40
+ def tune_intern_patch_embedding(vision_model, device):
41
+ patch_embedding = vision_model.embeddings.patch_embedding
42
+ patch_embedding = patch_embedding.to(device)
43
+
44
+ image = (
45
+ torch.randn((1, patch_embedding.in_channels, 336, 336))
46
+ .to(device)
47
+ .to(patch_embedding.weight.dtype)
48
+ )
49
+ for i in range(100):
50
+ patch_embedding(image)
51
+
52
+
53
+ def main(args):
54
+ # Accelerate model initialization
55
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
56
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
57
+ torch.nn.init.kaiming_uniform_ = skip
58
+ torch.nn.init.kaiming_normal_ = skip
59
+ torch.nn.init.uniform_ = skip
60
+ torch.nn.init.normal_ = skip
61
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
62
+
63
+ # Prepare model
64
+ from tinychat.models import InternVL3
65
+ from tinychat.models.internvl.internvit import InternVisionModel
66
+ from transformers import AutoConfig
67
+ from tinychat.models.qwen2 import Qwen2ForCausalLM
68
+
69
+ config = AutoConfig.from_pretrained(args.model_path, trust_remote_code=True)
70
+ config.resume_path = args.model_path
71
+ if args.quant_llm or args.all:
72
+ model = InternVL3.from_pretrained(args.model_path, config=config).half()
73
+ else:
74
+ llm = Qwen2ForCausalLM.from_pretrained(args.model_path)
75
+ llm = llm.cpu()
76
+ tokenizer = AutoTokenizer.from_pretrained(
77
+ args.model_path, use_fast=False, trust_remote_code=True
78
+ )
79
+ llm.resize_token_embeddings(len(tokenizer))
80
+ model = InternVL3(config, language_model=llm).half()
81
+
82
+ if args.smooth_VT or args.all:
83
+ from awq.quantize import smooth_lm
84
+
85
+ act_scales = torch.load(args.act_scale_path)
86
+ smooth_lm(model.vision_tower, act_scales, 0.3)
87
+ if args.quant_llm or args.all:
88
+ from tinychat.modules import (
89
+ make_quant_norm,
90
+ make_quant_attn,
91
+ make_fused_mlp,
92
+ make_fused_vision_attn,
93
+ )
94
+
95
+ model = load_awq_model(model, args.quant_path, 4, 128, args.device)
96
+ make_quant_attn(model, args.device, True)
97
+ make_quant_norm(model)
98
+ model.cpu()
99
+ model.resize_token_embeddings(len(model.tokenizer))
100
+ pass
101
+
102
+ if args.quant_VT or args.all:
103
+ from tinychat.modules import QuantInternVisionEncoder
104
+ model.vision_model.encoder = QuantInternVisionEncoder(model.vision_model.encoder)
105
+ # model.vision_model.encoder = torch.compile(model.vision_model.encoder)
106
+
107
+ model = model.cuda().eval()
108
+ device_warmup(args.device)
109
+ # tune_intern_patch_embedding(model.vision_model, device=args.device)
110
+
111
+ # Pre-prepare media
112
+ prompt = []
113
+ media_files = []
114
+ if args.media is not None:
115
+ for media in args.media or []:
116
+ if any(media.endswith(ext) for ext in [".jpg", ".jpeg", ".png"]):
117
+ media = Image(media)
118
+ media_files.append(media)
119
+ media_prompt = "<image>"
120
+ elif any(media.endswith(ext) for ext in [".mp4", ".mkv", ".webm"]):
121
+ media = Video(media)
122
+ media_files.append(media)
123
+ media_prompt = "<vila/video>"
124
+ else:
125
+ raise ValueError(f"Unsupported media type: {media}")
126
+ prompt.append(media)
127
+ media_num = len(media_files)
128
+ if args.vis_image:
129
+ print("=" * 50)
130
+ print("Input Image:")
131
+ vis_images(args.media)
132
+
133
+ conversation = [{"from": "human", "value": prompt}]
134
+ media, media_cfg = model.prepare_media(conversation)
135
+ # Prepare streaming
136
+ stream_generator = InternVLStreamGenerator
137
+ # Prepare prompt
138
+ if args.max_seq_len <= 1024:
139
+ short_prompt = True
140
+ else:
141
+ short_prompt = False
142
+ model_prompter = get_prompter(
143
+ args.model_type, args.model_path, short_prompt, args.empty_prompt
144
+ )
145
+ stop_token_ids = get_stop_token_ids(args.model_type, args.model_path)
146
+ count = 0
147
+
148
+ if args.empty_prompt:
149
+ input_indicator = "Input: "
150
+ output_indicator = "Generated: "
151
+ else:
152
+ input_indicator = "USER: "
153
+ output_indicator = "ASSISTANT: "
154
+
155
+ count = 0
156
+ model.eval()
157
+ time_stats = TimeStats()
158
+ start_pos = 0
159
+ while True:
160
+ # Get input from the user
161
+ print("=" * 50)
162
+ input_prompt = input(input_indicator)
163
+ print("-" * 50)
164
+ if input_prompt == "":
165
+ print("EXIT...")
166
+ time_stats.show()
167
+ break
168
+ if count == 0: # Insert media here
169
+ if args.media is not None:
170
+ if media_prompt in input_prompt:
171
+ input_prompt = input_prompt
172
+ else:
173
+ if media_prompt == "<image>":
174
+ input_prompt = media_prompt * media_num + input_prompt
175
+ elif media_prompt == "<vila/video>":
176
+ video_prefix = ''.join([f'Frame{i+1}: <image>\n' for i in range(len(media_cfg))])
177
+ input_prompt = video_prefix + input_prompt
178
+
179
+ model_prompter.insert_prompt(input_prompt)
180
+ else:
181
+ model_prompter.insert_prompt(input_prompt)
182
+ if args.chunk_prefilling:
183
+ media = None
184
+ media_cfg = None
185
+ output_stream = stream_generator(
186
+ model,
187
+ gen_params,
188
+ model_prompter.model_input,
189
+ media,
190
+ media_cfg,
191
+ start_pos,
192
+ device=args.device,
193
+ stop_token_ids=stop_token_ids,
194
+ chunk_prefilling=args.chunk_prefilling,
195
+ quant_llm=args.quant_llm or args.all,
196
+ )
197
+ print(output_indicator, end="", flush=True)
198
+ if count == 0:
199
+ outputs, total_tokens = stream_output(output_stream, time_stats)
200
+ else:
201
+ outputs, total_tokens = stream_output(output_stream)
202
+ if args.chunk_prefilling:
203
+ start_pos += total_tokens
204
+ if (
205
+ args.single_round is not True and args.max_seq_len > 512
206
+ ): # Only memorize previous conversations when kv_cache_size > 512
207
+ model_prompter.update_template(outputs, args.chunk_prefilling)
208
+ count += 1
209
+
210
+
211
+ if __name__ == "__main__":
212
+ parser = argparse.ArgumentParser()
213
+ parser.add_argument(
214
+ "--model_type", type=str, default="LLaMa", help="type of the model"
215
+ )
216
+ parser.add_argument(
217
+ "--model-path", type=str, default="/data/llm/checkpoints/llava/llava-v1.5-7b"
218
+ )
219
+ parser.add_argument(
220
+ "--quant_path",
221
+ type=str,
222
+ default="/data/llm/checkpoints/llava/llava-v1.5-7b-w4-g128-awq.pt",
223
+ )
224
+ parser.add_argument(
225
+ "--act_scale_path",
226
+ type=str,
227
+ default="/PATH/TO/SCALE",
228
+ )
229
+ parser.add_argument(
230
+ "--media", type=str, nargs="+", help="Multi-modal input (Video or image path)"
231
+ )
232
+ parser.add_argument("--device", type=str, default="cuda")
233
+ parser.add_argument("--max_seq_len", type=int, default=4098)
234
+ parser.add_argument(
235
+ "--single_round",
236
+ action="store_true",
237
+ help="whether to memorize previous conversations",
238
+ )
239
+ parser.add_argument(
240
+ "--vis-image",
241
+ action="store_true",
242
+ help="whether to visualize the image while chatting",
243
+ )
244
+ parser.add_argument(
245
+ "--empty-prompt",
246
+ action="store_true",
247
+ help="whether to use empty prompt template",
248
+ )
249
+ parser.add_argument(
250
+ "--flash_attn",
251
+ action="store_true",
252
+ help="whether to use flash attention",
253
+ )
254
+ parser.add_argument(
255
+ "--chunk_prefilling",
256
+ action="store_true",
257
+ help="If used, in context stage, the history tokens will not be recalculated, greatly speeding up the calculation",
258
+ )
259
+ # smooth and quantization options
260
+ parser.add_argument("--quant_llm", action="store_true")
261
+ parser.add_argument("--quant_VT", action="store_true")
262
+ parser.add_argument("--smooth_VT", action="store_true")
263
+ parser.add_argument("--all", action="store_true")
264
+ parser.add_argument(
265
+ "--fakequant_VT",
266
+ action="store_true",
267
+ help="Use fake quant or real quant for VisionTower",
268
+ )
269
+ args = parser.parse_args()
270
+ main(args)
llm-awq/tinychat/models/__init__.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from .falcon import FalconForCausalLM
2
+ from .llama import LlamaForCausalLM
3
+ from .mpt import MPTForCausalLM
4
+ from .llava_llama import LlavaLlamaForCausalLM
5
+ from .qwen2 import Qwen2ForCausalLM
6
+ try:
7
+ from .internvl3 import InternVL3
8
+ except ImportError as e:
9
+ print("InternVL3 model import failure. To activate, please install VILA at https://github.com/NVlabs/VILA.")
10
+
llm-awq/tinychat/models/internvl/configuration_internvl.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # --------------------------------------------------------
2
+ # InternVL
3
+ # Copyright (c) 2024 OpenGVLab
4
+ # Licensed under The MIT License [see LICENSE for details]
5
+ # --------------------------------------------------------
6
+
7
+ import os
8
+ from typing import Union
9
+ import copy
10
+
11
+ from transformers.configuration_utils import PretrainedConfig
12
+ from transformers.utils import logging
13
+ from transformers import AutoConfig, LlamaConfig, Qwen2Config
14
+
15
+ logger = logging.get_logger(__name__)
16
+
17
+
18
+ class InternVisionConfig(PretrainedConfig):
19
+ r"""
20
+ This is the configuration class to store the configuration of a [`InternVisionModel`]. It is used to
21
+ instantiate a vision encoder according to the specified arguments, defining the model architecture.
22
+
23
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
24
+ documentation from [`PretrainedConfig`] for more information.
25
+
26
+ Args:
27
+ num_channels (`int`, *optional*, defaults to 3):
28
+ Number of color channels in the input images (e.g., 3 for RGB).
29
+ patch_size (`int`, *optional*, defaults to 14):
30
+ The size (resolution) of each patch.
31
+ image_size (`int`, *optional*, defaults to 224):
32
+ The size (resolution) of each image.
33
+ qkv_bias (`bool`, *optional*, defaults to `False`):
34
+ Whether to add a bias to the queries and values in the self-attention layers.
35
+ hidden_size (`int`, *optional*, defaults to 3200):
36
+ Dimensionality of the encoder layers and the pooler layer.
37
+ num_attention_heads (`int`, *optional*, defaults to 25):
38
+ Number of attention heads for each attention layer in the Transformer encoder.
39
+ intermediate_size (`int`, *optional*, defaults to 12800):
40
+ Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder.
41
+ qk_normalization (`bool`, *optional*, defaults to `True`):
42
+ Whether to normalize the queries and keys in the self-attention layers.
43
+ num_hidden_layers (`int`, *optional*, defaults to 48):
44
+ Number of hidden layers in the Transformer encoder.
45
+ use_flash_attn (`bool`, *optional*, defaults to `True`):
46
+ Whether to use flash attention mechanism.
47
+ hidden_act (`str` or `function`, *optional*, defaults to `"gelu"`):
48
+ The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
49
+ `"relu"`, `"selu"` and `"gelu_new"` ``"gelu"` are supported.
50
+ layer_norm_eps (`float`, *optional*, defaults to 1e-6):
51
+ The epsilon used by the layer normalization layers.
52
+ dropout (`float`, *optional*, defaults to 0.0):
53
+ The dropout probability for all fully connected layers in the embeddings, encoder, and pooler.
54
+ drop_path_rate (`float`, *optional*, defaults to 0.0):
55
+ Dropout rate for stochastic depth.
56
+ attention_dropout (`float`, *optional*, defaults to 0.0):
57
+ The dropout ratio for the attention probabilities.
58
+ initializer_range (`float`, *optional*, defaults to 0.02):
59
+ The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
60
+ initializer_factor (`float`, *optional*, defaults to 0.1):
61
+ A factor for layer scale.
62
+ """
63
+
64
+ model_type = 'intern_vit_6b'
65
+
66
+ def __init__(
67
+ self,
68
+ num_channels=3,
69
+ patch_size=14,
70
+ image_size=224,
71
+ qkv_bias=False,
72
+ hidden_size=3200,
73
+ num_attention_heads=25,
74
+ intermediate_size=12800,
75
+ qk_normalization=True,
76
+ num_hidden_layers=48,
77
+ use_flash_attn=True,
78
+ hidden_act='gelu',
79
+ norm_type='rms_norm',
80
+ layer_norm_eps=1e-6,
81
+ dropout=0.0,
82
+ drop_path_rate=0.0,
83
+ attention_dropout=0.0,
84
+ initializer_range=0.02,
85
+ initializer_factor=0.1,
86
+ **kwargs,
87
+ ):
88
+ super().__init__(**kwargs)
89
+
90
+ self.hidden_size = hidden_size
91
+ self.intermediate_size = intermediate_size
92
+ self.dropout = dropout
93
+ self.drop_path_rate = drop_path_rate
94
+ self.num_hidden_layers = num_hidden_layers
95
+ self.num_attention_heads = num_attention_heads
96
+ self.num_channels = num_channels
97
+ self.patch_size = patch_size
98
+ self.image_size = image_size
99
+ self.initializer_range = initializer_range
100
+ self.initializer_factor = initializer_factor
101
+ self.attention_dropout = attention_dropout
102
+ self.layer_norm_eps = layer_norm_eps
103
+ self.hidden_act = hidden_act
104
+ self.norm_type = norm_type
105
+ self.qkv_bias = qkv_bias
106
+ self.qk_normalization = qk_normalization
107
+ self.use_flash_attn = use_flash_attn
108
+
109
+ @classmethod
110
+ def from_pretrained(cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs) -> 'PretrainedConfig':
111
+ config_dict, kwargs = cls.get_config_dict(pretrained_model_name_or_path, **kwargs)
112
+
113
+ if 'vision_config' in config_dict:
114
+ config_dict = config_dict['vision_config']
115
+
116
+ if 'model_type' in config_dict and hasattr(cls, 'model_type') and config_dict['model_type'] != cls.model_type:
117
+ logger.warning(
118
+ f"You are using a model of type {config_dict['model_type']} to instantiate a model of type "
119
+ f'{cls.model_type}. This is not supported for all configurations of models and can yield errors.'
120
+ )
121
+
122
+ return cls.from_dict(config_dict, **kwargs)
123
+
124
+
125
+ class InternVLChatConfig(PretrainedConfig):
126
+ model_type = 'internvl_chat'
127
+ is_composition = True
128
+
129
+ def __init__(
130
+ self,
131
+ vision_config=None,
132
+ llm_config=None,
133
+ use_backbone_lora=0,
134
+ use_llm_lora=0,
135
+ select_layer=-1,
136
+ force_image_size=None,
137
+ downsample_ratio=0.5,
138
+ template=None,
139
+ dynamic_image_size=False,
140
+ use_thumbnail=False,
141
+ ps_version='v1',
142
+ min_dynamic_patch=1,
143
+ max_dynamic_patch=6,
144
+ **kwargs):
145
+ super().__init__(**kwargs)
146
+
147
+ if vision_config is None:
148
+ vision_config = {'architectures': ['InternVisionModel']}
149
+ logger.info('vision_config is None. Initializing the InternVisionConfig with default values.')
150
+
151
+ if llm_config is None:
152
+ llm_config = {'architectures': ['Qwen2ForCausalLM']}
153
+ logger.info('llm_config is None. Initializing the LlamaConfig config with default values (`LlamaConfig`).')
154
+
155
+ self.vision_config = InternVisionConfig(**vision_config)
156
+ if llm_config.get('architectures')[0] == 'LlamaForCausalLM':
157
+ self.llm_config = LlamaConfig(**llm_config)
158
+ elif llm_config.get('architectures')[0] == 'Qwen2ForCausalLM':
159
+ self.llm_config = Qwen2Config(**llm_config)
160
+ else:
161
+ raise ValueError('Unsupported architecture: {}'.format(llm_config.get('architectures')[0]))
162
+ self.use_backbone_lora = use_backbone_lora
163
+ self.use_llm_lora = use_llm_lora
164
+ self.select_layer = select_layer
165
+ self.force_image_size = force_image_size
166
+ self.downsample_ratio = downsample_ratio
167
+ self.template = template
168
+ self.dynamic_image_size = dynamic_image_size
169
+ self.use_thumbnail = use_thumbnail
170
+ self.ps_version = ps_version # pixel shuffle version
171
+ self.min_dynamic_patch = min_dynamic_patch
172
+ self.max_dynamic_patch = max_dynamic_patch
173
+ # By default, we use tie_word_embeddings=False for models of all sizes.
174
+ self.tie_word_embeddings = self.llm_config.tie_word_embeddings
175
+
176
+ logger.info(f'vision_select_layer: {self.select_layer}')
177
+ logger.info(f'ps_version: {self.ps_version}')
178
+ logger.info(f'min_dynamic_patch: {self.min_dynamic_patch}')
179
+ logger.info(f'max_dynamic_patch: {self.max_dynamic_patch}')
180
+
181
+ def to_dict(self):
182
+ """
183
+ Serializes this instance to a Python dictionary. Override the default [`~PretrainedConfig.to_dict`].
184
+
185
+ Returns:
186
+ `Dict[str, any]`: Dictionary of all the attributes that make up this configuration instance,
187
+ """
188
+ output = copy.deepcopy(self.__dict__)
189
+ output['vision_config'] = self.vision_config.to_dict()
190
+ output['llm_config'] = self.llm_config.to_dict()
191
+ output['model_type'] = self.__class__.model_type
192
+ output['use_backbone_lora'] = self.use_backbone_lora
193
+ output['use_llm_lora'] = self.use_llm_lora
194
+ output['select_layer'] = self.select_layer
195
+ output['force_image_size'] = self.force_image_size
196
+ output['downsample_ratio'] = self.downsample_ratio
197
+ output['template'] = self.template
198
+ output['dynamic_image_size'] = self.dynamic_image_size
199
+ output['use_thumbnail'] = self.use_thumbnail
200
+ output['ps_version'] = self.ps_version
201
+ output['min_dynamic_patch'] = self.min_dynamic_patch
202
+ output['max_dynamic_patch'] = self.max_dynamic_patch
203
+
204
+ return output
llm-awq/tinychat/models/internvl/conversation.py ADDED
@@ -0,0 +1,391 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Conversation prompt templates.
3
+
4
+ We kindly request that you import fastchat instead of copying this file if you wish to use it.
5
+ If you have changes in mind, please contribute back so the community can benefit collectively and continue to maintain these valuable templates.
6
+
7
+ Modified from https://github.com/lm-sys/FastChat/blob/main/fastchat/conversation.py
8
+ """
9
+
10
+ import dataclasses
11
+ from enum import IntEnum, auto
12
+ from typing import Dict, List, Tuple, Union
13
+
14
+
15
+ class SeparatorStyle(IntEnum):
16
+ """Separator styles."""
17
+
18
+ ADD_COLON_SINGLE = auto()
19
+ ADD_COLON_TWO = auto()
20
+ ADD_COLON_SPACE_SINGLE = auto()
21
+ NO_COLON_SINGLE = auto()
22
+ NO_COLON_TWO = auto()
23
+ ADD_NEW_LINE_SINGLE = auto()
24
+ LLAMA2 = auto()
25
+ CHATGLM = auto()
26
+ CHATML = auto()
27
+ CHATINTERN = auto()
28
+ DOLLY = auto()
29
+ RWKV = auto()
30
+ PHOENIX = auto()
31
+ ROBIN = auto()
32
+ FALCON_CHAT = auto()
33
+ CHATGLM3 = auto()
34
+ INTERNVL_ZH = auto()
35
+ MPT = auto()
36
+
37
+
38
+ @dataclasses.dataclass
39
+ class Conversation:
40
+ """A class that manages prompt templates and keeps all conversation history."""
41
+
42
+ # The name of this template
43
+ name: str
44
+ # The template of the system prompt
45
+ system_template: str = '{system_message}'
46
+ # The system message
47
+ system_message: str = ''
48
+ # The names of two roles
49
+ roles: Tuple[str] = ('USER', 'ASSISTANT')
50
+ # All messages. Each item is (role, message).
51
+ messages: List[List[str]] = ()
52
+ # The number of few shot examples
53
+ offset: int = 0
54
+ # The separator style and configurations
55
+ sep_style: SeparatorStyle = SeparatorStyle.ADD_COLON_SINGLE
56
+ sep: str = '\n'
57
+ sep2: str = None
58
+ # Stop criteria (the default one is EOS token)
59
+ stop_str: Union[str, List[str]] = None
60
+ # Stops generation if meeting any token in this list
61
+ stop_token_ids: List[int] = None
62
+
63
+ def get_prompt(self) -> str:
64
+ """Get the prompt for generation."""
65
+ system_prompt = self.system_template.format(system_message=self.system_message)
66
+ if self.sep_style == SeparatorStyle.ADD_COLON_SINGLE:
67
+ ret = system_prompt + self.sep
68
+ for role, message in self.messages:
69
+ if message:
70
+ ret += role + ': ' + message + self.sep
71
+ else:
72
+ ret += role + ':'
73
+ return ret
74
+ elif self.sep_style == SeparatorStyle.ADD_COLON_TWO:
75
+ seps = [self.sep, self.sep2]
76
+ ret = system_prompt + seps[0]
77
+ for i, (role, message) in enumerate(self.messages):
78
+ if message:
79
+ ret += role + ': ' + message + seps[i % 2]
80
+ else:
81
+ ret += role + ':'
82
+ return ret
83
+ elif self.sep_style == SeparatorStyle.ADD_COLON_SPACE_SINGLE:
84
+ ret = system_prompt + self.sep
85
+ for role, message in self.messages:
86
+ if message:
87
+ ret += role + ': ' + message + self.sep
88
+ else:
89
+ ret += role + ': ' # must be end with a space
90
+ return ret
91
+ elif self.sep_style == SeparatorStyle.ADD_NEW_LINE_SINGLE:
92
+ ret = '' if system_prompt == '' else system_prompt + self.sep
93
+ for role, message in self.messages:
94
+ if message:
95
+ ret += role + '\n' + message + self.sep
96
+ else:
97
+ ret += role + '\n'
98
+ return ret
99
+ elif self.sep_style == SeparatorStyle.NO_COLON_SINGLE:
100
+ ret = system_prompt
101
+ for role, message in self.messages:
102
+ if message:
103
+ ret += role + message + self.sep
104
+ else:
105
+ ret += role
106
+ return ret
107
+ elif self.sep_style == SeparatorStyle.NO_COLON_TWO:
108
+ seps = [self.sep, self.sep2]
109
+ ret = system_prompt
110
+ for i, (role, message) in enumerate(self.messages):
111
+ if message:
112
+ ret += role + message + seps[i % 2]
113
+ else:
114
+ ret += role
115
+ return ret
116
+ elif self.sep_style == SeparatorStyle.RWKV:
117
+ ret = system_prompt
118
+ for i, (role, message) in enumerate(self.messages):
119
+ if message:
120
+ ret += (
121
+ role
122
+ + ': '
123
+ + message.replace('\r\n', '\n').replace('\n\n', '\n')
124
+ )
125
+ ret += '\n\n'
126
+ else:
127
+ ret += role + ':'
128
+ return ret
129
+ elif self.sep_style == SeparatorStyle.LLAMA2:
130
+ seps = [self.sep, self.sep2]
131
+ if self.system_message:
132
+ ret = system_prompt
133
+ else:
134
+ ret = '[INST] '
135
+ for i, (role, message) in enumerate(self.messages):
136
+ tag = self.roles[i % 2]
137
+ if message:
138
+ if i == 0:
139
+ ret += message + ' '
140
+ else:
141
+ ret += tag + ' ' + message + seps[i % 2]
142
+ else:
143
+ ret += tag
144
+ return ret
145
+ elif self.sep_style == SeparatorStyle.CHATGLM:
146
+ # source: https://huggingface.co/THUDM/chatglm-6b/blob/1d240ba371910e9282298d4592532d7f0f3e9f3e/modeling_chatglm.py#L1302-L1308
147
+ # source2: https://huggingface.co/THUDM/chatglm2-6b/blob/e186c891cf64310ac66ef10a87e6635fa6c2a579/modeling_chatglm.py#L926
148
+ round_add_n = 1 if self.name == 'chatglm2' else 0
149
+ if system_prompt:
150
+ ret = system_prompt + self.sep
151
+ else:
152
+ ret = ''
153
+
154
+ for i, (role, message) in enumerate(self.messages):
155
+ if i % 2 == 0:
156
+ ret += f'[Round {i//2 + round_add_n}]{self.sep}'
157
+
158
+ if message:
159
+ ret += f'{role}:{message}{self.sep}'
160
+ else:
161
+ ret += f'{role}:'
162
+ return ret
163
+ elif self.sep_style == SeparatorStyle.CHATML:
164
+ ret = '' if system_prompt == '' else system_prompt + self.sep + '\n'
165
+ for role, message in self.messages:
166
+ if message:
167
+ ret += role + '\n' + message + self.sep + '\n'
168
+ else:
169
+ ret += role + '\n'
170
+ return ret
171
+ elif self.sep_style == SeparatorStyle.CHATGLM3:
172
+ ret = ''
173
+ if self.system_message:
174
+ ret += system_prompt
175
+ for role, message in self.messages:
176
+ if message:
177
+ ret += role + '\n' + ' ' + message
178
+ else:
179
+ ret += role
180
+ return ret
181
+ elif self.sep_style == SeparatorStyle.CHATINTERN:
182
+ # source: https://huggingface.co/internlm/internlm-chat-7b-8k/blob/bd546fa984b4b0b86958f56bf37f94aa75ab8831/modeling_internlm.py#L771
183
+ seps = [self.sep, self.sep2]
184
+ ret = system_prompt
185
+ for i, (role, message) in enumerate(self.messages):
186
+ # if i % 2 == 0:
187
+ # ret += "<s>"
188
+ if message:
189
+ ret += role + ':' + message + seps[i % 2] + '\n'
190
+ else:
191
+ ret += role + ':'
192
+ return ret
193
+ elif self.sep_style == SeparatorStyle.DOLLY:
194
+ seps = [self.sep, self.sep2]
195
+ ret = system_prompt
196
+ for i, (role, message) in enumerate(self.messages):
197
+ if message:
198
+ ret += role + ':\n' + message + seps[i % 2]
199
+ if i % 2 == 1:
200
+ ret += '\n\n'
201
+ else:
202
+ ret += role + ':\n'
203
+ return ret
204
+ elif self.sep_style == SeparatorStyle.PHOENIX:
205
+ ret = system_prompt
206
+ for role, message in self.messages:
207
+ if message:
208
+ ret += role + ': ' + '<s>' + message + '</s>'
209
+ else:
210
+ ret += role + ': ' + '<s>'
211
+ return ret
212
+ elif self.sep_style == SeparatorStyle.ROBIN:
213
+ ret = system_prompt + self.sep
214
+ for role, message in self.messages:
215
+ if message:
216
+ ret += role + ':\n' + message + self.sep
217
+ else:
218
+ ret += role + ':\n'
219
+ return ret
220
+ elif self.sep_style == SeparatorStyle.FALCON_CHAT:
221
+ ret = ''
222
+ if self.system_message:
223
+ ret += system_prompt + self.sep
224
+ for role, message in self.messages:
225
+ if message:
226
+ ret += role + ': ' + message + self.sep
227
+ else:
228
+ ret += role + ':'
229
+
230
+ return ret
231
+ elif self.sep_style == SeparatorStyle.INTERNVL_ZH:
232
+ seps = [self.sep, self.sep2]
233
+ ret = self.system_message + seps[0]
234
+ for i, (role, message) in enumerate(self.messages):
235
+ if message:
236
+ ret += role + ': ' + message + seps[i % 2]
237
+ else:
238
+ ret += role + ':'
239
+ return ret
240
+ elif self.sep_style == SeparatorStyle.MPT:
241
+ ret = system_prompt + self.sep
242
+ for role, message in self.messages:
243
+ if message:
244
+ if type(message) is tuple:
245
+ message, _, _ = message
246
+ ret += role + message + self.sep
247
+ else:
248
+ ret += role
249
+ return ret
250
+ else:
251
+ raise ValueError(f'Invalid style: {self.sep_style}')
252
+
253
+ def set_system_message(self, system_message: str):
254
+ """Set the system message."""
255
+ self.system_message = system_message
256
+
257
+ def append_message(self, role: str, message: str):
258
+ """Append a new message."""
259
+ self.messages.append([role, message])
260
+
261
+ def update_last_message(self, message: str):
262
+ """Update the last output.
263
+
264
+ The last message is typically set to be None when constructing the prompt,
265
+ so we need to update it in-place after getting the response from a model.
266
+ """
267
+ self.messages[-1][1] = message
268
+
269
+ def to_gradio_chatbot(self):
270
+ """Convert the conversation to gradio chatbot format."""
271
+ ret = []
272
+ for i, (role, msg) in enumerate(self.messages[self.offset :]):
273
+ if i % 2 == 0:
274
+ ret.append([msg, None])
275
+ else:
276
+ ret[-1][-1] = msg
277
+ return ret
278
+
279
+ def to_openai_api_messages(self):
280
+ """Convert the conversation to OpenAI chat completion format."""
281
+ ret = [{'role': 'system', 'content': self.system_message}]
282
+
283
+ for i, (_, msg) in enumerate(self.messages[self.offset :]):
284
+ if i % 2 == 0:
285
+ ret.append({'role': 'user', 'content': msg})
286
+ else:
287
+ if msg is not None:
288
+ ret.append({'role': 'assistant', 'content': msg})
289
+ return ret
290
+
291
+ def copy(self):
292
+ return Conversation(
293
+ name=self.name,
294
+ system_template=self.system_template,
295
+ system_message=self.system_message,
296
+ roles=self.roles,
297
+ messages=[[x, y] for x, y in self.messages],
298
+ offset=self.offset,
299
+ sep_style=self.sep_style,
300
+ sep=self.sep,
301
+ sep2=self.sep2,
302
+ stop_str=self.stop_str,
303
+ stop_token_ids=self.stop_token_ids,
304
+ )
305
+
306
+ def dict(self):
307
+ return {
308
+ 'template_name': self.name,
309
+ 'system_message': self.system_message,
310
+ 'roles': self.roles,
311
+ 'messages': self.messages,
312
+ 'offset': self.offset,
313
+ }
314
+
315
+
316
+ # A global registry for all conversation templates
317
+ conv_templates: Dict[str, Conversation] = {}
318
+
319
+
320
+ def register_conv_template(template: Conversation, override: bool = False):
321
+ """Register a new conversation template."""
322
+ if not override:
323
+ assert (
324
+ template.name not in conv_templates
325
+ ), f'{template.name} has been registered.'
326
+
327
+ conv_templates[template.name] = template
328
+
329
+
330
+ def get_conv_template(name: str) -> Conversation:
331
+ """Get a conversation template."""
332
+ return conv_templates[name].copy()
333
+
334
+
335
+ # Both Hermes-2 and internlm2-chat are chatml-format conversation templates. The difference
336
+ # is that during training, the preprocessing function for the Hermes-2 template doesn't add
337
+ # <s> at the beginning of the tokenized sequence, while the internlm2-chat template does.
338
+ # Therefore, they are completely equivalent during inference.
339
+ register_conv_template(
340
+ Conversation(
341
+ name='Hermes-2',
342
+ system_template='<|im_start|>system\n{system_message}',
343
+ # note: The new system prompt was not used here to avoid changes in benchmark performance.
344
+ # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',
345
+ system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',
346
+ roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),
347
+ sep_style=SeparatorStyle.MPT,
348
+ sep='<|im_end|>',
349
+ stop_str='<|endoftext|>',
350
+ )
351
+ )
352
+
353
+
354
+ register_conv_template(
355
+ Conversation(
356
+ name='internlm2-chat',
357
+ system_template='<|im_start|>system\n{system_message}',
358
+ # note: The new system prompt was not used here to avoid changes in benchmark performance.
359
+ # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',
360
+ system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',
361
+ roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),
362
+ sep_style=SeparatorStyle.MPT,
363
+ sep='<|im_end|>',
364
+ )
365
+ )
366
+
367
+
368
+ register_conv_template(
369
+ Conversation(
370
+ name='phi3-chat',
371
+ system_template='<|system|>\n{system_message}',
372
+ # note: The new system prompt was not used here to avoid changes in benchmark performance.
373
+ # system_message='我是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',
374
+ system_message='你是由上海人工智能实验室联合商汤科技开发的书生多模态大模型,英文名叫InternVL, 是一个有用无害的人工智能助手。',
375
+ roles=('<|user|>\n', '<|assistant|>\n'),
376
+ sep_style=SeparatorStyle.MPT,
377
+ sep='<|end|>',
378
+ )
379
+ )
380
+
381
+
382
+ register_conv_template(
383
+ Conversation(
384
+ name='internvl2_5',
385
+ system_template='<|im_start|>system\n{system_message}',
386
+ system_message='你是书生·万象,英文名是InternVL,是由上海人工智能实验室、清华大学及多家合作单位联合开发的多模态大语言模型。',
387
+ roles=('<|im_start|>user\n', '<|im_start|>assistant\n'),
388
+ sep_style=SeparatorStyle.MPT,
389
+ sep='<|im_end|>\n',
390
+ )
391
+ )
llm-awq/tinychat/models/internvl/internvit.py ADDED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional, Tuple, Union
2
+
3
+ import torch
4
+ import torch.nn.functional as F
5
+ import torch.utils.checkpoint
6
+ from einops import rearrange
7
+ from timm.layers import DropPath
8
+ from torch import nn
9
+ from transformers.activations import ACT2FN
10
+ from transformers.modeling_outputs import (BaseModelOutput,
11
+ BaseModelOutputWithPooling)
12
+ from transformers.modeling_utils import PreTrainedModel
13
+ from transformers.utils import logging
14
+
15
+ from .configuration_internvl import InternVisionConfig
16
+
17
+ try:
18
+ from flash_attn.bert_padding import pad_input, unpad_input
19
+ from flash_attn.flash_attn_interface import \
20
+ flash_attn_varlen_qkvpacked_func
21
+ has_flash_attn = True
22
+ except:
23
+ print('FlashAttention2 is not installed.')
24
+ has_flash_attn = False
25
+
26
+ logger = logging.get_logger(__name__)
27
+
28
+
29
+ class FlashAttention(nn.Module):
30
+ """Implement the scaled dot product attention with softmax.
31
+ Arguments
32
+ ---------
33
+ softmax_scale: The temperature to use for the softmax attention.
34
+ (default: 1/sqrt(d_keys) where d_keys is computed at
35
+ runtime)
36
+ attention_dropout: The dropout rate to apply to the attention
37
+ (default: 0.0)
38
+ """
39
+
40
+ def __init__(self, softmax_scale=None, attention_dropout=0.0, device=None, dtype=None):
41
+ super().__init__()
42
+ self.softmax_scale = softmax_scale
43
+ self.dropout_p = attention_dropout
44
+
45
+ def forward(self, qkv, key_padding_mask=None, causal=False, cu_seqlens=None,
46
+ max_s=None, need_weights=False):
47
+ """Implements the multihead softmax attention.
48
+ Arguments
49
+ ---------
50
+ qkv: The tensor containing the query, key, and value. (B, S, 3, H, D) if key_padding_mask is None
51
+ if unpadded: (nnz, 3, h, d)
52
+ key_padding_mask: a bool tensor of shape (B, S)
53
+ """
54
+ assert not need_weights
55
+ assert qkv.dtype in [torch.float16, torch.bfloat16]
56
+ assert qkv.is_cuda
57
+
58
+ if cu_seqlens is None:
59
+ batch_size = qkv.shape[0]
60
+ seqlen = qkv.shape[1]
61
+ if key_padding_mask is None:
62
+ qkv = rearrange(qkv, 'b s ... -> (b s) ...')
63
+ max_s = seqlen
64
+ cu_seqlens = torch.arange(0, (batch_size + 1) * seqlen, step=seqlen, dtype=torch.int32,
65
+ device=qkv.device)
66
+ output = flash_attn_varlen_qkvpacked_func(
67
+ qkv, cu_seqlens, max_s, self.dropout_p if self.training else 0.0,
68
+ softmax_scale=self.softmax_scale, causal=causal
69
+ )
70
+ output = rearrange(output, '(b s) ... -> b s ...', b=batch_size)
71
+ else:
72
+ nheads = qkv.shape[-2]
73
+ x = rearrange(qkv, 'b s three h d -> b s (three h d)')
74
+ x_unpad, indices, cu_seqlens, max_s = unpad_input(x, key_padding_mask)
75
+ x_unpad = rearrange(x_unpad, 'nnz (three h d) -> nnz three h d', three=3, h=nheads)
76
+ output_unpad = flash_attn_varlen_qkvpacked_func(
77
+ x_unpad, cu_seqlens, max_s, self.dropout_p if self.training else 0.0,
78
+ softmax_scale=self.softmax_scale, causal=causal
79
+ )
80
+ output = rearrange(pad_input(rearrange(output_unpad, 'nnz h d -> nnz (h d)'),
81
+ indices, batch_size, seqlen),
82
+ 'b s (h d) -> b s h d', h=nheads)
83
+ else:
84
+ assert max_s is not None
85
+ output = flash_attn_varlen_qkvpacked_func(
86
+ qkv, cu_seqlens, max_s, self.dropout_p if self.training else 0.0,
87
+ softmax_scale=self.softmax_scale, causal=causal
88
+ )
89
+
90
+ return output, None
91
+
92
+
93
+ class InternRMSNorm(nn.Module):
94
+ def __init__(self, hidden_size, eps=1e-6):
95
+ super().__init__()
96
+ self.weight = nn.Parameter(torch.ones(hidden_size))
97
+ self.variance_epsilon = eps
98
+
99
+ def forward(self, hidden_states):
100
+ input_dtype = hidden_states.dtype
101
+ hidden_states = hidden_states.to(torch.float32)
102
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
103
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
104
+ return self.weight * hidden_states.to(input_dtype)
105
+
106
+
107
+ try:
108
+ from apex.normalization import FusedRMSNorm
109
+
110
+ InternRMSNorm = FusedRMSNorm # noqa
111
+
112
+ logger.info('Discovered apex.normalization.FusedRMSNorm - will use it instead of InternRMSNorm')
113
+ except ImportError:
114
+ # using the normal InternRMSNorm
115
+ pass
116
+ except Exception:
117
+ logger.warning('discovered apex but it failed to load, falling back to InternRMSNorm')
118
+ pass
119
+
120
+
121
+ NORM2FN = {
122
+ 'rms_norm': InternRMSNorm,
123
+ 'layer_norm': nn.LayerNorm,
124
+ }
125
+
126
+
127
+ class InternVisionEmbeddings(nn.Module):
128
+ def __init__(self, config: InternVisionConfig):
129
+ super().__init__()
130
+ self.config = config
131
+ self.embed_dim = config.hidden_size
132
+ self.image_size = config.image_size
133
+ self.patch_size = config.patch_size
134
+
135
+ self.class_embedding = nn.Parameter(
136
+ torch.randn(1, 1, self.embed_dim),
137
+ )
138
+
139
+ self.patch_embedding = nn.Conv2d(
140
+ in_channels=3, out_channels=self.embed_dim, kernel_size=self.patch_size, stride=self.patch_size
141
+ )
142
+
143
+ self.num_patches = (self.image_size // self.patch_size) ** 2
144
+ self.num_positions = self.num_patches + 1
145
+
146
+ self.position_embedding = nn.Parameter(torch.randn(1, self.num_positions, self.embed_dim))
147
+
148
+ def _get_pos_embed(self, pos_embed, H, W):
149
+ target_dtype = pos_embed.dtype
150
+ pos_embed = pos_embed.float().reshape(
151
+ 1, self.image_size // self.patch_size, self.image_size // self.patch_size, -1).permute(0, 3, 1, 2)
152
+ pos_embed = F.interpolate(pos_embed, size=(H, W), mode='bicubic', align_corners=False). \
153
+ reshape(1, -1, H * W).permute(0, 2, 1).to(target_dtype)
154
+ return pos_embed
155
+
156
+ def forward(self, pixel_values: torch.FloatTensor) -> torch.Tensor:
157
+ target_dtype = self.patch_embedding.weight.dtype
158
+ patch_embeds = self.patch_embedding(pixel_values) # shape = [*, channel, width, height]
159
+ batch_size, _, height, width = patch_embeds.shape
160
+ patch_embeds = patch_embeds.flatten(2).transpose(1, 2)
161
+ class_embeds = self.class_embedding.expand(batch_size, 1, -1).to(target_dtype)
162
+ embeddings = torch.cat([class_embeds, patch_embeds], dim=1)
163
+ position_embedding = torch.cat([
164
+ self.position_embedding[:, :1, :],
165
+ self._get_pos_embed(self.position_embedding[:, 1:, :], height, width)
166
+ ], dim=1)
167
+ embeddings = embeddings + position_embedding.to(target_dtype)
168
+ return embeddings
169
+
170
+
171
+ class InternAttention(nn.Module):
172
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
173
+
174
+ def __init__(self, config: InternVisionConfig):
175
+ super().__init__()
176
+ self.config = config
177
+ self.embed_dim = config.hidden_size
178
+ self.num_heads = config.num_attention_heads
179
+ self.use_flash_attn = config.use_flash_attn and has_flash_attn
180
+ if config.use_flash_attn and not has_flash_attn:
181
+ print('Warning: Flash Attention is not available, use_flash_attn is set to False.')
182
+ self.head_dim = self.embed_dim // self.num_heads
183
+ if self.head_dim * self.num_heads != self.embed_dim:
184
+ raise ValueError(
185
+ f'embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:'
186
+ f' {self.num_heads}).'
187
+ )
188
+
189
+ self.scale = self.head_dim ** -0.5
190
+ self.qkv = nn.Linear(self.embed_dim, 3 * self.embed_dim, bias=config.qkv_bias)
191
+ self.attn_drop = nn.Dropout(config.attention_dropout)
192
+ self.proj_drop = nn.Dropout(config.dropout)
193
+
194
+ self.qk_normalization = config.qk_normalization
195
+
196
+ if self.qk_normalization:
197
+ self.q_norm = InternRMSNorm(self.embed_dim, eps=config.layer_norm_eps)
198
+ self.k_norm = InternRMSNorm(self.embed_dim, eps=config.layer_norm_eps)
199
+
200
+ if self.use_flash_attn:
201
+ self.inner_attn = FlashAttention(attention_dropout=config.attention_dropout)
202
+ self.proj = nn.Linear(self.embed_dim, self.embed_dim)
203
+
204
+ def _naive_attn(self, x):
205
+ B, N, C = x.shape
206
+ qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
207
+ q, k, v = qkv.unbind(0) # make torchscript happy (cannot use tensor as tuple)
208
+
209
+ if self.qk_normalization:
210
+ B_, H_, N_, D_ = q.shape
211
+ q = self.q_norm(q.transpose(1, 2).flatten(-2, -1)).view(B_, N_, H_, D_).transpose(1, 2)
212
+ k = self.k_norm(k.transpose(1, 2).flatten(-2, -1)).view(B_, N_, H_, D_).transpose(1, 2)
213
+
214
+ attn = ((q * self.scale) @ k.transpose(-2, -1))
215
+ attn = attn.softmax(dim=-1)
216
+ attn = self.attn_drop(attn)
217
+
218
+ x = (attn @ v).transpose(1, 2).reshape(B, N, C)
219
+ x = self.proj(x)
220
+ x = self.proj_drop(x)
221
+ return x
222
+
223
+ def _flash_attn(self, x, key_padding_mask=None, need_weights=False):
224
+ qkv = self.qkv(x)
225
+ qkv = rearrange(qkv, 'b s (three h d) -> b s three h d', three=3, h=self.num_heads)
226
+
227
+ if self.qk_normalization:
228
+ q, k, v = qkv.unbind(2)
229
+ q = self.q_norm(q.flatten(-2, -1)).view(q.shape)
230
+ k = self.k_norm(k.flatten(-2, -1)).view(k.shape)
231
+ qkv = torch.stack([q, k, v], dim=2)
232
+
233
+ context, _ = self.inner_attn(
234
+ qkv, key_padding_mask=key_padding_mask, need_weights=need_weights, causal=False
235
+ )
236
+ outs = self.proj(rearrange(context, 'b s h d -> b s (h d)'))
237
+ outs = self.proj_drop(outs)
238
+ return outs
239
+
240
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
241
+ x = self._naive_attn(hidden_states) if not self.use_flash_attn else self._flash_attn(hidden_states)
242
+ return x
243
+
244
+
245
+ class InternMLP(nn.Module):
246
+ def __init__(self, config: InternVisionConfig):
247
+ super().__init__()
248
+ self.config = config
249
+ self.act = ACT2FN[config.hidden_act]
250
+ self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
251
+ self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
252
+
253
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
254
+ hidden_states = self.fc1(hidden_states)
255
+ hidden_states = self.act(hidden_states)
256
+ hidden_states = self.fc2(hidden_states)
257
+ return hidden_states
258
+
259
+
260
+ class InternVisionEncoderLayer(nn.Module):
261
+ def __init__(self, config: InternVisionConfig, drop_path_rate: float):
262
+ super().__init__()
263
+ self.embed_dim = config.hidden_size
264
+ self.intermediate_size = config.intermediate_size
265
+ self.norm_type = config.norm_type
266
+
267
+ self.attn = InternAttention(config)
268
+ self.mlp = InternMLP(config)
269
+ self.norm1 = NORM2FN[self.norm_type](self.embed_dim, eps=config.layer_norm_eps)
270
+ self.norm2 = NORM2FN[self.norm_type](self.embed_dim, eps=config.layer_norm_eps)
271
+
272
+ self.ls1 = nn.Parameter(config.initializer_factor * torch.ones(self.embed_dim))
273
+ self.ls2 = nn.Parameter(config.initializer_factor * torch.ones(self.embed_dim))
274
+ self.drop_path1 = DropPath(drop_path_rate) if drop_path_rate > 0. else nn.Identity()
275
+ self.drop_path2 = DropPath(drop_path_rate) if drop_path_rate > 0. else nn.Identity()
276
+
277
+ def forward(
278
+ self,
279
+ hidden_states: torch.Tensor,
280
+ ) -> Tuple[torch.FloatTensor, Optional[torch.FloatTensor], Optional[Tuple[torch.FloatTensor]]]:
281
+ """
282
+ Args:
283
+ hidden_states (`Tuple[torch.FloatTensor, Optional[torch.FloatTensor]]`): input to the layer of shape `(batch, seq_len, embed_dim)`
284
+ """
285
+ hidden_states = hidden_states + self.drop_path1(self.attn(self.norm1(hidden_states).to(hidden_states.dtype)) * self.ls1)
286
+
287
+ hidden_states = hidden_states + self.drop_path2(self.mlp(self.norm2(hidden_states).to(hidden_states.dtype)) * self.ls2)
288
+
289
+ return hidden_states
290
+
291
+
292
+ class InternVisionEncoder(nn.Module):
293
+ """
294
+ Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
295
+ [`InternEncoderLayer`].
296
+
297
+ Args:
298
+ config (`InternConfig`):
299
+ The corresponding vision configuration for the `InternEncoder`.
300
+ """
301
+
302
+ def __init__(self, config: InternVisionConfig):
303
+ super().__init__()
304
+ self.config = config
305
+ # stochastic depth decay rule
306
+ dpr = [x.item() for x in torch.linspace(0, config.drop_path_rate, config.num_hidden_layers)]
307
+ self.layers = nn.ModuleList([
308
+ InternVisionEncoderLayer(config, dpr[idx]) for idx in range(config.num_hidden_layers)])
309
+ self.gradient_checkpointing = True
310
+
311
+ def forward(
312
+ self,
313
+ inputs_embeds,
314
+ output_hidden_states: Optional[bool] = None,
315
+ return_dict: Optional[bool] = None,
316
+ ) -> Union[Tuple, BaseModelOutput]:
317
+ r"""
318
+ Args:
319
+ inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
320
+ Embedded representation of the inputs. Should be float, not int tokens.
321
+ output_hidden_states (`bool`, *optional*):
322
+ Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors
323
+ for more detail.
324
+ return_dict (`bool`, *optional*):
325
+ Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
326
+ """
327
+ output_hidden_states = (
328
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
329
+ )
330
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
331
+
332
+ encoder_states = () if output_hidden_states else None
333
+ hidden_states = inputs_embeds
334
+
335
+ for idx, encoder_layer in enumerate(self.layers):
336
+ if output_hidden_states:
337
+ encoder_states = encoder_states + (hidden_states,)
338
+ if self.gradient_checkpointing and self.training:
339
+ layer_outputs = torch.utils.checkpoint.checkpoint(
340
+ encoder_layer,
341
+ hidden_states)
342
+ else:
343
+ layer_outputs = encoder_layer(
344
+ hidden_states,
345
+ )
346
+ hidden_states = layer_outputs
347
+
348
+ if output_hidden_states:
349
+ encoder_states = encoder_states + (hidden_states,)
350
+
351
+ if not return_dict:
352
+ return tuple(v for v in [hidden_states, encoder_states] if v is not None)
353
+ return BaseModelOutput(
354
+ last_hidden_state=hidden_states, hidden_states=encoder_states
355
+ )
356
+
357
+
358
+ class InternVisionModel(PreTrainedModel):
359
+ main_input_name = 'pixel_values'
360
+ _supports_flash_attn_2 = True
361
+ supports_gradient_checkpointing = True
362
+ config_class = InternVisionConfig
363
+ _no_split_modules = ['InternVisionEncoderLayer']
364
+
365
+ def __init__(self, config: InternVisionConfig):
366
+ super().__init__(config)
367
+ self.config = config
368
+
369
+ self.embeddings = InternVisionEmbeddings(config)
370
+ self.encoder = InternVisionEncoder(config)
371
+
372
+ def resize_pos_embeddings(self, old_size, new_size, patch_size):
373
+ pos_emb = self.embeddings.position_embedding
374
+ _, num_positions, embed_dim = pos_emb.shape
375
+ cls_emb = pos_emb[:, :1, :]
376
+ pos_emb = pos_emb[:, 1:, :].reshape(1, old_size // patch_size, old_size // patch_size, -1).permute(0, 3, 1, 2)
377
+ pos_emb = F.interpolate(pos_emb.float(), size=new_size // patch_size, mode='bicubic', align_corners=False)
378
+ pos_emb = pos_emb.to(cls_emb.dtype).reshape(1, embed_dim, -1).permute(0, 2, 1)
379
+ pos_emb = torch.cat([cls_emb, pos_emb], dim=1)
380
+ self.embeddings.position_embedding = nn.Parameter(pos_emb)
381
+ self.embeddings.image_size = new_size
382
+ logger.info('Resized position embeddings from {} to {}'.format(old_size, new_size))
383
+
384
+ def get_input_embeddings(self):
385
+ return self.embeddings
386
+
387
+ def forward(
388
+ self,
389
+ pixel_values: Optional[torch.FloatTensor] = None,
390
+ output_hidden_states: Optional[bool] = None,
391
+ return_dict: Optional[bool] = None,
392
+ pixel_embeds: Optional[torch.FloatTensor] = None,
393
+ ) -> Union[Tuple, BaseModelOutputWithPooling]:
394
+ output_hidden_states = (
395
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
396
+ )
397
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
398
+
399
+ if pixel_values is None and pixel_embeds is None:
400
+ raise ValueError('You have to specify pixel_values or pixel_embeds')
401
+
402
+ if pixel_embeds is not None:
403
+ hidden_states = pixel_embeds
404
+ else:
405
+ if len(pixel_values.shape) == 4:
406
+ hidden_states = self.embeddings(pixel_values)
407
+ else:
408
+ raise ValueError(f'wrong pixel_values size: {pixel_values.shape}')
409
+ encoder_outputs = self.encoder(
410
+ inputs_embeds=hidden_states,
411
+ output_hidden_states=output_hidden_states,
412
+ return_dict=return_dict,
413
+ )
414
+ last_hidden_state = encoder_outputs.last_hidden_state
415
+ pooled_output = last_hidden_state[:, 0, :]
416
+
417
+ if not return_dict:
418
+ return (last_hidden_state, pooled_output) + encoder_outputs[1:]
419
+
420
+ return BaseModelOutputWithPooling(
421
+ last_hidden_state=last_hidden_state,
422
+ pooler_output=pooled_output,
423
+ hidden_states=encoder_outputs.hidden_states,
424
+ attentions=encoder_outputs.attentions,
425
+ )
llm-awq/tinychat/models/internvl/media.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import numpy as np
3
+ import torch
4
+ import torchvision.transforms as T
5
+ from decord import VideoReader, cpu
6
+ from PIL import Image
7
+ from torchvision.transforms.functional import InterpolationMode
8
+
9
+ IMAGENET_MEAN = (0.485, 0.456, 0.406)
10
+ IMAGENET_STD = (0.229, 0.224, 0.225)
11
+
12
+ def build_transform(input_size):
13
+ MEAN, STD = IMAGENET_MEAN, IMAGENET_STD
14
+ transform = T.Compose([
15
+ T.Lambda(lambda img: img.convert('RGB') if img.mode != 'RGB' else img),
16
+ T.Resize((input_size, input_size), interpolation=InterpolationMode.BICUBIC),
17
+ T.ToTensor(),
18
+ T.Normalize(mean=MEAN, std=STD)
19
+ ])
20
+ return transform
21
+
22
+ def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
23
+ best_ratio_diff = float('inf')
24
+ best_ratio = (1, 1)
25
+ area = width * height
26
+ for ratio in target_ratios:
27
+ target_aspect_ratio = ratio[0] / ratio[1]
28
+ ratio_diff = abs(aspect_ratio - target_aspect_ratio)
29
+ if ratio_diff < best_ratio_diff:
30
+ best_ratio_diff = ratio_diff
31
+ best_ratio = ratio
32
+ elif ratio_diff == best_ratio_diff:
33
+ if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
34
+ best_ratio = ratio
35
+ return best_ratio
36
+
37
+ def dynamic_preprocess(image, min_num=1, max_num=12, image_size=448, use_thumbnail=False):
38
+ orig_width, orig_height = image.size
39
+ aspect_ratio = orig_width / orig_height
40
+
41
+ # calculate the existing image aspect ratio
42
+ target_ratios = set(
43
+ (i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1) if
44
+ i * j <= max_num and i * j >= min_num)
45
+ target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])
46
+
47
+ # find the closest aspect ratio to the target
48
+ target_aspect_ratio = find_closest_aspect_ratio(
49
+ aspect_ratio, target_ratios, orig_width, orig_height, image_size)
50
+
51
+ # calculate the target width and height
52
+ target_width = image_size * target_aspect_ratio[0]
53
+ target_height = image_size * target_aspect_ratio[1]
54
+ blocks = target_aspect_ratio[0] * target_aspect_ratio[1]
55
+
56
+ # resize the image
57
+ resized_img = image.resize((target_width, target_height))
58
+ processed_images = []
59
+ for i in range(blocks):
60
+ box = (
61
+ (i % (target_width // image_size)) * image_size,
62
+ (i // (target_width // image_size)) * image_size,
63
+ ((i % (target_width // image_size)) + 1) * image_size,
64
+ ((i // (target_width // image_size)) + 1) * image_size
65
+ )
66
+ # split the image
67
+ split_img = resized_img.crop(box)
68
+ processed_images.append(split_img)
69
+ assert len(processed_images) == blocks
70
+ if use_thumbnail and len(processed_images) != 1:
71
+ thumbnail_img = image.resize((image_size, image_size))
72
+ processed_images.append(thumbnail_img)
73
+ return processed_images
74
+
75
+ def load_image(image_file, input_size=448, max_num=12):
76
+ image = Image.open(image_file).convert('RGB')
77
+ transform = build_transform(input_size=input_size)
78
+ images = dynamic_preprocess(image, image_size=input_size, use_thumbnail=True, max_num=max_num)
79
+ pixel_values = [transform(image) for image in images]
80
+ pixel_values = torch.stack(pixel_values)
81
+ return pixel_values
82
+
83
+ def get_index(bound, fps, max_frame, first_idx=0, num_segments=32):
84
+ if bound:
85
+ start, end = bound[0], bound[1]
86
+ else:
87
+ start, end = -100000, 100000
88
+ start_idx = max(first_idx, round(start * fps))
89
+ end_idx = min(round(end * fps), max_frame)
90
+ seg_size = float(end_idx - start_idx) / num_segments
91
+ frame_indices = np.array([
92
+ int(start_idx + (seg_size / 2) + np.round(seg_size * idx))
93
+ for idx in range(num_segments)
94
+ ])
95
+ return frame_indices
96
+
97
+ def load_video(video_path, bound=None, input_size=448, max_num=1, num_segments=32):
98
+ vr = VideoReader(video_path, ctx=cpu(0), num_threads=1)
99
+ max_frame = len(vr) - 1
100
+ fps = float(vr.get_avg_fps())
101
+
102
+ pixel_values_list, num_patches_list = [], []
103
+ transform = build_transform(input_size=input_size)
104
+ frame_indices = get_index(bound, fps, max_frame, first_idx=0, num_segments=num_segments)
105
+ for frame_index in frame_indices:
106
+ img = Image.fromarray(vr[frame_index].asnumpy()).convert('RGB')
107
+ img = dynamic_preprocess(img, image_size=input_size, use_thumbnail=True, max_num=max_num)
108
+ pixel_values = [transform(tile) for tile in img]
109
+ pixel_values = torch.stack(pixel_values)
110
+ num_patches_list.append(pixel_values.shape[0])
111
+ pixel_values_list.append(pixel_values)
112
+
113
+ return pixel_values_list, num_patches_list
llm-awq/tinychat/models/llama.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # This software may be used and distributed according to the terms of the GNU General Public License version 3.
3
+
4
+ from typing import Optional, Tuple
5
+ from dataclasses import dataclass
6
+ import math
7
+
8
+ import torch
9
+ from torch import nn
10
+ import torch.nn.functional as F
11
+ import awq_inference_engine
12
+ from transformers.models.llama.modeling_llama import LlamaRotaryEmbedding
13
+
14
+ # from flash_attn.flash_attn_interface import flash_attn_unpadded_func
15
+
16
+ import tinychat.utils.constants
17
+
18
+ max_batch_size = tinychat.utils.constants.max_batch_size
19
+ multiple_of = tinychat.utils.constants.llama_multiple_of
20
+ max_seq_len = tinychat.utils.constants.max_seq_len
21
+ from flash_attn import flash_attn_func
22
+
23
+
24
+ class RMSNorm(torch.nn.Module):
25
+ def __init__(self, dim: int, eps: float = 1e-6):
26
+ super().__init__()
27
+ self.eps = eps
28
+ self.weight = nn.Parameter(torch.ones(dim))
29
+
30
+ def _norm(self, x):
31
+ return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
32
+
33
+ def forward(self, x):
34
+ output = torch.empty_like(x)
35
+ awq_inference_engine.layernorm_forward_cuda(x, self.weight, output, self.eps)
36
+ return output
37
+
38
+
39
+ def precompute_freqs_cis(
40
+ dim: int, end: int, theta: float = 10000.0, scale: float = 1.0
41
+ ):
42
+ freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
43
+ t = torch.arange(end, device=freqs.device) # type: ignore
44
+ freqs = torch.outer(t * scale, freqs).float() # type: ignore
45
+
46
+ freqs_cis = torch.polar(torch.ones_like(freqs), freqs) # complex64
47
+ return freqs_cis
48
+
49
+
50
+ def precompute_freqs(
51
+ dim: int, end: int, theta: float = 10000.0, scale: float = 1.0, device=None
52
+ ):
53
+ inv_freq = 1.0 / (theta ** (torch.arange(0, dim, 2).float().to(device) / dim))
54
+ seq = torch.arange(end, dtype=inv_freq.dtype, device=device)
55
+ freqs = torch.einsum("i , j -> i j", seq, inv_freq)
56
+ freqs = freqs.reshape(freqs.shape[0], 1, 1, -1)
57
+ return torch.cat((freqs, freqs), dim=-1)
58
+
59
+
60
+ def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor):
61
+ ndim = x.ndim
62
+ assert 0 <= 1 < ndim
63
+ assert freqs_cis.shape == (x.shape[1], x.shape[-1])
64
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
65
+ return freqs_cis.view(*shape)
66
+
67
+
68
+ def apply_rotary_emb(
69
+ xq: torch.Tensor,
70
+ xk: torch.Tensor,
71
+ freqs_cis: torch.Tensor,
72
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
73
+ # xq_ = torch.view_as_complex(xq.float().reshape(*xq.shape[:-1], -1, 2))
74
+ # k_ = torch.view_as_complex(xk.float().reshape(*xk.shape[:-1], -1, 2))
75
+ xq_ = torch.view_as_complex(
76
+ xq.float().reshape(*xq.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
77
+ )
78
+ xk_ = torch.view_as_complex(
79
+ xk.float().reshape(*xk.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
80
+ )
81
+ freqs_cis = reshape_for_broadcast(freqs_cis, xq_)
82
+ xq_out = torch.view_as_real(xq_ * freqs_cis).transpose(-2, -1).flatten(3)
83
+ xk_out = torch.view_as_real(xk_ * freqs_cis).transpose(-2, -1).flatten(3)
84
+ return xq_out.type_as(xq), xk_out.type_as(xk)
85
+
86
+
87
+ class LlamaAttentionFused(nn.Module):
88
+ def __init__(self, args):
89
+ super().__init__()
90
+ self.args = args
91
+ self.n_local_heads = args.num_attention_heads
92
+ self.hidden_size = args.hidden_size
93
+ self.num_heads = args.num_attention_heads
94
+ self.head_dim = self.hidden_size // self.num_heads
95
+
96
+ self.num_key_value_heads = args.num_key_value_heads
97
+ self.num_key_value_groups = self.num_heads // self.num_key_value_heads
98
+ self.max_position_embeddings = args.max_position_embeddings
99
+ self.rope_theta = args.rope_theta
100
+ self.rope_scaling = args.rope_scaling
101
+ if self.rope_scaling is None:
102
+ self.rope_scaling = 1.0
103
+ else:
104
+ self.rope_scaling = 1.0 / self.rope_scaling["factor"]
105
+ self.kv_max_seq_len = min(max_seq_len, self.max_position_embeddings)
106
+ self.q_proj = nn.Linear(
107
+ self.hidden_size,
108
+ self.num_heads * self.head_dim,
109
+ bias=False,
110
+ )
111
+ self.k_proj = nn.Linear(
112
+ self.hidden_size,
113
+ self.num_key_value_heads * self.head_dim,
114
+ bias=False,
115
+ )
116
+ self.v_proj = nn.Linear(
117
+ self.hidden_size,
118
+ self.num_key_value_heads * self.head_dim,
119
+ bias=False,
120
+ )
121
+ self.o_proj = nn.Linear(
122
+ self.num_heads * self.head_dim,
123
+ self.hidden_size,
124
+ bias=False,
125
+ )
126
+
127
+ # following fastertransformer definition
128
+ self.cache_v = (
129
+ torch.zeros(
130
+ (
131
+ max_batch_size,
132
+ self.num_key_value_heads,
133
+ # args.max_position_embeddings,
134
+ self.kv_max_seq_len,
135
+ self.head_dim,
136
+ )
137
+ )
138
+ .cuda()
139
+ .half()
140
+ ) # added to half
141
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
142
+ self.cache_k = (
143
+ torch.zeros(
144
+ (
145
+ max_batch_size,
146
+ self.num_key_value_heads,
147
+ self.head_dim // 8,
148
+ # args.max_position_embeddings,
149
+ self.kv_max_seq_len,
150
+ 8,
151
+ )
152
+ )
153
+ .cuda()
154
+ .half()
155
+ ) # added to half
156
+ # dummy
157
+ self.rotary_emb = LlamaRotaryEmbedding(
158
+ self.head_dim, max_position_embeddings=2048, device="cuda:0"
159
+ )
160
+
161
+ def forward(
162
+ self,
163
+ x: torch.Tensor,
164
+ start_pos: int,
165
+ freqs_cis: torch.Tensor,
166
+ mask: Optional[torch.Tensor],
167
+ chunk_prefilling: bool,
168
+ ):
169
+ bsz, seqlen, _ = x.shape
170
+ # xqkv = self.qkv_proj(x)
171
+ # xqkv = xqkv.view(bsz, seqlen, -1, self.n_local_heads, self.head_dim)
172
+ # xq = xqkv[:, :, 0]
173
+ # xk = xqkv[:, :, 1]
174
+ # xv = xqkv[:, :, 2]
175
+
176
+ xq, xk, xv = self.q_proj(x), self.k_proj(x), self.v_proj(x)
177
+
178
+ if seqlen > 1:
179
+ xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
180
+ xk = xk.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
181
+ xv = xv.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
182
+
183
+ xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs_cis)
184
+
185
+ self.cache_k = self.cache_k.to(xq)
186
+ self.cache_v = self.cache_v.to(xq)
187
+
188
+ values_store = xv.transpose(2, 1)
189
+ keys_store = (
190
+ xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
191
+ .permute(0, 2, 3, 1, 4)
192
+ .contiguous()
193
+ )
194
+
195
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
196
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
197
+
198
+ if chunk_prefilling:
199
+ keys = self.cache_k[:, :, :, 0 : start_pos + seqlen, :]
200
+ keys = (
201
+ keys.permute(0, 3, 1, 2, 4)
202
+ .reshape(
203
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
204
+ )
205
+ .contiguous()
206
+ )
207
+ values = self.cache_v[:, :, 0 : start_pos + seqlen, :]
208
+ values = (
209
+ values.transpose(2, 1)
210
+ .reshape(
211
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
212
+ )
213
+ .contiguous()
214
+ )
215
+ else:
216
+ keys = xk
217
+ values = xv
218
+ output = flash_attn_func(
219
+ q=xq,
220
+ k=keys,
221
+ v=values,
222
+ causal=True,
223
+ )
224
+ output = output.contiguous().view(bsz, seqlen, -1)
225
+ else:
226
+ xq = xq.view(bsz, self.n_local_heads, self.head_dim)
227
+ xk = xk.view(bsz, self.num_key_value_heads, self.head_dim)
228
+ xv = xv.view(bsz, self.num_key_value_heads, self.head_dim)
229
+
230
+ output = awq_inference_engine.single_query_attention(
231
+ xq,
232
+ xk,
233
+ xv,
234
+ self.cache_k,
235
+ self.cache_v,
236
+ None,
237
+ # alibi position encodings
238
+ None,
239
+ start_pos,
240
+ self.head_dim,
241
+ self.rope_theta,
242
+ self.rope_scaling,
243
+ True,
244
+ )
245
+ output = output.reshape(bsz, 1, -1)
246
+
247
+ return self.o_proj(output)
248
+
249
+
250
+ class LlamaMLP(nn.Module):
251
+ def __init__(self, args):
252
+ super().__init__()
253
+ self.hidden_size = args.hidden_size
254
+ self.intermediate_size = args.intermediate_size
255
+
256
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
257
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
258
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
259
+
260
+ def forward(self, x):
261
+ return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
262
+
263
+
264
+ class TransformerBlock(nn.Module):
265
+ def __init__(self, layer_id: int, args):
266
+ super().__init__()
267
+ self.n_heads = args.num_attention_heads
268
+ self.dim = args.hidden_size
269
+ self.head_dim = args.hidden_size // args.num_attention_heads
270
+ self.self_attn = LlamaAttentionFused(args)
271
+ self.mlp = LlamaMLP(args)
272
+ self.layer_id = layer_id
273
+ self.input_layernorm = RMSNorm(args.hidden_size, eps=args.rms_norm_eps)
274
+ self.post_attention_layernorm = RMSNorm(args.hidden_size, eps=args.rms_norm_eps)
275
+
276
+ def forward(
277
+ self,
278
+ x: torch.Tensor,
279
+ start_pos: int,
280
+ freqs_cis: torch.Tensor,
281
+ mask: Optional[torch.Tensor],
282
+ chunk_prefilling: bool,
283
+ ):
284
+ h = x + self.self_attn.forward(
285
+ self.input_layernorm(x), start_pos, freqs_cis, mask, chunk_prefilling
286
+ )
287
+ out = h + self.mlp.forward(self.post_attention_layernorm(h))
288
+ return out
289
+
290
+
291
+ class Transformer(nn.Module):
292
+ def __init__(self, params):
293
+ super().__init__()
294
+ self.params = params
295
+ self.vocab_size = params.vocab_size
296
+ self.n_layers = params.num_hidden_layers
297
+
298
+ self.embed_tokens = nn.Embedding(params.vocab_size, params.hidden_size)
299
+
300
+ self.layers = torch.nn.ModuleList()
301
+ for layer_id in range(params.num_hidden_layers):
302
+ self.layers.append(TransformerBlock(layer_id, params))
303
+
304
+ self.norm = RMSNorm(params.hidden_size, eps=params.rms_norm_eps)
305
+
306
+ # Note (Haotian): rope_theta has to be defined here, otherwise context stage is wrong.
307
+ rope_scale = self.params.rope_scaling
308
+ if rope_scale is None:
309
+ rope_scale = 1.0
310
+ else:
311
+ rope_scale = 1.0 / rope_scale["factor"]
312
+ self.freqs = precompute_freqs(
313
+ self.params.hidden_size // self.params.num_attention_heads,
314
+ self.params.max_position_embeddings * 2,
315
+ self.params.rope_theta,
316
+ rope_scale,
317
+ )
318
+ self.freqs_cis = precompute_freqs_cis(
319
+ self.params.hidden_size // self.params.num_attention_heads,
320
+ self.params.max_position_embeddings * 2,
321
+ self.params.rope_theta,
322
+ rope_scale,
323
+ )
324
+
325
+ @torch.inference_mode()
326
+ def forward(
327
+ self,
328
+ tokens: torch.Tensor,
329
+ start_pos: int,
330
+ inputs_embeds: torch.Tensor = None,
331
+ chunk_prefilling: bool = False,
332
+ ):
333
+ if tokens is not None:
334
+ _bsz, seqlen = tokens.shape
335
+ h = self.embed_tokens(tokens)
336
+ else:
337
+ h = inputs_embeds
338
+ seqlen = inputs_embeds.shape[1]
339
+ self.freqs = self.freqs.to(h.device)
340
+ freqs = self.freqs[start_pos : start_pos + seqlen]
341
+
342
+ mask = None
343
+ if seqlen > 1:
344
+ mask = torch.full((1, 1, seqlen, seqlen), float("-inf"), device=h.device)
345
+ mask = torch.triu(mask, diagonal=1).type_as(h)
346
+ if chunk_prefilling:
347
+ mask_history = torch.zeros(
348
+ (1, 1, seqlen, start_pos), dtype=torch.float16, device=h.device
349
+ ).type_as(h)
350
+ mask = torch.cat((mask_history, mask), dim=-1)
351
+ for layer in self.layers:
352
+ h = layer(h, start_pos, freqs, mask, chunk_prefilling)
353
+ h = h[:, -1:, :] # Only the last token is useful
354
+ h = self.norm(h)
355
+ return h
356
+
357
+ @torch.inference_mode()
358
+ def forwardfp16(
359
+ self,
360
+ tokens: torch.Tensor,
361
+ start_pos: int,
362
+ inputs_embeds: torch.Tensor = None,
363
+ chunk_prefilling: bool = False,
364
+ ):
365
+ if tokens is not None:
366
+ _bsz, seqlen = tokens.shape
367
+ h = self.embed_tokens(tokens)
368
+ else:
369
+ h = inputs_embeds
370
+ seqlen = inputs_embeds.shape[1]
371
+ self.freqs_cis = self.freqs_cis.to(h.device)
372
+ freqs_cis = self.freqs_cis[start_pos : start_pos + seqlen]
373
+
374
+ mask = None
375
+ if seqlen > 1:
376
+ mask = torch.full((1, 1, seqlen, seqlen), float("-inf"), device=h.device)
377
+ mask = torch.triu(mask, diagonal=1).type_as(h)
378
+ if chunk_prefilling:
379
+ mask_history = torch.zeros(
380
+ (1, 1, seqlen, start_pos), dtype=torch.float16, device=h.device
381
+ ).type_as(h)
382
+ mask = torch.cat((mask_history, mask), dim=-1)
383
+ for layer in self.layers:
384
+ h = layer(h, start_pos, freqs_cis, mask, chunk_prefilling)
385
+ h = h[:, -1:, :] # Only the last token is useful
386
+ h = self.norm(h)
387
+ return h
388
+
389
+
390
+ class LlamaForCausalLM(nn.Module):
391
+ def __init__(self, params):
392
+ super().__init__()
393
+ self.config = params
394
+ self.model = Transformer(params)
395
+ self.lm_head = nn.Linear(params.hidden_size, params.vocab_size, bias=False)
396
+
397
+ @torch.inference_mode()
398
+ def forward(
399
+ self,
400
+ tokens: torch.Tensor,
401
+ start_pos: int,
402
+ inputs_embeds: torch.Tensor = None,
403
+ chunk_prefilling=False,
404
+ quant=True,
405
+ ):
406
+ if quant:
407
+ h = self.model(tokens, start_pos, inputs_embeds, chunk_prefilling)
408
+ else:
409
+ h = self.model.forwardfp16(
410
+ tokens, start_pos, inputs_embeds, chunk_prefilling
411
+ )
412
+ output = self.lm_head(h) # only compute last logits
413
+ return output.float()
llm-awq/tinychat/models/llava_base/llava_arch.py ADDED
@@ -0,0 +1,412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/haotian-liu/LLaVA
2
+ # Copyright 2023 Haotian Liu
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+
17
+ from abc import ABC, abstractmethod
18
+
19
+ import torch
20
+ import torch.nn as nn
21
+
22
+ from .multimodal_encoder.builder import build_vision_tower
23
+ from .multimodal_projector.builder import build_vision_projector
24
+
25
+ from tinychat.utils.constants import (
26
+ LLAVA_IGNORE_INDEX,
27
+ LLAVA_DEFAULT_IMAGE_TOKEN_IDX,
28
+ LLAVA_DEFAULT_IMAGE_PATCH_TOKEN,
29
+ LLAVA_DEFAULT_IM_START_TOKEN,
30
+ LLAVA_DEFAULT_IM_END_TOKEN,
31
+ )
32
+
33
+
34
+ class LlavaMetaModel:
35
+ def __init__(self, config):
36
+ super(LlavaMetaModel, self).__init__(config)
37
+
38
+ if hasattr(config, "mm_vision_tower"):
39
+ self.vision_tower = build_vision_tower(config, delay_load=True)
40
+ self.mm_projector = build_vision_projector(config)
41
+
42
+ def get_vision_tower(self):
43
+ vision_tower = getattr(self, "vision_tower", None)
44
+ if type(vision_tower) is list:
45
+ vision_tower = vision_tower[0]
46
+ return vision_tower
47
+
48
+ def initialize_vision_modules(self, model_args, fsdp=None):
49
+ vision_tower = model_args.vision_tower
50
+ mm_vision_select_layer = model_args.mm_vision_select_layer
51
+ mm_vision_select_feature = model_args.mm_vision_select_feature
52
+ pretrain_mm_mlp_adapter = model_args.pretrain_mm_mlp_adapter
53
+
54
+ self.config.mm_vision_tower = vision_tower
55
+
56
+ if self.get_vision_tower() is None:
57
+ vision_tower = build_vision_tower(model_args)
58
+
59
+ if fsdp is not None and len(fsdp) > 0:
60
+ self.vision_tower = [vision_tower]
61
+ else:
62
+ self.vision_tower = vision_tower
63
+ else:
64
+ if fsdp is not None and len(fsdp) > 0:
65
+ vision_tower = self.vision_tower[0]
66
+ else:
67
+ vision_tower = self.vision_tower
68
+ vision_tower.load_model()
69
+
70
+ self.config.use_mm_proj = True
71
+ self.config.mm_projector_type = getattr(
72
+ model_args, "mm_projector_type", "linear"
73
+ )
74
+ self.config.mm_hidden_size = vision_tower.hidden_size
75
+ self.config.mm_vision_select_layer = mm_vision_select_layer
76
+ self.config.mm_vision_select_feature = mm_vision_select_feature
77
+
78
+ if getattr(self, "mm_projector", None) is None:
79
+ self.mm_projector = build_vision_projector(self.config)
80
+ else:
81
+ # In case it is frozen by LoRA
82
+ for p in self.mm_projector.parameters():
83
+ p.requires_grad = True
84
+
85
+ if pretrain_mm_mlp_adapter is not None:
86
+ mm_projector_weights = torch.load(
87
+ pretrain_mm_mlp_adapter, map_location="cpu"
88
+ )
89
+
90
+ def get_w(weights, keyword):
91
+ return {
92
+ k.split(keyword + ".")[1]: v
93
+ for k, v in weights.items()
94
+ if keyword in k
95
+ }
96
+
97
+ self.mm_projector.load_state_dict(
98
+ get_w(mm_projector_weights, "mm_projector")
99
+ )
100
+
101
+
102
+ class LlavaMetaForCausalLM(ABC):
103
+ @abstractmethod
104
+ def get_model(self):
105
+ pass
106
+
107
+ def get_vision_tower(self):
108
+ return self.get_model().get_vision_tower()
109
+
110
+ def encode_images(self, images):
111
+ vision_tower = self.get_model().get_vision_tower().half()
112
+ image_features = vision_tower(images)
113
+ image_features = self.get_model().mm_projector(image_features)
114
+ return image_features
115
+
116
+ def prepare_inputs_labels_for_multimodal(
117
+ self, input_ids, position_ids, attention_mask, past_key_values, labels, images
118
+ ):
119
+ vision_tower = self.get_vision_tower()
120
+ if vision_tower is None or images is None or input_ids.shape[1] == 1:
121
+ if (
122
+ past_key_values is not None
123
+ and vision_tower is not None
124
+ and images is not None
125
+ and input_ids.shape[1] == 1
126
+ ):
127
+ target_shape = past_key_values[-1][-1].shape[-2] + 1
128
+ attention_mask = torch.cat(
129
+ (
130
+ attention_mask,
131
+ torch.ones(
132
+ (
133
+ attention_mask.shape[0],
134
+ target_shape - attention_mask.shape[1],
135
+ ),
136
+ dtype=attention_mask.dtype,
137
+ device=attention_mask.device,
138
+ ),
139
+ ),
140
+ dim=1,
141
+ )
142
+ position_ids = torch.sum(attention_mask, dim=1).unsqueeze(-1) - 1
143
+ return (
144
+ input_ids,
145
+ position_ids,
146
+ attention_mask,
147
+ past_key_values,
148
+ None,
149
+ labels,
150
+ )
151
+
152
+ if type(images) is list or images.ndim == 5:
153
+ concat_images = torch.cat([image for image in images], dim=0)
154
+ image_features = self.encode_images(concat_images)
155
+ split_sizes = [image.shape[0] for image in images]
156
+ image_features = torch.split(image_features, split_sizes, dim=0)
157
+ image_features = [x.flatten(0, 1).to(self.device) for x in image_features]
158
+ else:
159
+ image_features = self.encode_images(images).to(self.device)
160
+
161
+ # TODO: image start / end is not implemented here to support pretraining.
162
+ if getattr(self.config, "tune_mm_mlp_adapter", False) and getattr(
163
+ self.config, "mm_use_im_start_end", False
164
+ ):
165
+ raise NotImplementedError
166
+
167
+ # Let's just add dummy tensors if they do not exist,
168
+ # it is a headache to deal with None all the time.
169
+ # But it is not ideal, and if you have a better idea,
170
+ # please open an issue / submit a PR, thanks.
171
+ _labels = labels
172
+ _position_ids = position_ids
173
+ _attention_mask = attention_mask
174
+ if attention_mask is None:
175
+ attention_mask = torch.ones_like(input_ids, dtype=torch.bool)
176
+ else:
177
+ attention_mask = attention_mask.bool()
178
+ if position_ids is None:
179
+ position_ids = torch.arange(
180
+ 0, input_ids.shape[1], dtype=torch.long, device=input_ids.device
181
+ )
182
+ if labels is None:
183
+ labels = torch.full_like(input_ids, LLAVA_IGNORE_INDEX)
184
+
185
+ # remove the padding using attention_mask -- TODO: double check
186
+ input_ids = [
187
+ cur_input_ids[cur_attention_mask]
188
+ for cur_input_ids, cur_attention_mask in zip(input_ids, attention_mask)
189
+ ]
190
+ labels = [
191
+ cur_labels[cur_attention_mask]
192
+ for cur_labels, cur_attention_mask in zip(labels, attention_mask)
193
+ ]
194
+
195
+ new_input_embeds = []
196
+ new_labels = []
197
+ cur_image_idx = 0
198
+ for batch_idx, cur_input_ids in enumerate(input_ids):
199
+ num_images = (cur_input_ids == LLAVA_DEFAULT_IMAGE_TOKEN_IDX).sum()
200
+ if num_images == 0:
201
+ cur_image_features = image_features[cur_image_idx]
202
+ cur_input_embeds_1 = self.get_model().embed_tokens(cur_input_ids)
203
+ cur_input_embeds = torch.cat(
204
+ [cur_input_embeds_1, cur_image_features[0:0]], dim=0
205
+ )
206
+ new_input_embeds.append(cur_input_embeds)
207
+ new_labels.append(labels[batch_idx])
208
+ cur_image_idx += 1
209
+ continue
210
+
211
+ image_token_indices = (
212
+ [-1]
213
+ + torch.where(cur_input_ids == LLAVA_DEFAULT_IMAGE_TOKEN_IDX)[
214
+ 0
215
+ ].tolist()
216
+ + [cur_input_ids.shape[0]]
217
+ )
218
+ cur_input_ids_noim = []
219
+ cur_labels = labels[batch_idx]
220
+ cur_labels_noim = []
221
+ for i in range(len(image_token_indices) - 1):
222
+ cur_input_ids_noim.append(
223
+ cur_input_ids[
224
+ image_token_indices[i] + 1 : image_token_indices[i + 1]
225
+ ]
226
+ )
227
+ cur_labels_noim.append(
228
+ cur_labels[image_token_indices[i] + 1 : image_token_indices[i + 1]]
229
+ )
230
+ split_sizes = [x.shape[0] for x in cur_labels_noim]
231
+ cur_input_embeds = self.get_model().embed_tokens(
232
+ torch.cat(cur_input_ids_noim)
233
+ )
234
+ cur_input_embeds_no_im = torch.split(cur_input_embeds, split_sizes, dim=0)
235
+ cur_new_input_embeds = []
236
+ cur_new_labels = []
237
+
238
+ for i in range(num_images + 1):
239
+ cur_new_input_embeds.append(cur_input_embeds_no_im[i])
240
+ cur_new_labels.append(cur_labels_noim[i])
241
+ if i < num_images:
242
+ cur_image_features = image_features[cur_image_idx]
243
+ cur_image_idx += 1
244
+ cur_new_input_embeds.append(cur_image_features)
245
+ cur_new_labels.append(
246
+ torch.full(
247
+ (cur_image_features.shape[0],),
248
+ LLAVA_IGNORE_INDEX,
249
+ device=cur_labels.device,
250
+ dtype=cur_labels.dtype,
251
+ )
252
+ )
253
+
254
+ cur_new_input_embeds = torch.cat(cur_new_input_embeds)
255
+ cur_new_labels = torch.cat(cur_new_labels)
256
+
257
+ new_input_embeds.append(cur_new_input_embeds)
258
+ new_labels.append(cur_new_labels)
259
+
260
+ # Truncate sequences to max length as image embeddings can make the sequence longer
261
+ tokenizer_model_max_length = getattr(
262
+ self.config, "tokenizer_model_max_length", None
263
+ )
264
+ if tokenizer_model_max_length is not None:
265
+ new_input_embeds = [
266
+ x[:tokenizer_model_max_length] for x in new_input_embeds
267
+ ]
268
+ new_labels = [x[:tokenizer_model_max_length] for x in new_labels]
269
+
270
+ # Combine them
271
+ max_len = max(x.shape[0] for x in new_input_embeds)
272
+ batch_size = len(new_input_embeds)
273
+
274
+ new_input_embeds_padded = []
275
+ new_labels_padded = torch.full(
276
+ (batch_size, max_len),
277
+ LLAVA_IGNORE_INDEX,
278
+ dtype=new_labels[0].dtype,
279
+ device=new_labels[0].device,
280
+ )
281
+ attention_mask = torch.zeros(
282
+ (batch_size, max_len),
283
+ dtype=attention_mask.dtype,
284
+ device=attention_mask.device,
285
+ )
286
+ position_ids = torch.zeros(
287
+ (batch_size, max_len), dtype=position_ids.dtype, device=position_ids.device
288
+ )
289
+
290
+ for i, (cur_new_embed, cur_new_labels) in enumerate(
291
+ zip(new_input_embeds, new_labels)
292
+ ):
293
+ cur_len = cur_new_embed.shape[0]
294
+ if getattr(self.config, "tokenizer_padding_side", "right") == "left":
295
+ new_input_embeds_padded.append(
296
+ torch.cat(
297
+ (
298
+ torch.zeros(
299
+ (max_len - cur_len, cur_new_embed.shape[1]),
300
+ dtype=cur_new_embed.dtype,
301
+ device=cur_new_embed.device,
302
+ ),
303
+ cur_new_embed,
304
+ ),
305
+ dim=0,
306
+ )
307
+ )
308
+ if cur_len > 0:
309
+ new_labels_padded[i, -cur_len:] = cur_new_labels
310
+ attention_mask[i, -cur_len:] = True
311
+ position_ids[i, -cur_len:] = torch.arange(
312
+ 0, cur_len, dtype=position_ids.dtype, device=position_ids.device
313
+ )
314
+ else:
315
+ new_input_embeds_padded.append(
316
+ torch.cat(
317
+ (
318
+ cur_new_embed,
319
+ torch.zeros(
320
+ (max_len - cur_len, cur_new_embed.shape[1]),
321
+ dtype=cur_new_embed.dtype,
322
+ device=cur_new_embed.device,
323
+ ),
324
+ ),
325
+ dim=0,
326
+ )
327
+ )
328
+ if cur_len > 0:
329
+ new_labels_padded[i, :cur_len] = cur_new_labels
330
+ attention_mask[i, :cur_len] = True
331
+ position_ids[i, :cur_len] = torch.arange(
332
+ 0, cur_len, dtype=position_ids.dtype, device=position_ids.device
333
+ )
334
+
335
+ new_input_embeds = torch.stack(new_input_embeds_padded, dim=0)
336
+
337
+ if _labels is None:
338
+ new_labels = None
339
+ else:
340
+ new_labels = new_labels_padded
341
+
342
+ if _attention_mask is None:
343
+ attention_mask = None
344
+ else:
345
+ attention_mask = attention_mask.to(dtype=_attention_mask.dtype)
346
+
347
+ if _position_ids is None:
348
+ position_ids = None
349
+
350
+ return (
351
+ None,
352
+ position_ids,
353
+ attention_mask,
354
+ past_key_values,
355
+ new_input_embeds,
356
+ new_labels,
357
+ )
358
+
359
+ def initialize_vision_tokenizer(self, model_args, tokenizer):
360
+ if model_args.mm_use_im_patch_token:
361
+ tokenizer.add_tokens([LLAVA_DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
362
+ self.resize_token_embeddings(len(tokenizer))
363
+
364
+ if model_args.mm_use_im_start_end:
365
+ num_new_tokens = tokenizer.add_tokens(
366
+ [LLAVA_DEFAULT_IM_START_TOKEN, LLAVA_DEFAULT_IM_END_TOKEN],
367
+ special_tokens=True,
368
+ )
369
+ self.resize_token_embeddings(len(tokenizer))
370
+
371
+ if num_new_tokens > 0:
372
+ input_embeddings = self.get_input_embeddings().weight.data
373
+ output_embeddings = self.get_output_embeddings().weight.data
374
+
375
+ input_embeddings_avg = input_embeddings[:-num_new_tokens].mean(
376
+ dim=0, keepdim=True
377
+ )
378
+ output_embeddings_avg = output_embeddings[:-num_new_tokens].mean(
379
+ dim=0, keepdim=True
380
+ )
381
+
382
+ input_embeddings[-num_new_tokens:] = input_embeddings_avg
383
+ output_embeddings[-num_new_tokens:] = output_embeddings_avg
384
+
385
+ if model_args.tune_mm_mlp_adapter:
386
+ for p in self.get_input_embeddings().parameters():
387
+ p.requires_grad = True
388
+ for p in self.get_output_embeddings().parameters():
389
+ p.requires_grad = False
390
+
391
+ if model_args.pretrain_mm_mlp_adapter:
392
+ mm_projector_weights = torch.load(
393
+ model_args.pretrain_mm_mlp_adapter, map_location="cpu"
394
+ )
395
+ embed_tokens_weight = mm_projector_weights["model.embed_tokens.weight"]
396
+ assert num_new_tokens == 2
397
+ if input_embeddings.shape == embed_tokens_weight.shape:
398
+ input_embeddings[-num_new_tokens:] = embed_tokens_weight[
399
+ -num_new_tokens:
400
+ ]
401
+ elif embed_tokens_weight.shape[0] == num_new_tokens:
402
+ input_embeddings[-num_new_tokens:] = embed_tokens_weight
403
+ else:
404
+ raise ValueError(
405
+ f"Unexpected embed_tokens_weight shape. Pretrained: {embed_tokens_weight.shape}. Current: {input_embeddings.shape}. Numer of new tokens: {num_new_tokens}."
406
+ )
407
+ elif model_args.mm_use_im_patch_token:
408
+ if model_args.tune_mm_mlp_adapter:
409
+ for p in self.get_input_embeddings().parameters():
410
+ p.requires_grad = False
411
+ for p in self.get_output_embeddings().parameters():
412
+ p.requires_grad = False
llm-awq/tinychat/models/llava_base/multimodal_encoder/builder.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/haotian-liu/LLaVA
2
+
3
+ import os
4
+ from .clip_encoder import CLIPVisionTower
5
+
6
+
7
+ def build_vision_tower(vision_tower_cfg, **kwargs):
8
+ vision_tower = getattr(
9
+ vision_tower_cfg,
10
+ "mm_vision_tower",
11
+ getattr(vision_tower_cfg, "vision_tower", None),
12
+ )
13
+ is_absolute_path_exists = os.path.exists(vision_tower)
14
+ if (
15
+ is_absolute_path_exists
16
+ or vision_tower.startswith("openai")
17
+ or vision_tower.startswith("laion")
18
+ ):
19
+ return CLIPVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
20
+
21
+ raise ValueError(f"Unknown vision tower: {vision_tower}")
llm-awq/tinychat/models/llava_base/multimodal_encoder/clip_encoder.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/haotian-liu/LLaVA
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+
6
+ from transformers import CLIPVisionModel, CLIPImageProcessor, CLIPVisionConfig
7
+
8
+
9
+ class CLIPVisionTower(nn.Module):
10
+ def __init__(self, vision_tower, args, delay_load=False):
11
+ super().__init__()
12
+
13
+ self.is_loaded = False
14
+
15
+ self.vision_tower_name = vision_tower
16
+ self.select_layer = args.mm_vision_select_layer
17
+ self.select_feature = getattr(args, "mm_vision_select_feature", "patch")
18
+
19
+ if not delay_load:
20
+ self.load_model()
21
+ else:
22
+ self.cfg_only = CLIPVisionConfig.from_pretrained(self.vision_tower_name)
23
+
24
+ def load_model(self):
25
+ self.image_processor = CLIPImageProcessor.from_pretrained(
26
+ self.vision_tower_name
27
+ )
28
+ self.vision_tower = CLIPVisionModel.from_pretrained(self.vision_tower_name)
29
+ self.vision_tower.requires_grad_(False)
30
+
31
+ self.is_loaded = True
32
+
33
+ def feature_select(self, image_forward_outs):
34
+ image_features = image_forward_outs.hidden_states[self.select_layer]
35
+ if self.select_feature == "patch":
36
+ image_features = image_features[:, 1:]
37
+ elif self.select_feature == "cls_patch":
38
+ image_features = image_features
39
+ else:
40
+ raise ValueError(f"Unexpected select feature: {self.select_feature}")
41
+ return image_features
42
+
43
+ @torch.no_grad()
44
+ def forward(self, images):
45
+ if type(images) is list:
46
+ image_features = []
47
+ for image in images:
48
+ image_forward_out = self.vision_tower(
49
+ image.to(device=self.device, dtype=self.dtype).unsqueeze(0),
50
+ output_hidden_states=True,
51
+ )
52
+ image_feature = self.feature_select(image_forward_out).to(image.dtype)
53
+ image_features.append(image_feature)
54
+ else:
55
+ # import time
56
+ # torch.cuda.synchronize()
57
+ # image2 = images.to(self.dtype)
58
+ # print("model dtype:", self.dtype)
59
+ # print("image dtype:", images.dtype)
60
+ # st11 = time.time()
61
+ image_forward_outs = self.vision_tower(
62
+ images.to(device=self.device, dtype=self.dtype),
63
+ output_hidden_states=True,
64
+ )
65
+ # torch.cuda.synchronize()
66
+ # ed11 = time.time()
67
+ # print("hh2", (ed11 - st11)*1000)
68
+ image_features = self.feature_select(image_forward_outs).to(images.dtype)
69
+
70
+ return image_features
71
+
72
+ @property
73
+ def dummy_feature(self):
74
+ return torch.zeros(1, self.hidden_size, device=self.device, dtype=self.dtype)
75
+
76
+ @property
77
+ def dtype(self):
78
+ return self.vision_tower.dtype
79
+
80
+ @property
81
+ def device(self):
82
+ return self.vision_tower.device
83
+
84
+ @property
85
+ def config(self):
86
+ if self.is_loaded:
87
+ return self.vision_tower.config
88
+ else:
89
+ return self.cfg_only
90
+
91
+ @property
92
+ def hidden_size(self):
93
+ return self.config.hidden_size
94
+
95
+ @property
96
+ def num_patches(self):
97
+ return (self.config.image_size // self.config.patch_size) ** 2
llm-awq/tinychat/models/llava_base/multimodal_projector/builder.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/haotian-liu/LLaVA
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+ import re
6
+
7
+
8
+ class IdentityMap(nn.Module):
9
+ def __init__(self):
10
+ super().__init__()
11
+
12
+ def forward(self, x, *args, **kwargs):
13
+ return x
14
+
15
+ @property
16
+ def config(self):
17
+ return {"mm_projector_type": "identity"}
18
+
19
+
20
+ class SimpleResBlock(nn.Module):
21
+ def __init__(self, channels):
22
+ super().__init__()
23
+ self.pre_norm = nn.LayerNorm(channels)
24
+
25
+ self.proj = nn.Sequential(
26
+ nn.Linear(channels, channels), nn.GELU(), nn.Linear(channels, channels)
27
+ )
28
+
29
+ def forward(self, x):
30
+ x = self.pre_norm(x)
31
+ return x + self.proj(x)
32
+
33
+
34
+ def build_vision_projector(config, delay_load=False, **kwargs):
35
+ projector_type = getattr(config, "mm_projector_type", "linear")
36
+
37
+ if projector_type == "linear":
38
+ return nn.Linear(config.mm_hidden_size, config.hidden_size)
39
+
40
+ mlp_gelu_match = re.match(r"^mlp(\d+)x_gelu$", projector_type)
41
+ if mlp_gelu_match:
42
+ mlp_depth = int(mlp_gelu_match.group(1))
43
+ modules = [nn.Linear(config.mm_hidden_size, config.hidden_size)]
44
+ for _ in range(1, mlp_depth):
45
+ modules.append(nn.GELU())
46
+ modules.append(nn.Linear(config.hidden_size, config.hidden_size))
47
+ return nn.Sequential(*modules)
48
+
49
+ if projector_type == "identity":
50
+ return IdentityMap()
51
+
52
+ if projector_type == "linearclip":
53
+ # load min, max range
54
+ min_max_range = torch.load(config.min_max_range_path)
55
+ assert min_max_range is not None
56
+
57
+ class RangeClip(nn.Module): # actually KNN projector
58
+ def __init__(self, min, max) -> None:
59
+ super().__init__()
60
+ self.register_buffer("min", min.detach().view(1, -1))
61
+ self.register_buffer("max", max.detach().view(1, -1))
62
+
63
+ def forward(self, x):
64
+ # dimension broadcast auto done
65
+ return torch.clamp(x, self.min.detach(), self.max.detach())
66
+
67
+ return nn.Sequential(
68
+ nn.Linear(config.mm_hidden_size, config.hidden_size),
69
+ RangeClip(*min_max_range),
70
+ )
71
+
72
+ raise ValueError(f"Unknown projector type: {projector_type}")
llm-awq/tinychat/models/llava_llama.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/haotian-liu/LLaVA
2
+ # Copyright 2023 Haotian Liu
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import os
17
+ import warnings
18
+ import shutil
19
+ import torch
20
+ import torch.nn as nn
21
+ from typing import List, Optional, Tuple, Union
22
+
23
+ from transformers import CLIPVisionModel
24
+
25
+ from transformers.modeling_outputs import CausalLMOutputWithPast
26
+
27
+ from .llava_base.llava_arch import LlavaMetaModel, LlavaMetaForCausalLM
28
+ from .llama import LlamaForCausalLM, Transformer
29
+
30
+
31
+ class LlavaLlamaModel(LlavaMetaModel, Transformer):
32
+ def __init__(self, config):
33
+ super(LlavaLlamaModel, self).__init__(config)
34
+
35
+
36
+ class LlavaLlamaForCausalLM(LlamaForCausalLM, LlavaMetaForCausalLM):
37
+ def __init__(self, config, dev="cuda"):
38
+ super(LlavaLlamaForCausalLM, self).__init__(config)
39
+ self.model = LlavaLlamaModel(config)
40
+ self.pretraining_tp = config.pretraining_tp
41
+ self.vocab_size = config.vocab_size
42
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
43
+ self.config = config
44
+ self.device = dev
45
+
46
+ def get_model(self):
47
+ return self.model
48
+
49
+ def default_inputs_embeds_for_multimodal(self, input_ids, inputs_embeds, images):
50
+ if inputs_embeds is None:
51
+ inputs_embeds = self.get_model().embed_tokens(input_ids)
52
+ vision_tower = self.get_vision_tower().vision_tower
53
+ from contextlib import nullcontext
54
+
55
+ if (
56
+ vision_tower is not None
57
+ and (input_ids.shape[1] != 1 or self.training)
58
+ and images is not None
59
+ ):
60
+ from tinychat.utils.constants import LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX
61
+
62
+ with (
63
+ nullcontext()
64
+ if getattr(self.config, "tune_vision_encoder", False)
65
+ else torch.no_grad()
66
+ ):
67
+ if type(images) is list:
68
+ images = [
69
+ image.unsqueeze(0) if len(image.shape) == 3 else image
70
+ for image in images
71
+ ]
72
+ images = torch.cat(images, dim=0)
73
+ dtype = next(vision_tower.parameters()).dtype
74
+ if "visiontransformer" in vision_tower.__class__.__name__.lower():
75
+ image_features = vision_tower(images.to(dtype))
76
+ else:
77
+ image_forward_outs = vision_tower(
78
+ images.to(dtype), output_hidden_states=True
79
+ )
80
+ select_hidden_state_layer = getattr(
81
+ self.config, "mm_vision_select_layer", -1
82
+ )
83
+ if abs(select_hidden_state_layer) > 100: # TOOD: find a better impl
84
+ # -212 -> 12,
85
+ idx1, idx2 = abs(select_hidden_state_layer) % 100, -(
86
+ abs(select_hidden_state_layer) // 100
87
+ )
88
+ # print("selecting multiple indices", idx1, idx2)
89
+ image_features = torch.cat(
90
+ (
91
+ image_forward_outs.hidden_states[idx1],
92
+ image_forward_outs.hidden_states[idx2],
93
+ ),
94
+ dim=-1,
95
+ )
96
+ else:
97
+ image_features = image_forward_outs.hidden_states[
98
+ select_hidden_state_layer
99
+ ]
100
+ if isinstance(vision_tower, CLIPVisionModel): # clip case, not for sam
101
+ image_features = image_features[:, 1:].to(images.dtype) # (B, N, D)
102
+
103
+ image_features = self.model.mm_projector(image_features)
104
+
105
+ if hasattr(self.config, "neftune_alpha") and self.config.neftune_alpha > 0:
106
+ # print("using neftune tuning with alpha", self.config.neftune_alpha)
107
+ dims = torch.tensor(image_features.shape[-2] * image_features.shape[-1])
108
+ mag_norm = self.config.neftune_alpha / torch.sqrt(dims)
109
+ image_features = image_features + torch.zeros_like(
110
+ image_features
111
+ ).uniform_(-mag_norm, mag_norm)
112
+
113
+ if self.config.mm_projector_type == "dsresampler":
114
+ dummy_feat_shape = (1, 1024, 1664)
115
+ elif self.config.mm_projector_type == "linear2":
116
+ dummy_feat_shape = (1, 256, self.config.mm_hidden_size * 2)
117
+ else:
118
+ dummy_feat_shape = (1, 256, self.config.mm_hidden_size)
119
+
120
+ dummy_image_features = torch.zeros(
121
+ *dummy_feat_shape,
122
+ device=inputs_embeds.device,
123
+ dtype=inputs_embeds.dtype,
124
+ )
125
+ dummy_image_features = self.model.mm_projector(dummy_image_features)[
126
+ 0
127
+ ] # (1, N, D)
128
+
129
+ new_input_embeds = []
130
+ cur_image_idx = 0
131
+
132
+ image_token_idx = []
133
+
134
+ num_patches = -1
135
+ for i_sample, (cur_input_ids, cur_input_embeds) in enumerate(
136
+ zip(input_ids, inputs_embeds)
137
+ ):
138
+ if (cur_input_ids == LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX).sum() == 0:
139
+ # multimodal LLM, but the current sample is not multimodal
140
+ cur_input_embeds = (
141
+ cur_input_embeds + (0.0 * dummy_image_features).sum()
142
+ )
143
+ new_input_embeds.append(cur_input_embeds)
144
+ # cur_image_idx += 1
145
+ continue
146
+ # TODO: Need to fix if vision_tower.config.use_im_start_end == True
147
+ num_total_patches = (
148
+ (cur_input_ids == LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX).sum().item()
149
+ )
150
+ masked_indices = torch.where(
151
+ cur_input_ids == LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX
152
+ )[0]
153
+
154
+ while num_total_patches:
155
+ if cur_image_idx >= image_features.shape[0]: # SHOULD NOT HAPPEN!!!
156
+ if self.training:
157
+ print("%" * 20, "INDEXING ERROR!")
158
+ break
159
+ else:
160
+ raise ValueError("INDEXING ERROR!")
161
+ cur_image_features = image_features[cur_image_idx]
162
+ num_patches = cur_image_features.shape[0]
163
+ mask_index_start = masked_indices[0]
164
+ masked_indices = masked_indices[num_patches:]
165
+
166
+ image_token_idx.append(
167
+ (
168
+ i_sample,
169
+ mask_index_start.item(),
170
+ (mask_index_start + num_patches).item(),
171
+ )
172
+ )
173
+
174
+ orig_embeds_params = None
175
+ if orig_embeds_params is not None:
176
+ cur_input_embeds = torch.cat(
177
+ (
178
+ cur_input_embeds[:mask_index_start].detach(),
179
+ cur_image_features,
180
+ cur_input_embeds[
181
+ mask_index_start + num_patches :
182
+ ].detach(),
183
+ ),
184
+ dim=0,
185
+ )
186
+ else:
187
+ cur_input_embeds = torch.cat(
188
+ (
189
+ cur_input_embeds[:mask_index_start],
190
+ cur_image_features,
191
+ cur_input_embeds[mask_index_start + num_patches :],
192
+ ),
193
+ dim=0,
194
+ )
195
+ num_total_patches -= num_patches
196
+ assert num_total_patches >= 0, (num_total_patches, num_patches)
197
+ cur_image_idx += 1
198
+
199
+ new_input_embeds.append(cur_input_embeds)
200
+ if self.training:
201
+ if not masked_indices.numel() == 0:
202
+ print("%" * 20, "ERROR! masked_indices not empty...")
203
+ else:
204
+ assert masked_indices.numel() == 0
205
+
206
+ inputs_embeds = torch.stack(new_input_embeds, dim=0)
207
+
208
+ return inputs_embeds
209
+
210
+ def forward(
211
+ self,
212
+ input_ids: torch.LongTensor = None,
213
+ start_pos: int = None,
214
+ attention_mask: Optional[torch.Tensor] = None,
215
+ position_ids: Optional[torch.LongTensor] = None,
216
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
217
+ inputs_embeds: Optional[torch.FloatTensor] = None,
218
+ labels: Optional[torch.LongTensor] = None,
219
+ use_cache: Optional[bool] = None,
220
+ output_attentions: Optional[bool] = None,
221
+ output_hidden_states: Optional[bool] = None,
222
+ images: Optional[torch.FloatTensor] = None,
223
+ return_dict: Optional[bool] = None,
224
+ special_token: bool = False,
225
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
226
+ if inputs_embeds is None:
227
+ if special_token:
228
+ (
229
+ input_ids,
230
+ position_ids,
231
+ attention_mask,
232
+ past_key_values,
233
+ inputs_embeds,
234
+ labels,
235
+ ) = self.prepare_inputs_labels_for_multimodal(
236
+ input_ids,
237
+ position_ids,
238
+ attention_mask,
239
+ past_key_values,
240
+ labels,
241
+ images,
242
+ )
243
+ else:
244
+ inputs_embeds = self.default_inputs_embeds_for_multimodal(
245
+ input_ids, inputs_embeds, images
246
+ )
247
+ input_ids = None
248
+
249
+ if start_pos == None:
250
+ out = super().forward(
251
+ input_ids=input_ids,
252
+ attention_mask=attention_mask,
253
+ position_ids=position_ids,
254
+ past_key_values=past_key_values,
255
+ inputs_embeds=inputs_embeds,
256
+ labels=labels,
257
+ use_cache=use_cache,
258
+ output_attentions=output_attentions,
259
+ output_hidden_states=output_hidden_states,
260
+ return_dict=return_dict,
261
+ )
262
+ else:
263
+ out = super().forward(
264
+ tokens=input_ids,
265
+ start_pos=start_pos,
266
+ inputs_embeds=inputs_embeds,
267
+ )
268
+ return out
269
+
270
+ def prepare_inputs_for_generation(
271
+ self, input_ids, past_key_values=None, inputs_embeds=None, **kwargs
272
+ ):
273
+ images = kwargs.pop("images", None)
274
+ _inputs = super().prepare_inputs_for_generation(
275
+ input_ids,
276
+ past_key_values=past_key_values,
277
+ inputs_embeds=inputs_embeds,
278
+ **kwargs,
279
+ )
280
+ if images is not None:
281
+ _inputs["images"] = images
282
+ return _inputs
llm-awq/tinychat/models/mpt.py ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # This software may be used and distributed according to the terms of the GNU General Public License version 3.
3
+
4
+ from typing import Optional, Tuple
5
+ from dataclasses import dataclass
6
+ import math
7
+
8
+ import torch
9
+ from torch import nn
10
+ import torch.nn.functional as F
11
+ import awq_inference_engine
12
+ from transformers.models.llama.modeling_llama import LlamaRotaryEmbedding
13
+
14
+ # from flash_attn.flash_attn_interface import flash_attn_unpadded_func
15
+
16
+ import tinychat.utils.constants
17
+
18
+ max_batch_size = tinychat.utils.constants.max_batch_size
19
+ global_max_seq_len = tinychat.utils.constants.max_seq_len
20
+
21
+
22
+ def gen_slopes(n_heads, alibi_bias_max=8):
23
+ _n_heads = 2 ** math.ceil(math.log2(n_heads))
24
+ m = torch.arange(1, _n_heads + 1, dtype=torch.float32)
25
+ m = m.mul(alibi_bias_max / _n_heads)
26
+ slopes = 1.0 / torch.pow(2, m)
27
+ if _n_heads != n_heads:
28
+ slopes = torch.concat([slopes[1::2], slopes[::2]])[:n_heads]
29
+ return slopes.view(1, n_heads, 1, 1)
30
+
31
+
32
+ def build_alibi_bias(
33
+ n_heads, seq_len, full=False, alibi_bias_max=8, dtype=torch.float32
34
+ ):
35
+ alibi_bias = torch.arange(1 - seq_len, 1, dtype=torch.int32).view(1, 1, 1, seq_len)
36
+ if full:
37
+ alibi_bias = alibi_bias - torch.arange(1 - seq_len, 1, dtype=torch.int32).view(
38
+ 1, 1, seq_len, 1
39
+ )
40
+ alibi_bias = alibi_bias.abs().mul(-1)
41
+ slopes = gen_slopes(n_heads, alibi_bias_max)
42
+ alibi_bias = alibi_bias * slopes
43
+ slopes = slopes.squeeze(0).squeeze(-1).squeeze(-1)
44
+ return slopes.to(dtype=dtype), alibi_bias.to(dtype=dtype)
45
+
46
+
47
+ def _cast_if_autocast_enabled(tensor):
48
+ if torch.is_autocast_enabled():
49
+ if tensor.device.type == "cuda":
50
+ dtype = torch.get_autocast_gpu_dtype()
51
+ elif tensor.device.type == "cpu":
52
+ dtype = torch.get_autocast_cpu_dtype()
53
+ else:
54
+ raise NotImplementedError()
55
+ return tensor.to(dtype=dtype)
56
+ return tensor
57
+
58
+
59
+ class LPLayerNorm(torch.nn.LayerNorm):
60
+ def __init__(self, normalized_shape, eps=1e-05, elementwise_affine=True):
61
+ super().__init__(
62
+ normalized_shape=normalized_shape,
63
+ eps=eps,
64
+ elementwise_affine=elementwise_affine,
65
+ )
66
+
67
+ def forward(self, x):
68
+ module_device = x.device
69
+ downcast_x = _cast_if_autocast_enabled(x)
70
+ downcast_weight = (
71
+ _cast_if_autocast_enabled(self.weight)
72
+ if self.weight is not None
73
+ else self.weight
74
+ )
75
+ downcast_bias = (
76
+ _cast_if_autocast_enabled(self.bias) if self.bias is not None else self.bias
77
+ )
78
+ with torch.autocast(enabled=False, device_type=module_device.type):
79
+ return torch.nn.functional.layer_norm(
80
+ downcast_x,
81
+ self.normalized_shape,
82
+ downcast_weight,
83
+ downcast_bias,
84
+ self.eps,
85
+ )
86
+
87
+
88
+ class SharedEmbedding(nn.Embedding):
89
+ def forward(self, input: torch.Tensor, unembed: bool = False) -> torch.Tensor:
90
+ if unembed:
91
+ return F.linear(input, self.weight)
92
+ return super().forward(input)
93
+
94
+
95
+ class MPTAttentionFused(nn.Module):
96
+ def __init__(self, args):
97
+ super().__init__()
98
+ self.args = args
99
+ self.n_local_heads = args.n_heads
100
+ self.head_dim = args.d_model // args.n_heads
101
+ args.max_seq_len = min(args.max_seq_len, global_max_seq_len)
102
+
103
+ self.Wqkv = nn.Linear(
104
+ args.d_model,
105
+ args.n_heads * self.head_dim * 3,
106
+ bias=False,
107
+ )
108
+
109
+ self.out_proj = nn.Linear(
110
+ args.n_heads * self.head_dim,
111
+ args.d_model,
112
+ bias=False,
113
+ )
114
+
115
+ # following fastertransformer definition
116
+
117
+ self.cache_v = (
118
+ torch.zeros(
119
+ (
120
+ max_batch_size,
121
+ self.n_local_heads,
122
+ args.max_seq_len,
123
+ self.head_dim,
124
+ )
125
+ )
126
+ .cuda()
127
+ .half()
128
+ ) # added to half
129
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
130
+ self.cache_k = (
131
+ torch.zeros(
132
+ (
133
+ max_batch_size,
134
+ self.n_local_heads,
135
+ self.head_dim // 8,
136
+ args.max_seq_len,
137
+ 8,
138
+ )
139
+ )
140
+ .cuda()
141
+ .half()
142
+ ) # added to half
143
+
144
+ alibi_slopes, alibi_bias = build_alibi_bias(
145
+ self.n_local_heads, args.max_seq_len
146
+ )
147
+ # TODO (Haotian): fix device
148
+ self.alibi_slopes = alibi_slopes.float().to("cuda:0")
149
+ self.alibi_bias = alibi_bias.to("cuda:0")
150
+
151
+ def forward(
152
+ self,
153
+ x: torch.Tensor,
154
+ start_pos: int,
155
+ mask: Optional[torch.Tensor],
156
+ ):
157
+ bsz, seqlen, _ = x.shape
158
+ xqkv = self.Wqkv(x)
159
+ xqkv = xqkv.view(bsz, seqlen, -1, self.n_local_heads, self.head_dim)
160
+ xq = xqkv[:, :, 0]
161
+ xk = xqkv[:, :, 1]
162
+ xv = xqkv[:, :, 2]
163
+
164
+ if seqlen > 1:
165
+ xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
166
+ xk = xk.view(bsz, seqlen, self.n_local_heads, self.head_dim)
167
+ xv = xv.view(bsz, seqlen, self.n_local_heads, self.head_dim)
168
+
169
+ self.cache_k = self.cache_k.to(xq)
170
+ self.cache_v = self.cache_v.to(xq)
171
+
172
+ values_store = xv.transpose(2, 1)
173
+ keys_store = (
174
+ xk.reshape(bsz, seqlen, self.n_local_heads, self.head_dim // 8, 8)
175
+ .permute(0, 2, 3, 1, 4)
176
+ .contiguous()
177
+ )
178
+
179
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
180
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
181
+
182
+ keys = xk
183
+ values = xv
184
+
185
+ xq = xq.transpose(1, 2)
186
+ keys = keys.transpose(1, 2)
187
+ values = values.transpose(1, 2)
188
+ scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
189
+ scores += self.alibi_bias[..., :seqlen]
190
+ if mask is not None:
191
+ scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
192
+ scores = F.softmax(scores.float(), dim=-1).type_as(xq)
193
+ output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
194
+ output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
195
+ else:
196
+ # xq = xq[:, 0, :, :]
197
+ # xk = xk[:, 0, :, :]
198
+ # xv = xv[:, 0, :, :]
199
+ xq = xq.view(bsz, self.n_local_heads, self.head_dim)
200
+ xk = xk.view(bsz, self.n_local_heads, self.head_dim)
201
+ xv = xv.view(bsz, self.n_local_heads, self.head_dim)
202
+ output = awq_inference_engine.single_query_attention(
203
+ xq,
204
+ xk,
205
+ xv,
206
+ self.cache_k,
207
+ self.cache_v,
208
+ None,
209
+ # with alibi embedding
210
+ self.alibi_slopes.float(),
211
+ start_pos,
212
+ # rotary embed dim = 0 => no rotary embedding
213
+ 0,
214
+ 10000,
215
+ 1.0,
216
+ True,
217
+ )
218
+ output = output.reshape(bsz, 1, -1)
219
+
220
+ return self.out_proj(output)
221
+
222
+
223
+ class MPTMLP(nn.Module):
224
+ def __init__(self, d_model: int, expansion_ratio: int):
225
+ super().__init__()
226
+ self.up_proj = nn.Linear(d_model, expansion_ratio * d_model, bias=False)
227
+ self.act = nn.GELU(approximate="none")
228
+ self.down_proj = nn.Linear(expansion_ratio * d_model, d_model, bias=False)
229
+ self.down_proj._is_residual = True
230
+
231
+ def forward(self, x):
232
+ return self.down_proj(self.act(self.up_proj(x)))
233
+
234
+
235
+ class MPTBlock(nn.Module):
236
+ def __init__(self, layer_id: int, args):
237
+ super().__init__()
238
+ self.n_heads = args.n_heads
239
+ self.dim = args.d_model
240
+ self.head_dim = args.d_model // args.n_heads
241
+ self.attn = MPTAttentionFused(args)
242
+ self.ffn = MPTMLP(d_model=args.d_model, expansion_ratio=4)
243
+ self.layer_id = layer_id
244
+ self.norm_1 = LPLayerNorm(args.d_model, eps=1e-6)
245
+ self.norm_2 = LPLayerNorm(args.d_model, eps=1e-6)
246
+
247
+ def forward(
248
+ self,
249
+ x: torch.Tensor,
250
+ start_pos: int,
251
+ mask: Optional[torch.Tensor],
252
+ ):
253
+ h = x + self.attn.forward(self.norm_1(x), start_pos, mask)
254
+ out = h + self.ffn.forward(self.norm_2(h))
255
+ return out
256
+
257
+
258
+ class Transformer(nn.Module):
259
+ def __init__(self, params):
260
+ super().__init__()
261
+ self.params = params
262
+ self.vocab_size = params.vocab_size
263
+ self.n_layers = params.n_layers
264
+
265
+ self.wte = SharedEmbedding(params.vocab_size, params.d_model)
266
+
267
+ self.blocks = torch.nn.ModuleList()
268
+ for layer_id in range(params.n_layers):
269
+ self.blocks.append(MPTBlock(layer_id, params))
270
+
271
+ self.norm_f = LPLayerNorm(params.d_model, eps=1e-6)
272
+
273
+ @torch.inference_mode()
274
+ def forward(self, tokens: torch.Tensor, start_pos: int):
275
+ _bsz, seqlen = tokens.shape
276
+ h = self.wte(tokens)
277
+
278
+ mask = None
279
+ if seqlen > 1:
280
+ mask = torch.full(
281
+ (1, 1, seqlen, seqlen), float("-inf"), device=tokens.device
282
+ )
283
+ mask = torch.triu(mask, diagonal=start_pos + 1).type_as(h)
284
+ for layer in self.blocks:
285
+ h = layer(h, start_pos, mask)
286
+ h = self.norm_f(h)
287
+ return h
288
+
289
+
290
+ class MPTForCausalLM(nn.Module):
291
+ def __init__(self, params):
292
+ super().__init__()
293
+ self.config = params
294
+ self.transformer = Transformer(params)
295
+ if params.no_bias:
296
+ for module in self.modules():
297
+ if hasattr(module, "bias") and isinstance(module.bias, nn.Parameter):
298
+ module.register_parameter("bias", None)
299
+
300
+ @torch.inference_mode()
301
+ def forward(self, tokens: torch.Tensor, start_pos: int):
302
+ h = self.transformer(tokens, start_pos)
303
+ output = self.transformer.wte(h, unembed=True) # only compute last logits
304
+ return output.float()
llm-awq/tinychat/models/nvila/configuration_llava.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 NVIDIA CORPORATION & AFFILIATES
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+ # SPDX-License-Identifier: Apache-2.0
16
+
17
+ from typing import Optional
18
+
19
+ from transformers import PretrainedConfig
20
+
21
+
22
+ class LlavaConfig(PretrainedConfig):
23
+ model_type = "llava"
24
+
25
+ def __init__(
26
+ self,
27
+ llm_cfg=None,
28
+ vision_tower_cfg=None,
29
+ mm_projector_cfg=None,
30
+ architectures=None,
31
+ resume_path=None,
32
+ hidden_size=None,
33
+ mm_hidden_size=None,
34
+ image_aspect_ratio=None,
35
+ num_video_frames=None,
36
+ fps=None,
37
+ mm_vision_select_layer=None,
38
+ mm_vision_select_feature=None,
39
+ mm_use_im_start_end=False,
40
+ mm_use_im_patch_token=False,
41
+ mm_projector_lr=None,
42
+ vision_tower_lr=None,
43
+ vision_resolution=None,
44
+ interpolate_mode=None,
45
+ s2=None,
46
+ dynamic_s2=None,
47
+ s2_scales=None,
48
+ s2_max_split_size=None,
49
+ s2_resize_output_to_scale_idx=0,
50
+ min_tiles: Optional[int] = 1,
51
+ max_tiles: Optional[int] = 12,
52
+ num_time_tokens=None,
53
+ time_token_format=None,
54
+ image_encoder: str = '{"_target_": "llava.model.encoders.BasicImageEncoder"}',
55
+ video_encoder: str = '{"_target_": "llava.model.encoders.BasicVideoEncoder"}',
56
+ **kwargs,
57
+ ):
58
+ super().__init__()
59
+ self.architectures = architectures
60
+ self.llm_cfg = llm_cfg
61
+ self.vision_tower_cfg = vision_tower_cfg
62
+ self.mm_projector_cfg = mm_projector_cfg
63
+ self.resume_path = resume_path
64
+
65
+ self.hidden_size = hidden_size
66
+ self.mm_hidden_size = mm_hidden_size
67
+ self.image_aspect_ratio = image_aspect_ratio
68
+ self.num_video_frames = num_video_frames
69
+ self.fps = fps
70
+ self.mm_vision_select_layer = mm_vision_select_layer
71
+ self.mm_vision_select_feature = mm_vision_select_feature
72
+ self.mm_use_im_start_end = mm_use_im_start_end
73
+ self.mm_use_im_patch_token = mm_use_im_patch_token
74
+ self.mm_projector_lr = mm_projector_lr
75
+ self.vision_tower_lr = vision_tower_lr
76
+ self.vision_resolution = vision_resolution
77
+ self.interpolate_mode = interpolate_mode
78
+ self.s2 = s2
79
+ self.dynamic_s2 = dynamic_s2
80
+ self.s2_scales = s2_scales
81
+ self.s2_max_split_size = s2_max_split_size
82
+ self.s2_resize_output_to_scale_idx = s2_resize_output_to_scale_idx
83
+ self.min_tiles = min_tiles
84
+ self.max_tiles = max_tiles
85
+ self.num_time_tokens = num_time_tokens
86
+ self.time_token_format = time_token_format
87
+
88
+ self.image_encoder = image_encoder
89
+ self.video_encoder = video_encoder
llm-awq/tinychat/models/nvila_qwen2.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 Haotian Liu
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # This file is modified from https://github.com/haotian-liu/LLaVA/
16
+
17
+
18
+ import os
19
+ from collections import defaultdict
20
+ from typing import Dict, List, Optional, Tuple, Union
21
+
22
+ import torch
23
+ from transformers import AutoConfig, AutoModel, PretrainedConfig, PreTrainedModel
24
+ from transformers.modeling_outputs import CausalLMOutputWithPast
25
+
26
+
27
+ from .nvila.configuration_llava import LlavaConfig
28
+ from .nvila.llava_arch import LlavaMetaForCausalLM, LlavaMetaModel
29
+ from .qwen2 import Qwen2ForCausalLM
30
+
31
+
32
+ def skip(*args, **kwargs):
33
+ pass
34
+
35
+
36
+ torch.nn.init.kaiming_uniform_ = skip
37
+ torch.nn.init.kaiming_normal_ = skip
38
+ torch.nn.init.uniform_ = skip
39
+ torch.nn.init.normal_ = skip
40
+ from transformers import modeling_utils
41
+
42
+ modeling_utils._init_weights = False
43
+
44
+
45
+ class LlavaLlamaConfig(LlavaConfig):
46
+ model_type = "llava_llama"
47
+
48
+
49
+ class NVILAQwen2(LlavaMetaModel, LlavaMetaForCausalLM, PreTrainedModel):
50
+ config_class = LlavaLlamaConfig
51
+ main_input_name = "input_embeds"
52
+ supports_gradient_checkpointing = True
53
+ _supports_flash_attn_2 = True
54
+
55
+ def __init__(
56
+ self, config: LlavaLlamaConfig = None, llm=True, *args, **kwargs
57
+ ) -> None:
58
+ super().__init__(config)
59
+ self.init_vlm(config=config, *args, **kwargs)
60
+ # TODO: Skip the weight loading to save time
61
+ self.llm_cfg = AutoConfig.from_pretrained(self.llm_cfg, init_weights=False)
62
+ if llm:
63
+ self.llm = Qwen2ForCausalLM.from_pretrained(self.llm_cfg._name_or_path)
64
+ self.llm = self.llm.cpu()
65
+ self.llm.resize_token_embeddings(len(self.tokenizer))
66
+ else:
67
+ self.llm = None
68
+
69
+ @classmethod
70
+ def from_pretrained(
71
+ cls,
72
+ pretrained_model_name_or_path: Optional[Union[str, os.PathLike]],
73
+ *model_args,
74
+ config: Optional[Union[PretrainedConfig, str, os.PathLike]] = None,
75
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
76
+ ignore_mismatched_sizes: bool = False,
77
+ force_download: bool = False,
78
+ local_files_only: bool = False,
79
+ token: Optional[Union[str, bool]] = None,
80
+ revision: str = "main",
81
+ use_safetensors: bool = None,
82
+ **kwargs,
83
+ ):
84
+ if hasattr(cls, "load_pretrained"):
85
+ return cls.load_pretrained(
86
+ pretrained_model_name_or_path,
87
+ *model_args,
88
+ config=config,
89
+ cache_dir=cache_dir,
90
+ ignore_mismatched_sizes=ignore_mismatched_sizes,
91
+ force_download=force_download,
92
+ local_files_only=local_files_only,
93
+ token=token,
94
+ revision=revision,
95
+ use_safetensors=use_safetensors,
96
+ **kwargs,
97
+ )
98
+ return super(NVILAQwen2).from_pretrained(
99
+ pretrained_model_name_or_path,
100
+ *model_args,
101
+ config=config,
102
+ cache_dir=cache_dir,
103
+ ignore_mismatched_sizes=ignore_mismatched_sizes,
104
+ force_download=force_download,
105
+ local_files_only=local_files_only,
106
+ token=token,
107
+ revision=revision,
108
+ use_safetensors=use_safetensors,
109
+ **kwargs,
110
+ )
111
+
112
+ def forward(
113
+ self,
114
+ input_ids: torch.LongTensor = None,
115
+ media: Optional[Dict[str, List[torch.Tensor]]] = None,
116
+ images: Optional[torch.FloatTensor] = None,
117
+ media_config: Optional[List] = None,
118
+ attention_mask: Optional[torch.Tensor] = None,
119
+ position_ids: Optional[torch.LongTensor] = None,
120
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
121
+ inputs_embeds: Optional[torch.FloatTensor] = None,
122
+ labels: Optional[torch.LongTensor] = None,
123
+ packing: bool = True,
124
+ seqlens_in_batch: Optional[torch.LongTensor] = None,
125
+ dpo_forward: bool = False,
126
+ **kwargs,
127
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
128
+ self.freezed_module_patch()
129
+
130
+ if images is not None:
131
+ if media is not None:
132
+ raise ValueError(
133
+ "Both 'media' and 'images' are provided. Please provide only one."
134
+ )
135
+ media = {"image": images}
136
+
137
+ if media_config is None:
138
+ media_config = defaultdict(dict)
139
+
140
+ if inputs_embeds is None:
141
+ inputs_embeds, labels, attention_mask = self._embed(
142
+ input_ids, media, media_config, labels, attention_mask
143
+ )
144
+
145
+ outputs = self.llm(
146
+ inputs_embeds=inputs_embeds,
147
+ attention_mask=attention_mask,
148
+ position_ids=position_ids,
149
+ past_key_values=past_key_values,
150
+ labels=labels,
151
+ **kwargs,
152
+ )
153
+
154
+ if dpo_forward:
155
+ return outputs.logits, labels
156
+
157
+ return outputs
llm-awq/tinychat/modules/__init__.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from .fused_norm import *
2
+ from .fused_attn import *
3
+ from .fused_mlp import *
4
+ from .fused_vision_attn import *
5
+ try:
6
+ from .fused_siglipdecoder import *
7
+ from .fused_internencoder import *
8
+ except ImportError as e:
9
+ print("InternVL3 model import failure. To activate, please install VILA at https://github.com/NVlabs/VILA.")
llm-awq/tinychat/modules/fused_mlp.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+ from torch.cuda.amp import custom_bwd, custom_fwd
6
+ from transformers.models.llama.modeling_llama import LlamaMLP
7
+
8
+ import awq_inference_engine
9
+
10
+
11
+ class QuantLlamaMLP(nn.Module):
12
+ def __init__(
13
+ self,
14
+ gate_proj,
15
+ down_proj,
16
+ up_proj,
17
+ ):
18
+ super().__init__()
19
+ self.register_buffer("gate_proj_qweight", gate_proj.qweight)
20
+ self.register_buffer("gate_proj_scales", gate_proj.scales)
21
+ self.register_buffer("gate_proj_scaled_zeros", gate_proj.scaled_zeros)
22
+ self.register_buffer("up_proj_qweight", up_proj.qweight)
23
+ self.register_buffer("up_proj_scales", up_proj.scales)
24
+ self.register_buffer("up_proj_scaled_zeros", up_proj.scaled_zeros)
25
+
26
+ self.in_features = gate_proj.in_features
27
+ self.intermediate_size = gate_proj.out_features
28
+ self.out_features = down_proj.out_features
29
+ self.w_bit = gate_proj.w_bit
30
+ self.down_proj = down_proj
31
+ self.split_k_iters = down_proj.split_k_iters
32
+
33
+ def forward(self, x):
34
+ return self.down_proj(self.our_llama_mlp(x))
35
+
36
+ def our_llama_mlp(self, x):
37
+ # out_shape = x.shape[:-1] + (self.intermediate_size,)
38
+ # x = x.reshape(-1, x.shape[-1])
39
+ if x.numel() // x.shape[-1] < 8:
40
+ gate_output = awq_inference_engine.gemv_forward_cuda_new(
41
+ x,
42
+ self.gate_proj_qweight,
43
+ self.gate_proj_scales,
44
+ self.gate_proj_scaled_zeros,
45
+ x.numel() // x.shape[-1],
46
+ self.intermediate_size,
47
+ self.in_features,
48
+ self.down_proj.group_size,
49
+ )
50
+ gate_output = F.silu(gate_output)
51
+ up_output = awq_inference_engine.gemv_forward_cuda_new(
52
+ x,
53
+ self.up_proj_qweight,
54
+ self.up_proj_scales,
55
+ self.up_proj_scaled_zeros,
56
+ x.numel() // x.shape[-1],
57
+ self.intermediate_size,
58
+ self.in_features,
59
+ self.down_proj.group_size,
60
+ )
61
+ else:
62
+ # num_mn_tiles = (x.shape[0] // 32) * (self.intermediate_size // 128)
63
+ # cuda_Semaphores_gate = torch.empty(num_mn_tiles).int().to(x.device)
64
+ # cuda_Semaphores_up = torch.empty(num_mn_tiles).int().to(x.device)
65
+ gate_output = awq_inference_engine.gemm_forward_cuda_new(
66
+ x,
67
+ self.gate_proj_qweight,
68
+ self.gate_proj_scales,
69
+ self.gate_proj_scaled_zeros - 8 * self.gate_proj_scales,
70
+ # self.gate_cuda_semaphores
71
+ )
72
+ up_output = awq_inference_engine.gemm_forward_cuda_new(
73
+ x,
74
+ self.up_proj_qweight,
75
+ self.up_proj_scales,
76
+ self.up_proj_scaled_zeros - 8 * self.up_proj_scales,
77
+ # self.up_cuda_semaphores
78
+ )
79
+ gate_output = F.silu(gate_output)
80
+
81
+ c = gate_output * up_output
82
+ # c = c.reshape(out_shape)
83
+ return c
84
+
85
+
86
+ def make_fused_mlp(m, parent_name=""):
87
+ if not hasattr(make_fused_mlp, "called"):
88
+ # print("[Warning] Calling a fake MLP fusion. But still faster than Huggingface Implimentation.")
89
+ make_fused_mlp.called = True
90
+ """
91
+ Replace all LlamaMLP modules with QuantLlamaMLP modules, which fuses many of the operations.
92
+ """
93
+ if m.__class__.__name__ in ["LlamaMLP"]:
94
+ return QuantLlamaMLP(m.gate_proj, m.down_proj, m.up_proj)
95
+
96
+ for name, child in m.named_children():
97
+ child = make_fused_mlp(child, parent_name=f"{parent_name}.{name}")
98
+
99
+ if isinstance(child, QuantLlamaMLP):
100
+ setattr(m, name, child)
101
+ return m
llm-awq/tinychat/nvila_benchmark.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from termcolor import colored
4
+
5
+ import llava
6
+ from llava import conversation as clib
7
+ from llava.media import Image, Video
8
+ import torch
9
+ from awq.quantize import fake_quant
10
+ from awq.quantize.quantizer import real_quantize_model_weight
11
+ from transformers import AutoConfig
12
+ import tinychat
13
+
14
+
15
+ def skip(*args, **kwargs):
16
+ pass
17
+
18
+
19
+ def main() -> None:
20
+ parser = argparse.ArgumentParser()
21
+ parser.add_argument(
22
+ "--model-path",
23
+ "-m",
24
+ type=str,
25
+ default="/home/yuming/workspace/qwen/models/nvila-internal-8b-v1",
26
+ )
27
+ parser.add_argument(
28
+ "--quant_path",
29
+ type=str,
30
+ default="/PATH/TO/QUANT",
31
+ )
32
+ # parser.add_argument("--model-path", "-m", type=str, default="Efficient-Large-Model/J65")
33
+ # parser.add_argument("--quant_path", type=str, default="/home/yuming/workspace/qwen/models/J65/llm/vila2-J65-w4-g128-awq-v2.pt")
34
+ parser.add_argument("--conv-mode", "-c", type=str, default="auto")
35
+ # parser.add_argument("--media", type=str, default="/home/yuming/workspace/space_woaudio.mp4")
36
+ parser.add_argument("--device", type=str, default="cuda:0")
37
+ parser.add_argument(
38
+ "--act_scale_path",
39
+ type=str,
40
+ default="/PATH/TO/SCALE",
41
+ )
42
+ # quantization options
43
+ parser.add_argument("--quant_llm", action="store_true")
44
+ parser.add_argument("--quant_VT", action="store_true")
45
+ # Four basic tasks
46
+ parser.add_argument("--video_caption", action="store_true")
47
+ parser.add_argument("--video_QA", action="store_true")
48
+ parser.add_argument("--image_caption", action="store_true")
49
+ parser.add_argument("--image_QA", action="store_true")
50
+
51
+ parser.add_argument(
52
+ "--all",
53
+ action="store_true",
54
+ help="Whether to quantize visiontower and llm, and test all 4 tasks",
55
+ )
56
+ parser.add_argument(
57
+ "--fakequant_VT",
58
+ action="store_true",
59
+ help="Use fake quant or real quant for VisionTower",
60
+ )
61
+ parser.add_argument(
62
+ "--all_task", action="store_true", help="Whether to test all 4 tasks"
63
+ )
64
+ parser.add_argument(
65
+ "--video_path", type=str, default="../figures/nvila_demo_video.mp4"
66
+ )
67
+ parser.add_argument("--image_path", type=str, default="../figures/vila-logo.jpg")
68
+ parser.add_argument("--max_seq_len", type=int, default=8192)
69
+ args = parser.parse_args()
70
+
71
+ torch.nn.init.kaiming_uniform_ = skip
72
+ torch.nn.init.kaiming_normal_ = skip
73
+ torch.nn.init.uniform_ = skip
74
+ torch.nn.init.normal_ = skip
75
+ import tinychat.utils.constants
76
+
77
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
78
+ from transformers import modeling_utils
79
+
80
+ modeling_utils._init_weights = False
81
+
82
+ # Load model
83
+ from tinychat.models.nvila_qwen2 import NVILAQwen2
84
+
85
+ config = AutoConfig.from_pretrained(args.model_path)
86
+ config.resume_path = args.model_path
87
+ model = NVILAQwen2(config).half()
88
+ model.llm = model.llm.eval()
89
+ if args.quant_llm or args.all:
90
+ from tinychat.modules import (
91
+ make_quant_norm,
92
+ make_quant_attn,
93
+ make_fused_mlp,
94
+ make_fused_vision_attn,
95
+ )
96
+
97
+ real_quantize_model_weight(
98
+ model.llm,
99
+ w_bit=4,
100
+ q_config=dict(q_group_size=128, zero_point=True),
101
+ init_only=True,
102
+ )
103
+ make_quant_attn(model.llm, "cuda", True)
104
+ make_quant_norm(model.llm)
105
+ make_fused_mlp(model.llm)
106
+ model = model.to("cuda")
107
+ model = model.to(args.device)
108
+ if args.quant_VT or args.all:
109
+ from tinychat.modules import QuantSiglipEncoder
110
+
111
+ model.vision_tower.vision_tower.vision_model.encoder = QuantSiglipEncoder(
112
+ model.vision_tower.vision_tower.vision_model.encoder
113
+ )
114
+ model = model.cuda().eval()
115
+
116
+ if args.video_caption or args.all or args.all_task:
117
+ print("-" * 80)
118
+ print("Video_Caption")
119
+ # Set conversation mode
120
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
121
+ media = Video(args.video_path)
122
+ text = "Elaborate on the visual and narrative elements of the video in detail." # + "1"+" 1"*3069
123
+ prompt = [media, text]
124
+ # Generate response
125
+ with torch.no_grad():
126
+ response = model.benchmark(prompt, args.quant_llm)
127
+ if args.video_QA or args.all or args.all_task:
128
+ print("-" * 80)
129
+ print("Video_QA")
130
+ # Set conversation mode
131
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
132
+ media = Video(args.video_path)
133
+ text = "What is the person in the video doing? Select the option that best describes their action: A. Folding paper B. Playing computer games C. Sleeping." # + "1"+" 1"*3069
134
+ prompt = [media, text]
135
+ # Generate response
136
+ with torch.no_grad():
137
+ response = model.benchmark(prompt, args.quant_llm)
138
+ if args.image_caption or args.all or args.all_task:
139
+ print("-" * 80)
140
+ print("Image_Caption")
141
+ # Set conversation mode
142
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
143
+ media = Image(args.image_path)
144
+ text = "Describe the image in detail."
145
+ prompt = [media, text]
146
+ # Generate response
147
+ with torch.no_grad():
148
+ response = model.benchmark(prompt, args.quant_llm)
149
+ if args.image_QA or args.all or args.all_task:
150
+ print("-" * 80)
151
+ print("Image_QA")
152
+ # Set conversation mode
153
+ clib.default_conversation = clib.conv_templates[args.conv_mode].copy()
154
+ media = Image(args.image_path)
155
+ text = "What does the text in the image say? Choose the option that best matches: A. VILA B. AIIV C. ALIV."
156
+ prompt = [media, text]
157
+ # Generate response
158
+ with torch.no_grad():
159
+ response = model.benchmark(prompt, args.quant_llm)
160
+
161
+
162
+ if __name__ == "__main__":
163
+ main()
llm-awq/tinychat/nvila_demo.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from termcolor import colored
4
+ from huggingface_hub import hf_hub_download
5
+ import os
6
+ import llava
7
+ from llava import conversation as clib
8
+ from llava.media import Image, Video
9
+ import torch
10
+ from awq.quantize import fake_quant
11
+ from transformers import AutoConfig
12
+ from tinychat.utils.load_quant import load_awq_model
13
+ from tinychat.utils.llava_image_processing import (
14
+ load_images,
15
+ vis_images,
16
+ )
17
+
18
+
19
+ def skip(*args, **kwargs):
20
+ pass
21
+
22
+
23
+ from tinychat.utils.tune import (
24
+ device_warmup,
25
+ tune_all_wqlinears,
26
+ tune_llava_patch_embedding,
27
+ )
28
+ from tinychat.utils.prompt_templates import (
29
+ get_prompter,
30
+ get_stop_token_ids,
31
+ get_image_token,
32
+ )
33
+ from llava.utils.media import extract_media
34
+ import tinychat.utils.constants
35
+ from tinychat.stream_generators.NVILA_stream_gen import NVILAStreamGenerator
36
+ from tinychat.utils.conversation_utils import gen_params, stream_output, TimeStats
37
+
38
+ os.environ["CUDA_VISIBLE_DEVICES"] = "0"
39
+
40
+ def download_model_file(
41
+ repo_id: str = "Efficient-Large-Model/NVILA-AWQ",
42
+ filename: str = None,
43
+ local_dir: str = "./hf_cache",
44
+ force_download: bool = False,
45
+ ) -> str:
46
+ os.makedirs(local_dir, exist_ok=True)
47
+ local_path = os.path.join(local_dir, filename)
48
+ if force_download or not os.path.exists(local_path):
49
+ print(f"Downloading {filename} from {repo_id}...")
50
+ hf_hub_download(
51
+ repo_id=repo_id,
52
+ filename=filename,
53
+ local_dir=local_dir,
54
+ local_dir_use_symlinks=False,
55
+ resume_download=True,
56
+ force_download=force_download,
57
+ )
58
+ print(f"File saved to: {local_path}")
59
+
60
+ return local_path
61
+
62
+
63
+
64
+ def main(args):
65
+ # Accelerate model initialization
66
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
67
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
68
+ torch.nn.init.kaiming_uniform_ = skip
69
+ torch.nn.init.kaiming_normal_ = skip
70
+ torch.nn.init.uniform_ = skip
71
+ torch.nn.init.normal_ = skip
72
+ tinychat.utils.constants.max_seq_len = args.max_seq_len
73
+
74
+ # Prepare model
75
+ from tinychat.models.nvila_qwen2 import NVILAQwen2
76
+ from transformers import AutoConfig
77
+ from tinychat.models.qwen2 import Qwen2ForCausalLM
78
+
79
+ config = AutoConfig.from_pretrained(args.model_path)
80
+ config.resume_path = args.model_path
81
+ if args.quant_llm or args.all:
82
+ model = NVILAQwen2(config, False).half()
83
+ else:
84
+ model = NVILAQwen2(config, True).half()
85
+
86
+ if args.smooth_VT or args.all:
87
+ from awq.quantize import smooth_lm
88
+ args.act_scale_path=download_model_file(filename=args.act_scale_path)
89
+ act_scales = torch.load(args.act_scale_path)
90
+ smooth_lm(model.vision_tower, act_scales, 0.3)
91
+ if args.quant_llm or args.all:
92
+ from tinychat.modules import (
93
+ make_quant_norm,
94
+ make_quant_attn,
95
+ make_fused_mlp,
96
+ make_fused_vision_attn,
97
+ )
98
+ args.quant_path=download_model_file(filename=args.quant_path)
99
+ model.llm = Qwen2ForCausalLM(model.llm_cfg).half()
100
+ model.llm = load_awq_model(model.llm, args.quant_path, 4, 128, args.device)
101
+ make_quant_attn(model.llm, args.device, True)
102
+ make_quant_norm(model.llm)
103
+ model.llm.cpu()
104
+ model.llm.resize_token_embeddings(len(model.tokenizer))
105
+
106
+ if args.quant_VT or args.all:
107
+ from tinychat.modules import QuantSiglipEncoder
108
+
109
+ if args.fakequant_VT:
110
+ fake_quant(model.vision_tower.vision_tower.vision_model.encoder)
111
+ else:
112
+ model.vision_tower.vision_tower.vision_model.encoder = QuantSiglipEncoder(
113
+ model.vision_tower.vision_tower.vision_model.encoder
114
+ )
115
+ model = model.cuda().eval()
116
+ device_warmup(args.device)
117
+ tune_llava_patch_embedding(model.vision_tower, device=args.device)
118
+
119
+ # Pre-prepare media
120
+ prompt = []
121
+ media_files = []
122
+ if args.media is not None:
123
+ for media in args.media or []:
124
+ if any(media.endswith(ext) for ext in [".jpg", ".jpeg", ".png"]):
125
+ media = Image(media)
126
+ media_files.append(media)
127
+ media_prompt = "<image>"
128
+ elif any(media.endswith(ext) for ext in [".mp4", ".mkv", ".webm"]):
129
+ media = Video(media)
130
+ media_files.append(media)
131
+ media_prompt = "<vila/video>"
132
+ else:
133
+ raise ValueError(f"Unsupported media type: {media}")
134
+ prompt.append(media)
135
+ media_num = len(media_files)
136
+ if args.vis_image:
137
+ print("=" * 50)
138
+ print("Input Image:")
139
+ vis_images(args.media)
140
+ conversation = [{"from": "human", "value": prompt}]
141
+ media, media_cfg = model.prepare_media(conversation)
142
+ # Prepare streaming
143
+ stream_generator = NVILAStreamGenerator
144
+ # Prepare prompt
145
+ if args.max_seq_len <= 1024:
146
+ short_prompt = True
147
+ else:
148
+ short_prompt = False
149
+ model_prompter = get_prompter(
150
+ args.model_type, args.model_path, short_prompt, args.empty_prompt
151
+ )
152
+ stop_token_ids = get_stop_token_ids(args.model_type, args.model_path)
153
+ count = 0
154
+
155
+ if args.empty_prompt:
156
+ input_indicator = "Input: "
157
+ output_indicator = "Generated: "
158
+ else:
159
+ input_indicator = "USER: "
160
+ output_indicator = "ASSISTANT: "
161
+
162
+ count = 0
163
+ model.eval()
164
+ time_stats = TimeStats()
165
+ start_pos = 0
166
+ while True:
167
+ # Get input from the user
168
+ print("=" * 50)
169
+ input_prompt = input(input_indicator)
170
+ print("-" * 50)
171
+ if input_prompt == "":
172
+ print("EXIT...")
173
+ time_stats.show()
174
+ break
175
+ if count == 0: # Insert media here
176
+ if args.media is not None:
177
+ if media_prompt in input_prompt:
178
+ input_prompt = input_prompt
179
+ else:
180
+ input_prompt = media_prompt * media_num + input_prompt
181
+ model_prompter.insert_prompt(input_prompt)
182
+ else:
183
+ model_prompter.insert_prompt(input_prompt)
184
+ if args.chunk_prefilling:
185
+ media = None
186
+ media_cfg = None
187
+ output_stream = stream_generator(
188
+ model,
189
+ gen_params,
190
+ model_prompter.model_input,
191
+ media,
192
+ media_cfg,
193
+ start_pos,
194
+ device=args.device,
195
+ stop_token_ids=stop_token_ids,
196
+ chunk_prefilling=args.chunk_prefilling,
197
+ quant_llm=args.quant_llm or args.all,
198
+ )
199
+ print(output_indicator, end="", flush=True)
200
+ if count == 0:
201
+ outputs, total_tokens = stream_output(output_stream, time_stats)
202
+ else:
203
+ outputs, total_tokens = stream_output(output_stream)
204
+ if args.chunk_prefilling:
205
+ start_pos += total_tokens
206
+ if (
207
+ args.single_round is not True and args.max_seq_len > 512
208
+ ): # Only memorize previous conversations when kv_cache_size > 512
209
+ model_prompter.update_template(outputs, args.chunk_prefilling)
210
+ count += 1
211
+
212
+
213
+ if __name__ == "__main__":
214
+ parser = argparse.ArgumentParser()
215
+ parser.add_argument(
216
+ "--model_type", type=str, default="LLaMa", help="type of the model"
217
+ )
218
+ parser.add_argument(
219
+ "--model-path", type=str, default="/data/llm/checkpoints/llava/llava-v1.5-7b"
220
+ )
221
+ parser.add_argument(
222
+ "--quant_path",
223
+ type=str,
224
+ default="/data/llm/checkpoints/llava/llava-v1.5-7b-w4-g128-awq.pt",
225
+ )
226
+ parser.add_argument(
227
+ "--act_scale_path",
228
+ type=str,
229
+ default="/PATH/TO/SCALE",
230
+ )
231
+ parser.add_argument(
232
+ "--media", type=str, nargs="+", help="Multi-modal input (Video or image path)"
233
+ )
234
+ parser.add_argument("--device", type=str, default="cuda:0")
235
+ parser.add_argument("--max_seq_len", type=int, default=2048)
236
+ parser.add_argument(
237
+ "--single_round",
238
+ action="store_true",
239
+ help="whether to memorize previous conversations",
240
+ )
241
+ parser.add_argument(
242
+ "--vis-image",
243
+ action="store_true",
244
+ help="whether to visualize the image while chatting",
245
+ )
246
+ parser.add_argument(
247
+ "--empty-prompt",
248
+ action="store_true",
249
+ help="whether to use empty prompt template",
250
+ )
251
+ parser.add_argument(
252
+ "--flash_attn",
253
+ action="store_true",
254
+ help="whether to use flash attention",
255
+ )
256
+ parser.add_argument(
257
+ "--chunk_prefilling",
258
+ action="store_true",
259
+ help="If used, in context stage, the history tokens will not be recalculated, greatly speeding up the calculation",
260
+ )
261
+ # smooth and quantization options
262
+ parser.add_argument("--quant_llm", action="store_true")
263
+ parser.add_argument("--quant_VT", action="store_true")
264
+ parser.add_argument("--smooth_VT", action="store_true")
265
+ parser.add_argument("--all", action="store_true")
266
+ parser.add_argument(
267
+ "--fakequant_VT",
268
+ action="store_true",
269
+ help="Use fake quant or real quant for VisionTower",
270
+ )
271
+ args = parser.parse_args()
272
+ main(args)
llm-awq/tinychat/offline-weight-repacker.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import numpy as np
4
+ from typing import List
5
+ from collections import OrderedDict
6
+
7
+
8
+ def qweight_unpack(qweight):
9
+ assert qweight.dtype == torch.int32
10
+ n = qweight.shape[0]
11
+ k = qweight.shape[1] * 8
12
+ unpacked_qweight = torch.zeros((n, k), dtype=torch.int32, device=qweight.device)
13
+ mask = 0x0000000F
14
+ for kk in range(k):
15
+ ele_offset = kk // 8
16
+ bit_offset = (kk % 8) * 4
17
+ unpacked_qweight[:, kk] = (qweight[:, ele_offset] >> bit_offset) & mask
18
+
19
+ return unpacked_qweight
20
+
21
+
22
+ def packing_v2_from_unpacked(unpacked_qweight, interleave, kstride):
23
+ # unpacked_qweight: [N, K]
24
+ N = unpacked_qweight.shape[0]
25
+ K = unpacked_qweight.shape[1]
26
+
27
+ Packed_Kernel = unpacked_qweight.cpu().numpy().reshape(N, K // 32, 32)
28
+ # np.arange(32).reshape(4, 4, 2).transpose(1, 0, 2) => [0, 1, 8, 9, 16, 17, 24, 25, ...]
29
+ Packed_Kernel = Packed_Kernel.reshape(N, K // 32, 4, 4, 2).transpose(0, 1, 3, 2, 4)
30
+ Packed_Kernel = Packed_Kernel.reshape(N, K // 32, 32)
31
+
32
+ # reorder each 8 weights for fast dequantization
33
+ # [0, 1, 2, 3, 4, 5, 6, 7] => [0, 2, 4, 6, 1, 3, 5, 7]
34
+ Packed_Kernel = Packed_Kernel.reshape(N, K // 32, 4, 8)
35
+ Packed_Kernel = Packed_Kernel.reshape(N, K // 32, 4, 4, 2).transpose(0, 1, 2, 4, 3)
36
+ Packed_Kernel = Packed_Kernel.reshape(N, K)
37
+
38
+ # interleaving every four rows
39
+ Packed_Kernel = Packed_Kernel.reshape(
40
+ N // interleave, interleave, K // kstride, kstride
41
+ )
42
+ # N // 4, K // 64, 4, 64
43
+ Packed_Kernel = Packed_Kernel.transpose(0, 2, 1, 3)
44
+ Packed_Kernel = Packed_Kernel.reshape(
45
+ N // interleave, K // kstride, kstride, interleave
46
+ )
47
+ # Packing -> (N // 4, K // 64, 64)
48
+ Packed_Kernel = (
49
+ Packed_Kernel[..., 0]
50
+ | (Packed_Kernel[..., 1] << 4)
51
+ | (Packed_Kernel[..., 2] << 8)
52
+ | (Packed_Kernel[..., 3] << 12)
53
+ )
54
+ # reshape to (N // 4, K), FP16 format
55
+ Packed_Kernel = Packed_Kernel.reshape(N // interleave, K)
56
+ qweight_v2 = (
57
+ torch.tensor(Packed_Kernel.astype("int16"))
58
+ .to(unpacked_qweight.device)
59
+ .contiguous()
60
+ )
61
+ return qweight_v2
62
+
63
+
64
+ def multiply_scale_qzero_negative(scales, qzeros, zp_shift=-8):
65
+ pack_size = 8
66
+ k_groups = scales.shape[1]
67
+ scaled_zeros = torch.zeros_like(scales)
68
+ for group_idx in range(k_groups):
69
+ zero_idx = group_idx // pack_size
70
+ zero_offset = group_idx % pack_size
71
+ zero = qzeros[:, zero_idx] >> (4 * zero_offset) & 0x0000000F
72
+ scaled_zeros[:, group_idx] = scales[:, group_idx] * zero.to(scales.dtype)
73
+ return -(scaled_zeros + (zp_shift * scales))
74
+
75
+
76
+ def qweight_pack_v1_to_v2(qweight, interleave, kstride):
77
+ unpacked_qweight = qweight_unpack(qweight)
78
+ qweight_v2 = packing_v2_from_unpacked(unpacked_qweight, interleave, kstride)
79
+ return qweight_v2
80
+
81
+
82
+ def ckpt_check():
83
+ parser = argparse.ArgumentParser()
84
+ parser.add_argument("--input1", type=str, default="./vicuna-7b-w4-g128-awq-v2-1.pt")
85
+ parser.add_argument("--input2", type=str, default="./vicuna-7b-w4-g128-awq-v2-2.pt")
86
+ args = parser.parse_args()
87
+
88
+ model_dict1 = torch.load(args.input1)
89
+ model_dict2 = torch.load(args.input2)
90
+
91
+ keys = model_dict1.keys()
92
+ for key in keys:
93
+ param = model_dict1[key]
94
+ assert type(param) == torch.Tensor
95
+ if (
96
+ "qweight" in key
97
+ or "scales" in key
98
+ or "qzeros" in key
99
+ or "scaled_zeros" in key
100
+ ):
101
+ print("=" * 50)
102
+ print(key)
103
+ # print(model_dict1[key])
104
+ # print(model_dict2[key])
105
+ diff = torch.max(torch.abs(model_dict2[key] - model_dict1[key]))
106
+ print(diff)
107
+ assert diff < 1e-6
108
+ print("=" * 50)
109
+
110
+
111
+ def offline_repacker():
112
+ parser = argparse.ArgumentParser()
113
+ parser.add_argument("--input", type=str, default="./vicuna-7b-w4-g128-awq.pt")
114
+ parser.add_argument("--output", type=str, default="./vicuna-7b-w4-g128-awq-v2.pt")
115
+ args = parser.parse_args()
116
+
117
+ model_dict = torch.load(args.input)
118
+ model_dict_v2 = OrderedDict()
119
+
120
+ keys = model_dict.keys()
121
+ for key in keys:
122
+ param = model_dict[key]
123
+ assert type(param) == torch.Tensor
124
+ if "qweight" in key:
125
+ print("repacking:", key)
126
+ qweight = param
127
+ qweight_v2 = qweight_pack_v1_to_v2(qweight, interleave=4, kstride=64)
128
+ model_dict_v2[key] = qweight_v2
129
+ elif "scales" in key:
130
+ print("repacking:", key)
131
+ scales = param
132
+ # print(scales.shape)
133
+ scales_v2 = scales.transpose(1, 0).contiguous()
134
+ model_dict_v2[key] = scales_v2
135
+
136
+ # deal with corresponding zero points
137
+ zeros_key = key.replace("scales", "qzeros")
138
+ print("repacking:", zeros_key)
139
+
140
+ zeros_key_v2 = key.replace("scales", "scaled_zeros")
141
+ qzeros = model_dict[zeros_key]
142
+ scaled_zeros_v2 = multiply_scale_qzero_negative(scales, qzeros, zp_shift=0)
143
+ # K // G, N
144
+ scaled_zeros_v2 = scaled_zeros_v2.transpose(1, 0).contiguous()
145
+ model_dict_v2[zeros_key_v2] = scaled_zeros_v2
146
+ elif "qzeros" in key:
147
+ pass
148
+ else:
149
+ print("copying:", key)
150
+ model_dict_v2[key] = param
151
+
152
+ torch.save(model_dict_v2, args.output)
153
+
154
+
155
+ if __name__ == "__main__":
156
+ offline_repacker()
157
+ # ckpt_check()
llm-awq/tinychat/scripts/llama2_demo.sh ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MODEL_PATH=/data/llm/checkpoints/llama2-hf
2
+ MODEL_NAME=llama-2-7b-chat
3
+
4
+ # # Perform AWQ search and save search results (we already did it for you):
5
+ # mkdir -p awq_cache
6
+ # python -m awq.entry --model_path $MODEL_PATH/$MODEL_NAME \
7
+ # --w_bit 4 --q_group_size 128 \
8
+ # --run_awq --dump_awq awq_cache/llama-2-7b-chat-w4-g128.pt
9
+
10
+ # Generate real quantized weights (INT4):
11
+ mkdir -p quant_cache
12
+ python -m awq.entry --model_path $MODEL_PATH/$MODEL_NAME \
13
+ --w_bit 4 --q_group_size 128 \
14
+ --load_awq awq_cache/llama-2-7b-chat-w4-g128.pt \
15
+ --q_backend real --dump_quant quant_cache/llama-2-7b-chat-w4-g128-awq.pt
16
+
17
+ # Run the TinyChat demo:
18
+ python demo.py --model_type llama \
19
+ --model_path $MODEL_PATH/$MODEL_NAME \
20
+ --q_group_size 128 --load_quant quant_cache/llama-2-7b-chat-w4-g128-awq.pt \
21
+ --precision W4A16
22
+
23
+ # Split checkpoint into shards for mem-efficient loading:
24
+ python split_ckpt.py --input_path quant_cache/llama-2-7b-chat-w4-g128-awq.pt \
25
+ --output_path quant_cache/llama-2-7b-chat-w4-g128-awq
26
+
27
+ # Run the TinyChat demo in mem_efficient_load mode:
28
+ python demo.py --model_type llama \
29
+ --model_path $MODEL_PATH/$MODEL_NAME \
30
+ --q_group_size 128 --load_quant quant_cache/llama-2-7b-chat-w4-g128-awq \
31
+ --precision W4A16 --mem_efficient_load --flash --chunk_prefilling
llm-awq/tinychat/split_ckpt.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import torch
4
+ import argparse
5
+
6
+
7
+ def split(
8
+ ckpt_path: str,
9
+ out_folder_path: str,
10
+ ):
11
+ os.system(f"mkdir -p {out_folder_path}")
12
+ ckpt = torch.load(ckpt_path)
13
+ count = 0
14
+ for key, value in ckpt.items():
15
+ output_dict = {key: value}
16
+ output_name = out_folder_path + "/" + key + ".pt"
17
+ torch.save(output_dict, output_name)
18
+ count += 1
19
+ print(f"Finished splitting the original checkpoint into {count} shards.")
20
+
21
+
22
+ def ckpt_folder_reader(ckpt_folder_path: str):
23
+ file_list = [f for f in os.listdir(ckpt_folder_path) if f.endswith(".pt")]
24
+ for ckpt in file_list:
25
+ print(ckpt)
26
+
27
+
28
+ if __name__ == "__main__":
29
+ parser = argparse.ArgumentParser()
30
+ parser.add_argument(
31
+ "--input_path",
32
+ type=str,
33
+ default=None,
34
+ help="Path to the original checkpoint (ends with *.pt)",
35
+ )
36
+ parser.add_argument(
37
+ "--output_path",
38
+ type=str,
39
+ default=None,
40
+ help="Folder to store the splitted checkpoint shards",
41
+ )
42
+
43
+ args = parser.parse_args()
44
+ assert (
45
+ args.input_path is not None
46
+ ), "Please specify the path to the original checkpoint."
47
+ if args.output_path is None:
48
+ suffix = r"\.pt$"
49
+ args.output_path = re.sub(suffix, "", args.input_path)
50
+
51
+ split(args.input_path, args.output_path)
llm-awq/tinychat/vila15_demo.py ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+
4
+ from PIL import Image
5
+ from tqdm import tqdm
6
+
7
+ from transformers import AutoConfig, AutoTokenizer
8
+ from accelerate import load_checkpoint_and_dispatch
9
+
10
+ from tinychat.utils.tune import (
11
+ device_warmup,
12
+ tune_all_wqlinears,
13
+ tune_llava_patch_embedding,
14
+ )
15
+ from tinychat.utils.prompt_templates import (
16
+ get_prompter,
17
+ get_stop_token_ids,
18
+ get_image_token,
19
+ )
20
+ from tinychat.utils.llava_image_processing import (
21
+ process_images,
22
+ load_images,
23
+ vis_images,
24
+ )
25
+ import tinychat.utils.constants
26
+
27
+ # from tinychat.models.llava_llama import LlavaLlamaForCausalLM
28
+ from tinychat.models.vila_llama import VilaLlamaForCausalLM
29
+ from tinychat.stream_generators.llava_stream_gen import LlavaStreamGenerator
30
+ from tinychat.utils.conversation_utils import gen_params, stream_output, TimeStats
31
+
32
+ import os
33
+
34
+ os.environ["CUDA_VISIBLE_DEVICES"] = "0"
35
+
36
+
37
+ def image_parser(args):
38
+ out = args.image_file.split(args.im_sep)
39
+ return out
40
+
41
+
42
+ def skip(*args, **kwargs):
43
+ pass
44
+
45
+
46
+ def main(args):
47
+ # Accelerate model initialization
48
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
49
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
50
+ torch.nn.init.kaiming_uniform_ = skip
51
+ torch.nn.init.kaiming_normal_ = skip
52
+ torch.nn.init.uniform_ = skip
53
+ torch.nn.init.normal_ = skip
54
+
55
+ tokenizer = AutoTokenizer.from_pretrained(
56
+ os.path.join(args.model_path, "llm"), use_fast=False
57
+ )
58
+ tinychat.utils.constants.LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX = (
59
+ tokenizer.convert_tokens_to_ids(
60
+ [tinychat.utils.constants.LLAVA_DEFAULT_IMAGE_PATCH_TOKEN]
61
+ )[0]
62
+ )
63
+ config = AutoConfig.from_pretrained(args.model_path, trust_remote_code=True)
64
+ model = VilaLlamaForCausalLM(config).half()
65
+ tinychat.utils.constants.LLAVA_DEFAULT_IMAGE_PATCH_TOKEN_IDX = (
66
+ tokenizer.convert_tokens_to_ids(
67
+ [tinychat.utils.constants.LLAVA_DEFAULT_IMAGE_PATCH_TOKEN]
68
+ )[0]
69
+ )
70
+ vision_tower = model.get_vision_tower()
71
+ # if not vision_tower.is_loaded:
72
+ # vision_tower.load_model()
73
+ image_processor = vision_tower.image_processor
74
+ # vision_tower = vision_tower.half()
75
+
76
+ if args.precision == "W16A16":
77
+ pbar = tqdm(range(1))
78
+ pbar.set_description("Loading checkpoint shards")
79
+ for i in pbar:
80
+ model.llm = load_checkpoint_and_dispatch(
81
+ model.llm,
82
+ os.path.join(args.model_path, "llm"),
83
+ no_split_module_classes=[
84
+ "OPTDecoderLayer",
85
+ "LlamaDecoderLayer",
86
+ "BloomBlock",
87
+ "MPTBlock",
88
+ "DecoderLayer",
89
+ "CLIPEncoderLayer",
90
+ ],
91
+ ).to(args.device)
92
+ model = model.to(args.device)
93
+
94
+ elif args.precision == "W4A16":
95
+ from tinychat.utils.load_quant import load_awq_model
96
+
97
+ model.llm = load_awq_model(model.llm, args.quant_path, 4, 128, args.device)
98
+ from tinychat.modules import (
99
+ make_quant_norm,
100
+ make_quant_attn,
101
+ make_fused_mlp,
102
+ make_fused_vision_attn,
103
+ )
104
+
105
+ if args.flash_attn:
106
+ print("Enabling flash-attention!")
107
+ make_quant_attn(model.llm, args.device, 1)
108
+ else:
109
+ print("Disabling flash-attention!")
110
+ make_quant_attn(model.llm, args.device)
111
+ make_quant_norm(model.llm)
112
+ # make_fused_mlp(model)
113
+ # make_fused_vision_attn(model,args.device)
114
+ model = model.to(args.device)
115
+
116
+ else:
117
+ raise NotImplementedError(f"Precision {args.precision} is not supported.")
118
+
119
+ image_files = image_parser(args)
120
+ image_num = len(image_files)
121
+ images = load_images(image_files)
122
+ if args.vis_image:
123
+ print("=" * 50)
124
+ print("Input Image:")
125
+ vis_images(image_files)
126
+ # Similar operation in model_worker.py
127
+ image_tensor = process_images(images, image_processor, model.config)
128
+ if type(image_tensor) is list:
129
+ image_tensor = [
130
+ image.to(args.device, dtype=torch.float16) for image in image_tensor
131
+ ]
132
+ else:
133
+ image_tensor = image_tensor.to(args.device, dtype=torch.float16)
134
+
135
+ device_warmup(args.device)
136
+ tune_llava_patch_embedding(vision_tower, device=args.device)
137
+
138
+ stream_generator = LlavaStreamGenerator
139
+
140
+ if args.max_seq_len <= 1024:
141
+ short_prompt = True
142
+ else:
143
+ short_prompt = False
144
+ model_prompter = get_prompter(
145
+ args.model_type, args.model_path, short_prompt, args.empty_prompt
146
+ )
147
+ stop_token_ids = get_stop_token_ids(args.model_type, args.model_path)
148
+ count = 0
149
+
150
+ if args.empty_prompt:
151
+ input_indicator = "Input: "
152
+ output_indicator = "Generated: "
153
+ else:
154
+ input_indicator = "USER: "
155
+ output_indicator = "ASSISTANT: "
156
+
157
+ model.eval()
158
+ time_stats = TimeStats()
159
+ start_pos = 0
160
+ while True:
161
+ # Get input from the user
162
+ print("=" * 50)
163
+ input_prompt = input(input_indicator)
164
+ print("-" * 50)
165
+ if input_prompt == "":
166
+ print("EXIT...")
167
+ time_stats.show()
168
+ break
169
+ if count == 0: # Insert image here
170
+ image_token = get_image_token(model, args.model_path)
171
+ image_token_holder = (
172
+ tinychat.utils.constants.LLAVA_DEFAULT_IM_TOKEN_PLACE_HOLDER
173
+ )
174
+ im_token_count = input_prompt.count(image_token_holder)
175
+ if im_token_count == 0:
176
+ model_prompter.insert_prompt(image_token * image_num + input_prompt)
177
+ else:
178
+ assert im_token_count == image_num
179
+ input_prompt = input_prompt.replace(image_token_holder, image_token)
180
+ model_prompter.insert_prompt(input_prompt)
181
+ else:
182
+ model_prompter.insert_prompt(input_prompt)
183
+ if args.chunk_prefilling:
184
+ image_tensor = None # Can insert more images in future
185
+ output_stream = stream_generator(
186
+ model,
187
+ tokenizer,
188
+ model_prompter.model_input,
189
+ start_pos,
190
+ gen_params,
191
+ device=args.device,
192
+ stop_token_ids=stop_token_ids,
193
+ image_tensor=image_tensor,
194
+ chunk_prefilling=args.chunk_prefilling,
195
+ )
196
+ print(output_indicator, end="", flush=True)
197
+ if count == 0:
198
+ outputs, total_tokens = stream_output(output_stream, time_stats)
199
+ else:
200
+ outputs, total_tokens = stream_output(output_stream)
201
+ if args.chunk_prefilling:
202
+ start_pos += total_tokens
203
+ if (
204
+ args.single_round is not True and args.max_seq_len > 512
205
+ ): # Only memorize previous conversations when kv_cache_size > 512
206
+ model_prompter.update_template(outputs, args.chunk_prefilling)
207
+ count += 1
208
+
209
+
210
+ if __name__ == "__main__":
211
+ parser = argparse.ArgumentParser()
212
+ parser.add_argument(
213
+ "--model_type", type=str, default="LLaMa", help="type of the model"
214
+ )
215
+ parser.add_argument(
216
+ "--model-path", type=str, default="/data/llm/checkpoints/llava/llava-v1.5-7b"
217
+ )
218
+ parser.add_argument(
219
+ "--quant-path",
220
+ type=str,
221
+ default="/data/llm/checkpoints/llava/llava-v1.5-7b-w4-g128-awq.pt",
222
+ )
223
+ parser.add_argument(
224
+ "--precision", type=str, default="W4A16", help="compute precision"
225
+ )
226
+ parser.add_argument(
227
+ "--image-file",
228
+ type=str,
229
+ default="https://llava.hliu.cc/file=/nobackup/haotian/code/LLaVA/llava/serve/examples/extreme_ironing.jpg",
230
+ )
231
+ parser.add_argument(
232
+ "--im-sep",
233
+ type=str,
234
+ default=",",
235
+ )
236
+ parser.add_argument("--device", type=str, default="cuda")
237
+ parser.add_argument("--max_seq_len", type=int, default=2048)
238
+ parser.add_argument(
239
+ "--single_round",
240
+ action="store_true",
241
+ help="whether to memorize previous conversations",
242
+ )
243
+ parser.add_argument(
244
+ "--vis-image",
245
+ action="store_true",
246
+ help="whether to visualize the image while chatting",
247
+ )
248
+ parser.add_argument(
249
+ "--empty-prompt",
250
+ action="store_true",
251
+ help="whether to use empty prompt template",
252
+ )
253
+ parser.add_argument(
254
+ "--flash_attn",
255
+ action="store_true",
256
+ help="whether to use flash attention",
257
+ )
258
+ parser.add_argument(
259
+ "--chunk_prefilling",
260
+ action="store_true",
261
+ help="If used, in context stage, the history tokens will not be recalculated, greatly speeding up the calculation",
262
+ )
263
+ args = parser.parse_args()
264
+ main(args)