# compressed-tensors

[compressed-tensors](https://github.com/neuralmagic/compressed-tensors) mở rộng các tệp [safetensors](https://github.com/huggingface/safetensors) sang các kiểu dữ liệu tensor nén để cung cấp một định dạng checkpoint thống nhất cho việc lưu trữ và nạp các định dạng lượng tử hóa khác nhau như dense, int-quantized (int8), float-quantized (fp8), và pack-quantized (int4 hoặc int8 weight-quantized được đóng gói vào int32).

compressed-tensors hỗ trợ fine-tuning với [PEFT](https://huggingface.co/docs/peft) và bao gồm các tính năng sau.

- độ chính xác trọng số và kích hoạt fp8, int4, int8.
- Các chiến lược về thang lượng tử hóa và điểm không cho [tensor, kênh, nhóm, khối, token](https://github.com/neuralmagic/compressed-tensors/blob/83b2e7a969d70606421a76b9a3d112646077c8de/src/compressed_tensors/quantization/quant_args.py#L43-L52).
- Lượng tử hóa kích hoạt động theo từng token (hoặc bất kỳ chiến lược tĩnh nào).
- Lượng tử hóa các module tùy ý, không chỉ giới hạn ở các module [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html).
- Hỗ trợ có mục tiêu cho các module cụ thể theo tên hoặc lớp.

Cài đặt compressed-tensors từ [PyPI](https://pypi.org/project/compressed-tensors) để có bản phát hành ổn định mới nhất (khuyến nghị) hoặc cài đặt từ mã nguồn để có các tính năng mới nhất.

```bash
pip install compressed-tensors
```

```bash
git clone https://github.com/neuralmagic/compressed-tensors
cd compressed-tensors
pip install -e .
```

Tìm kiếm bằng thẻ [compressed-tensors](https://huggingface.co/models?other=compressed-tensors) để tìm một mô hình tương thích trên Hugging Face Hub.

Các mô hình đã được lượng tử hóa trước có thể được tải trực tiếp. Để lượng tử hóa một mô hình sang định dạng compressed-tensors, hãy xem [llm-compressor](https://github.com/vllm-project/llm-compressor). Ngoài ra, các mô hình có thể được tạo độc lập và được serialize với một cấu hình compressed-tensors.

```python
from transformers import AutoModelForCausalLM

ct_model = AutoModelForCausalLM.from_pretrained("nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf", device_map="auto")

# measure memory usage
mem_params = sum([param.nelement()*param.element_size() for param in ct_model.parameters()])
print(f"{mem_params/2**30:.4f} GB")
# 8.4575 GB
```

## Các chế độ tải

Checkpoint của compressed-tensors lưu trữ trọng số ở dạng nén (fp8, hoặc int4/int8 đã đóng gói). Cách chúng được thực thi phụ thuộc vào hai đối số của [CompressedTensorsConfig](/docs/transformers/main/vi/main_classes/quantization#transformers.CompressedTensorsConfig).

| Cấu hình | Trọng số sau khi tải | Thực thi |
|---------------|-----------------------|-----------|
| default | được lưu ở định dạng compressed-tensors: mọi tensor được serialize (`weight_packed`, `weight_scale`, `weight_zero_point`, ...) đều được nạp đúng như cách lưu trữ | compressed-tensors sở hữu các lớp và giải nén mô hình trong lần truyền tiến đầu tiên |
| `dequantize=True` | được giải nén khi nạp vào kiểu dữ liệu của mô hình (ví dụ: BF16) | một mô hình dense thông thường không còn `quantization_scheme`, do đó các activation w8a8 cũng không được lượng tử hóa; nó có thể được fine-tune hoặc lưu trữ ở dtype đó |
| `use_optimized_inference=True` | được giữ ở dạng lượng tử hóa | các lớp có sơ đồ mà một kernel chạy xuyên qua, hiện tại là W8A8 fp8; chỉ dành cho suy luận |

Với cài đặt mặc định, [save_pretrained()](/docs/transformers/main/vi/main_classes/model#transformers.PreTrainedModel.save_pretrained) ghi các tensor nén trở lại mà không thay đổi, do đó một model đã được nạp sẽ được lưu ở định dạng compressed-tensors tương tự.

## Tăng tốc kernel FP8

Truyền `use_optimized_inference=True` để giữ mô hình compressed-tensors nén FP8 ở định dạng FP8 và chạy các phép nhân ma trận của nó thông qua các kernel FP8 được tăng tốc bằng phần cứng ([torch.nn.functional.scaled_mm](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_mm.html), điều phối đến `torch._scaled_mm_v2`; các phiên bản torch cũ hơn sẽ dùng phương án dự phòng `torch._scaled_mm`), thay vì khử lượng hóa trọng số trở lại BF16. Việc giữ trọng số ở FP8 trong suốt quá trình suy luận giúp giảm mức sử dụng bộ nhớ và tăng tốc độ tính toán. Tính năng này chỉ dành cho suy luận, vì vậy hãy tắt nó đi khi tinh chỉnh (fine-tune).

| Thiết bị | Kernel | Ghi chú |
|--------|--------|-------|
| Intel XPU | `torch.nn.functional.scaled_mm` | Tất cả các thiết bị XPU hỗ trợ FP8 |
| NVIDIA CUDA (SM89+) | `torch.nn.functional.scaled_mm` | Ada Lovelace (L4, L40), Hopper (H100), Blackwell và các thế hệ mới hơn |
| Apple silicon (MPS) | `torch.nn.functional.scaled_mm` | Yêu cầu torch >= 2.15 |
| CPU / CUDA SM80 (A100) / MPS với torch < 2.15 | Dự phòng | `use_optimized_inference=True` bị bỏ qua, mô hình chạy ở chế độ khử lượng tử hóa |

Lộ trình kernel FP8 hỗ trợ các bố cục lượng tử hóa sau.

| Chiến lược | Mô hình ví dụ |
|----------|---------------|
| Động theo kênh | [RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic](https://huggingface.co/RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic) |
| Tĩnh cho từng tensor | [RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8](https://huggingface.co/RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8) |

### Tải một mô hình FP8 đã lượng tử hóa

Các kernel FP8 là tùy chọn: yêu cầu chúng bằng `use_optimized_inference=True`, và chúng sẽ được sử dụng khi cấu hình của mô hình chỉ định lượng hóa FP8 và có sẵn GPU được hỗ trợ.

```python
from transformers import AutoModelForCausalLM, AutoTokenizer, CompressedTensorsConfig

model = AutoModelForCausalLM.from_pretrained(
    "RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic",
    quantization_config=CompressedTensorsConfig(use_optimized_inference=True),
    device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic")
inputs = tokenizer("Hello, how are you?", return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
```

### Khử lượng tử hóa khi tải

Nếu không có `use_optimized_inference=True`, mô hình sẽ đi theo đường dẫn compressed-tensors thông thường: các trọng số được giữ ở dạng nén và compressed-tensors sẽ giải nén chúng trong lần truyền tiến đầu tiên. Truyền `dequantize=True` để giải nén chúng trong quá trình tải, đây là điều bạn muốn khi tinh chỉnh mô hình hoặc lưu trữ nó ở độ chính xác gốc (ví dụ: BF16). Kết quả là một mô hình dense thông thường: không có lược đồ compressed-tensors nào được gắn kèm, do đó lượng tử hóa kích hoạt (ví dụ: w8a8) cũng bị loại bỏ.

```python
from transformers import AutoModelForCausalLM, CompressedTensorsConfig

model = AutoModelForCausalLM.from_pretrained(
    "RedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic",
    quantization_config=CompressedTensorsConfig(dequantize=True),
    device_map="auto",
)
```

## Điểm kiểm tra của mô hình

Mô hình compressed-tensor được định nghĩa thông qua mục cấu hình của nó. Ví dụ dưới đây được lấy từ tệp `config.json` của [nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf](https://huggingface.co/nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf/blob/main/config.json).

Có rất nhiều mục để cho phép biểu đạt linh hoạt cả trong và sau quá trình nén, nhưng các mục cho việc tải và suy luận có thể được đơn giản hóa để tập trung vào một vài mục chính.

```json
"quantization_config": {
  "config_groups": {
    "group_0": {
      "input_activations": {
        "num_bits": 8,
        "strategy": "tensor",
        "type": "float"
      },
      "targets": ["Linear"],
      "weights": {
        "num_bits": 8,
        "strategy": "tensor",
        "type": "float"
      }
    }
  },
  "format": "naive-quantized",
  "ignore": ["lm_head"],
  "quant_method": "compressed-tensors",
  "quantization_status": "frozen"
},
```

Tệp cấu hình xác định lượng tử hóa của một nhóm cấu hình (`group_0`), bao gồm lượng tử hóa trọng số và kích hoạt sang fp8 với chiến lược tĩnh trên mỗi tensor. Module `lm_head` không được lượng tử hóa như thể hiện trong khóa `ignore`.

Để xem chi tiết hơn về trọng số của mô hình, hãy sử dụng [safetensors viewer](https://huggingface.co/nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf?show_file_info=model.safetensors.index.json) trên thẻ mô hình để xem trọng số đã lượng tử hóa, thang đo đầu vào và thang đo trọng số cho tất cả các module [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html).

| Tensors | Hình dạng | Độ chính xác |
| ------- | ----- | --------- |
|model.layers.0.input_layernorm.weight | [4 096] | BF16|
|model.layers.0.mlp.down_proj.input_scale | [1] | BF16|
|model.layers.0.mlp.down_proj.weight | [4 096, 14 336] | F8_E4M3|
|model.layers.0.mlp.down_proj.weight_scale | [1] | BF16|
|model.layers.0.mlp.gate_proj.input_scale | [1] | BF16|
|model.layers.0.mlp.gate_proj.weight | [14 336, 4 096] | F8_E4M3|
|model.layers.0.mlp.gate_proj.weight_scale | [1] | BF16|
|model.layers.0.mlp.up_proj.input_scale| [1] |BF16|
|model.layers.0.mlp.up_proj.weight | [14 336, 4 096] | F8_E4M3|
|model.layers.0.mlp.up_proj.weight_scale | [1] | BF16|
|model.layers.0.post_attention_layernorm.weight | [4 096] |BF16|
|model.layers.0.self_attn.k_proj.input_scale | [1] |  BF16|
|model.layers.0.self_attn.k_proj.weight | [1 024, 4 096]| F8_E4M3|
|model.layers.0.self_attn.k_proj.weight_scale |[1] | BF16|
|model.layers.0.self_attn.o_proj.input_scale | [1] | BF16|
|model.layers.0.self_attn.o_proj.weight | [4 096, 4 096] | F8_E4M3|
|model.layers.0.self_attn.o_proj.weight_scale | [1] | BF16|
|model.layers.0.self_attn.q_proj.input_scale | [1] | BF16|
|model.layers.0.self_attn.q_proj.weight | [4 096, 4 096] | F8_E4M3|
|model.layers.0.self_attn.q_proj.weight_scale | [1] | BF16|
|model.layers.0.self_attn.v_proj.input_scale | [1] | BF16|
|model.layers.0.self_attn.v_proj.weight | [1 024, 4 096] | F8_E4M3|
|model.layers.0.self_attn.v_proj.weight_scale | [1] | BF16|

Khi nạp một mô hình compressed-tensors với tích hợp `~quantizers.HFQuantizer`, các module đích được chuyển giao cho compressed-tensors: nó gắn `quantization_scheme` đã được giải quyết, đặt `quantization_status`, đăng ký các tham số mà checkpoint lưu trữ (`weight` ở fp8, cùng với `weight_scale` và, đối với chiến lược tĩnh, `input_scale`) và cài đặt quá trình forward riêng của nó lên chúng. Chúng vẫn là các instance [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html), vì vậy đó là những gì `print` hiển thị — các phiên bản compressed-tensors gần đây không còn bọc chúng trong lớp con `CompressedLinear` nữa. Các module được liệt kê dưới `ignore`, chẳng hạn như `lm_head`, được giữ nguyên không thay đổi.

Với `dequantize=False` (mặc định), các trọng số vẫn được nén sau khi quá trình tải hoàn tất, và compressed-tensors sẽ giải nén toàn bộ mô hình ở bước forward đầu tiên. `dequantize=True` sẽ giải nén từng trọng số trong khi tải, do đó không cần bước forward để có được các trọng số dense, và các module sẽ là các lớp dense thuần túy không có `quantization_scheme`.

```python
import torch
from transformers import AutoModelForCausalLM, CompressedTensorsConfig

model_id = "nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf"

ct_model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=CompressedTensorsConfig(dequantize=False),
    device_map="auto",
)
q_proj = ct_model.model.layers[0].self_attn.q_proj
print(q_proj, q_proj.quantization_status)
# Linear(in_features=4096, out_features=4096, bias=False) QuantizationStatus.COMPRESSED
# ^ compressed-tensors module: fp8 weight, weight_scale, and its own forward

ct_model(input_ids=torch.tensor([[0, 1, 2]], device=ct_model.device))
print(q_proj, q_proj.quantization_status)
# Linear(in_features=4096, out_features=4096, bias=False) QuantizationStatus.DECOMPRESSED
# ^ weight is BF16 now, decompressed by that forward pass

ct_model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=CompressedTensorsConfig(dequantize=True),
    device_map="auto",
)
print(ct_model.model.layers[0].self_attn.q_proj)
# Linear(in_features=4096, out_features=4096, bias=False)      weight: BF16
```

Với `use_optimized_inference=True`, các lớp được bao phủ bởi một nhóm cấu hình fp8 sẽ được thay thế bằng `CompressedTensorsFP8Linear`, thành phần này lưu trữ trọng số fp8 cùng với hệ số tỷ lệ của nó theo bố trí mà nhân matmul theo hàng của nó yêu cầu. Các trọng số đó vẫn ở dạng fp8, kể cả trong các lần truyền tiến.

```python
from transformers import AutoModelForCausalLM, CompressedTensorsConfig

ct_model = AutoModelForCausalLM.from_pretrained(
    "nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf",
    quantization_config=CompressedTensorsConfig(use_optimized_inference=True),
    device_map="auto",
)
print(ct_model.model.layers[0].self_attn.q_proj)
# CompressedTensorsFP8Linear(in_features=4096, out_features=4096, bias=False)      weight: F8_E4M3
```

