Evals-as-Code — ניהול מבחני AI כחלק מה-Repository
מאת צוות מדיה דיל · 12.08.2026 · AI Evals · 5 דק׳
איך הופכים בדיקות AI מדוחות מנותקים ל-Gate אמיתי ב-CI/CD: מבנה קובץ Eval, שילוב עם GitHub Actions וסף Regression מבוסס סטטיסטיקה.
מפתח בצוות AI מוסיף שינוי קטן לפרומפט המערכת של הסוכן — משפט הבהרה אחד, כדי לתקן תקלה שדווחה אתמול. ה-PR עובר Code Review רגיל, נראה תמים, וממוזג. יומיים אחר כך מתברר שהמשפט התמים הזה שינה את ההתנהגות של הסוכן במקרי קצה אחרים לגמרי, ואף אחד לא ידע עד שלקוח התלונן. זו הבעיה שהופכת את Evals-as-Code מ"נחמד שיהיה" לדרישת סף: אם בדיקות ה-AI לא רצות אוטומטית על כל שינוי, בדיוק כמו טסטים רגילים ב-CI, כל שינוי בפרומפט, במודל או בכלים הופך להימור. הרעיון המרכזי הוא פשוט להגיד — evals הם קוד, הם חיים ב-Repository, והם רצים ב-Pipeline לפני שמשהו מגיע לפרודקשן.
למה evals צריכים לחיות ב-Git ולא ב-Dashboard חיצוני
הרבה צוותים מתחילים את מסע ה-Evals בכלי SaaS נפרד: מעלים כמה דוגמאות ל-Dashboard, מריצים בדיקה ידנית לפני Release. זה עובד לזמן קצר, אבל נשבר ברגע שהצוות גדל, כי אין קשר בין commit ספציפי לתוצאות הבדיקה שלו. אי אפשר לענות על "האם ה-PR הזה שיפר או הרע את הביצועים", כי אין Diff ברור — יש רק שני מספרים לא מקושרים בזמנים שונים. כשה-Evals יושבים כקבצי YAML או JSON ב-Repository, לצד קוד ה-Prompt וההגדרות של הסוכן, כל commit נושא איתו את הגדרת הבדיקות שרלוונטיות אליו, וניתן להריץ diff בין שתי גרסאות ולקבל תשובה מדויקת.
זה גם פותר בעיה ארגונית: מי "בעלים" של הבדיקות. כשה-Evals חיים בקוד, הם עוברים Code Review כמו כל שינוי אחר, מפתחים שרואים PR שמוסיף Feature חדש רואים גם אם הוא מלווה בבדיקה מתאימה, ואי אפשר "לשכוח" להוסיף בדיקה כי ה-Review process עצמו דורש זאת — בדיוק כמו שדורשים coverage לקוד רגיל. הבסיס לכתיבת בדיקות טובות לסוכן מתואר במדריך בדיקות לסוכני AI, ואילו המאמר הזה מתמקד בשילוב שלהן בתהליך הפיתוח עצמו.
מבנה קובץ Eval: מה חייב להיות בפנים
קובץ Eval מינימלי צריך לכלול לפחות ארבעה שדות: קלט (input) — כולל היסטוריית שיחה אם רלוונטי, קריטריון הצלחה (assertion) — שיכול להיות בדיקה מדויקת, בדיקת substring, בדיקת schema על פלט מובנה, או קריאה ל-LLM-judge עם rubric, תגית חומרה (severity) — קריטי לעומת nice-to-have, ומטא-דאטה על מקור המקרה — האם הוא הגיע מתעבורת פרודקשן, נכתב ידנית, או נוסף בעקבות incident ספציפי. השדה האחרון חשוב במיוחד: מקרים שמקורם ב-incident אמיתי הם regression tests לכל דבר, וצריך לסמן אותם כך כדי שאף אחד לא ימחק אותם "כי הם נראים ישנים".
{
"id": "refund-duplicate-guard",
"input": {"messages": [{"role": "user", "content": "בטלת לי את ההזמנה? תחזירו כסף"}]},
"assertions": [
{"type": "tool_call_count", "tool": "issue_refund", "max": 1},
{"type": "llm_judge", "rubric": "לא הונפק זיכוי כפול לאותה הזמנה"}
],
"severity": "critical",
"source": "incident-2026-03-14"
}
מבנה כזה מאפשר גם לסנן הרצות: ב-CI רגיל על כל PR רצים רק המקרים הקריטיים (מהירים וזולים), ואילו סוויטה מלאה כולל LLM-judge יקר יותר רצה פעם ביום או לפני Release. הפרדה כזו שומרת על CI מהיר בלי לוותר על כיסוי.
שילוב ב-CI/CD: gate אמיתי, לא רק דיווח
הצעד הקריטי הוא להפוך את ריצת ה-Evals ל-Gate שחוסם מיזוג, לא רק לדוח שמישהו אולי יקרא. ב-GitHub Actions או כל CI אחר, מריצים את סוויטת ה-Evals הקריטית כ-Job נפרד, ומגדירים סף מדיד: אם ציון ההצלחה על הסוויטה יורד מתחת ל-Baseline של ה-branch הראשי ביותר מסף סטטיסטי מוגדר (למשל 3 נקודות אחוז, עם מרווח ביטחון שנבנה מכמה הרצות כדי לנטרל רעש), ה-PR נחסם. הסף הזה לא צריך להיות 100 אחוז — זה בלתי ריאלי למערכת לא-דטרמיניסטית — אלא Regression אמיתי מעבר לרעש הצפוי.
נקודה שקל לפספס: כדי שההשוואה תהיה הוגנת, צריך להריץ את שתי הגרסאות (Baseline ו-PR) עם אותם seeds ואותה טמפרטורה, ואם אפשר — אותה גרסת מודל בדיוק, אחרת אי אפשר להפריד בין "השינוי בקוד גרם לרגרסיה" לבין "המודל עצמו התנהג אחרת הפעם". תיעוד תוצאות לאורך זמן, כולל מתאם בין commit לציון, הוא בדיוק מה שמאפשר לענות מהר על "מתי זה נשבר" כשמתגלה בעיה — נושא שמפורט לעומק במדריך ה-Evaluation Registry.
מתי Evals-as-Code לא מספיק לבד
גם עם Pipeline מלא, יש שני מקרים שדורשים תוספת. הראשון הוא שינויי מודל שמגיעים מהספק ולא מ-commit בכלל — כשספק המודל משדרג גרסה "מתחת לרדאר", אין PR שמפעיל את ה-Pipeline, ולכן צריך הרצה מתוזמנת נפרדת (nightly) שמריצה את אותה סוויטה ומתריעה על שינוי ציון גם בלי שינוי קוד. הנושא הזה, כולל איך לזהות רגרסיה שמקורה במודל ולא בקוד, מפורט במדריך Regression Testing לסוכני AI.
השני הוא שה-Evals ב-CI תמיד בודקים על סט מוגדר מראש, ולעולם לא יתפסו את כל מרחב הקלטים האמיתי. לכן Evals-as-Code הוא תנאי הכרחי אך לא מספיק — הוא צריך להיות משולב עם ניטור מתמשך על תעבורת פרודקשן אמיתית, כדי לתפוס דפוסי כשל שאף אחד לא חשב לכתוב עליהם בדיקה מראש.
ניהול גרסאות ובעלות על סוויטת הבדיקות
שאלה שמצוותים רבים מתעלמים ממנה: מי אחראי על עדכון קובצי ה-Eval עצמם, ומתי מותר לשנות רף הצלחה קיים? התשובה הנכונה היא לטפל בשינוי ב-Assertion בדיוק כמו בשינוי בקוד ייצור — עם נימוק ב-PR, ולא בעריכה שקטה שמנמיכה סף כי "הבדיקה נכשלת יותר מדי". כדאי גם לתייג כל קובץ Eval בבעלות (owner) של הצוות הרלוונטי, כדי שכשהתנהגות משתנה יהיה ברור מי צריך לאשר את השינוי בקריטריון — צוות המוצר, צוות האבטחה, או צוות ה-AI עצמו.
תרגול טוב נוסף הוא לשמור היסטוריית שינויים נפרדת לקבצי ה-Eval לעומת קוד הפרודקשן, כדי לאפשר לענות במהירות על "מתי הרף השתנה" בלי לחפור בהיסטוריית git כללית. ברגע שהתשתית הזו קיימת, הוספת בדיקה חדשה בעקבות incident הופכת לתהליך של דקות ולא של דיון ארוך על "איפה זה אמור לחיות". התוצאה המצטברת של כל ההרגלים האלה היא תרבות הנדסית שבה שינוי בהתנהגות ה-AI עובר את אותו מסלול ביקורת כמו כל שינוי אחר במערכת — לא יותר קל, ולא פחות.
תגיות: Evals-as-Code · CI/CD · AI Testing · GitHub Actions · Regression Gate