פרק 3 מתוך 5
GPU Notebooks בפועל: מדריך הישרדות ל-Colab ו-Kaggle
בפרק הקודם קיבלתם דרך להריץ מודלים חזקים דרך API חינמי בלי לגעת ב-GPU. עכשיו אנחנו עוברים לשכבה שבה אתם כן מקבלים GPU זמני: Colab, Kaggle ומחברות ענן דומות. המטרה אינה רק לפתוח notebook וללחוץ Run. המטרה היא לבנות הרגל עבודה שורד ניתוקים, מכבד quotas, מודד VRAM לפני שהוא מתפוצץ, ומשאיר אחריו artifact שאפשר להמשיך ממנו מחר.
מה יהיה לכם בסוף הפרק
- מחברת Colab עם תא startup שמחבר Drive, יוצר תיקיות קבועות, מדפיס GPU ומגדיר נתיבי checkpoints.
- דפוס checkpoint save/restore שאפשר להדביק לכל job ארוך כדי לא לאבד התקדמות אחרי disconnect.
- מחברת Kaggle שמריצה ניסוי קטן, שומרת output תחת
/kaggle/working, וניתנת להרצה נקייה מלמעלה למטה. - טבלת VRAM budgeting מעשית ל-T4: מה נכנס, מה גבולי, ומה צריך להוריד לפני שמקבלים OOM.
- Runbook קצר ל-ComfyUI על Colab עם workflow JSON שמור ב-Drive ו-ngrok tunnel זמני לדמו בלבד.
- עץ החלטה אישי: מתי לבחור Colab, מתי Kaggle, מתי inference API, ומתי לחכות לפרק 4 ולעבור ל-local.
בסוף הפרק תוכלו ל...
- להגדיר notebook על Colab כך שכל state חשוב נשמר מחוץ ל-runtime הזמני.
- לכתוב קוד checkpointing שממשיך מהריצה האחרונה במקום להתחיל מאפס.
- להשתמש ב-Kaggle עבור ריצות נקיות, Outputs וגרסאות שאפשר לשחזר.
- לתקצב VRAM להרצת inference על T4 ולהחליט מה להקטין כשיש OOM.
- להריץ דמו ComfyUI קצר עם tunnel זמני בלי להפוך את ה-notebook לשרת ציבורי מסוכן.
לפני שמתחילים
- פרקים קודמים: רצוי שסיימתם את פרק 1, ובעיקר את מפת ההחלטה בין notebook GPU, inference API ו-local. פרק 2 נותן fallback חשוב אם ה-GPU לא זמין.
- חשבונות: Google account עבור Colab ו-Drive, חשבון Kaggle, חשבון Hugging Face אם תורידו מודלים gated, וחשבון ngrok רק לתרגיל הדמו.
- ידע טכני: אתם יודעים להריץ תא ב-notebook, לקרוא שגיאת Python בסיסית, ולהעתיק נתיב קובץ בלי לפחד מסלאשים.
- זמן עבודה: 2.5 עד 3.5 שעות אם מבצעים את כל התרגילים, או כ-70 דקות אם רק קוראים ומעתיקים את skeletons למחברת שלכם.
הפרויקט שלך
בפרק 2 בניתם דפוס עבודה שמריץ מודלים דרך inference APIs חינמיים ומחליף ספק כשמגיעים ל-429. בפרק הזה אתם מוסיפים שכבת GPU זמנית שמאפשרת הרצה, בדיקה ויצירת artifacts כאשר API חיצוני לא מספיק. בפרק 4 תשתמשו באותה חשיבה של VRAM ו-fallback כדי להריץ מודלים מקומית עם Ollama, GGUF ו-quantization.
מונחים שתפגשו בפרק
| Term | תרגום שימושי | הגדרה קצרה |
|---|---|---|
| Ephemeral Disk | דיסק זמני | אחסון שנעלם כשה-runtime מתנתק או נבנה מחדש. |
| Runtime | סביבת הרצה | המכונה הזמנית שמריצה את תאי המחברת שלכם. |
| Checkpoint | נקודת שחזור | צילום מצב שמאפשר להמשיך job מהנקודה האחרונה שנשמרה. |
| Startup Cell | תא אתחול | תא ראשון במחברת שמקים מחדש את הסביבה בכל session. |
| VRAM | זיכרון GPU | הזיכרון שבו נמצאים weights, cache ו-tensors בזמן הרצה. |
| OOM | Out Of Memory | כשל שנוצר כשאין מספיק GPU memory או RAM לפעולה. |
| KV Cache | מטמון הקשר | זיכרון נוסף שמודל טקסט צריך בזמן generation, גדל עם אורך context. |
| Save & Run All | הרצה נקייה | ב-Kaggle: יצירת גרסה שמריצה את המחברת מלמעלה למטה במצב נקי. |
| ngrok Tunnel | מנהרה זמנית | כתובת HTTPS שמעבירה תעבורה לשירות מקומי שרץ בתוך ה-notebook. |
| Workflow JSON | קובץ תהליך | קובץ ששומר גרף ComfyUI כך שאפשר לטעון אותו שוב בעתיד. |
למה GPU Notebook חינמי דורש משמעת עבודה
GPU notebook חינמי הוא לא שרת שלכם. זו נקודת פתיחה קריטית. Colab, Kaggle וסביבות דומות נותנות לכם גישה נדיבה למכונה חזקה, אבל הן נותנות אותה בתנאים של מערכת משותפת: זמינות משתנה, session זמני, idle timeout, מגבלות usage, ולעיתים סביבת קבצים שנמחקת ברגע שה-runtime נבנה מחדש. אם אתם מתייחסים לזה כמו VPS קטן, אתם תיפגעו. אם אתם מתייחסים לזה כמו מעבדה זמנית עם מחברת שנבנתה לחזור לחיים, אתם יכולים להוציא מזה המון.
הטעות של מתחילים היא להתלהב מה-GPU הירוק בתפריט, להתקין עשרה packages, להוריד מודל גדול, להריץ job של שעה, ואז לגלות שכל מה שהיה בתוך Ephemeral Disk (דיסק זמני) נעלם. הדיסק הזמני הוא המקום הנוח ביותר לעבוד בו כי הוא מהיר וזמין, אבל הוא לא המקום שבו שמים משהו שאכפת לכם ממנו. כל דבר שאמור לשרוד צריך לצאת החוצה: ל-Google Drive, ל-Kaggle Output, ל-Hugging Face Hub, ל-dataset פרטי, או לכל יעד אחר שאינו תלוי ב-runtime.
בפרק הזה נשתמש בעיקר בשני עקרונות. הראשון: restartability (יכולת להתחיל מחדש). מחברת טובה היא לא מחברת שרצה פעם אחת כשהכוכבים הסתדרו. מחברת טובה היא מחברת שאפשר להריץ מלמעלה למטה גם אחרי disconnect, גם אחרי שה-packages נעלמו, וגם אחרי שה-GPU הוחלף. השני: small visible wins (ניצחונות קטנים ונראים). לפני שמריצים job ארוך, מריצים בדיקת עשן קטנה. לפני שמעלים batch size, מודדים VRAM. לפני שפותחים tunnel, מוודאים שאין secrets. לפני שמתחילים training, מוכיחים ש-checkpoint נטען.
3 דקות כתבו לעצמכם על דף או בתא Markdown: אם הסשן מת עכשיו, מה הולך לאיבוד? חלקו לשלוש עמודות: files, packages, Python state. ליד כל פריט כתבו איפה הוא צריך להישמר כדי לשרוד.
מסגרת החלטה: כלל ההישרדות של Notebook
| אם... | אז... | למה זה חשוב |
|---|---|---|
| התוצר חשוב | שמרו אותו מחוץ ל-runtime לפני הצעד הבא | כי disconnect יכול לקרות בלי לשאול אתכם. |
| ההתקנה חשובה | שימו אותה ב-startup cell | כי packages שהותקנו ידנית ייעלמו. |
| ה-state חשוב | כתבו checkpoint כל N צעדים | כי זיכרון Python לא שורד restart. |
| ה-job ארוך | הריצו קודם smoke test קצר | כי עדיף לגלות שגיאה בדקה 2 ולא בדקה 72. |
שימו לב למה לא ננסה לעשות: לא ננסה לעקוף מדיניות של Colab, לא ננסה להפוך notebook חינמי לשרת production, ולא נבנה תהליך שמניח GPU מובטח. Colab עצמו אומר שהמשאבים אינם מובטחים ושהמגבלות משתנות. לכן chapter בריא לא אומר לכם 'תעשו keep-alive וזהו'. הוא אומר: גם אם ה-keep-alive נכשל, גם אם קיבלתם CPU במקום GPU, גם אם התא רץ שוב אחרי יום, אתם יודעים בדיוק מאיפה ממשיכים.
טעות נפוצה: לבנות על מזל במקום על שחזור
הטעות: להחזיק את הטאב פתוח, להזיז את העכבר מדי פעם, ולהרגיש שזה פתרון. למה זה מפתה? כי לפעמים זה עובד. מה לעשות במקום: להתייחס לניתוק כאל אירוע רגיל. כל notebook בפרק הזה יתחיל מתא setup, יבדוק איפה הוא נמצא, וידע לטעון את הקובץ האחרון שנשמר.
החשיבה הזאת גם חוסכת כסף. בישראל קל להסתכל על Colab Pro כעל 'רק כמה עשרות שקלים בחודש', אבל הקורס הזה עוסק ב-$0. כדי להישאר ב-$0, צריך לבנות סביב מגבלות. לא בכעס, לא בתחושת קיפוח, אלא כמו מהנדס שמכיר את המערכת. Free tier הוא משאב מתכלה. GPU-hours הם תקציב. Drive I/O הוא צוואר בקבוק. Tunnel ציבורי הוא סיכון. מי שמתכנן סביב זה, מקבל מכונת ניסויים חזקה מאוד בלי לשלם שקל.
Colab: להפוך סשן זמני למחברת שמתחילה מחדש נקי
Colab הוא המקום הכי מהיר להתחיל בו. יש לכם Google account, אתם פותחים מחברת, בוחרים Runtime, משנים Hardware accelerator ל-GPU אם זמין, ומריצים Python. אבל דווקא בגלל שהכניסה כל כך קלה, קל לכתוב מחברת שלא תשרוד את היום הראשון. התא הראשון שלכם צריך להיות לא תא import אקראי, אלא Startup Cell (תא אתחול): תא שמקים את הפרויקט מחדש בכל פעם.
Startup Cell טוב עושה חמישה דברים. הוא מחבר Google Drive. הוא מגדיר תיקיית root אחת לפרויקט. הוא יוצר תיקיות משנה ל-checkpoints, models, outputs ו-cache. הוא מדפיס מה ה-GPU הזמין כרגע. והוא מגדיר משתנים שבהם כל שאר התאים משתמשים. אם נתיב מופיע בעשרה תאים, אתם מזמינים bug. אם הנתיב מוגדר פעם אחת בראש המחברת, אפשר לשנות אותו אחרי restart בלי לצוד string בכל הקובץ.
4 דקות פתחו Google Drive וצרו תיקייה בשם free-gpu-lab. בתוכה צרו checkpoints, models, outputs, workflows. אל תשימו אותה ב-root עמוס עם אלפי קבצים; שמרו אותה כתיקייה נקייה.
# Colab startup cell
from pathlib import Path
import os
import subprocess
try:
from google.colab import drive
drive.mount('/content/drive')
DRIVE_ROOT = Path('/content/drive/MyDrive/free-gpu-lab')
except Exception:
DRIVE_ROOT = Path('./free-gpu-lab')
CHECKPOINT_DIR = DRIVE_ROOT / 'checkpoints'
MODEL_DIR = DRIVE_ROOT / 'models'
OUTPUT_DIR = DRIVE_ROOT / 'outputs'
WORKFLOW_DIR = DRIVE_ROOT / 'workflows'
for path in [CHECKPOINT_DIR, MODEL_DIR, OUTPUT_DIR, WORKFLOW_DIR]:
path.mkdir(parents=True, exist_ok=True)
print('Project root:', DRIVE_ROOT)
print('Checkpoint dir:', CHECKPOINT_DIR)
subprocess.run(['nvidia-smi'], check=False)
התא הזה לא מושלם ולא קסום, אבל הוא משנה את היחס שלכם לסביבה. אם אין Drive, הוא נופל לתיקייה מקומית כדי שתוכלו לבדוק את המחברת גם מחוץ ל-Colab. אם יש Drive, כל נתיב חשוב מצביע לשם. אם אין GPU, nvidia-smi יגיד לכם את זה מיד במקום שתגלו אחרי התקנת חבילות. התיקיות נוצרות בכל הרצה, אבל אם הן כבר קיימות לא קורה נזק. זו בדיוק התכונה שאתם רוצים: תא שאפשר להריץ שוב ושוב בלי לפחד.
עכשיו מגיע החלק שמתחילים מדלגים עליו: התקנות. ב-Colab, packages שהתקנתם עם pip חיים בסשן הנוכחי. מחר הם לא בהכרח יהיו שם. לכן התקנות צריכות להיות חלק מהמחברת, לא הערה בזיכרון שלכם. אבל גם לא צריך להתקין עולם שלם בכל פעם. תעדיפו תא install קצר, pinned במידה סבירה, שמתקין רק מה שהפרק צריך. אם אתם עובדים על ComfyUI, זה סיפור נפרד בהמשך. אם אתם עובדים על inference קטן, אל תגררו סביבת training מלאה.
4 דקות הוסיפו מתחת לתא ה-startup תא בשם environment check. הוא צריך להדפיס Python version, CUDA availability, ואת המקום הפנוי בדיסק. אל תריצו מודל לפני שהתא הזה נותן תמונה ברורה.
# Environment check
import sys
import shutil
print('Python:', sys.version.split()[0])
try:
import torch
print('CUDA available:', torch.cuda.is_available())
if torch.cuda.is_available():
print('GPU:', torch.cuda.get_device_name(0))
except Exception as exc:
print('torch not ready:', exc)
usage = shutil.disk_usage('/content' if Path('/content').exists() else '.')
print('Free disk GB:', round(usage.free / 1024**3, 2))
למה כל זה חשוב? כי הרבה בעיות שנראות כמו בעיות מודל הן בעיות סביבה. אין GPU. ה-GPU קיים אבל לא נוצל. הדיסק מלא כי הורדתם weights גדולים מדי. Drive מחובר אבל הנתיב שגוי. חבילת torch הוחלפה אחרי install לא מתאים. אם אתם מזהים את הבעיה בתא בדיקה, אתם לא מבזבזים חצי שעה על stack trace שאינו שייך למשימה.
תרגיל 1: בונים Colab Survival Skeleton
זמן: 25 דקות. תוצר: מחברת Colab שאפשר להריץ מחדש אחרי disconnect והיא עדיין מוצאת את תיקיות העבודה.
- פתחו מחברת Colab חדשה וקראו לה
free_gpu_survival_ch03. - הדביקו את תא ה-startup מהפרק והריצו אותו. אשרו את חיבור Drive אם Colab מבקש הרשאה.
- הדביקו תא environment check והריצו אותו. אם אין GPU, אל תנסו לתקן בכוח; רשמו בתא Markdown:
GPU unavailable now, fallback to API from chapter 2. - צרו קובץ קטן בתיקיית outputs:
hello_gpu_notebook.txtעם timestamp ושם ה-GPU אם קיים. - בחרו Runtime > Disconnect and delete runtime, התחברו מחדש, והריצו את שני התאים הראשונים בלבד.
- בדקו שהקובץ עדיין קיים ב-Drive. אם כן, המחברת עברה את מבחן ההישרדות הראשון.
פלט צפוי: תיקיית free-gpu-lab ב-Drive, ארבע תיקיות משנה, קובץ בדיקה ב-outputs, ותא שמדפיס GPU או אומר במפורש שאין GPU כרגע.
אל תזלזלו בתרגיל הזה בגלל שהוא קטן. זה בדיוק ההבדל בין notebook חובבני לבין מחברת שאפשר לבנות עליה. עוד לא אימנו, עוד לא יצרנו תמונה, עוד לא הרצנו LLM. רק הוכחנו שהמחברת יודעת לקום מחדש. זו בדיקת הבסיס לפני כל עבודה יקרה.
כדי להפוך את ה-skeleton הזה לתבנית קבועה, הוסיפו לו תא config קצר אחרי ה-startup. בתא הזה לא מתקינים כלום ולא מריצים מודל. רק מגדירים את שם הפרויקט, שם ה-run, מצב debug, והאם להשתמש ב-GPU או fallback. זה נשמע בירוקרטי, אבל זה מציל מחברות. כאשר כל הריצה נשענת על משתנים מרכזיים, אתם יכולים לשכפל את המחברת לפרויקט חדש בלי להחליף ידנית עשרים נתיבים. אתם גם יכולים לשלוח את המחברת לחבר צוות ולדעת איפה הוא אמור לשנות דברים.
# Project config cell
PROJECT_NAME = 'free_gpu_lab_ch03'
RUN_ID = 'baseline_restart_test_001'
USE_GPU = True
DEBUG_MODE = True
PROJECT_DIR = DRIVE_ROOT / PROJECT_NAME
PROJECT_DIR.mkdir(parents=True, exist_ok=True)
RUN_OUTPUT_DIR = OUTPUT_DIR / RUN_ID
RUN_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
print('Project:', PROJECT_NAME)
print('Run:', RUN_ID)
print('Outputs:', RUN_OUTPUT_DIR)
הפרדה בין startup לבין config חשובה כי אלה שני סוגי מידע שונים. Startup עונה על השאלה: איך מרימים סביבה. Config עונה על השאלה: מה הריצה הנוכחית מנסה לעשות. אם מערבבים ביניהם, כל שינוי קטן הופך לסיכון. למשל, אתם רוצים לבדוק מודל אחר. אם שם המודל מופיע בתא setup יחד עם mount ו-install, אתם עלולים לשבור את הסביבה רק כדי לשנות ניסוי. אם שם המודל נמצא בתא config, שינוי הניסוי לא נוגע ביסודות.
הוסיפו גם תא קצר של secrets policy. לא צריך לשמור בו סודות. להפך: הוא צריך להזכיר איפה סודות אמורים להיות. Colab מאפשר מנגנוני secrets, Kaggle מאפשר Secrets, וכלים שונים מחזיקים משתני סביבה. אבל במחברת לימודית קל מאוד להדביק token בתוך תא כי רוצים להתקדם. אל תעשו את זה. אם token מופיע במחברת, הוא יופיע גם בשיתוף, בגרסה, בצילום מסך או בהיסטוריה. כלל העבודה: במחברת יש שמות משתנים, לא ערכים סודיים.
עוד הרגל קטן: הוסיפו תא שמדפיס את עץ התיקיות החשובות. לא בשביל יופי. בשביל לאבחון. כאשר learner מתחיל אומר 'זה לא שומר', הרבה פעמים הבעיה היא שהוא שמר למקום אחר. אם התא מדפיס CHECKPOINT_DIR, OUTPUT_DIR, MODEL_DIR, ואת הקבצים האחרונים בכל אחד מהם, אפשר לזהות מהר אם הנתיב שגוי או אם הקובץ לא נוצר. זו אחת הסיבות שמחברת טובה כוללת תאי אבחון קטנים, לא רק תאי עבודה גדולים.
לבסוף, אל תריצו עבודה כבדה ישירות מול Drive אם היא קוראת אלפי קבצים קטנים. Colab FAQ עצמו מזהיר ש-Drive operations יכולים להיכשל או להאט כאשר יש הרבה קבצים ותיקיות. הדפוס היציב יותר הוא לשמור artifacts חשובים ב-Drive, אבל להעתיק archive מקומי לפני עבודה אינטנסיבית. למשל, dataset קטן אפשר לשמור כ-zip ב-Drive, להעתיק ל-/content, לפתוח מקומית, להריץ, ואז לשמור רק checkpoint ותוצרים חזרה ל-Drive. כך אתם משתמשים ב-Drive כמחסן, לא כדיסק עבודה אינטנסיבי.
Checkpointing: להציל עבודה לפני שהמחברת נעלמת
Checkpoint הוא הסכם עם העתיד. אתם אומרים: אם הסביבה תמות, אני לא אתחיל מאפס. בעולם training זה יכול להיות weights, optimizer state ו-step number. בעולם image generation זה יכול להיות workflow JSON, seed, prompt, output אחרון ורשימת קבצים שכבר נוצרו. בעולם data processing זה יכול להיות קובץ parquet אחרי כל batch. הפורמט משתנה, הרעיון זהה: העבודה היקרה נשמרת בשלבים קטנים.
הדפוס הבטוח מורכב משלושה חלקים. קודם מגדירים RUN_ID קבוע. אחר כך שומרים checkpoint בשם שמכיל step או timestamp. בסוף, בתחילת המחברת, מחפשים את ה-checkpoint האחרון וטוענים אותו אם הוא קיים. חשוב שהקוד לא יניח שיש checkpoint. בהרצה הראשונה אין. בהרצה השנייה אולי יש. אחרי שחזור חלקי אולי יש checkpoint פגום. קוד טוב מתייחס לזה במפורש.
2 דקות בחרו שם run קצר וקבוע, למשל sdxl_prompt_test_001 או tiny_llm_smoke_001. כתבו אותו בתא config אחד בלבד. אל תכתבו את השם ידנית בתוך שמות קבצים בהמשך.
# Generic checkpoint pattern
from pathlib import Path
import json
import time
RUN_ID = 'tiny_llm_smoke_001'
RUN_DIR = CHECKPOINT_DIR / RUN_ID
RUN_DIR.mkdir(parents=True, exist_ok=True)
def save_checkpoint(step, payload):
checkpoint_path = RUN_DIR / f'checkpoint_step_{step:05d}.json'
payload = dict(payload)
payload['step'] = step
payload['saved_at'] = time.strftime('%Y-%m-%d %H:%M:%S')
checkpoint_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding='utf-8')
print('saved', checkpoint_path)
def latest_checkpoint():
files = sorted(RUN_DIR.glob('checkpoint_step_*.json'))
return files[-1] if files else None
ckpt = latest_checkpoint()
if ckpt:
state = json.loads(ckpt.read_text(encoding='utf-8'))
print('resuming from', ckpt.name, 'step', state.get('step'))
else:
state = {'step': 0, 'items_done': []}
print('starting new run')
בדוגמה הזאת ה-checkpoint הוא JSON פשוט. באימון אמיתי תשתמשו אולי ב-trainer.save_model, ב-torch.save, או בפונקציה של framework אחר. אל תיתקעו על הפורמט. מה שחשוב הוא שהמחברת יודעת לענות על שלוש שאלות: איפה שומרים? מה השם של הריצה? מה הדבר האחרון שהושלם בהצלחה? אם אין תשובה ברורה, ה-checkpoint הוא קישוט.
יש גם צד שני: לא לשמור יותר מדי. Drive יכול להיות איטי, וקריאה/כתיבה של אלפי קבצים קטנים עלולה להכאיב. לכן שומרים נקודות משמעותיות, לא כל שורה. באימון קטן אולי כל 100 steps. בעיבוד רשימה אולי כל 20 items. בהפקת תמונות אולי אחרי כל prompt או batch. בנוסף, שמרו קובץ latest.json קטן שמצביע ל-checkpoint האחרון, או השתמשו במיון שמות עקבי כמו בדוגמה.
טעות נפוצה: לשמור checkpoints רק ל-/content
הטעות: ליצור תיקיית /content/checkpoints ולהרגיש מוגנים. למה זה מפתה? כי זה מהיר, וזה נראה כאילו הקבצים קיימים. מה לעשות במקום: לשמור ל-Drive, ל-Kaggle Output, או ל-Hub. אם צריך מהירות, אפשר לכתוב זמנית לדיסק המקומי ואז להעתיק checkpoint דחוס החוצה בסוף כל שלב.
תרגיל 2: מוסיפים checkpoint save/restore ל-run ארוך
זמן: 25 דקות. תוצר: דפוס שחזור עובד שאפשר להדביק ל-training, generation או batch processing.
- באותה מחברת Colab, הגדירו
RUN_IDקבוע ו-RUN_DIRתחת תיקיית checkpoints ב-Drive. - הדביקו את פונקציות
save_checkpointו-latest_checkpoint. - צרו לולאה מדומה של 10 צעדים. בכל צעד הוסיפו מספר לרשימת
items_doneושמרו checkpoint. - עצרו ידנית את התא אחרי 4 או 5 צעדים. הריצו מחדש את תא ה-startup ואת תא ה-checkpoint.
- שנו את הלולאה כך שתתחיל מ-
state['step'] + 1במקום מ-1. - הריצו עד הסוף ובדקו שלא נוצרו כפילויות ברשימת items.
פלט צפוי: תיקיית run עם קבצי checkpoint מסודרים, והדפסה שמראה resume מה-step האחרון שנשמר.
בשלב הזה אתם כבר לא תלויים בטאב. אתם תלויים בהרגל. זאת נקודה חשובה מאוד לקראת פרק 5, שבו תאימון LoRA על Kaggle יכול לקחת שעות. בלי checkpointing, session שנחתך אחרי כמה שעות הוא אסון קטן. עם checkpointing, זה אירוע מעצבן אבל צפוי: מתחברים, מריצים startup, טוענים checkpoint, ממשיכים.
Kaggle: כשצריך ריצה נקייה, Outputs וגרסה שאפשר לשחזר
Kaggle מרגיש דומה ל-Colab כי גם הוא notebook בדפדפן, אבל פילוסופיית העבודה שונה. Colab מצוין להתנסות אינטראקטיבית מהירה. Kaggle מצוין כשאתם רוצים ריצה שאפשר לשחזר, לשמור כ-Version, ולהסתכל על Outputs אחר כך. ב-Kaggle יש חשיבה מובנית של Notebook Versions: אתם יכולים לעבוד אינטראקטיבית, ואז לעשות Save & Run All כדי להריץ את הכל מלמעלה למטה בסביבה נקייה. אם זה עובר, יש לכם הוכחה שהמחברת לא תלויה ב-state סודי שנשאר מאיזה תא שרץ לפני שעתיים.
זה יתרון עצום לפרויקטים אמיתיים. הרבה מחברות נראות עובדות כי המשתנה model נשאר בזיכרון, כי cell ישן יצר תיקייה, או כי package הותקן ידנית. ברגע שמריצים נקי, כל ההנחות הנסתרות יוצאות לאור. לכן תרגיל Kaggle בפרק הזה לא רק 'פותחים GPU'. הוא מלמד לכתוב מחברת שמייצרת artifact ברור תחת /kaggle/working ומצליחה להריץ clean run.
4 דקות פתחו Kaggle Notebook חדש. לפני כתיבת קוד, מצאו בעיניים את Settings, Accelerator, Internet, Output ו-Save Version. כתבו בתא Markdown מה ההבדל בין Quick Save לבין Save & Run All.
ב-Kaggle, קבצי output שנכתבים למיקום הנכון נשמרים כחלק מהגרסה. זה לא אומר שכל דבר בכל מקום נשמר לנצח, וזה לא אומר שאפשר להתעלם מ-quota. אבל זה כן נותן לכם יעד ברור לתוצרים. כתבו ל-/kaggle/working. אם צריך קובץ input קבוע, השתמשו ב-Dataset attached או במודל attached. אם צריך להוריד package, ודאו ש-Internet מופעל או השתמשו ב-Dependency Manager כאשר התחרות או הסביבה דורשת internet disabled.
# Kaggle smoke cell
from pathlib import Path
import subprocess
import json
import time
WORKING = Path('/kaggle/working') if Path('/kaggle/working').exists() else Path('./kaggle-working')
WORKING.mkdir(parents=True, exist_ok=True)
subprocess.run(['nvidia-smi'], check=False)
report = {
'created_at': time.strftime('%Y-%m-%d %H:%M:%S'),
'working_dir': str(WORKING),
'note': 'If this file appears in Outputs, the notebook produces an artifact.'
}
(WORKING / 'gpu_notebook_smoke_report.json').write_text(json.dumps(report, indent=2), encoding='utf-8')
print('wrote', WORKING / 'gpu_notebook_smoke_report.json')
היתרון של Kaggle אינו רק storage. הוא discipline. אם אתם עושים Save & Run All ומקבלים failure, זה סימן טוב. כן, טוב. זה אומר שמצאתם הנחה נסתרת עכשיו, לפני שהמחברת הפכה לחלק מ-pipeline. הכישלונות הנפוצים: שכחתם install; כתבתם נתיב מקומי שאינו קיים בריצה נקייה; הורדתם מודל בלי לאשר license; Internet כבוי; או שה-output נכתב למיקום שלא נשמר. כל אחד מהם קל לתיקון כשמגלים מוקדם.
טעות נפוצה: לחשוב ש-quota שבועי הוא session רצוף
הטעות: לראות מספר גדול של GPU-hours ולהניח שאפשר להריץ job אחד רצוף עד הסוף. למה זה מפתה? כי המספר השבועי נשמע כמו בנק שעות אחד. מה לעשות במקום: לתכנן את המחברת כך שכל שלב יכול להיעצר ולהתחיל מחדש. גם ב-Kaggle, session boundaries ו-runtime limits הם חלק מהמשחק.
Kaggle גם טוב כשאתם רוצים לשתף או לתעד תוצאה. גרסת Notebook שכוללת logs ו-output היא artifact לימודי. אפשר לראות איך נוצר הקובץ, לא רק את הקובץ עצמו. אם אתם עובדים עם לקוח ישראלי קטן, למשל סטודיו שמנסה ליצור תמונות מוצר או לבדוק fine-tune קטן, היכולת לשלוח notebook version שמראה ריצה נקייה חוסכת הרבה 'אבל אצלי זה עבד'.
תרגיל 3: Kaggle notebook שרץ נקי ומוציא artifact
זמן: 30 דקות. תוצר: Kaggle Version עם קובץ output שאפשר להוריד או לחבר למחברת אחרת.
- צרו Notebook חדש ב-Kaggle וקראו לו
free_gpu_artifact_ch03. - ב-Settings בחרו Accelerator זמין. אם אין GPU כרגע, כתבו זאת בתא Markdown והריצו את התרגיל על CPU רק כדי לבדוק output.
- ודאו ש-Internet מופעל אם אתם מתקינים package קטן. אל תורידו מודל גדול בתרגיל הזה.
- הדביקו את תא ה-smoke שמייצר
gpu_notebook_smoke_report.jsonתחת/kaggle/working. - לחצו Save Version ובחרו Save & Run All. חכו לסיום הריצה.
- פתחו את Output ובדקו שהקובץ מופיע. הורידו אותו או צרפו אותו כ-input למחברת אחרת אם אתם רוצים להמשיך.
פלט צפוי: גרסת Kaggle נקייה עם JSON output, בלי תלות בתא שרץ ידנית לפני כן.
הדפוס הזה יהיה הבסיס ל-QLoRA בפרק 5. שם כבר יהיו checkpoints, adapters ו-Hugging Face Hub. כאן אתם מתרגלים על קובץ קטן כדי לא לערבב שתי בעיות: איך שומרים artifact ואיך מאמנים מודל. קודם מוכיחים את הצינור. אחר כך מכניסים אליו עבודה כבדה.
בחירה בין Accelerator types ב-Kaggle צריכה להיות החלטה ולא ניחוש. אם יש לכם P100, הוא יכול להיות נוח למשימות מסוימות בזכות VRAM ופשטות של GPU יחיד. אם יש לכם T4 x2, אל תניחו אוטומטית שכל קוד משתמש בשני הכרטיסים. רוב notebook code הפשוט יראה רק GPU אחד או ישתמש רק ב-device הראשון אלא אם הגדרתם multi-GPU במפורש. לכן T4 x2 הוא יתרון רק כאשר הספרייה או הקוד שלכם יודעים לעבוד במקביל, או כאשר אתם מפצלים jobs ידנית. לפרק הזה, GPU יחיד יציב ומובן עדיף על dual GPU שלא ברור איך מנוצל.
יש גם הבדל בין עבודה אינטראקטיבית לבין גרסת notebook. בזמן עריכה, אתם חיים בתוך session שיש לו state. אתם יכולים להריץ תא מספר 8 לפני תא מספר 4, לשנות משתנה ביד, ולשכוח שעשיתם את זה. בזמן Save & Run All, Kaggle מריץ את המחברת מלמעלה למטה. זה מעצבן רק אם המחברת שלכם לא מסודרת. אם היא מסודרת, זה נותן לכם ביטחון. לכן לפני כל גרסה משמעותית, שאלו: האם כל import מופיע לפני השימוש? האם כל path מוגדר לפני כתיבה? האם כל download או install מתועד? האם output נכתב למקום שנשמר?
כאשר עובדים עם datasets, אל תערבבו בין input קבוע לבין output שנוצר. Input הוא משהו שאתם מצרפים למחברת: dataset, model, קובץ config או קובץ דוגמה. Output הוא מה שה-run הנוכחי יצר. אם אתם משתמשים בקובץ שנוצר אתמול כאילו הוא input, צרפו אותו כ-dataset או תעדו מאיפה הוא מגיע. אחרת clean run ייכשל כי הקובץ היה קיים רק בזיכרון או ב-output של session קודם. זה בדיוק סוג ה-state הנסתר ש-Kaggle עוזר לחשוף.
לצוותים קטנים, במיוחד כשיש לקוח או שותף לא טכני, Kaggle Version יכול לשמש דוח עבודה. במקום לומר 'הרצתי וזה הצליח', אתם מראים גרסה עם logs ו-output. אם התוצר הוא adapter קטן, CSV, benchmark JSON או batch של תמונות, ה-output הופך למסמך אמון. זה לא מחליף deployment, אבל זה שלב מעולה לפני deployment: אפשר לבדוק שהתהליך רץ נקי, שהתוצרים במקום, ושאין תלות במחשב האישי שלכם.
החיסרון: Kaggle לא אמור להיות מחסן לכל דבר. אל תעלו secrets ל-Datasets. אל תשמרו מידע לקוח רגיש אם אין לכם אישור ותנאים ברורים. אל תבנו סביב assumption שה-quota שלכם זהה ל-quota של מישהו אחר. כמו Colab, גם Kaggle הוא free compute עם חוקים. ההבדל הוא ש-Kaggle נותן לכם יותר כלים למסמוך והרצה נקייה. השתמשו בזה כדי להקטין אי ודאות, לא כדי להעמיס עבודה שאינה שייכת לשם.
VRAM Budgeting על T4: למדוד לפני שמקבלים OOM
ה-T4 הוא ה-GPU החינמי הקלאסי: מספיק טוב להמון ניסויים, לא סלחן לבזבוז. כשאנחנו אומרים VRAM Budgeting (תכנון זיכרון GPU), הכוונה היא לא לנחש אם מודל 'אמור להיכנס'. הכוונה היא לפרק את הדרישה לזיכרון לגורמים: weights, precision או quantization, KV cache במקרה של LLM, activations, batch size, resolution במקרה של diffusion, ומעט overhead של framework. ברגע שמסתכלים על זה כתקציב, OOM מפסיק להיות הפתעה מיסטית.
הכלל הפשוט: התחילו קטן, מדדו, ורק אז הגדילו. אל תתחילו SDXL עם batch size 4. אל תתחילו LLM עם context 32K. אל תוסיפו ControlNet לפני שראיתם שהבסיס עובד. ב-T4 של כ-15GB VRAM, הרבה דברים אפשריים אם מתחילים שמרני. SDXL ברזולוציה סבירה וב-batch 1 יכול לעבוד. מודל 7B quantized יכול לעבוד בקונטקסט קצר. Flux.1 Schnell יכול להיות אפשרי בדפוסים מסוימים, אבל הוא רגיש יותר לזיכרון וליישום. כל אחד מהם צריך בדיקת עשן, לא אמונה.
4 דקות לפני כל job, כתבו בשורה אחת: model, precision/quantization, context או resolution, batch size, target output. אם אחד מהם ריק, אתם עדיין לא מוכנים להרצה.
| Job | מה מתחילים ממנו | מה מורידים ראשון ב-OOM | סימן שהגיע הזמן ל-fallback |
|---|---|---|---|
| 7B LLM inference | 4-bit או Q4, context קצר, batch 1 | context length, max tokens, batch | גם context קצר לא עולה או latency בלתי שמיש |
| SDXL image generation | batch 1, resolution מתונה, בלי ControlNet | resolution, steps, extra nodes | כל תוספת קטנה מפילה את הריצה |
| Flux-style workflow | מודל קל/גרסת schnell, batch 1, workflow מינימלי | resolution, offload settings, nodes | התקנה/טעינה אוכלת את כל הסשן |
| LoRA training קטן | QLoRA, micro batch 1, gradient accumulation | sequence length, rank, batch | אין מקום גם אחרי הקטנות בסיסיות |
בכל הרצה מעשית, מדידה פשוטה טובה יותר מנוסחה יפה. הריצו nvidia-smi לפני טעינת המודל, אחרי טעינת המודל, ואחרי generation ראשון. הפער בין לפני ואחרי טעינה הוא בערך עלות weights ועוד overhead. הפער בזמן generation מלמד אתכם על activations ו-cache. אם הזיכרון עולה ולא חוזר, יכול להיות שאתם מחזיקים tensors בזיכרון או שה-framework שומר cache. לפעמים הפתרון הוא torch.cuda.empty_cache(), אבל לא להפוך את זה לקמע. אם התהליך ממשיך לצבור זיכרון, צריך להבין מה נשמר.
2 דקות בכל notebook שבו יש GPU, הריצו nvidia-smi לפני טעינת מודל ואחרי טעינה. כתבו ליד שם המודל כמה GB נוספו. זה יוצר לכם intuition הרבה יותר מהר מקריאת בלוגים.
מסגרת החלטה: VRAM triage בזמן OOM
- אם OOM קורה בזמן טעינת המודל: המודל או ה-precision גדולים מדי. עברו לגרסה קטנה, quantization נמוך יותר, או API fallback מפרק 2.
- אם OOM קורה בזמן generation: הורידו context, resolution, batch size או מספר nodes פעילים.
- אם OOM קורה אחרי כמה איטרציות: בדקו שאתם לא שומרים tensors, outputs או pipelines בזיכרון בלי צורך.
- אם OOM קורה רק אחרי הוספת feature: חזרו לבסיס שעבד והוסיפו feature אחד בכל פעם.
טעות נפוצה: להעלות batch size לפני שיש baseline
הטעות: לראות שה-GPU לא מנוצל ב-100% ולהעלות batch size מיד. למה זה מפתה? כי זה מרגיש כמו optimization. מה לעשות במקום: קודם לקבל פלט נכון ב-batch 1. אחר כך למדוד VRAM. רק אם יש headroom ברור, מעלים בהדרגה.
שימו לב שהמספרים בפרק הזה הם דפוסי עבודה, לא חוזה. VRAM בפועל מושפע מגרסת PyTorch, attention backend, drivers, model implementation, dtype, quantization, scheduler, וגם מאילו תאים רצו לפני כן. לכן טבלת VRAM היא מפה, לא GPS. הדבר המקצועי הוא לצרף לטבלה מדידה משלכם. אחרי כמה ניסויים, תדעו מהר מאוד מה ה-T4 הנוכחי שלכם מסוגל לסחוב ומה צריך לעבור ל-Kaggle, ל-API או ל-local.
כדי שהמדידה תהיה שימושית, שמרו אותה בקובץ קטן ולא רק ב-output של התא. אפשר ליצור vram_log.jsonl, וכל שורה בו מתארת אירוע: before_load, after_load, after_generation, after_cleanup. כל אירוע כולל timestamp, שם מודל, batch size, context או resolution, והזיכרון שנצפה. אחרי שבוע של ניסויים יהיה לכם dataset אישי שמספר מה באמת עובד על הסביבה שלכם. זה הרבה יותר טוב מרשימת שמועות ברשת, כי הוא נמדד אצלכם.
# Simple VRAM experiment log
import json
import time
from pathlib import Path
VRAM_LOG = OUTPUT_DIR / 'vram_log.jsonl'
def log_vram_event(event, model_name, settings, observed_note):
row = {
'time': time.strftime('%Y-%m-%d %H:%M:%S'),
'event': event,
'model': model_name,
'settings': settings,
'observed': observed_note
}
with VRAM_LOG.open('a', encoding='utf-8') as f:
f.write(json.dumps(row, ensure_ascii=False) + '\n')
print('logged', event)
log_vram_event(
event='before_load',
model_name='example-7b-q4',
settings={'context': 2048, 'batch': 1},
observed_note='record nvidia-smi value manually or parse it later'
)
אל תנסו לאוטומט הכל מהיום הראשון. אפשר להתחיל ב-manual note: לפני טעינה 1.2GB בשימוש, אחרי טעינה 6.8GB, אחרי generation 8.1GB. זה מספיק כדי ללמד. בהמשך אפשר לפרסר את nvidia-smi או להשתמש ב-torch.cuda.memory_allocated(). העיקר הוא שהמדידה צמודה להגדרות. מספר VRAM בלי context length או resolution הוא כמעט חסר ערך, כי אין דרך לדעת מה גרם לו.
ב-image workflows, שימו לב במיוחד לצמתים שמוסיפים זיכרון בלי שנראה כאילו הם 'מודל גדול'. ControlNet, upscale, hires fix, inpainting masks, previews איכותיים ו-batch latent יכולים להזיז את התקציב מהר מאוד. לכן תבנו workflow בסיסי שעובד, תשמרו אותו, ואז תוסיפו node אחד בכל פעם. אם אחרי הוספת node יש OOM, אתם יודעים מי החשוד. אם הוספתם חמישה דברים בבת אחת, אתם חוזרים לניחוש.
ב-LLM workflows, האויב השקט הוא context. משתמש רואה חלון context גדול וחושב שהוא מתנה. מבחינת VRAM, זו התחייבות. ככל שה-context גדל, KV cache גדל. אם אתם רק בודקים prompt קצר, אין סיבה לפתוח context ענק. התחילו ב-2K או 4K, קבלו פלט, ואז הגדילו רק אם המשימה דורשת. מי שמתחיל ב-32K כי 'אולי נצטרך', משלם על אולי בזיכרון אמיתי.
Inference 7B: בדיקת עשן שלא שורפת את כל הסשן
לפני שמריצים מודל 7B על notebook חינמי, צריך לשאול למה. אם המטרה היא chatbot או סקריפט טקסט רגיל, פרק 2 כבר נתן לכם inference APIs חינמיים שכנראה יהיו מהירים יותר וקלים יותר. GPU notebook מוצדק כשאתם צריכים לשלוט בסביבה, לבדוק קוד מודל, להריץ pipeline שכולל קבצים מקומיים, למדוד VRAM, או להכין בסיס ל-training. כלומר, לא כל LLM צריך GPU notebook. אבל כשכן צריך, הבדיקה הראשונה צריכה להיות קטנה.
בדיקת עשן טובה לא מנסה להפיק תשובה מושלמת. היא עונה על ארבע שאלות: האם המודל נטען, כמה VRAM הוא תפס, האם generation קצר עובד, והאם אפשר לשחרר או להמשיך בלי להרוג את הסשן. אם הבדיקה הזאת נכשלת, אל תמשיכו ל-prompt ארוך. אם היא מצליחה, אפשר להרחיב בהדרגה.
# Minimal measurement pattern for a small model load
import subprocess
def show_gpu(label):
print('\n---', label, '---')
subprocess.run(['nvidia-smi'], check=False)
show_gpu('before load')
# Load your small/quantized model here.
# Keep the first prompt tiny and max_new_tokens low.
show_gpu('after load')
prompt = 'ענה בעברית במשפט אחד: למה checkpoint חשוב ב-Colab?'
print('prompt ready:', prompt)
# Run generation here, then measure again.
show_gpu('after first generation')
3 דקות הכינו בתא אחד פונקציה בשם show_gpu שמדפיסה nvidia-smi עם label. השתמשו בה לפני טעינה, אחרי טעינה ואחרי generation ראשון.
בשלב הזה אתם לא צריכים להתחייב לספריית inference אחת. חלק מהלומדים ישתמשו ב-transformers, חלק ב-llama.cpp binding, חלק ב-notebook מוכן של מודל מסוים. מה שחשוב הוא שצורת העבודה נשארת זהה: תא setup, תא measurement, טעינה קטנה, פלט קצר, שמירת תוצאה. אם אתם מוצאים את עצמכם מתקינים 15 חבילות ומחכים 20 דקות לפני שראיתם GPU memory, עצרו. פצלו את העבודה לשלבים קטנים יותר.
יש גם כלל fallback: אם אתם לא צריכים fine-tune, לא צריכים גישה ל-weights, ולא צריכים סביבת notebook, API מפרק 2 הוא כנראה הבחירה הנכונה. הנטייה של vibe coders היא להריץ הכל בעצמם כי זה מרגיש יותר 'אמיתי'. אבל engineering טוב הוא לבחור את השכבה הנכונה. Notebook GPU הוא יקר בזמן ובשבריריות, גם כשהוא חינם בכסף. השתמשו בו כשיש סיבה.
ComfyUI על Colab: דמו קצר, Workflow שמור, Tunnel זמני
ComfyUI הוא דוגמה מצוינת ל-GPU notebook כי הוא משלב התקנה, מודלים גדולים, UI מקומי, workflow JSON, ותוצר חזותי. הוא גם דוגמה מצוינת למה לא להפוך Colab חינמי לשרת. Colab מיועד ל-interactive compute, לא לשירות web ציבורי שמשרת משתמשים. לכן בפרק הזה ComfyUI הוא דמו קצר ולמידה, לא deployment. בפרק 5 נבנה pipeline אחראי יותר; כאן אנחנו רוצים להבין איך לשמור workflow ולשרוד session loss.
העיקרון: הקוד יכול להיבנות מחדש, המודלים יכולים לרדת מחדש אם חייבים, אבל workflow JSON ותוצרים חשובים צריכים להישמר מחוץ ל-runtime. אם אתם מתקינים custom nodes, תעדו אותם בתא startup. אם אתם מורידים models, שמרו רשימת URLs או מקורות. אם אתם מייצרים workflow יפה, שמרו אותו ל-Drive מיד. מי שסומך על זה שה-UI עדיין פתוח אחרי disconnect, לומד בדרך הקשה.
2 דקות בתוך תיקיית Drive של הפרק צרו קובץ ריק בשם workflow-backup.json. המטרה היא להזכיר לכם שה-workflow הוא artifact, לא משהו שחי רק בתוך canvas פתוח.
# Sketch of a Colab ComfyUI setup cell
from pathlib import Path
COMFY_ROOT = Path('/content/ComfyUI')
WORKFLOW_BACKUP = WORKFLOW_DIR / 'workflow-backup.json'
print('workflow backup target:', WORKFLOW_BACKUP)
# Typical flow, keep this restartable:
# 1. git clone ComfyUI if missing
# 2. pip install requirements
# 3. put models in persistent or documented locations
# 4. run python main.py --listen 0.0.0.0 --port 8188
כאן חשוב לדבר על ngrok. ngrok Tunnel הוא דרך נוחה לתת כתובת HTTPS זמנית לשירות שרץ בתוך ה-notebook, למשל ComfyUI על port 8188. זה מעולה לבדיקה קצרה. זה מסוכן אם אתם שוכחים שהשירות נגיש מהאינטרנט. אל תשימו tokens בתוך UI. אל תחשפו תיקיות עם מידע רגיש. אל תשאירו tunnel פתוח אחרי שסיימתם. אם אתם צריכים לשתף עם לקוח, השתמשו ב-demo קצר, תנו לו לראות, ואז סגרו. זה לא hosting.
# ngrok sketch, demo only
# Install pyngrok or ngrok agent according to current docs.
# Add your auth token securely in Colab secrets or prompt, not hardcoded in a public notebook.
# Example shell shape:
# python main.py --listen 0.0.0.0 --port 8188
# ngrok http 8188
טעות נפוצה: לפתוח tunnel ציבורי עם secrets בסביבה
הטעות: להעתיק auth token או API key לתא גלוי, לפתוח ComfyUI דרך ngrok, ולשתף את ה-URL. למה זה מפתה? כי זה עובד מהר. מה לעשות במקום: להשתמש ב-Colab secrets או prompt זמני, לא לשמור secrets במחברת, לסגור tunnel מיד, ולהתייחס לדמו כאירוע זמני בלבד.
ComfyUI עובד דרך גרף nodes. הגרף הזה הוא בדיוק מה שאתם רוצים לשמור. הוא כולל prompts, models, sampler, resolution, seed וקשרים בין nodes. אם אתם מייצרים תמונה טובה אבל לא שומרים את workflow JSON, יש לכם screenshot יפה ולא תהליך. אם אתם שומרים JSON, יש לכם מתכון שאפשר להריץ שוב, לשנות, להראות, ולחבר ל-pipeline.
תרגיל 4: ComfyUI demo עם workflow שנשמר מחוץ לסשן
זמן: 30 דקות. תוצר: URL זמני לדמו, workflow JSON שמור ב-Drive, ותיעוד קצר שמסביר איך להריץ מחדש.
- פתחו מחברת Colab נפרדת או העתק של המחברת הקיימת. אל תערבבו ComfyUI עם תרגילי ה-LLM אם אתם רוצים לשמור על ניקיון.
- הריצו startup cell שמחבר Drive ומגדיר
WORKFLOW_DIR. - התקינו ComfyUI לפי ההוראות העדכניות של הפרויקט: clone, install requirements, run server. שמרו את פקודות ההתקנה בתא אחד מסודר.
- הריצו את ComfyUI על port 8188 ופתחו tunnel זמני עם ngrok או כלי דומה. אל תכתבו auth token בתוך מחברת ציבורית.
- בתוך ComfyUI, צרו workflow מינימלי או טענו דוגמה קיימת. שמרו את workflow JSON לתיקיית Drive שהגדרתם.
- סגרו את ה-tunnel, נתקו runtime, התחברו מחדש, והריצו רק את תאי setup. בדקו שה-workflow JSON עדיין קיים.
פלט צפוי: קובץ workflow-backup.json ב-Drive, הערת Markdown עם פקודות restart, וידיעה ברורה שה-URL הזמני אינו deployment.
יש כאן נקודת בגרות: לא כל מה שאפשר לחשוף באינטרנט צריך לחשוף. אם אתם בונים Discord bot לתמונות, כמו בדוגמה היצירתית של הקורס, Kaggle או Colab יכולים להיות מנוע זמני לניסויים. אבל ברגע שיש משתמשים אמיתיים, צריך לחשוב על quotas, תורים, אבטחה, עלויות ותנאי שימוש. בפרק הזה אנחנו לומדים mechanics. לא מדלגים מכאן ל-production.
כדאי לכתוב runbook קצר ליד מחברת ComfyUI, לא בתוך הראש. Runbook טוב כולל ארבעה חלקים: איך מתקינים, איפה שמים מודלים, איך מפעילים server, ואיך סוגרים אותו. לכל פקודה צריכה להיות סיבה. אם אתם מתקינים custom nodes, כתבו מאיפה הם באים ולמה צריך אותם. אם אתם מורידים checkpoint גדול, כתבו מה הגודל המשוער ומה יעשה מי שאין לו מקום. אם אתם משתמשים ב-ngrok, כתבו איפה סוגרים את ה-process. מסמך כזה נשמע מיותר עד הפעם הראשונה שבה אתם חוזרים למחברת אחרי שבוע ולא זוכרים מה היה ידני.
דפוס טוב ל-ComfyUI על notebook חינמי הוא 'מינימום קבוע, הרחבות זמניות'. המינימום הקבוע הוא startup, workflow folder, output folder ורשימת מודלים. ההרחבות הזמניות הן custom nodes, tunnels, ניסויי UI ושינויים ב-graph. כאשר הרחבה הופכת לחשובה, מעבירים אותה לרשימת setup מסודרת. כך המחברת לא מתנפחת לאוסף פקודות היסטוריות שכל אחת אולי עדיין נחוצה. אחת לשבוע, מחקו או העבירו לארכיון תאים שאינם חלק מהריצה הנקייה.
עוד כלל: לעולם אל תמדדו הצלחה לפי זה שה-UI נפתח. UI שנפתח הוא רק שלב. הצלחה היא workflow נטען, model נמצא, generation קצר הצליח, output נשמר, workflow JSON נשמר, וה-tunnel נסגר. אם אחד מהם חסר, הדמו עדיין לא שלם. זה נכון גם לדברים שאינם ComfyUI. כל כלי notebook עם UI צריך success criteria ברורים, אחרת הלומד מתרגש מהמסך ושוכח את artifact.
לגבי מודלים גדולים, אל תשתמשו ב-Drive כתיקיית models פעילה אם זה גורם לקריאות איטיות. הרבה פעמים עדיף לשמור model source ותסריט הורדה, ולהוריד מחדש לדיסק המקומי כאשר הסשן מתחיל. במקרים אחרים, אם המודל לא גדול מדי וה-Drive יציב, אפשר לשמור אותו שם כדי לחסוך זמן. אין כלל אחד. יש tradeoff: מהירות התחלה מול אמינות I/O מול מקום פנוי. לכן הפרק מלמד אתכם למדוד ולתעד, לא רק להעתיק פקודות.
כאשר אתם משתפים דמו עם לקוח ישראלי או חבר צוות, הסבירו מראש שזה דמו זמני. אל תגידו 'המערכת באוויר'. תגידו: 'פתחתי tunnel זמני למחברת GPU, הוא ייסגר בסוף הבדיקה'. ניסוח כזה מונע ציפיות שגויות. הוא גם מכריח אתכם להבחין בין prototype לבין service. הרבה פרויקטי $0 נופלים לא בגלל שהטכנולוגיה לא עובדת, אלא בגלל שהציגו ניסוי כאילו הוא תשתית.
מסגרות החלטה: Colab, Kaggle או בכלל API
אחרי כל התרגילים, קל לחשוב ש-Colab ו-Kaggle הם שתי גרסאות של אותו דבר. בפועל, הם כלים שונים. Colab הוא שולחן עבודה מהיר. Kaggle הוא סביבת ריצה עם גרסאות ו-outputs. API הוא בכלל מסלול אחר: אין לכם GPU, אין לכם weights, אבל יש לכם latency נמוך ופחות תחזוקת סביבה. Local, שנלמד בפרק הבא, הוא המסלול היחיד שהוא באמת שלכם, אבל הוא דורש חומרה וזמן setup.
מסגרת החלטה: בחירת פלטפורמה לפי צורת ה-job
| הצורך | בחירה ראשונה | Fallback |
|---|---|---|
| בדיקת notebook אינטראקטיבית עם GPU | Colab | Kaggle אם צריך output משוחזר |
| ריצה שצריכה artifact נקי לשיתוף | Kaggle | Colab עם Drive ו-report מסודר |
| Text inference בלבד | API מפרק 2 | Local בפרק 4 אם פרטיות חשובה |
| דמו UI קצר עם GPU | Colab + tunnel זמני | HF Space או Kaggle לניסוי אחר |
| עבודה קבועה ללא מגבלות ענן | Local בפרק 4 | API כאשר local איטי מדי |
4 דקות קחו פרויקט אחד שלכם, למשל image bot, prompt tester או dataset cleaner. כתבו לו פלטפורמה ראשית ופלטפורמת fallback. אם אין לכם fallback, אתם עדיין לא מוכנים להריץ אותו לאורך זמן.
דוגמא מייצגת: אתם רוצים ליצור 200 תמונות מוצר בשבוע עבור חנות קטנה בישראל בלי לשלם על GPU. Colab יכול לעבוד לניסוי ידני קצר. Kaggle יכול להיות טוב יותר אם אתם מריצים batch מתועד ושומרים outputs. ComfyUI דרך tunnel נחמד לדמו, אבל לא כשרת קבוע. אם החנות צריכה ממשק קבוע, צריך לשלב API, queue, storage ותהליך שמכבד מגבלות. זו לא בעיה של 'איזה GPU הכי חזק'. זו בעיה של צורת עבודה.
דוגמא אחרת: אתם בונים coding assistant פנימי שמריץ מודל 70B לשאלות קוד. GPU notebook הוא כמעט תמיד הבחירה הלא נכונה. אין לכם צורך ב-training, אין צורך ב-weights, ואתם רוצים זמינות. פרק 2 נתן APIs חינמיים עם rotation. אם צריך פרטיות מלאה, חכו לפרק 4 ובנו local קטן. Notebook GPU יהיה רק רעש.
כדי להפוך את ההחלטה הזאת להרגל, כתבו לכל job כרטיס תכנון קצר לפני שאתם פותחים notebook. הכרטיס צריך לכלול: מה התוצר, כמה זמן הריצה צפויה לקחת, האם צריך GPU state, האם יש מידע רגיש, איפה נשמר output, ומה קורה אם הסשן מת. זה נשמע איטי, אבל זה חוסך שעות. אם הכרטיס אומר 'התוצר הוא תשובת טקסט קצרה, אין קבצים, אין training, אין צורך ב-weights', אתם לא צריכים GPU notebook. אם הכרטיס אומר 'התוצר הוא adapter, צריך לשמור checkpoints, צריך לקרוא dataset, והריצה עשויה להימשך שעות', notebook GPU מתאים, אבל רק אם יש checkpointing.
הכרטיס הזה גם עוזר מול מגבלות $0. Free compute אינו חינם מבחינת תשומת לב. הוא דורש תזמון, בדיקות, fallback ותחזוקה. אם אתם מריצים job קטן פעם בחודש, Colab יכול להספיק. אם אתם מריצים job שבועי שצריך output משוחזר, Kaggle כנראה נוח יותר. אם אתם צריכים endpoint שעובד כל יום, free notebook הוא כמעט בוודאות השכבה הלא נכונה. אל תבחרו לפי מה שהכי מרגש לפתוח. בחרו לפי מה שיקטין את מספר הדברים שיכולים להישבר.
בפועל, הרבה פרויקטים משלבים כמה שכבות. למשל, מחקר prompt יכול להתחיל ב-API מפרק 2, לעבור ל-Colab כאשר צריך לבדוק מודל קטן עם קבצים, לעבור ל-Kaggle כאשר צריך run נקי ו-output, ואז לעבור ל-local בפרק 4 כאשר רוצים פרטיות או עבודה ללא quotas. המעבר בין שכבות אינו כישלון. הוא סימן שאתם מבינים את הצורה של הבעיה. הבעיה משתנה, הפלטפורמה משתנה איתה.
שאלו גם מי המשתמש של ה-output. אם זה אתם, notebook אינטראקטיבי יכול להיות מספיק. אם זה חבר צוות, צריך README קטן, config ברור ו-output שאפשר להוריד. אם זה לקוח, צריך artifact שאפשר להסביר בלי שיצטרך לפתוח את כל המחברת. אם זה משתמש קצה, אתם כבר בעולם deployment ולא בעולם notebook. ההבחנה הזאת מונעת את הטעות הנפוצה של להציג notebook כ'מוצר'. Notebook הוא סדנה, מעבדה, או תהליך batch. מוצר דורש שכבה אחרת.
עוד שאלה: מה יקרה כשהפלטפורמה לא זמינה בשעה שבה תכננתם לעבוד? Colab יכול לתת CPU במקום GPU. Kaggle יכול לשים אתכם בתור או להגביל session. ngrok tunnel יכול להיסגר. Drive יכול להיתקע על I/O. אם התשובה היא 'אני מחכה', זה בסדר לפרויקט לימודי. אם התשובה היא 'הלקוח מחכה', זה סימן שצריך fallback או שכבת serving אחרת. בפרק 2 כבר בנינו fallback API. בפרק 4 נבנה fallback local. כאן אתם לומדים לא להשאיר את עצמכם עם דרך אחת בלבד.
לבסוף, תנו שם מפורש לכל job. לא 'test', לא 'new notebook', לא 'final final'. שם טוב כולל מטרה, תאריך או מספר run, ופלטפורמה. לדוגמה: ch03_colab_sdxl_smoke_001, kaggle_7b_vram_log_002, comfyui_workflow_backup_003. שם כזה הופך folder מבולגן ליומן עבודה. כאשר תחזרו אחרי שבוע, תדעו מה היה ניסוי, מה היה baseline, ומה אפשר למחוק. זה נשמע קטן, אבל בפרויקטי free compute, סדר הוא חלק מהביצועים.
אם אתם עובדים בצוות, הוסיפו בסוף כל notebook תא Markdown בשם Handoff. בתא הזה כתבו: מה רץ, מה נשמר, איפה ה-checkpoint, מה נכשל, ומה הצעד הבא. אל תשאירו את המידע הזה רק ב-output של תאים. Output נגלל, נמחק או מתיישן. Handoff כתוב הופך מחברת חד-פעמית לכלי עבודה. זו גם דרך טובה להבחין בין ניסוי שראוי להמשיך לבין ניסוי שצריך לארכב.
כדאי להוסיף גם תא Recovery Drill קטן, במיוחד במחברות שאתם מתכננים להשתמש בהן יותר מפעם אחת. התא הזה לא מריץ את כל העבודה מחדש; הוא רק בודק שהמחברת יודעת להתאושש. הוא קורא את קובץ ה-config, מאמת שהתיקיות הקבועות קיימות, מחפש את ה-checkpoint האחרון, מדפיס את שם ה-GPU הנוכחי, ובודק שאפשר לכתוב קובץ קטן לתיקיית output. אם התא נכשל, אל תתחילו run ארוך. תקנו את recovery לפני העבודה עצמה. זה נשמע כמו טקס מיותר עד הפעם הראשונה שבה Colab מתנתק אחרי שעתיים, ואתם מגלים שהנתיב ששמרתם אליו היה ephemeral.
Recovery Drill טוב צריך להיות קצר מספיק כדי שתפעילו אותו באמת. למשל: שלוש בדיקות filesystem, בדיקת GPU אחת, בדיקת package version אחת, וטעינה יבשה של artifact אחד. אל תכניסו אליו training, download כבד או התקנת סביבה מלאה. המטרה היא לקבל תשובה בתוך דקה: אפשר להמשיך, צריך fallback, או צריך לעצור. אם אתם עובדים עם Kaggle, התא יכול גם לבדוק ש-Output מהגרסה הקודמת זמין וששם הקובץ תואם למה שהסקריפט מצפה. אם אתם עובדים עם Drive, התא צריך לבדוק שה-mount לא רק הצליח אלא גם באמת מכיל את תיקיית הפרויקט.
הוסיפו גם מדיניות ניקוי. Free notebooks נוטים להפוך למחסן: checkpoints כפולים, models שהורדו פעמיים, תמונות ביניים, logs ענקיים, וקבצי zip שלא ברור מי צריך אותם. בסוף כל run שאלו מה חייב להישאר כדי לשחזר תוצאה: config, seed, prompt, checkpoint אחרון, output סופי, ושורת פקודה או cell שמייצר אותם. כל השאר הוא מועמד למחיקה או ארכוב. ניקוי אינו רק עניין אסתטי. כאשר Drive מתמלא או Kaggle output גדל מדי, runs מתחילים להיכשל בדרכים שנראות כמו בעיות קוד אבל הן בעצם בעיות תחזוקה.
לבסוף, הפרידו בין מחברת לימודית למחברת production-like. במחברת לימודית מותר לחקור, להדביק תאים, להוסיף printים ולשנות סדר. במחברת production-like הסדר קבוע: imports, config, environment check, data, model, run, save, evaluation, handoff. אם אתם רוצים להעביר עבודה מהלימודית למסודרת, אל תגררו את כל ההיסטוריה. העתיקו רק את החלקים שעברו smoke test. כך אתם מקבלים best of both worlds: חופש ניסוי מצד אחד, ושחזור אמין מצד שני. זו מיומנות קטנה, אבל היא מבדילה בין notebook שעבד במקרה לבין workflow שאפשר לסמוך עליו.
שגרת עבודה וסגירת הפרק
הדבר החשוב ביותר בפרק הזה אינו קוד מסוים. הקוד ישתנה, Colab ישנה UI, Kaggle יעדכן Docker images, ComfyUI יזיז תיקיות, ngrok ישנה ניסוח בתיעוד. ההרגלים נשארים: תא startup, מדידת GPU, checkpoint, output מחוץ ל-runtime, בדיקת clean run, ו-fallback. אם אתם מאמצים את ההרגלים האלה, אתם יכולים להשתמש כמעט בכל notebook GPU חינמי בלי להרגיש שכל session הוא הימור.
שגרה טובה מתחילה עוד לפני ה-run. פתחו את המחברת וקראו רק את התאים הראשונים: startup, config, environment check. אם אתם לא מבינים תוך שתי דקות לאן ייכתבו outputs ואיפה נמצאים checkpoints, המחברת לא מוכנה. אחר כך בדקו את ה-fallback: אם אין GPU, האם יש API path? אם Drive לא מתחבר, האם יש הודעת שגיאה ברורה? אם model download נכשל, האם המחברת עוצרת בצורה מובנת או ממשיכה לזרוק errors עמומים? אלה שאלות של תפעול, לא של אלגוריתם.
בסוף כל run, אל תסגרו את הטאב מיד. הקדישו חמש דקות לסגירה מסודרת. בדקו איזה artifacts נוצרו, מחקו קבצים זמניים שאינם נדרשים, כתבו Handoff קצר, וסמנו האם ה-run הצליח, נכשל או דורש המשך. אם נוצר checkpoint טוב, ציינו את שמו. אם נוצר output טוב, ציינו איפה הוא נמצא. אם משהו נכשל, כתבו את השגיאה ואת ההשערה הראשונה. ביום הבא, חמש הדקות האלה יהיו ההבדל בין המשך עבודה לבין חפירה מחדש.
שמרו גם 'רשימת לא לעשות'. למשל: לא להריץ training בלי checkpoint; לא לפתוח tunnel עם secrets; לא להגדיל batch לפני baseline; לא לשמור אלפי קבצים קטנים ב-Drive; לא לסמוך על GPU זמין בשעת עומס; לא להציג notebook כ-deployment. רשימה כזאת נשמעת שלילית, אבל היא מקצרת החלטות. במקום לנהל ויכוח פנימי בכל פעם, אתם נשענים על כללים שנולדו מכשלונות ידועים.
כאשר מחברת הופכת לחשובה, העבירו אותה ממצב ניסוי למצב template. מחקו תאים מתים, אחדו התקנות, הפרידו config, הוסיפו Handoff, ובדקו clean run. אם היא לא עוברת clean run, היא עדיין ניסוי. אם היא עוברת, אפשר להשתמש בה כבסיס לפרק 5, לצוות, או לפרויקט לקוח קטן. זאת התקדמות אמיתית: לא עוד notebook שעבד במקרה, אלא כלי שאפשר להסביר ולשחזר.
שגרת עבודה ל-GPU Notebooks חינמיים
| תדירות | פעולות | סימן שהשגרה עובדת |
|---|---|---|
| כל יום עבודה | הריצו startup cell, בדקו GPU, בדקו מקום פנוי, ודאו שה-checkpoint האחרון קריא. | אתם יודעים תוך 2 דקות אם אפשר להתחיל או צריך fallback. |
| כל שבוע | נקו outputs זמניים, דחסו checkpoints ישנים, ושמרו רק artifacts שצריך לשחזר. | Drive או Kaggle Output לא מתמלאים בזבל שלא יודעים להסביר. |
| כל חודש | בדקו אם quotas, UI או install commands השתנו; עדכנו את startup cell וה-runbook. | מחברת ישנה עדיין רצה מלמעלה למטה בלי חיפוש נואש בגוגל. |
אם אתם עושים רק דבר אחד מהפרק הזה
5 דקות הוסיפו לכל notebook GPU שלכם תא ראשון שמחבר persistent storage, יוצר תיקיות, מדפיס GPU, ומראה איפה יישמר checkpoint. זה הדבר הקטן שמונע את רוב ההפסדים הכואבים.
בדקו את עצמכם
- למה checkpointing חשוב יותר מלהשאיר את הטאב פתוח? רמז: חשבו על מה קורה ל-runtime.
- איך תחליטו אם job מתאים ל-Colab או ל-Kaggle? רמז: interactive מול reproducible artifact.
- למה מודל 7B יכול להיכנס בקונטקסט קצר ולהיכשל בקונטקסט ארוך? רמז: KV cache.
- איך Save & Run All חושף state נסתר במחברת? רמז: ריצה נקייה מלמעלה למטה.
- למה tunnel זמני יכול להיות סיכון גם אם הוא פתוח רק לדמו? רמז: שירות מקומי הופך לנגיש מבחוץ.
סיכום הפרק
GPU notebook חינמי הוא לא הבטחה למשאב קבוע, אלא הזדמנות להשתמש במשאב זמני בצורה מקצועית. למדנו להפוך Colab למחברת restartable בעזרת Drive, startup cell ו-checkpoints; להשתמש ב-Kaggle כאשר צריך גרסה נקייה ו-output שנשמר; ולמדוד VRAM לפני שמגדילים מודל, context או batch. הרעיון המחבר הוא פשוט: כל דבר חשוב יוצא מה-runtime לפני שה-runtime מקבל הזדמנות להיעלם. בפרק הבא נעבור ל-local inference עם Ollama, GGUF ו-quantization, ונראה מה משתנה כשהמחשב שלכם, ולא notebook חינמי, הוא סביבת ההרצה.
Checklist סיום
- ☐ יצרתי תיקיית
free-gpu-labעם checkpoints, models, outputs ו-workflows. - ☐ בניתי Colab startup cell שמחבר Drive ומדפיס GPU.
- ☐ הרצתי environment check לפני טעינת מודל.
- ☐ יצרתי קובץ output קטן והוכחתי שהוא שורד disconnect.
- ☐ כתבתי RUN_ID קבוע ולא פיזרתי שמות קבצים ידנית בתאים.
- ☐ שמרתי checkpoint מדומה וטענתי אותו אחרי restart.
- ☐ יצרתי Kaggle notebook שמוציא artifact ל-
/kaggle/working. - ☐ הרצתי או תכננתי Save & Run All כדי לבדוק ריצה נקייה.
- ☐ מדדתי VRAM לפני ואחרי טעינת מודל או workflow.
- ☐ הורדתי batch size/context/resolution לפני שניסיתי פתרונות מורכבים ל-OOM.
- ☐ שמרתי workflow JSON של ComfyUI מחוץ ל-runtime.
- ☐ סגרתי tunnel זמני אחרי הדמו ולא שמרתי secrets במחברת.
- ☐ בחרתי לכל פרויקט פלטפורמה ראשית ופלטפורמת fallback.