บทที่ 5 จาก 5 · Fine-tune โมเดลภาษา — เมื่อไหร่ควรทำ ทำอย่างไร และรู้ได้อย่างไรว่าได้ผล
นำโมเดลที่ fine-tune แล้วไปใช้: รวม adapter แปลงเป็น GGUF และรันด้วย Ollama หรือ vLLM
จาก adapter ไปถึงโมเดลที่รันได้จริง รวม adapter เข้ากับโมเดลฐาน แปลงเป็น GGUF แล้วบีบให้เล็กลงด้วย llama.cpp นำเข้า Ollama ซึ่งเลิกรับ LoRA adapter แยกแล้วตั้งแต่เดือนกันยายน 2026 หรือเสิร์ฟ adapter ตรง ๆ ด้วย vLLM พร้อมเงื่อนไขไลเซนส์ตอนเผยแพร่
เทรนเสร็จแล้วจะได้ adapter ไฟล์เล็ก ๆ ที่ต้องใช้คู่กับโมเดลฐาน บทนี้ว่าด้วยสองเส้นทางที่ใช้บ่อย คือรวมเป็นโมเดลเดียวแล้วรันบนเครื่องด้วย Ollama หรือเสิร์ฟ adapter ตรง ๆ ด้วย vLLM
5.1 รวม adapter เข้ากับโมเดลฐาน
PEFT มีฟังก์ชัน merge_and_unload() สำหรับรวมน้ำหนักของ adapter เข้าไปในโมเดลฐาน ผลคือได้โมเดลปกติที่ไม่ต้องพึ่ง adapter และไม่มีเวลาตอบที่เพิ่มขึ้นจาก adapter
ถ้าเทรนด้วย QLoRA อย่ารวมบนโมเดล 4 บิตที่ใช้เทรน โมเดลที่รวมแล้วจะยังเป็นแบบ bitsandbytes 4 บิต ซึ่งสคริปต์แปลงของ llama.cpp ในขั้นถัดไปไม่รองรับ ให้โหลดโมเดลฐานใหม่แบบ 16 บิต แล้วค่อยใส่ adapter และรวม
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("<โมเดลฐาน>", dtype=torch.bfloat16)
model = PeftModel.from_pretrained(base, "./my-adapter")
model = model.merge_and_unload()
model.save_pretrained("./my-merged-model")
AutoTokenizer.from_pretrained("./my-adapter").save_pretrained("./my-merged-model")
บรรทัดสุดท้ายบันทึก tokenizer ไว้ในโฟลเดอร์เดียวกัน เพราะสคริปต์แปลงอ่าน tokenizer จากโฟลเดอร์ของโมเดล ใช้ tokenizer ตัวที่ใช้ตอนเทรน (ถ้าไม่ได้บันทึกไว้กับ adapter ให้ใช้ของโมเดลฐาน) เอกสารของ PEFT ยังเตือนว่า merge_and_unload() ไม่ได้แก้โมเดลเดิมโดยตรง แต่คืนโมเดลใหม่ออกมา ต้องรับค่าที่คืนมาแบบในตัวอย่าง
5.2 แปลงเป็น GGUF และบีบให้เล็กลง
GGUF เป็นรูปแบบไฟล์ของ llama.cpp ที่ Ollama และโปรแกรมรันบนเครื่องอีกหลายตัวใช้ ต้องดาวน์โหลดและ build llama.cpp และติดตั้งแพ็กเกจ Python ตาม requirements ของมันก่อน จากนั้นมีสองขั้น
- แปลงโมเดล Hugging Face เป็น GGUF ด้วยสคริปต์
convert_hf_to_gguf.pyของ llama.cpp เลือกชนิดข้อมูลด้วย--outtypeเช่นbf16 - บีบให้เล็กลง (quantize) ด้วย
llama-quantizeเช่นแบบQ4_K_M
python convert_hf_to_gguf.py ./my-merged-model --outfile my-model-bf16.gguf --outtype bf16
./build/bin/llama-quantize my-model-bf16.gguf my-model-Q4_K_M.gguf Q4_K_M
ตัวอย่างขนาดจากเอกสารของ llama.cpp: โมเดล Llama-3.1-8B แบบ F16 ใช้พื้นที่ 14.96 GiB ส่วนแบบ Q4_K_M เหลือ 4.58 GiB เอกสารยังเตือนว่าการบีบซ้ำจากไฟล์ที่บีบแล้ว อาจทำให้คุณภาพลดลงมาก ให้บีบจากไฟล์ 16 หรือ 32 บิตเสมอ
หลังบีบแล้วต้องวัดผลซ้ำ ด้วยชุดทดสอบจากบทที่ 4 เพราะการบีบอาจทำให้คุณภาพลดลง โดยเฉพาะกับงานที่ต้องการความแม่นยำ
5.3 รันด้วย Ollama: ต้องรวมก่อน
สิ่งที่เปลี่ยนในเดือนกันยายน 2026: Ollama เลิกรองรับ LoRA adapter แล้ว คำสั่ง ADAPTER หายไปจากเอกสาร Modelfile และตั้งแต่ Ollama v0.34.1 คำสั่ง ollama create จะปฏิเสธไฟล์ที่มี ADAPTER บทความเก่าที่สอนให้ใส่ adapter ใน Modelfile จึงใช้กับ Ollama รุ่นปัจจุบันไม่ได้
สำหรับ GGUF ให้ รวม adapter ก่อน (5.1) แปลงและบีบเป็น GGUF (5.2) แล้วนำเข้า (เอกสารของ Ollama ยังมีวิธีนำเข้าโฟลเดอร์ safetensors โดยตรงด้วย ดูเอกสารของรุ่นที่ใช้)
FROM ./my-model-Q4_K_M.gguf
บันทึกเป็นไฟล์ชื่อ Modelfile แล้วรัน ollama create my-model ในโฟลเดอร์เดียวกัน เอกสารของ Ollama ย้ำว่า Ollama ไม่บีบไฟล์ GGUF ให้ตอนนำเข้า ต้องบีบให้เสร็จก่อน
หลังนำเข้า ให้ตรวจ chat template ด้วย ollama show --modelfile my-model ว่าตรงกับที่ใช้ตอนเทรน (บทที่ 2) ถ้าไม่ตรง ให้กำหนด TEMPLATE ใน Modelfile
5.4 เสิร์ฟ adapter ด้วย vLLM
ถ้ามีเซิร์ฟเวอร์ที่ใช้ vLLM ไม่ต้องรวม adapter ก็ได้ vLLM เสิร์ฟ adapter คู่กับโมเดลฐานได้โดยตรง และเสิร์ฟหลาย adapter บนโมเดลฐานตัวเดียวได้
vllm serve <โมเดลฐาน> --enable-lora --lora-modules my-task=./my-adapter
ค่า rank สูงสุดของ adapter ใน vLLM ตั้งไว้ที่ 16 ถ้า adapter ของคุณเทรนด้วย rank สูงกว่านั้น เช่น 32 หรือ 64 ต้องเพิ่ม --max-lora-rank
vLLM มีตัวเลือกโหลด adapter ระหว่างเซิร์ฟเวอร์ทำงาน แต่เอกสารเตือนว่า ไม่ควรใช้ใน production เว้นแต่อยู่ในสภาพแวดล้อมที่แยกและเชื่อถือได้ทั้งหมด
5.5 เผยแพร่โมเดล: อ่านไลเซนส์อีกรอบ
ถ้าจะแจกหรือขายโมเดลที่ fine-tune แล้ว เงื่อนไขของโมเดลฐานยังตามไปด้วย
| โมเดลฐาน | สิ่งที่ต้องทำเมื่อเผยแพร่ (ตามไลเซนส์ที่ตรวจได้) |
|---|---|
| Llama 4 | โมเดลที่ fine-tune จาก Llama หรือเทรนจาก output ของ Llama แล้วเผยแพร่ ต้องมีชื่อขึ้นต้นด้วย “Llama” แนบสำเนาไลเซนส์ และแสดงข้อความ “Built with Llama” |
| Gemma รุ่นก่อน Gemma 4 | ส่งต่อข้อจำกัดการใช้งานของ Gemma ไปในข้อตกลงกับผู้รับ แนบสำเนาเงื่อนไข ใส่ประกาศในไฟล์ที่แก้ และแนบไฟล์ “Notice” |
| Gemma 4, Qwen3.8-27B และโมเดล Apache 2.0 อื่น | ทำตามเงื่อนไขของ Apache 2.0 เช่น แนบไลเซนส์และประกาศการแก้ไข |
| โมเดลที่สร้างต่อจากโมเดลอื่นอีกชั้น | อ่านไลเซนส์ทั้งของโมเดลที่ใช้และของโมเดลต้นทาง (บทที่ 3) |
ตารางนี้ไม่ได้ครบทุกข้อ และไม่ใช่คำแนะนำทางกฎหมาย อ่านไลเซนส์ฉบับเต็มก่อนเผยแพร่
5.6 ตัวอย่างสมมติ: เร็วขึ้น แต่ผิดขึ้น
ร้านในบทก่อน ๆ บีบโมเดลจัดหมวดเป็นแบบ 4 บิตให้รันเร็วบนเครื่องในร้าน แล้วเปิดใช้เลยโดยไม่วัดซ้ำ ต่อมาพบว่าหมวด “ร้องเรียน” ซึ่งมีตัวอย่างน้อยถูกจัดผิดบ่อยขึ้น
บทเรียนคือทุกครั้งที่เปลี่ยนรูปแบบโมเดล ไม่ว่าจะรวม adapter แปลง หรือบีบ ให้รันชุดทดสอบเดิมซ้ำ และดูคะแนนแยกทีละหมวด ไม่ใช่ดูแค่คะแนนรวม
5.7 ทั้งซีรีส์เป็นรายการตรวจ
| บท | ตรวจ |
|---|---|
| 1 | ลอง prompt จริงจังแล้ว ปัญหาเป็นเรื่องรูปแบบหรือพฤติกรรม ไม่ใช่ข้อมูลที่เปลี่ยนบ่อย |
| 2 | ข้อมูลอยู่ในรูปแบบ messages เดียวกับที่ใช้จริง ใช้ chat template ของโมเดลฐาน มีคำนิยามการติดป้าย และไลเซนส์ของข้อมูลกับเงื่อนไขของผู้ให้บริการอนุญาต |
| 3 | โมเดลฐานรองรับภาษาไทยพอ ไลเซนส์ทั้งสองชั้นตรงกับการใช้งาน และใช้ตัวอย่างจากเอกสารของเครื่องมือรุ่นที่ติดตั้ง |
| 4 | มีชุดทดสอบที่แยกจริง มีเส้นฐานจากโมเดลฐาน ตรวจการลืม และตรวจว่าคำตอบเป็นภาษาไทย |
| 5 | รวม adapter ก่อนนำเข้า Ollama วัดผลซ้ำหลังบีบ และทำตามเงื่อนไขไลเซนส์ตอนเผยแพร่ |
แหล่งอ้างอิง
- Hugging Face PEFT — LoRA (merge_and_unload)
- llama.cpp — quantize README
- llama.cpp — convert_hf_to_gguf.py
- Ollama — Importing a model
- Ollama — Modelfile reference
- Ollama — commit removing LoRA adapter support
- vLLM — LoRA adapters
- Meta — Llama 4 Community License
- Gemma Terms of Use · Gemma 4 (Apache 2.0)