דלג לתוכן הראשי
רמה: מומחה עודכן: אוגוסט 2026

LLMOps — LLM בייצור

לבנות prototype זה קל. להריץ מוצר LLM אמין, זול ובטוח מול אלפי משתמשים — זו הנדסה אמיתית. כך עושים את זה נכון.

שלוש תכונות ששוברות את ההרגלים

LLMOps נשמע כמו עוד ראשי תיבות שמוסיפים ל-DevOps, וזו טעות שימושית להסיר מוקדם. יש שלושה הבדלים מבניים בין מוצר שמבוסס על מודל שפה לבין תוכנה רגילה, וכל פרקטיקה בתחום נגזרת מהם.

המסקנה שכל השאר נבנה עליה: אי אפשר לנהל את זה בלי מדידה רציפה. בתוכנה רגילה, קוד שלא נגעת בו ממשיך לעבוד. כאן — לא בהכרח, וההנחה הזאת היא מקור רוב ההפתעות.

בשורה אחת

בתוכנה רגילה אתה שואל "מה נשבר". כאן אתה צריך לדעת קודם כל שמשהו נשבר — וזה לא מגיע אליך מעצמו.

מחזור החיים, ומה משתנה בכל שלב

מוצר מבוסס מודל עובר ארבעה שלבים, ובכל אחד מהם "נכון" מוגדר אחרת. רוב הכאב נגרם מהחלת הכללים של שלב אחד על שלב אחר.

  1. הוכחת היתכנות. השאלה היחידה היא אם המשימה בכלל פתירה. מותר לעבוד בממשק, מותר לקבע מספרים, מותר לא למדוד. מה שכן שווה כבר עכשיו: לשמור את הפרומפטים שעבדו ואת הדוגמאות שנכשלו — משם תיבנה ערכת ההערכה.
  2. פיילוט. משתמשים אמיתיים, מעטים. כאן חייב להופיע הלוג עם חמשת השדות, כי זה השלב שבו מתגלה מה באמת קורה. וכאן נבנית הערכה מתוך הכישלונות האמיתיים, לא מדמיון.
  3. ייצור. נוסף כל השאר: ולידציה על הפלט, מודל חלופי, ניטור, התראה אחת לפחות, ופריסה מדורגת לשינויים.
  4. תחזוקה. השלב הארוך ביותר והכי פחות מדובר. כאן העבודה היא לא לבנות אלא לשים לב — לדרדור שקט, לעליית עלות, למסמכים שהתיישנו.

הטעות הנפוצה היא לדלג מהראשון לשלישי. צוות שעובר מפרוטוטייפ שעבד יפה ישר לייצור מגיע בלי ערכת הערכה ובלי לוג — ואז השינוי הראשון שיצטרך לעשות יהיה עיוור.

והטעות ההפוכה, פחות נפוצה ולא פחות יקרה: לבנות תשתית מדידה מלאה לפני שיש משתמש אחד. בלי קלט אמיתי אין מה למדוד, והערכה שהומצאה מהראש בודקת את מה שדמיינת ולא את מה שקורה.

הפרומפט הוא קוד

הנוהג הנפוץ הוא לערוך פרומפטים בממשק של הספק או בקובץ שמישהו מעדכן ישירות. זה נוח, וזה מייצר בדיוק את המצב שבו אף אחד לא יודע למה המערכת התנהגה אחרת ביום שלישי.

פרומפט עומד בכל הקריטריונים של קוד: הוא משנה התנהגות, הוא נשבר, וצריך לדעת מי שינה אותו ומתי. לכן:

ומה שכדאי להוציא מהפרומפט החוצה: מזהי מודלים, ספים, ומספרים. הם משתנים בקצב אחר מהטקסט, ועדיף שיהיו בהגדרה.

מזהי מודלים: הבאג שתמיד חוזר

דוגמה מהאתר הזה, כי היא מדגימה את זה טוב יותר מכל הסבר.

שניים מהמדריכים כאן הכילו מזהי מודלים ומספרי גרסאות בתוך דוגמאות קוד. הם נכתבו בזמן מסוים, נשארו בקובץ, ואיש לא חזר אליהם. בקוד אמיתי, אותו דפוס הוא לא מבוכה אלא השבתה: ביום שהספק מוציא גרסה משימוש, הקריאה מחזירה שגיאה, והמערכת נופלת בלי ששינית שורה.

מה שמונע את זה:

# ✗ מפוזר בקוד
resp = client.create(model="some-model-v3", ...)

# ✓ במקום אחד, מהגדרה
MODEL = os.environ["LLM_MODEL"]
FALLBACK_MODEL = os.environ.get("LLM_FALLBACK_MODEL")

resp = client.create(model=MODEL, ...)

ושני הרגלים שמשלימים את זה: לתעד את המזהה שבאמת שירת כל בקשה — כי ספקים מפנים לעיתים גרסה כללית לגרסה ספציפית, ואתה רוצה לדעת לאיזו; ולעקוב אחרי הודעות הוצאה משימוש של הספק שאתה משתמש בו. זו הדקה היחידה שמפרידה בין מעבר מתוכנן לתקלה בלילה.

הערכות הן ה-CI של זה

אם יש רכיב אחד שבלעדיו אי אפשר לעבוד, זה הוא. ערכת הערכה היא מה שמאפשר לשנות משהו ולדעת אם עשית טוב או רע — וזה בדיוק מה שאין בלעדיה.

מה שצריך, וזה פחות ממה שנדמה:

  1. שלושים עד מאה מקרים אמיתיים מהמוצר שלך, עם התוצאה הנכונה לצידם.
  2. כולל מקרים שאין להם תשובה — לפחות רבע. אלה בודקים אם המערכת יודעת לסרב, וזה המדד שהכי משפיע על אמון.
  3. כולל את המקרים המכוערים — קלט מנוסח רע, מעורב עברית-אנגלית, חסר.
  4. הרצה אוטומטית לפני כל שינוי בפרומפט, במודל או בשליפה.

והכלל שהופך את זה לנכס: כל תקלה בייצור מוסיפה מקרה לערכה. אחרי חצי שנה יש לך אוסף של בדיוק מה שמפיל אותך, וכל שינוי עתידי נבדק מולו. הרחבה: Evals.

ולגבי שיפוט אוטומטי — מודל שמדרג פלט של מודל אחר עובד סביר להשוואה יחסית ("איזו משתי הגרסאות טובה יותר") ופחות טוב לציון מוחלט. ובעברית שווה לבדוק את המשפט עצמו לפני שסומכים עליו, כי שופט שאומן לאנגלית מדרג טקסט עברי גרוע יותר מכפי שהוא.

ניטור: מה למדוד כשאין "נכשל"

המדדים הרגילים — חביון, שגיאות, תפוקה — עדיין נחוצים ולא מספיקים, כי הכשל האופייני כאן מחזיר 200 ונראה תקין.

ארבעה מדדים שתופסים דרדור שקט:

ושלושתם נמדדים כהתפלגות ולא כממוצע. ממוצע מסתיר בדיוק את מה שמעניין: המקרים החריגים. אחוזון 95 של החביון אומר יותר מהחציון, ואותו דבר נכון לעלות.

הרחבה על השכבה הזאת: Observability.

חמישה דברים לתעד, אחרת אין תחקיר

זה החלק שהכי משתלם לעשות מוקדם והכי כואב להוסיף אחרי הראשונה. תלונה של משתמש הופכת לחקירה של חמש דקות או לניחוש, בהתאם לאלה:

  1. הקלט המדויק — אחרי כל שכתוב ועיבוד שעשית לו.
  2. ההקשר שנשלף — הקטעים עצמם והציונים, לא רק המזהים.
  3. מזהה המודל שבאמת שירת — לא זה שביקשת.
  4. גרסת הפרומפט.
  5. הפלט הגולמי — לפני פירסור, אחרי הכל.

בלי החמישה, האבחון נעצר ב"המודל טעה". איתם, הוא כמעט תמיד מצביע על אחד משלושה: לא נשלף, נשלף והפלט סתר, או שהמקור עצמו שגוי.

ופרט שקל לפספס: מה שמתעדים הוא לרוב מידע אישי. שאלות משתמשים מכילות שמות, כתובות ופרטי חשבון. תחום שמירה, גישה מוגבלת, ודרך למחוק לפי משתמש — הם חלק מהתכנון ולא נספח.

האיכות ירדה ואין הסבר

התרחיש הכי מתסכל: הכל היה בסדר, לא פרסתם כלום, והמשתמשים מתלוננים. סדר בדיקה שמצמצם במהירות:

  1. להריץ את ערכת ההערכה עכשיו. אם היא נפלה לעומת ההרצה הקודמת — משהו במערכת השתנה. אם היא עברה — המערכת בסדר והקלט השתנה, וזה כיוון חקירה אחר לגמרי.
  2. להשוות מזהה מודל. מה שירת לפני שבוע מול מה ששירת אתמול. אם זה לא אותו דבר, מצאת.
  3. לבדוק את ציוני השליפה. ירידה בממוצע אומרת שהאינדקס או המסמכים השתנו — לא המודל.
  4. להסתכל על אורך הפלט. קפיצה או צניחה בהתפלגות היא אות כמעט ודאי לשינוי בהתנהגות המודל.
  5. לקרוא עשרים תלונות ברצף. השלב שהכי קל לדלג עליו והכי מהר מאבחן. אם כולן על אותו נושא, הבעיה במסמך ולא במערכת.

ושלוש סיבות שכדאי לשלול מוקדם כי הן נפוצות ולא אינטואיטיביות: מסמך שעודכן ושינה את מה שנשלף; שינוי בהתנהגות המשתמשים — קמפיין שהביא קהל ששואל אחרת; וגדילה של האינדקס, שמורידה את הדיוק של השליפה בלי שאף אחד נגע בקוד.

הכלל: אל תשנה את הפרומפט לפני שאתה יודע מה השתנה. זו התגובה האינסטינקטיבית, והיא מוסיפה משתנה בדיוק כשאתה מנסה לבודד אחד.

ניתוב ונפילה חכמה

ספקים נופלים, מגבילים קצב, ומאטים. מערכת שתלויה בספק אחד תלויה גם בזמינות שלו.

הפתרון המקובל הוא מודל חלופי — ויש בו מלכודת שכמעט תמיד מגלים בזמן התקלה: הפרומפט שלך מכויל למודל אחד. מודל אחר יחזיר פורמט קצת אחר, יסרב על דברים אחרים, ויתנהג אחרת על אותה הנחיה.

def ask(messages, schema):
    for model in (PRIMARY, FALLBACK):
        try:
            out = call(model, messages, schema)
            if validate(out, schema):     # חובה, בשני המסלולים
                return out, model
            log("schema_fail", model=model)
        except (RateLimit, Unavailable) as e:
            log("provider_error", model=model, err=e)
    raise NoUsableResponse()

שתי נקודות בקוד הזה. הראשונה: הוולידציה רצה גם על החלופי — אחרת נפילה שקטה מחליפה נפילה רועשת. השנייה: מחזירים איזה מודל שירת, כי בלי זה לא תדע שרבע מהתנועה שלך רץ שבוע על החלופי.

וההכרח שקודם לקוד: להריץ את ערכת ההערכה על שני המודלים. חלופי שלא נבדק הוא לא חלופי — הוא הימור שנשמר ליום הגרוע.

חביון: מה שהמשתמש באמת מרגיש

מודל שפה איטי בסדר גודל מקריאה רגילה למסד נתונים, וזה משנה החלטות תכנון שבתוכנה רגילה לא היו עולות.

מאיפה הזמן מגיע, בסדר יורד:

ומה שעובד בממשק יותר מכל אופטימיזציה: הזרמה. תשובה שמתחילה להופיע אחרי חצי שנייה נתפסת כמהירה גם כשהיא נמשכת עשר שניות, ואותה תשובה שמגיעה בבת אחת בסוף נתפסת כתקועה. זה שינוי בחוויה בלי שינוי בזמן.

ולסוכנים — להראות מה קורה. "מחפש במסמכים", "בודק מלאי". משתמש שרואה התקדמות ממתין; משתמש שרואה מסך ריק מרענן, וכל רענון הוא קריאה נוספת שאתה משלם עליה.

עלות: לאן הכסף באמת הולך

חשבון של מוצר LLM מתנפח לרוב לא מהמקום שמצפים לו.

ומה שכדאי למדוד: עלות לבקשה, בהתפלגות. הממוצע יסתיר את העשירון שצורך פי עשרה — ובדרך כלל שם נמצאת גם באג: לולאה שלא נעצרת, היסטוריה שלא נחתכת, או משתמש אחד שמריץ משהו אוטומטי. שווה להגדיר תקרה לבקשה בודדת ולהתריע על חריגה, כי הסעיף הזה הוא היחיד שיכול להכפיל את החשבון ביום. הרחבה: עלויות.

לפרוס שינוי בלי לשבור

שינוי פרומפט מרגיש קטן ומשפיע על כל התנועה בבת אחת. הסדר שעובד:

  1. ערכת ההערכה. אם היא נופלת, נעצרים כאן.
  2. מצב צל. הגרסה החדשה רצה במקביל, הפלט שלה נשמר ולא מוצג. משווים לא-מקוון, בלי סיכון.
  3. קנרי. אחוזים בודדים מהתנועה, עם מעקב על ארבעת המדדים מסעיף הניטור.
  4. הרחבה הדרגתית, עם דרך חזרה בלחיצה.

ונקודה שמפתיעה צוותים שהורגלו למוצר רגיל: בדיקת A/B על פלט של מודל דורשת יותר תנועה ממה שנדמה. השונות בין תשובות גבוהה, ולכן הפרש קטן נבלע ברעש. הרבה "ניצחונות" שמדווחים אחרי יומיים הם רעש — ובמוצר עם מעט משתמשים, הערכה לא-מקוונת על ערכה קבועה אמינה יותר מניסוי חי.

וכשהספק הוא זה שהשתנה

יקרה, ולא תקבל על זה התראה מראש. תוכנית פעולה קצרה:

ושווה לקבוע מראש מי מקבל התראה כששיעור כישלון הסכימה חורג. מערכת שמדרדרת בשקט בשלוש בלילה היא בדיוק התרחיש שכל הסעיף הזה נועד למנוע.

ופרט אחרון שחוסך הפתעות: תקרא את דף השינויים של הספק פעם בחודש. זה עשר דקות, והוא מכיל בדרך כלל את ההודעות על הוצאה משימוש כמה שבועות לפני שהן נכנסות לתוקף. הפער בין לדעת מראש לבין לגלות מהמערכת הוא ההבדל בין מעבר מתוכנן לתקלה.

אבטחה שנכנסת לתמונה

שתי נקודות שספציפיות למוצר מבוסס מודל, ושנוטות ליפול בין הכיסאות:

ועוד אחת מעשית: הגבלת קצב לפי משתמש. בלעדיה, משתמש אחד עם לולאה יכול לשרוף את התקציב החודשי ביום.

ומי אחראי על מה

בצוות קטן זה נשמע מיותר, וזה בדיוק המקום שבו דברים נופלים — כי פרומפט הוא ארטיפקט שגם מהנדס וגם מי שמבין את התחום נוגעים בו.

החלוקה שעובדת:

ופרקטיקה אחת שמחזירה יותר מכל השאר: שמישהו יקרא עשרים שיחות אמיתיות בשבוע. לא מדדים — שיחות. זה תופס דברים שאף מדד לא מגדיר, וזה גם מייצר את רוב המקרים שנכנסים לערכת ההערכה.

צוות קטן: המינימום שבאמת נדרש

הכלים בתחום הזה נמכרים כאילו צריך פלטפורמה. לצוות של אחד עד שלושה, זה מה שבאמת חייב להתקיים:

  1. פרומפטים בריפוזיטורי. קובץ. לא ממשק.
  2. שלושים מקרי בדיקה וסקריפט שמריץ אותם. אפשר בשעה.
  3. לוג עם חמשת השדות. טבלה מספיקה.
  4. מזהה מודל בהגדרה, לא בקוד.
  5. התראה אחת — על שיעור כישלון סכימה.

חמשת אלה מכסים את רוב מה שמפיל מערכות בשלב הזה, ואף אחד מהם לא דורש כלי. כל השאר יכול לחכות — ולרוב צריך לחכות, כי פלטפורמה שנבחרה לפני שידעת מה אתה מודד היא פלטפורמה שתחליף.

ומתי כן שווה כלי ייעודי: כשהערכה גדלה מספיק שהרצה שלה ידנית מעצבנת, כשיש יותר מאדם אחד שנוגע בפרומפטים, או כשצריך להשוות כמה גרסאות בו-זמנית. שלושת הסימנים האלה מגיעים מעצמם, ועד שהם מגיעים — טבלה וסקריפט עושים את העבודה בלי תלות שתצטרך להחליף.

מתי זה מיותר

טעויות שחוזרות

הצעד הבא

העמק ברכיבים הקריטיים של ייצור: ניטור, הערכות ובטיחות.