אפשר לעשות fine-tuning למודל open-weights של 8B על הנתונים שלכם עם QLoRA, על GPU שכור אחד של 24 GB, והרצה טיפוסית עולה פחות מדולר. השאלות הקשות באות קודם: האם fine-tuning הוא בכלל הפתרון הנכון (לעובדות, אחזור בדרך כלל מנצח), ואיך הנתונים שלכם נשארים פרטיים על מכונה שמישהו אחר מחזיק.
המדריך הזה מכסה את שתיהן, ואחר כך את ה-VRAM שצריך לפי גודל המודל, את הכלים הנוכחיים, סקריפט אימון שעובד, חישוב עלות ואיך להגיש את התוצאה. הכול נבדק בספטמבר 2026; המקורות בסוף.
fine-tuning, RAG או פרומפטים טובים יותר
fine-tuning משנה את ההתנהגות של מודל. זו דרך גרועה ללמד אותו עובדות. Ovadia ועמיתיו השוו בין השתיים להזרקת ידע ומצאו ש-RAG “עוקף בעקביות” fine-tuning לא מפוקח, “גם בידע קיים שנתקלו בו באימון וגם בידע חדש לגמרי”. הסיכום שלהם: ל-LLMs קשה ללמוד עובדות חדשות דרך fine-tuning.
אז לפני ששוכרים משהו, עברו על העץ הזה:
סיבות טובות ל-fine-tuning:
- פורמט פלט קשיח. חילוץ שדות לסכמה שלכם בכל קריאה, בלי עמוד של הוראות בכל פרומפט.
- סגנון וטון. תשובות תמיכה שנשמעות כמו הצוות שלכם, או דוחות במבנה קבוע.
- משימה צרה שמודל קטן מבצע. מודל של 8B שעבר אימון יכול להחליף מודל כללי גדול בעבודה אחת, וזה חשוב כשמגישים אותו על חומרה זולה.
- פרומפטים קצרים יותר. התנהגות שנלמדה במשקלים לא צריכה לחזור בכל בקשה.
LoRA ו-QLoRA
fine-tuning מלא מעדכן כל משקל, כך שה-GPU צריך להחזיק gradients ו-optimizer state לכולם, בנוסף למודל עצמו. LoRA מקפיא את מודל הבסיס ומאמן מטריצות קטנות בדרגה נמוכה לצד השכבות שלו; המאמר המקורי דיווח על פי 10,000 פחות פרמטרים לאימון ופי 3 פחות זיכרון GPU, בהשוואה ל-fine-tuning מלא של GPT-3 175B עם Adam.
QLoRA הולך רחוק יותר: מודל הבסיס הקפוא נטען בדיוק של 4 ביט NF4, ורק ה-adapters מאומנים ב-16 ביט. Dettmers ועמיתיו השתמשו בו כדי לעשות fine-tuning למודל של 65B על GPU יחיד של 48 GB, “תוך שמירה על הביצועים של fine-tuning מלא ב-16 ביט”. המאמר הוסיף שלושה רכיבים שהכלים משתמשים בהם עד היום: סוג הנתונים NF4, קוונטיזציה כפולה של קבועי הקוונטיזציה, ו-paged optimizers שסופגים קפיצות בזיכרון.
התוצאה של שניהם היא adapter, תיקייה של כמה טנזורים, שמפעילים מעל מודל הבסיס שלא השתנה. אפשר להשאיר אותו נפרד או למזג אותו לתוך המשקלים. מודלים של תמונות משתמשים באותה שיטה: LoRA ל-Stable Diffusion מתאמן על כרטיס 24 GB מושכר אחד בהרבה פחות מ-$10.
כמה VRAM צריך
Unsloth מפרסמת טבלה של ה-VRAM המינימלי ל-fine-tuning לפי גודל המודל. אלה המספרים שלה, עם אופטימיזציות הזיכרון שלה; אימון רגיל של Hugging Face צריך יותר, ורצפים ארוכים יותר או batches גדולים יותר מעלים כל שורה.
| גודל מודל | QLoRA (4 ביט) | LoRA (16 ביט) | כרטיס שכור שמריץ QLoRA בנוחות |
|---|---|---|---|
| 3B | 3.5 GB | 8 GB | כל כרטיס של 12 GB ומעלה |
| 8B | 6 GB | 22 GB | RTX 3090 / 4090 (24 GB) |
| 14B | 8.5 GB | 33 GB | RTX 3090 / 4090 (24 GB) |
| 32B | 26 GB | 76 GB | כרטיס של 48 GB (RTX A6000, A40, L40S) |
| 70B | 41 GB | 164 GB | כרטיס של 80 GB (A100, H100) |
ברירת המחדל שלי היא מודל של 8B או 14B על RTX 4090. זה הכרטיס השכור הזול ביותר שמשאיר מקום לרצפים של 2,048 טוקנים ול-batch סביר, ומודלים בטווח הזה קלים להגשה אחר כך. לבחירת מודל בסיס לפי ה-VRAM שעליו תגישו אותו, ראו אילו מודלי AI נכנסים ל-VRAM של ה-GPU שלכם.
בחירת כלי: TRL, Unsloth או Axolotl
שלושתם קוד פתוח, ושלושתם עושים LoRA ו-QLoRA.
| כלי | איך משתמשים בו | חוזקה | שימו לב |
|---|---|---|---|
| Hugging Face TRL + PEFT | Python (SFTTrainer) | מימוש הייחוס; DPO, GRPO ועוד באותו API | צורך יותר זיכרון מ-Unsloth באותה הרצה |
| Unsloth | Python, או ממשק ה-web של Unsloth Studio | טוען למהירות כפולה ול-70% פחות VRAM; ייצוא ישיר ל-GGUF | ממשק Studio ברישיון AGPL-3.0 (הליבה ב-Apache 2.0) |
| Axolotl | קובץ YAML אחד, axolotl train config.yml | ריבוי GPUs (FSDP, DeepSpeed), הרבה מתכונים מוכנים | דורש Python 3.11 ומעלה ו-PyTorch 2.11 ומעלה |
נכון לספטמבר 2026, TRL בגרסה 1.14 ו-PEFT בגרסה 0.21. Unsloth צריך Python 3.11 עד 3.13 ו-GPU של NVIDIA עם CUDA capability 7.0 ומעלה (V100, T4, סדרת RTX 20 ומעלה). Axolotl ממליץ על Python 3.12 ו-PyTorch 2.12.1.
השתמשו ב-TRL אם אתם רוצים להבין כל שורה, ב-Unsloth אם חסר לכם VRAM או שאתם רוצים ייצוא ל-GGUF בקריאה אחת, וב-Axolotl אם תחזרו על הרצות עם הגדרות שונות או תעברו לכמה GPUs. הסקריפט בהמשך משתמש ב-TRL, כי זו הדרך הקצרה ביותר שמראה כל חלק נע.
הכנת הנתונים
SFTTrainer של TRL קורא שיחות באותו מבנה של בקשה ל-API צ’אט. אובייקט JSON אחד בכל שורה ב-train.jsonl:
{"messages": [{"role": "system", "content": "Extract the invoice fields as JSON."}, {"role": "user", "content": "Invoice 4471 from Norden AB, due 12 March, total 1,250 EUR"}, {"role": "assistant", "content": "{\"invoice_id\": \"4471\", \"supplier\": \"Norden AB\", \"due\": \"2026-03-12\", \"total\": 1250, \"currency\": \"EUR\"}"}]}
כללים מעשיים:
- איכות לפני כמות. כמה מאות עד כמה אלפי דוגמאות עקביות ונכונות עדיפות על עשרות אלפים רועשות. כל טעות בנתונים היא התנהגות שאתם משלמים כדי ללמד.
- התאמה לפרודקשן. השתמשו בפרומפט המערכת ובפורמט הקלט שהאפליקציה שלכם באמת תשלח.
- הפרישו 5 עד 10%. שמרו דוגמאות שהמודל לא מתאמן עליהן אף פעם, כדי להשוות את מודל הבסיס ואת המודל המאומן זה לצד זה.
- הסירו את מה שלא צריך. שמות, כתובות מייל, מספרי חשבון ומזהים כמעט אף פעם לא עוזרים למודל ללמוד פורמט. החליפו אותם בערכים מדומים ומציאותיים לפני שהנתונים יוצאים מהמחשב שלכם.
הכלל האחרון נוגע ליותר מהמכונה השכורה. Carlini ועמיתיו חילצו מ-GPT-2 מאות רצפי אימון מילה במילה, כולל שמות, מספרי טלפון וכתובות מייל, שחלקם הופיעו במסמך אימון אחד בלבד. מודל שעבר fine-tuning יכול לחזור על מה שאומן עליו בפני כל מי שישתמש בו אחר כך.
שמירה על פרטיות הנתונים במכונה שכורה
בשוק GPU, המחשב שייך למישהו אחר. Vast.ai אומרת את זה בפשטות: “לקוחות מבודדים בקונטיינרים של Docker ללא הרשאות מיוחדות, ויש להם גישה רק לנתונים שלהם”, וגם “רמת האבטחה של ספקים משתנה מאוד”. הבידוד הזה מגן עליכם משוכרים אחרים. הוא לא מגן עליכם מהאדם שיש לו גישה פיזית והרשאות root על המארח.
לנתונים פרטיים:
- בחרו מארח בדאטה סנטר שעבר בדיקה. ספקי ה-Secure Cloud של Vast.ai הם “דאטה סנטרים שעברו בדיקה, עם הסמכת ISO 27001 ותקני דאטה סנטר Tier 3/4”, ו-Vast ממליצה עליהם לעבודה רגישה. ה-Secure Cloud של RunPod רץ בדאטה סנטרים ברמת T3/T4; ה-Community Cloud שלה מחבר אתכם לספקים פרטיים. השכבות של הדאטה סנטרים עולות יותר לשעה, וכאן זה שווה את זה.
- העלו רק את הדאטהסט הנקי, דרך SSH (
rsync -avPאוscp). אל תעבירו אותו בדרך דרך bucket ציבורי או קישור משותף. - השאירו את הלוגים מקומיים. ב-TRL 1.14 ברירת המחדל של
report_toהיא"none", כך ששום דבר לא נשלח לכלי מעקב ניסויים אלא אם תפעילו אותו. אל תקראו ל-push_to_hubעם adapter שאומן על נתונים פרטיים. - הוציאו את התוצאות, ואז מחקו את ה-instance. הורידו את ה-adapter ואת תוצאות ההערכה, התנתקו מ-Hugging Face (
hf auth logout) אם השתמשתם בטוקן, ומחקו את ה-instance ואת כל ה-volumes. ב-Vast.ai אחסון מחויב ונשמר עד שה-instance נמחק, לא רק נעצר.
מחיקת קבצים בתוך קונטיינר לא מבטיחה שהדיסק של המארח נמחק, כך שההגנה האמיתית היא שלבים 1 ו-2: לבחור מי מחזיק את החומרה, ולשלוח לו כמה שפחות. פרטים נוספים באיך לאבטח דאטהסט על צומת GPU ציבורי. אם המדיניות שלכם אוסרת כל חומרה של צד שלישי, אותו סקריפט רץ על כרטיס 24 GB משלכם.
אימון: סקריפט QLoRA עם TRL
על מכונת Linux שכורה עם RTX 3090 או 4090:
python -m venv venv && source venv/bin/activate
pip install torch trl peft bitsandbytes datasets
ואז train.py, לפי דפוס ה-QLoRA בתיעוד ה-PEFT של TRL. Qwen3-8B ברישיון Apache 2.0 ולא חסום, כך שלא צריך טוקן של Hugging Face:
import torch
from datasets import load_dataset
from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer
dataset = load_dataset("json", data_files="train.jsonl", split="train")
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
peft_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules="all-linear",
task_type="CAUSAL_LM",
)
args = SFTConfig(
output_dir="out",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_steps=20,
max_length=2048,
bf16=True,
logging_steps=10,
save_strategy="epoch",
model_init_kwargs={"dtype": torch.bfloat16},
)
trainer = SFTTrainer(
model="Qwen/Qwen3-8B",
args=args,
train_dataset=dataset,
quantization_config=bnb_config,
peft_config=peft_config,
)
trainer.train()
trainer.save_model("out/adapter")
הבחירות שמשנות:
learning_rate=2e-4. התיעוד של TRL ממליץ ב-QLoRA על קצב גבוה פי 10 בערך מהקצב הרגיל ל-fine-tuning. אם ה-loss על נתוני ההערכה עולה בזמן שה-loss על נתוני האימון יורד, יש overfitting: הורידו את מספר ה-epochs.r=16, target_modules="all-linear". adapters על כל שכבה לינארית, ההגדרה שבה משתמשים ה-benchmarks של Unsloth. דרגה 16 מספיקה לפורמט ולסגנון; העלו אותה למשימות קשות יותר.max_length=2048. דוגמאות ארוכות יותר נחתכות. בדקו את אורכי הטוקנים בנתונים שלכם; מגבלה ארוכה יותר צריכה יותר VRAM.- batch אפקטיבי של 16 (4 × 4 צעדי accumulation). אם נגמר לכם הזיכרון, הורידו את
per_device_train_batch_sizeוהעלו את ה-accumulation כדי לשמור על המכפלה.
לפני שאתם מכבים את המכונה, הריצו את הדוגמאות שהפרשתם דרך מודל הבסיס ודרך המודל המאומן והשוו ביניהם. זו הבדיקה היחידה שתגיד לכם אם הכסף עשה משהו.
כמה זה עולה
זמן האימון הוא סך הטוקנים ÷ תפוקה. GigaGPU, חברת אירוח, פרסמה מדידה של כ-3,500 טוקני אימון לשנייה ל-Llama 3.1 8B עם QLoRA על RTX 4090. בהנחה של קצב דומה ל-Qwen3-8B:
הרצה קטנה: 2,000 דוגמאות × 600 טוקנים × 3 epochs = 3.6 מיליון טוקנים. 3,600,000 ÷ 3,500 = 1,029 שניות, כ-17 דקות.
| שלב | זמן |
|---|---|
| הקמת הסביבה | 10 דק’ |
| הורדת Qwen3-8B (16.4 GB של משקלים) והעלאת הנתונים | 10 דק’ |
| אימון | 17 דק’ |
| השוואת מודל הבסיס והמודל המאומן על הנתונים שהופרשו | 15 דק’ |
| מיזוג, ייצוא, הורדה, מחיקת ה-instance | 15 דק’ |
| סך הכול | 67 דק’ (1.12 שעות) |
- RTX 4090 ב-Vast.ai ב-$0.31 לשעה: 1.12 × $0.31 = $0.35
- RTX 4090 ב-RunPod ב-$0.74 לשעה (מחיר המחירון בדף התמחור): 1.12 × $0.74 = $0.83
הרצה גדולה יותר: 20,000 דוגמאות × 1,000 טוקנים × 2 epochs = 40 מיליון טוקנים ÷ 3,500 = 11,429 שניות, כ-3.2 שעות. עם 50 דקות של אותה תקורה, 4.0 שעות: $1.24 ב-Vast.ai או $2.97 ב-RunPod.
למודל של 32B, כרטיסים של 48 GB מוצגים ב-RunPod ב-$0.49 לשעה (A40), $0.53 לשעה (RTX A6000) ו-$1.09 לשעה (L40S), נכון לספטמבר 2026. אין לי נתון תפוקה מפורסם ל-QLoRA של 32B על הכרטיסים האלה, אז הריצו 50 צעדים, קראו את זמן הצעד מהלוג, ועשו את אותו כפל לפני שאתם מתחייבים להרצה ארוכה.
המחירים הם הנתונים של ספטמבר 2026 מדף התמחור של RunPod וממעקב המחירים של getdeploying.com ל-Vast.ai. שכבות Secure/דאטה סנטר עולות יותר מההצעות הזולות ביותר בקהילה. התמונה הרחבה נמצאת בהשוואת מחירי השכרת GPU.
הגשת התוצאה
יש שתי אפשרויות: להשאיר את ה-adapter נפרד, או למזג אותו למודל.
להשאיר נפרד עם vLLM. vLLM טוען adapters של LoRA לצד מודל הבסיס וחושף כל אחד מהם כשם מודל בשרת התואם OpenAI שלו:
vllm serve Qwen/Qwen3-8B --enable-lora --lora-modules invoices=./out/adapter
הלקוחות שולחים אז "model": "invoices". כמה adapters יכולים לחלוק מודל בסיס אחד על GPU אחד.
למזג ולהריץ ב-Ollama. מזגו את ה-adapter למשקלים בדיוק מלא, המירו ל-GGUF עם llama.cpp, בצעו קוונטיזציה, וייבאו:
import torch
from peft import AutoPeftModelForCausalLM
from transformers import AutoTokenizer
model = AutoPeftModelForCausalLM.from_pretrained("out/adapter", dtype=torch.bfloat16)
model.merge_and_unload().save_pretrained("merged")
AutoTokenizer.from_pretrained("Qwen/Qwen3-8B").save_pretrained("merged")
python llama.cpp/convert_hf_to_gguf.py merged --outfile invoices-bf16.gguf --outtype bf16
./llama.cpp/build/bin/llama-quantize invoices-bf16.gguf invoices-Q4_K_M.gguf Q4_K_M
echo "FROM ./invoices-Q4_K_M.gguf" > Modelfile
ollama create invoices -f Modelfile
Unsloth עושה את המיזוג ואת הייצוא ל-GGUF בקריאה אחת (model.save_pretrained_gguf("dir", tokenizer, quantization_method="q4_k_m")). התיעוד שלו מזהיר שהסיבה הנפוצה ביותר לתשובות גרועות אחרי ייצוא היא chat template שגוי: הגישו עם אותה תבנית שאימנתם איתה. השיקולים בין Ollama, vLLM ו-TGI מפורטים במבחן הביצועים שלנו להסקה על RTX 4090.
איפה GPUFlow נכנסת לתמונה
GPUFlow לא יכולה לבצע את האימון: היא משכירה API תואם OpenAI על GPU של ספק, בלי shell, בלי SSH ובלי גישה לקבצים. היא גם לא יכולה להגיש את המודל שעבר fine-tuning. שוכרים לא יכולים להעלות מודלים; המודלים שמוצעים הם אלה שכל ספק התקין (בדרך כלל עם Ollama), כמו qwen2.5:7b או llama3.1:8b.
איפה שהיא כן יכולה לעזור הוא השלב שלפני כל זה: לבדוק, בכמה סנטים, אם מודל פתוח רגיל עם פרומפט טוב כבר עושה את העבודה, שזו התוצאה הזולה ביותר בעץ ההחלטות. השתמשו לשם כך בנתוני בדיקה, לא בנתונים הפרטיים שהמדריך הזה עוסק בהם: פרומפטים ותשובות עוברים דרך המכונה של הספק כטקסט גלוי בזמן שההשכרה רצה. איך זה עובד מוסבר במדריך ההתחלה המהירה ל-API, ושימוש במפתח באפליקציות מסביר איך לחבר אותו לכלים קיימים.
מקורות
כולם נבדקו בספטמבר 2026.
- מאמרים: Hu et al., LoRA; Dettmers et al., QLoRA; Ovadia et al., Fine-Tuning or Retrieval?; Carlini et al., Extracting Training Data from Large Language Models
- Hugging Face TRL: SFT Trainer, אינטגרציה עם PEFT ו-QLoRA
- Unsloth: דרישות וטבלת VRAM, benchmarks, שמירה ל-GGUF, GitHub
- Axolotl ב-GitHub
- מודל: כרטיס המודל של Qwen3-8B
- תפוקת אימון: GigaGPU, fine-tuning על RTX 4090
- מארחים ואבטחה: שאלות נפוצות על אבטחה ב-Vast.ai, התמחור של Vast.ai, סקירת Pods של RunPod
- מחירים: התמחור של RunPod, getdeploying.com עבור Vast.ai ו-RTX 4090
- הגשה: adapters של LoRA ב-vLLM, quantize ב-llama.cpp, ייבוא ל-Ollama
- GPUFlow: מדריך התחלה מהירה ל-API