Transformers documentation

compressed-tensors

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

compressed-tensors

يمدّد compressed-tensors ملفات safetensors بأنواع بيانات المصفوفات المضغوطة، ليوفّر صيغة نقطة تفتيش موحّدة لتخزين وتحميل صيغ التكميم المختلفة، مثل: الكثيف (dense)، والمكمّم بالأعداد الصحيحة (int8)، والمكمّم بالأعداد العشرية (fp8)، والمكمّم المُجمّع (int4 أو int8 مكمّم الأوزان ومُجمّع داخل int32).

يدعم compressed-tensors الضبط الدقيق باستخدام PEFT، كما يتضمن الميزات التالية.

  • دقة الأوزان والتفعيلات fp8 وint4 وint8.
  • استراتيجيات مقاييس التكميم ونقاط الصفر لـ المصفوفة، القناة، المجموعة، الكتلة، الرمز.
  • كمّية تنشيط ديناميكية لكل رمز (أو أي استراتيجية ثابتة).
  • كمّية وحدات اختيارية، وليس فقط وحدات nn.Linear.
  • دعم مخصص لوحدات محددة بالاسم أو بالفئة.

قم بتثبيت compressed-tensors من PyPI للحصول على أحدث إصدار مستقر (موصى به)، أو ثبّته من المصدر للحصول على أحدث الميزات.

PyPI
مصدر الكود
pip install compressed-tensors

ابحث باستخدام وسم compressed-tensors للعثور على نموذج متوافق على Hugging Face Hub.

يمكن تحميل النماذج المُكمّاة مسبقًا مباشرةً. ولتكميم نموذج إلى صيغة compressed-tensors، راجع llm-compressor. وبديلًا عن ذلك، يمكن إنشاء النماذج بشكل مستقل ثم تسلسلها مع إعداد compressed-tensors.

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

أوضاع التحميل

تُخزّن نقطة تفتيش compressed-tensors أوزانها مضغوطة (fp8، أو int4/int8 مُجمّعة). أما كيفية تنفيذها فتعتمد على حجّتين من CompressedTensorsConfig.

الإعدادالأوزان بعد التحميلالتنفيذ
افتراضيمضغوط على اليساريملك compressed-tensors الطبقات ويفك ضغط النموذج في أول تمريرة أمامية
dequantize=Trueتُفكّك إلى نوع البيانات الخاص بالنموذج (مثل BF16)عمليات ضرب المصفوفات الكثيفة العادية، ويمكن ضبط النموذج أو حفظه في ذلك النوع
use_optimized_inference=Trueبقي مُكمّطالطبقات التي يمرّ نواة (kernel) عبر مخططها، وهي حالياً W8A8 fp8؛ للاستدلال فقط

تسريع نواة FP8

مرّر use_optimized_inference=True للحفاظ على نموذج compressed-tensors المضغوط بصيغة FP8 في صيغة FP8، وتنفيذ عمليات ضرب المصفوفات (matmuls) الخاصة به عبر نوى FP8 المعززة بالعتاد (torch.nn.functional.scaled_mm، والتي تُوجَّه إلى torch._scaled_mm_v2؛ بينما تعود إصدارات torch الأقدم إلى torch._scaled_mm)، بدلاً من إلغاء تكميم الأوزان وإعادتها إلى BF16. إن إبقاء الأوزان بصيغة FP8 طوال عملية الاستدلال يقلل من استهلاك الذاكرة ويسرّع الحسابات. هذا الخيار مخصص للاستدلال فقط، لذا اتركه معطلاً عند إجراء الضبط الدقيق (fine-tuning).

الجهازالنواةملاحظات
Intel XPUtorch.nn.functional.scaled_mmجميع أجهزة XPU التي تدعم FP8
NVIDIA CUDA (SM89+)torch.nn.functional.scaled_mmآدا لوفليس (L4، L40)، هوبر (H100)، بلاكويل والأحدث
شريحة Apple (MPS)torch.nn.functional.scaled_mmيتطلب torch >= 2.15
CPU / CUDA SM80 (A100) / MPS مع torch < 2.15بديليتم تجاهل use_optimized_inference=True، ويعمل النموذج دون فك التكميم

يدعم مسار نواة FP8 تخطيطات التكميم التالية.

الاستراتيجيةنموذج مثال
ديناميكي لكل قناةRedHatAI/Meta-Llama-3.1-8B-Instruct-FP8-dynamic
ثابت لكل مشغّلRedHatAI/Meta-Llama-3.1-8B-Instruct-FP8

تحميل نموذج FP8 مُكمَّم مسبقًا

نوى FP8 اختيارية: اطلبها باستخدام use_optimized_inference=True، وتُستخدم عندما يحدد تكوين النموذج تكميم FP8 ويتوفر معالج رسومي مدعوم.

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))

إلغاء التكميم عند التحميل

بدون use_optimized_inference=True، يتبع النموذج المسار المعتاد لـ compressed-tensors: تبقى الأوزان مضغوطة، ثم يقوم compressed-tensors بفك ضغطها في أول تمريرة أمامية. مرّر dequantize=True لفك تكميمها أثناء التحميل بدلاً من ذلك، وهو ما تحتاجه إذا كنت تريد ضبط النموذج بدقة أو حفظه بدقة الأصلية (مثل BF16).

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",
)

نقطة تفتيش النموذج

تُعرَّف نماذج compressed-tensor عبر مدخلات إعداداتها. المثال التالي مأخوذ من ملف config.json الخاص بـ nm-testing/Meta-Llama-3.1-8B-Instruct-FP8-hf.

توجد العديد من الإدخالات للسماح بالتعبير المرن أثناء الضغط وبعده، لكن يمكن تبسيط الإدخالات الخاصة بالتحميل والاستدلال للتركيز على عدد قليل من الإدخالات الرئيسية فقط.

"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"
},

يحدد ملف الإعدادات التكميم لمجموعة الإعدادات (group_0)، والتي تتضمن تكميم الأوزان والتفعيلات إلى fp8 باستخدام استراتيجية ثابتة لكل متجه. كما أن وحدة lm_head غير مُكمَّمة كما هو موضح في المفتاح ignore.

للنظر في أوزان النموذج بشكل أكثر تفصيلاً، استخدم safetensors viewer في بطاقة النموذج لعرض الأوزان المُكمّمة، ومقياس الإدخال، ومقياس الوزن لجميع وحدات nn.Linear.

المصفوفاتالشكلالدقة
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

عند تحميل نموذج compressed-tensors باستخدام تكامل ~quantizers.HFQuantizer، تُسلَّم الوحدات المستهدفة إلى compressed-tensors: حيث يربط مخطط التكميم المُحلَّلة quantization_scheme، ويضبط quantization_status، ويسجّل المعاملات التي يخزّنها نقطة التفتيش (weight بصيغة fp8، بالإضافة إلى weight_scale و، في حالة استخدام استراتيجية ثابتة، input_scale)، ويثبّت مسارًا أماميًا خاصًا به فوقها. تبقى هذه الوحدات كائنات من nn.Linear، لذا هذا ما يعرضه print — فإصدارات compressed-tensors الحديثة لم تعد تغلّفها في فئة فرعية من CompressedLinear. أما الوحدات المدرجة تحت ignore، مثل lm_head، فتُترك دون أي تعديل.

عند استخدام dequantize=False (القيمة الافتراضية)، تبقى الأوزان مضغوطة بعد اكتمال التحميل، ويقوم compressed-tensors بفك ضغط النموذج بالكامل في أول تمريرة أمامية. أما dequantize=True فيقوم بذلك أثناء التحميل، فلا تكون هناك حاجة إلى تمريرة أمامية للحصول على أوزان كثيفة.

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

عند استخدام use_optimized_inference=True، تُستبدل الطبقات المشمولة بمجموعة إعدادات fp8 بـ CompressedTensorsFP8Linear، الذي يحتفظ بوزن fp8 ومقياسه في الترتيب الذي يتوقعه نواة ضرب المصفوفات الصفية. وتبقى هذه الأوزان في fp8، بما في ذلك عمليات المرور الأمامي.

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
Update on GitHub