# Bitsandbytes

A biblioteca [bitsandbytes](https://github.com/bitsandbytes-foundation/bitsandbytes) fornece ferramentas de quantização para LLMs por meio de um wrapper Python leve em torno de funções de aceleradores de hardware. Ela permite trabalhar com modelos grandes usando recursos computacionais limitados, reduzindo sua pegada de memória.

No seu núcleo, o bitsandbytes fornece:

- **Camadas lineares quantizadas**: camadas `Linear8bitLt` e `Linear4bit` que substituem as camadas lineares padrão do PyTorch por alternativas quantizadas com uso eficiente de memória
- **Otimizadores otimizados**: versões de 8 bits de otimizadores comuns por meio do módulo `optim`, permitindo o treinamento de modelos grandes com requisitos de memória reduzidos
- **Multiplicação de matrizes**: Operações de multiplicação de matrizes otimizadas que aproveitam o formato quantizado

bitsandbytes oferece dois recursos principais de quantização:

1. **LLM.int8()** - Um método de quantização de 8 bits que torna a inferência mais acessível sem uma degradação significativa de desempenho. Diferentemente da quantização ingênua, o [LLM.int8()](https://hf.co/papers/2208.07339) preserva dinamicamente uma precisão maior para cálculos críticos, evitando a perda de informações em partes sensíveis do modelo.

2. **QLoRA** - Uma técnica de quantização de 4 bits que comprime os modelos ainda mais, mantendo a treinabilidade ao inserir um pequeno conjunto de pesos treináveis de adaptação de baixo rank (LoRA).

> **Observação:** Para uma experiência de quantização mais amigável, você pode usar o [espaço da comunidade](https://huggingface.co/spaces/bnb-community/bnb-my-repo) do `bitsandbytes`.

Execute o comando abaixo para instalar o bitsandbytes.

```bash
pip install --upgrade transformers accelerate bitsandbytes
```

Para compilar a partir do código-fonte, siga as instruções no [guia de instalação do bitsandbytes](https://huggingface.co/docs/bitsandbytes/main/en/installation).

## Compatibilidade de Hardware

bitsandbytes é suportado em GPUs NVIDIA para versões de CUDA 11.8 - 13.0, Intel XPU, Intel Gaudi (HPU) e CPU. Há um esforço contínuo para suportar plataformas adicionais. Se você tiver interesse em fornecer feedback ou realizar testes, confira o [repositório bitsandbytes](https://github.com/bitsandbytes-foundation/bitsandbytes) para mais informações.

### GPUs da NVIDIA (CUDA)

Este backend é suportado nas plataformas Linux x86-64, Linux aarch64 e Windows.

| Recurso | Requisito Mínimo de Hardware |
|---------|-------------------------------|
| Otimizadores de 8 bits | GPUs NVIDIA Pascal (série GTX 10X0, P100) ou mais recentes * |
| LLM.int8() | GPUs NVIDIA Turing (série RTX 20X0, T4) ou mais recentes |
| Quantização NF4/FP4 | GPUs NVIDIA Pascal (série GTX 10X0, P100) ou mais recentes * |

### GPUs da Intel (XPU)

Este backend é suportado nas plataformas Linux x86-64 e Windows x86-64.

### Intel Gaudi (HPU)

Este backend é suportado no Linux x86-64 para Gaudi2 e Gaudi3.

### CPU

Este backend é suportado nas plataformas Linux x86-64, Linux aarch64 e Windows x86-64.

## Exemplos de Quantização

Quantize um modelo passando um [BitsAndBytesConfig](/docs/transformers/main/pt/main_classes/quantization#transformers.BitsAndBytesConfig) para [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained). Isso funciona para qualquer modelo em qualquer modalidade, desde que ele suporte [Accelerate](https://huggingface.co/docs/accelerate/index) e contenha camadas [torch.nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html).

Quantizar um modelo em 8 bits reduz o uso de memória pela metade e, para modelos grandes, defina `device_map="auto"` para distribuir os pesos de forma eficiente entre todas as GPUs disponíveis.

```py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_8bit=True)

model_8bit = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-1b7", 
    device_map="auto",
    quantization_config=quantization_config
)
```

Por padrão, todos os outros módulos, como [torch.nn.LayerNorm](https://pytorch.org/docs/stable/generated/torch.nn.LayerNorm.html), são definidos para o dtype padrão do torch. Você pode alterar o tipo de dados desses módulos com o parâmetro `dtype`. Definir `dtype="auto"` carrega o modelo no tipo de dados definido no arquivo `config.json` do modelo.

```py
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_8bit=True)

model_8bit = AutoModelForCausalLM.from_pretrained(
    "facebook/opt-350m", 
    device_map="auto",
    quantization_config=quantization_config, 
    dtype="auto"
)
model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtype
```

Uma vez que um modelo é quantizado para 8 bits, você não pode enviar os pesos quantizados para o Hub, a menos que esteja usando a versão mais recente de Transformers e bitsandbytes. Se você tiver as versões mais recentes, pode enviar o modelo de 8 bits para o Hub com [push_to_hub()](/docs/transformers/main/pt/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub). O arquivo de configuração de quantização config.json é enviado primeiro, seguido pelos pesos quantizados do modelo.

```py
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-560m", 
    device_map="auto",
    quantization_config=quantization_config
)

model.push_to_hub("bloom-560m-8bit")
```

Quantizar um modelo em 4 bits reduz o uso de memória em 4x e, para modelos grandes, defina `device_map="auto"` para distribuir os pesos de forma eficiente entre todas as GPUs disponíveis.

```py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model_4bit = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-1b7",
    device_map="auto",
    quantization_config=quantization_config
)
```

Por padrão, todos os outros módulos, como [torch.nn.LayerNorm](https://pytorch.org/docs/stable/generated/torch.nn.LayerNorm.html), são convertidos para `torch.float16`. Você pode alterar o tipo de dados desses módulos com o parâmetro `dtype`. Definir `dtype="auto"` carrega o modelo no tipo de dados definido no arquivo `config.json` do modelo.

```py
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model_4bit = AutoModelForCausalLM.from_pretrained(
    "facebook/opt-350m",
    device_map="auto",
    quantization_config=quantization_config, 
    dtype="auto"
)
model_4bit.model.decoder.layers[-1].final_layer_norm.weight.dtype
```

Certifique-se de ter a versão mais recente do bitsandbytes para que você possa serializar modelos de 4 bits e enviá-los ao Hub com [push_to_hub()](/docs/transformers/main/pt/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub). Use [save_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.save_pretrained) para salvar o modelo de 4 bits localmente.

```py
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-560m", 
    device_map="auto",
    quantization_config=quantization_config
)

model.push_to_hub("bloom-560m-4bit")
```

> [!WARNING]
> O treinamento em 8 e 4 bits é suportado apenas para o treinamento de parâmetros *extra*.

Verifique a sua pegada de memória com `get_memory_footprint`.

```py
print(model.get_memory_footprint())
```

Carregue modelos quantizados com [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) sem um `quantization_config`.

```py
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")
```

## LLM.int8

Esta seção explora alguns dos recursos específicos da quantização de 8 bits, como offloading, limiares de outliers, omissão da conversão de módulos e finetuning.

### Offloading

Modelos de 8 bits podem transferir pesos entre a CPU e a GPU para caber modelos muito grandes na memória. Os pesos enviados para a CPU são armazenados em **float32** e não são convertidos para 8 bits. Por exemplo, ative o offloading para [bigscience/bloom-1b7](https://huggingface.co/bigscience/bloom-1b7) por meio de [BitsAndBytesConfig](/docs/transformers/main/pt/main_classes/quantization#transformers.BitsAndBytesConfig).

```py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)
```

Projete um mapa de dispositivos personalizado para caber tudo na sua GPU, exceto o `lm_head`, que é despachado para a CPU.

```py
device_map = {
    "transformer.word_embeddings": 0,
    "transformer.word_embeddings_layernorm": 0,
    "lm_head": "cpu",
    "transformer.h": 0,
    "transformer.ln_f": 0,
}
```

Agora, carregue seu modelo com o `device_map` e o `quantization_config` personalizados.

```py
model_8bit = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-1b7",
    dtype="auto",
    device_map=device_map,
    quantization_config=quantization_config,
)
```

### Limiar de outlier

Um "outlier" é um valor de estado oculto maior que um determinado limiar, e esses valores são calculados em fp16. Embora os valores geralmente sigam uma distribuição normal ([-3.5, 3.5]), essa distribuição pode ser muito diferente para modelos grandes ([-60, 6] ou [6, 60]). A quantização de 8 bits funciona bem para valores ~5, mas, além disso, há uma penalidade significativa de desempenho. Um bom valor de limiar padrão é 6, mas um limiar menor pode ser necessário para modelos mais instáveis (modelos pequenos ou finetuning).

Para encontrar o melhor limiar para o seu modelo, experimente com o parâmetro `llm_int8_threshold` em [BitsAndBytesConfig](/docs/transformers/main/pt/main_classes/quantization#transformers.BitsAndBytesConfig). Por exemplo, definir o limiar como `0.0` acelera significativamente a inferência, com o possível custo de alguma perda de precisão.

```py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

model_id = "bigscience/bloom-1b7"

quantization_config = BitsAndBytesConfig(
    llm_int8_threshold=0.0,
    llm_int8_enable_fp32_cpu_offload=True
)

model_8bit = AutoModelForCausalLM.from_pretrained(
    model_id,
    dtype="auto",
    device_map=device_map,
    quantization_config=quantization_config,
)
```

### Pular a conversão de módulos

Para alguns modelos, como o Jukebox, não é necessário quantizar todos os módulos para 8 bits, pois isso pode causar instabilidade. No Jukebox, há vários módulos `lm_head` que devem ser ignorados usando o parâmetro `llm_int8_skip_modules` em [BitsAndBytesConfig](/docs/transformers/main/pt/main_classes/quantization#transformers.BitsAndBytesConfig).

```py
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

model_id = "bigscience/bloom-1b7"

quantization_config = BitsAndBytesConfig(
    llm_int8_skip_modules=["lm_head"],
)

model_8bit = AutoModelForCausalLM.from_pretrained(
    model_id,
    dtype="auto",
    device_map="auto",
    quantization_config=quantization_config,
)
```

### Ajuste fino

A biblioteca [PEFT](https://github.com/huggingface/peft) suporta o ajuste fino de modelos grandes como [flan-t5-large](https://huggingface.co/google/flan-t5-large) e [facebook/opt-6.7b](https://huggingface.co/facebook/opt-6.7b) com quantização de 8 bits. Você não precisa passar o parâmetro `device_map` para o treinamento, pois ele carrega automaticamente seu modelo em uma GPU. No entanto, você ainda pode personalizar o mapa de dispositivos com o parâmetro `device_map` (`device_map="auto"` deve ser usado apenas para inferência).

## QLoRA

Esta seção explora alguns dos recursos específicos da quantização de 4 bits, como a alteração do tipo de dados de computação, o tipo de dados Normal Float 4 (NF4) e a quantização aninhada.

### Tipo de dados de computação

Alterne o tipo de dados de float32 (o valor padrão) para bf16 em [BitsAndBytesConfig](/docs/transformers/main/pt/main_classes/quantization#transformers.BitsAndBytesConfig) para acelerar o cálculo.

```py
import torch
from transformers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
```

### Float 4 Normal (NF4)

NF4 é um tipo de dados de 4 bits do paper [QLoRA](https://hf.co/papers/2305.14314), adaptado para pesos inicializados a partir de uma distribuição normal. Você deve usar NF4 para treinar modelos base de 4 bits.

```py
from transformers import BitsAndBytesConfig

nf4_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, dtype="auto", quantization_config=nf4_config)
```

Para inferência, o `bnb_4bit_quant_type` não tem um grande impacto no desempenho. No entanto, para manter a consistência com os pesos do modelo, você deve usar os valores de `bnb_4bit_compute_dtype` e `dtype`.

### Quantização aninhada

A quantização aninhada pode economizar memória adicional sem custo de desempenho extra. Esse recurso realiza uma segunda quantização dos pesos já quantizados para economizar mais 0,4 bits/parâmetro. Por exemplo, com a quantização aninhada, é possível fazer o ajuste fino de um modelo [Llama-13b](https://huggingface.co/meta-llama/Llama-2-13b) em uma GPU NVIDIA T4 de 16GB com comprimento de sequência de 1024, tamanho de lote de 1 e acúmulo de gradiente habilitado com 4 etapas.

```py
from transformers import BitsAndBytesConfig

double_quant_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

model_double_quant = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-13b-chat-hf", dtype="auto", quantization_config=double_quant_config)
```

## Desquantizar modelos bitsandbytes

Uma vez quantizado, você pode [dequantize()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.dequantize) um modelo para a precisão original, mas isso pode resultar em alguma perda de qualidade. Certifique-se de ter memória de GPU suficiente para acomodar o modelo dequantizado.

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

model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m", BitsAndBytesConfig(load_in_4bit=True))
model.dequantize()
```

## Recursos

Saiba mais sobre os detalhes da quantização de 8 bits em [A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes](https://huggingface.co/blog/hf-bitsandbytes-integration).

Experimente a quantização de 4 bits neste [notebook](https://colab.research.google.com/drive/1ge2F1QSK8Q7h0hn3YKuBCOAS0bK8E0wf) e saiba mais sobre os detalhes em [Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA](https://huggingface.co/blog/4bit-transformers-bitsandbytes).

