כוונון עדין (fine-tuning) יש לבצע לא "ככל האפשר", אלא כאשר זה אכן הכרחי ומוצדק מנקודת מבט של זמינות נתונים חדשים, שיפור איכות צפוי, ועלויות משאבים (זמן וכסף). במקום לבצע כוונון עדין תכוף על כמויות נתונים קטנות, לפעמים יעיל יותר להשתמש בגישות אחרות, למשל Retrieval-Augmented Generation (RAG), שבהן המודל מקבל מידע עדכני בזמן השאילתה מבסיס ידע חיצוני.
מבחינה טכנית, אין מגבלות מחמירות מטעם הפלטפורמות (כמו Google Vertex AI, לדוגמה) על התדירות שבה ניתן להריץ תהליך כוונון עדין (fine-tuning), למעט מכסות כלליות על שימוש במשאבים והתקציב שלכם. ניתן להריץ תהליך כוונון עדין חדש אפילו שעה לאחר הקודם, אם יש צורך ומשאבים לכך.
עם זאת, מנקודת מבט מעשית, תדירות הכוונון העדין נקבעת על ידי הגורמים הבאים:
- זמינות נתונים חדשים: הסיבה העיקרית לכוונון עדין חוזר היא הופעה של כמות משמעותית של נתונים חדשים ואיכותיים, שיכולים לשפר את ביצועי המודל עבור המשימה שלכם. כוונון עדין על כמות קטנה של נתונים חדשים עשוי לא לתת אפקט ניכר, או אף להחמיר את המודל (אימון יתר על הנתונים החדשים).
- עלות: כל תהליך כוונון עדין דורש משאבי חישוב (GPU/TPU) ובהתאם, עולה כסף. כוונון עדין תכוף יכול להיות יקר למדי.
- זמן: תהליך הכוונון העדין אורך זמן – משעות ועד ימים, בהתאם לגודל המודל, כמות הנתונים והתצורה. בנוסף, זמן הכנה לנתונים והערכת התוצאה.
- צורך: האם באמת צריך לעדכן את המודל?
- האם השתנתה המשימה שעבורה אתם משתמשים במודל?
- האם איכות התשובות של המודל המאומן הנוכחי התדרדרה לאורך זמן (לדוגמה, עקב שינויים בעולם החיצוני שבאו לידי ביטוי בנתונים החדשים)?
- האם הוספת נתונים חדשים תניב שיפור מורגש באיכות, שיצדיק את העלויות?
- הערכה (Evaluation): לאחר כל כוונון עדין יש לבצע הערכה יסודית של המודל על סט נתוני בדיקה, כדי לוודא שהגרסה החדשה אכן טובה מקודמתה ושלא אירעה "שכחה קטסטרופלית" (כאשר המודל מחמיר את יכולותיו בתחומים שלא אומן עליהם הפעם).
מתי בדרך כלל מבצעים כוונון עדין חוזר:
- עם צבירה של בלוק משמעותי של נתונים חדשים רלוונטיים (לדוגמה, נתונים מהרבעון האחרון, החודש האחרון וכו').
- במקרה של שינויים משמעותיים בתחום הדעת או בדרישות המשימה.
- כאשר ניטור הביצועים מראה ירידה מורגשת באיכות המודל הנוכחי.
- באופן תקופתי (לדוגמה, פעם ברבעון או בחצי שנה), אם נתונים מגיעים באופן רציף ויש תקציב/משאבים לתחזוקת המודל במצב עדכני.
מבנה הקובץ עבור כוונון עדין (fine-tuning) תלוי בפלטפורמה שבה אתם משתמשים (לדוגמה, Google Vertex AI, OpenAI API, Hugging Face, etc.) ובסוג המשימה שעבורה אתם מאמנים את המודל.
עם זאת, הפורמט הנפוץ ביותר הוא JSON Lines (JSONL). בפורמט זה, כל שורה בקובץ מייצגת אובייקט JSON נפרד ותקף, המכיל דוגמה בודדת לאימון.
הרעיון הכללי של המבנה עבור מודלים גנרטיביים (כמו Gemini):
כל אובייקט JSON (כל שורה בקובץ .jsonl) מכיל בדרך כלל זוגות "קלט" -> "פלט צפוי".
דוגמאות לפורמטי נתונים עבור כוונון עדין:
1. משימות מסוג הוראה / צ'אט / שאלה-תשובה:
- אפשרות 1 (פשוטה):
{"prompt": "Переведи на английский: Как дела?", "completion": "How are you?"}
{"prompt": "Напиши короткое стихотворение о весне.", "completion": "Звенит капель, ручьи бегут,\nПодснежник первый тут как тут.\nПроснулся лес, проснулся луг,\nВесна пришла, мой милый друг!"}
{"prompt": "Столица Франции?", "completion": "Париж"}
{"instruction": "Напиши код на Python для вычисления факториала числа 5.", "output_text": "def factorial(n):\n if n == 0:\n return 1\n else:\n return n * factorial(n-1)\nprint(factorial(5))"}
{"instruction": "Суммируй числа от 1 до 10.", "output_text": "55"}
{"input_text": "Объясни концепцию квантовой запутанности простым языком.", "output_text": "Представь две монеты, которые каким-то образом связаны. Если одна выпадает орлом, другая автоматически выпадает решкой, независимо от расстояния между ними."}
- אפשרות 2 (מובנית יותר, עבור צ'אטים):
{"messages": [{"role": "user", "content": "Привет! Как дела?"}, {"role": "assistant", "content": "Привет! У меня всё отлично. Чем могу помочь?"}]}
{"messages": [{"role": "user", "content": "Объясни теорию относительности простыми словами."}, {"role": "assistant", "content": "Представь, что время и пространство - это как эластичная ткань..."}]}
{"messages": [{"role": "user", "content": "Расскажи анекдот про программистов."}, {"role": "assistant": "Почему программисты путают Рождество и Хэллоуин? Потому что Dec 25 == Oct 31"}]}
{"messages":[{"role":"user","content":"Какой сегодня день?"},{"role":"assistant","content":"Сегодня [дата]"} ]}
2. משימות יצירת טקסט (השלמת טקסט):
- אפשרות 1 (מאוחדת):
{"text": "Однажды зимним вечером, когда снег падал крупными хлопьями, и ветер выл, как голодный волк, в маленьком домике на опушке леса сидела старушка и вязала. Вдруг раздался стук в дверь… Это был…"}
{"text": "Рецепт яблочного пирога. Нам понадобятся: 200 г муки, 150 г сахара, 2 яйца, 100 г сливочного масла, 3 средних яблока… Способ приготовления: 1. Разогреть духовку до 180 градусов. 2. Взбить яйца с сахаром… Затем…"}
{"text": "В начале было Слово, и Слово было у Бога, и Слово было Бог. Оно было в начале у Бога. Все чрез Него начало быть, и без Него ничто не начало быть, что начало быть. В Нем была жизнь, и жизнь была свет человеков... "}
- אפשרות 2 (קידומת/המשך):
{"prompt": "Рецепт борща. Ингредиенты:", "completion": " свекла, капуста, картофель, морковь, лук, томатная паста..."}
{"prompt": "The quick brown fox jumps over the lazy dog. This sentence is a pangram because it ", "completion": "contains every letter of the alphabet."}
{"prompt":"Once upon a time, in a land far, far away, there lived a princess who...", "completion": "was known for her kindness and her love of adventure."}
3. משימות סיווג:
{"text": "Этот ресторан предлагает превосходную кухню и отличное обслуживание.", "label": "положительный"}
{"text": "К сожалению, заказ был доставлен с опозданием на два часа.", "label": "отрицательный"}
{"text": "Продукт соответствует описанию, но цена немного высоковата.", "label": "нейтральный"}
{"text": "Фильм скучный и неинтересный, я бы не рекомендовала его к просмотру.", "label": "отрицательный"}
{"text": "Книга написана хорошим языком и имеет увлекательный сюжет, рекомендую к прочтению.", "label": "положительный"}
{"text":"Этот отзыв очень полезен, спасибо автору!","label":"положительный"}
נקודות חשובות:
- חובה לעיין בתיעוד של הפלטפורמה שבה אתם מבצעים את הכוונון העדין! שמות השדות (
input_text
,output_text
,prompt
,completion
,text
,label
וכו') עשויים להשתנות. לדוגמה, Google Vertex AI משתמש לרוב ב-input_text
וב-output_text
עבור אימון מפוקח. - פורמט קובץ: ודאו שזהו אכן JSON Lines (.jsonl), ולא מערך JSON רגיל. כל שורה היא אובייקט JSON נפרד.
- קידוד: בדרך כלל נדרש UTF-8.
- הכי חשוב – זו האיכות והרלוונטיות של הנתונים שלכם. הם צריכים להיות נקיים, מדויקים ולהתאים למשימה שאתם רוצים שהמודל יפתור.
- גודל הנתונים: כמות הדוגמאות משפיעה על איכות הכוונון העדין. בדרך כלל נדרשות מאות או אלפי דוגמאות, בהתאם למורכבות המשימה והמודל.
דוגמה לקובץ my_finetuning_data.jsonl
עבור Google Vertex AI (כוונון מסוג הוראה):
{"input_text": "Напиши слоган для кофейни 'Утренний Луч'", "output_text": "Утренний Луч: Начни свой день с идеальной чашки!"}
{"input_text": "Кратко перескажи сюжет 'Гамлета'", "output_text": "Датский принц Гамлет мстит своему дяде Клавдию за убийство отца и узурпацию трона, что приводит к трагической гибели большинства главных героев."}
{"input_text": "Составь список из 5 идей для летнего отпуска в России", "output_text": "1. Поход по Алтаю\n2. Отдых на Байкале\n3. Путешествие по Золотому Кольцу\n4. Пляжный отдых в Сочи или Крыму\n5. Сплав по рекам Карелии"}
JSONL (JSON Lines) פורמט:
כל שורה בקובץ היא אובייקט JSON תקף. האובייקטים אינם מופרדים בפסיקים, כל שורה היא רשומה נפרדת.
{"поле1": "значение1", "поле2": "значение2", ...}
{"поле1": "значение3", "поле2": "значение4", ...}
...
1. פורמט "Prompt / Completion" (בקשה / השלמה)
זהו פורמט קלאסי, פופולרי במיוחד עבור מודלים של השלמת טקסט או הוראות פשוטות.
prompt
: טקסט קלט המוזן למודל (הוראה, שאלה, תחילת טקסט).completion
(אוoutput
,response
): התשובה הצפויה או המשך הטקסט שהמודל אמור לייצר.
מבנה:
{"prompt": "Ваш входной текст или инструкция...", "completion": "Ожидаемый результат модели..."}
{"prompt": "Переведи на английский: Привет, мир!", "completion": "Hello, world!"}
{"prompt": "Столица Франции?", "completion": "Париж"}
{"prompt": "Напиши короткий стих о коте.", "completion": "Пушистый зверь на солнце спит,\nМурлычет тихо и сопит.\nЗеленый глаз лениво щурит,\nМечтая рыбу утащить."}
2. פורמט "Instruction / Input / Output" (הוראה / קלט / פלט)
פורמט זה מובנה יותר עבור משימות ביצוע הוראות, כאשר ההוראה מופרדת מהנתונים הספציפיים שעליהם היא חלה.
instruction
: תיאור המשימה שהמודל אמור לבצע.input
(אופציונלי): הנתונים הספציפיים או ההקשר להוראה. יכול להיות ריק אם ההוראה מספיקה בפני עצמה.output
(אוresponse
): התוצאה הצפויה.
מבנה:
{"instruction": "Переведи следующий текст на английский.", "input": "Привет, мир!", "output": "Hello, world!"}
{"instruction": "Ответь на вопрос, используя предоставленный контекст.", "input": "Контекст: Париж - столица Франции. Вопрос: Какая столица Франции?", "output": "Париж"}
{"instruction": "Напиши короткий стих о коте.", "input": "", "output": "Пушистый зверь на солнце спит,\nМурлычет тихо и сопит.\nЗеленый глаз лениво щурит,\nМечтая рыбу утащить."}
{"instruction": "Определи тональность текста: позитивная, негативная или нейтральная.", "input": "Этот фильм был просто ужасен.", "output": "негативная"}
3. פורמט "Messages" (הודעות) עבור מודלים צ'אט
פורמט זה משמש לכוונון עדין של מודלים דיאלוגיים (לדוגמה, GPT-3.5/4 דרך API של OpenAI, או מודלים ב-Hugging Face המשתמשים ב-Chat Templates). הוא מייצג דיאלוג כרצף של הודעות עם ציון תפקיד השולח.
messages
: רשימה של מילונים, כאשר כל מילון מייצג הודעה אחת.role
: תפקיד השולח (system
,user
,assistant
).system
: מגדיר את ההתנהגות הכללית או ההקשר לאסיסטנט.user
: הודעה מהמשתמש.assistant
: התשובה הצפויה מהמודל (האסיסטנט).
content
: טקסט ההודעה.
מבנה:
{"messages": [{"role": "system", "content": "Ты - полезный ассистент."}, {"role": "user", "content": "Привет, как дела?"}, {"role": "assistant", "content": "Привет! У меня все отлично, я готова помочь. Чем могу быть полезна?"}]}
{"messages": [{"role": "user", "content": "Какая столица Франции?"}, {"role": "assistant", "content": "Столица Франции - Париж."}]}
{"messages": [{"role": "user", "content": "Напиши функцию на Python для сложения двух чисел."}, {"role": "assistant", "content": "Конечно! Вот простая функция:\n```python\ndef add_numbers(a, b):\n return a + b\n```"}]}
4. פורמט "Text" (טקסט) עבור Causal LM
לעיתים, עבור אימון מודלים של השלמה אוטומטית (Causal Language Models), משתמשים בפורמט פשוט שבו כל שורה מכילה מקטע טקסט שלם שהמודל לומד להשלים. לעיתים קרובות זהו שילוב של הוראה/שאלה ותשובה בשדה טקסט יחיד.
text
: הטקסט המלא של הדוגמה (כולל גם את ה"בקשה" וגם את ה"תשובה").
מבנה:
{"text": "Инструкция: Переведи на английский: Привет, мир!\nОтвет: Hello, world!"}
{"text": "Вопрос: Столица Франции?\nОтвет: Париж"}
{"text": "Диалог:\nПользователь: Привет!\nАссистент: Привет! Чем могу помочь?\nПользователь: Расскажи шутку.\nАссистент: Почему программисты путают Хэллоуин и Рождество? Потому что OCT 31 == DEC 25!"}
חשוב:
- בדקו את התיעוד: תמיד עיינו בתיעוד של הפלטפורמה או הספרייה הספציפית (OpenAI, Hugging Face TRL, Axolotl, Llama-Factory, Vertex AI וכו') כדי לדעת את הדרישות המדויקות לפורמט הנתונים עבור כוונון עדין. שמות השדות (
prompt
,completion
,instruction
,output
,text
,messages
) עשויים להשתנות. - עקביות: השתמשו בפורמט שנבחר באופן עקבי לאורך כל קובץ הנתונים.
- איכות הנתונים: האיכות והכמות של הנתונים בקובץ ה-JSONL שלכם משפיעים ישירות על תוצאת הכוונון העדין.
הפורמט המתאים לכם ביותר תלוי במשימה שלכם ובכלי שבו תשתמשו. עבור משימות פשוטות לרוב מספיק פורמט 1 או 4, עבור הוראות – 2, עבור דיאלוגים – 3.