บีบ LLM ให้รันได้บนเครื่องเรา: ลอง Quantization ดูกัน!
ช่วงนี้ใครๆ ก็พูดถึง LLM กันเนอะ ไม่ว่าจะเป็น ChatGPT, Llama, หรือ Mistral แต่ปัญหามันคือ โมเดลพวกนี้ โคตรกินแรม เลยเว้ย! คือบางทีจะลองเล่นแค่ 7B (7 พันล้านพารามิเตอร์) บนเครื่องบ้านๆ ก็แทบจะไหม้ละ ถ้าไม่ได้มีการ์ดจอเทพๆ หรือแรมเยอะๆ นี่คือจบเห่เลยอะ แล้วจะทำไงดีล่ะให้เราสามารถลองเล่น LLM บนเครื่องตัวเองได้แบบไม่กระตุก หรือไม่ต้องไปเช่า GPU แพงๆ?
คำตอบนึงที่ช่วยได้เยอะเลยคือ Quantization ครับพี่น้อง!
Quantization คืออะไรวะ?
หลักการง่ายๆ ของ Quantization คือการลดความละเอียดของตัวเลขในโมเดลครับ ปกติโมเดล AI ส่วนใหญ่ โดยเฉพาะพวก Deep Learning เนี่ย มันจะใช้เลขทศนิยมแบบ 32-bit (FP32) ในการคำนวณและเก็บค่าพารามิเตอร์ ซึ่งแม่นยำสูงมาก แต่ก็กินพื้นที่เยอะไง
ทีนี้ Quantization ก็คือการ บีบอัด เลขพวกนี้ให้ใช้บิตน้อยลง เช่น จาก FP32 ให้เหลือแค่ 8-bit (INT8) หรือแม้กระทั่ง 4-bit (NF4, FP4) ไปเลยดิ! แน่นอนว่าการลดความละเอียดลงมันอาจจะทำให้ความแม่นยำของโมเดลลดลงไปบ้างนะ แต่สำหรับ LLM หลายๆ ตัวในปัจจุบัน คือมันแทบไม่ต่างเลยเว้ยกับการรันแบบเต็มๆ ที่ FP32 แต่สิ่งที่เราได้มาคือ
- ประหยัด RAM: ตัวโมเดลเล็กลง กินแรมน้อยลงเยอะมาก!
- เร็วขึ้น: การคำนวณด้วยเลขบิตน้อยๆ มันก็เร็วกว่านิดหน่อยอะนะ
สุดยอดปะล่ะ!
มาลอง Quantization กับ Hugging Face Transformers กัน
โอเค! เกริ่นมาเยอะละ มาลองดูโค้ดกันเลยดีกว่าว่ามันทำยังไง เราจะใช้ไลบรารี bitsandbytes เข้ามาช่วย ซึ่งมันจะทำงานร่วมกับ Hugging Face Transformers ได้เนียนมากๆ เลย
เตรียมของก่อน
อันดับแรกเลยคือ ติดตั้งไลบรารีที่จำเป็นก่อนนะ ถ้าใครยังไม่มีก็ pip install โลด:
pip install transformers accelerate bitsandbytes torch
transformers: หัวใจหลักในการโหลดโมเดล LLMaccelerate: ช่วยจัดการเรื่องการรันโมเดลบน GPU ได้ดีขึ้นbitsandbytes: ตัวช่วยในการทำ Quantization ของจริงtorch: แบ็คเอนด์ของ Hugging Face
โค้ดตัวอย่าง
เราจะมาลองโหลดโมเดล Mistral-7B-v0.1 แบบ 4-bit Quantization ดูนะ โมเดลนี้ฟรีและค่อนข้างยอดนิยม
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
# 1. กำหนดค่า Quantization
# เราจะใช้ NF4 (NormalFloat 4-bit) ซึ่งเหมาะกับ Weight ของ Neural Network
# bnb_4bit_compute_dtype: เลือก dtype ที่ใช้ในการคำนวณ (bf16 หรือ fp16)
# ถ้าการ์ดจอรองรับ BF16 แนะนำใช้ตัวนี้เลย (NVIDIA Ampere ขึ้นไป)
# bnb_4bit_quant_type: กำหนดประเภทของ Quantization 'nf4' หรือ 'fp4'
# nf4 มักให้ผลดีกว่าเล็กน้อย
# bnb_4bit_use_double_quant: ช่วยบีบอัดเพิ่มเติมอีกนิดหน่อย
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16, # หรือ torch.float16 ถ้าไม่รองรับ bf16
bnb_4bit_use_double_quant=True,
)
# 2. กำหนดชื่อโมเดล
model_id = "mistralai/Mistral-7B-v0.1" # หรือโมเดลอื่นๆ ที่รองรับ
# 3. โหลด Tokenizer
print("กำลังโหลด Tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(model_id)
print("โหลด Tokenizer สำเร็จ!")
# 4. โหลดโมเดลพร้อม Quantization
print(f"กำลังโหลดโมเดล {model_id} แบบ 4-bit Quantization...")
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=bnb_config,
torch_dtype=torch.bfloat16, # ใช้ dtype เดียวกับการคำนวณ
device_map="auto", # ให้ Hugging Face จัดการการวางโมเดลบน GPU/CPU เอง
)
print("โหลดโมเดลสำเร็จ!")
# 5. ทดสอบการ Generate ข้อความ
# ลองถามคำถามง่ายๆ ดู
prompt = "Write a short poem about AI in 4 lines."
input_ids = tokenizer.encode(prompt, return_tensors="pt").to(model.device)
print(f"\nคำถาม: {prompt}")
print("กำลัง Generate คำตอบ...")
# generate_ids = model.generate(input_ids, max_new_tokens=50, do_sample=True, top_k=50, top_p=0.95)
# เพิ่มพารามิเตอร์เพื่อให้ผลลัพธ์น่าสนใจขึ้น
generate_ids = model.generate(
input_ids,
max_new_tokens=50, # จำนวนโทเค็นใหม่สูงสุดที่จะสร้าง
do_sample=True, # เปิดใช้งานการสุ่ม (สร้างคำตอบที่ไม่ใช่แค่ทางเลือกเดียว)
temperature=0.7, # ควบคุมความ 'สุ่ม' ของผลลัพธ์ (ค่าน้อย = สุ่มน้อย, ค่ามาก = สุ่มมาก)
top_k=50, # เลือกจาก K โทเค็นที่มีความน่าจะเป็นสูงสุด
top_p=0.95, # เลือกจากโทเค็นที่รวมกันแล้วมีความน่าจะเป็น P (ตัดส่วนหางที่ไม่ค่อยน่าจะเป็นออก)
eos_token_id=tokenizer.eos_token_id # หยุดเมื่อเจอ end-of-sequence token
)
response = tokenizer.decode(generate_ids[0], skip_special_tokens=True)
print(f"\nคำตอบ:\n{response}")
# เช็คว่าโมเดลโหลดมาแบบ Quantized จริงๆ มั้ย
print("\n--- ข้อมูลโมเดล ---")
print(f"Memory footprint: {model.get_memory_footprint() / (1024**3):.2f} GB")
print(f"Device: {model.device}")
# ลองเช็คประเภทของ Layer บาง Layer
# print(model.model.layers[0].self_attn.q_proj)
สิ่งที่ควรสังเกต:
load_in_4bit=True: นี่คือตัวหลักที่บอกให้bitsandbytesทำการโหลดโมเดลแบบ 4-bit นะbnb_4bit_compute_dtype: สำคัญมาก! คือเวลาโหลดโมเดลแบบ 4-bit มาแล้วเนี่ย ตอนคำนวณจริงๆ มันจะยังต้องมีการแปลงกลับไปเป็นfloat16หรือbfloat16ชั่วคราวเพื่อให้ GPU ทำงานได้ ลองเช็คดูว่าการ์ดจอเรา (ถ้าใช้ NVIDIA) รองรับbfloat16(Ampere Architecture ขึ้นไป เช่น RTX 30xx, 40xx) มั้ย ถ้าไม่รองรับก็ใช้torch.float16แทนนะdevice_map="auto": ให้Hugging Faceจัดการแบ่งส่วนโมเดลไปวางบน GPU หรือ CPU (ถ้า GPU แรมไม่พอ) อัตโนมัติเลย สะดวกมากๆ
เจอ Error แบบนี้ทำไงดี?
เคยเจอ Error แบบนี้บ่อยๆ ตอนที่ไม่ได้เตรียม environment ดีๆ:
CUDA_SETUP: WARNING: missing LD_LIBRARY_PATH.
...some more errors...
FileNotFoundError: libbitsandbytes_cudaXX.so
อันนี้คือ bitsandbytes มันหาไฟล์ไลบรารีของ CUDA ไม่เจอไง (ถ้าคุณพยายามจะรันบน GPU นะ) วิธีแก้คือ
- เช็ค CUDA Toolkit: ตรวจสอบว่าคุณติดตั้ง CUDA Toolkit เวอร์ชั่นที่เข้ากันได้กับการ์ดจอและ PyTorch ของคุณหรือเปล่า
- Environment Variables: ตรวจสอบ
LD_LIBRARY_PATH(Linux) หรือPATH(Windows) ว่าชี้ไปที่binและlibของ CUDA Toolkit ถูกต้องมั้ย บางทีก็ต้องexport LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATHอะไรแบบนั้น - Reinstall
bitsandbytes: บางทีก็ต้องลบแล้วลงใหม่ โดยระบุเวอร์ชั่นของ CUDA ด้วย เช่นpip install bitsandbytes==0.41.1 --extra-index-url https://download.pytorch.org/whl/cu118(ถ้าใช้ CUDA 11.8)
อีกอันที่เจอคือ:
KeyError: 'quantization_config'
อันนี้อาจจะเกิดจากเวอร์ชั่นของ transformers หรือ bitsandbytes มันเก่าเกินไป ไม่รองรับฟีเจอร์ Quantization แบบใหม่ๆ ก็ลอง pip install --upgrade transformers accelerate bitsandbytes ดูนะ
ความเห็นส่วนตัว:
สำหรับผมนะ การทำ Quantization เนี่ยโคตรมีประโยชน์เลย ถ้าเราไม่ได้จะเอาไปทำ Production ที่ต้องการความแม่นยำสูงแบบเป๊ะๆ หรือแค่จะเอามาลองเล่นๆ บนเครื่องตัวเอง ผมว่ามันเวิร์คมาก! จากที่โมเดล 7B ต้องใช้ RAM ประมาณ 14-16GB ตอนเป็น FP16/BF16 พอทำ 4-bit แล้ว บางทีก็เหลือแค่ 5-6GB เองอะ คือเอาไปรันบนการ์ดจอ 8GB หรือ 12GB อย่าง RTX 3060/3060 Ti ก็พอไหวละ (ถ้าไม่รันโมเดลใหญ่กว่านี้)
แน่นอนว่ามันก็มีเทรดออฟนะ โมเดลมันจะเล็กลง เร็วขึ้นนิดหน่อย แต่อาจจะเสียความแม่นยำไปบ้าง (นิดเดียวจริงๆ สำหรับหลายๆ เคส) แต่ถ้าเทียบกับว่าเราไม่ต้องไปลงทุนกับการ์ดจอโคตรแพง หรือเช่า Cloud GPU เดือนเป็นหมื่น ผมว่านี่คือทางออกที่ฉลาดมากเลย!
สรุป
ถ้าคุณอยากลองเล่น LLM แบบไม่ต้องมีเครื่องแรงๆ Quantization นี่แหละคือทางออกที่ดีที่สุดในตอนนี้ ลองเอาโค้ดไปรันดูนะ ไม่ยากอย่างที่คิด แล้วคุณจะทึ่งว่าโมเดลใหญ่ๆ ก็รันบนเครื่องเราได้นี่หว่า!
ขอให้สนุกกับการเล่น LLM ครับ!