הבאג הנפוץ ביותר בזרימת LLM בפרודקשן הוא זה שאיש לא שם לב אליו. איכות הפלט יורדת באחוז בשבוע, ספק המודל מוציא עדכון שקט, פרומפט עורכים בחיפזון, ושלושה חודשים אחר כך מגלים שצוות התמיכה מנקה בשקט את הבלגן שה-AI היה אמור לנקות בעצמו. התיקון הוא אותו תיקון כמו לכל חלק אחר של תוכנת פרודקשן: טסטים, שמורצים ב-CI, על כל שינוי. אנחנו קוראים לשלנו הארנס הערכה.
הפוסט הזה הוא הגרסה המינימלית של ההארנס שאנחנו משלחים. שלושה רכיבים, כולם משעממים. טבלת ציונים ב-Postgres. ג'וב CI שמריץ פרומפטים מול סט מבחנים קבוע וכותב תוצאות. דשבורד שמראה את חמישים ההרצות האחרונות זו לצד זו.
טבלת הציונים
כל הרצת הערכה מייצרת שורות. כל שורה היא שילוב יחיד של (פרומפט × מבחן × גרסת מודל), עם הקלט, הפלט, הפלט הצפוי, ציון בין 0 ל-1, זמן השהיה, והעלות בטוקנים. אנחנו שומרים כל שורה לתמיד. Postgres שמח עם שורה אחת לכל הרצה בסקייל שלנו; מעולם לא הגענו ללקוח שזה היה קרוב ליקר.
-- The table we never regret writing first.
CREATE TABLE eval_run (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
ts timestamptz NOT NULL DEFAULT now(),
prompt_id text NOT NULL,
case_id text NOT NULL,
model text NOT NULL,
input jsonb NOT NULL,
output jsonb NOT NULL,
expected jsonb,
score numeric(4,3),
latency_ms integer,
tokens_in integer,
tokens_out integer,
notes text
);
CREATE INDEX ON eval_run (prompt_id, ts);
הסכמה רחבה בכוונה. נשרפנו יותר מדי פעמים מטבלת הערכה שהתברר שחסר בה השדה שהיה עונה על השאלה. עמודות ב-Postgres זולות; אחסון זול; העלות של להריץ שמונה חודשי הערכה מחדש אחרי הוספת עמודה — לא זולה.
הג׳וב ב-CI
ההארנס רץ על כל pull request שנוגע בפרומפט, כלי, או קונפיג של שער מודל — ורץ לילי על main. הוא מושך את הגרסה העדכנית של כל פרומפט, מריץ מול סט מבחן, כותב שורה לכל הרצה, ומפרסם סיכום ב-PR. אם הציון על איזה פרומפט יורד ביותר מ-5% — הצ׳ק נכשל.
סט המבחן
סט המבחן הוא החלק הקשה ביותר, והיחיד שלא תוכלו להעתיק מהפוסט הזה. רשימה מתוחזקת ידנית של מקרי קלט, כל אחד עם פלט צפוי ופונקציית ניקוד. כל פרויקט מתחיל בעשרה מקרים שכותב הצוות. עד שאנחנו משלחים — הסט במאות הנמוכות, וגדל רגרסיה אחת בכל פעם.
כל רגרסיה שבורחת לפרודקשן הופכת למקרה מבחן בבוקר שאחרי. זה הכלל היחיד.
פונקציות ניקוד הן החלק הקשה הבא. התאמת תת-מחרוזת עובדת לחצי מהמקרים. Regex לעוד רבע. הרבע האחרון דורש רובריקת שיפוט בידי מודל, שמופעל על ידי ספק אחר מזה שמוערך. נסביר למה אנחנו בוחרים בראשון.
הדשבורד
הדשבורד הוא עמוד אחד שמרונדר מתוך טבלת הציונים. חמישים ההרצות האחרונות, כגריד של small-multiples: ציר X זמן, ציר Y ציון, חלון לכל פרומפט. ריחוף על חלון מציג את הפירוט לכל מקרה. דריפט בלתי אפשרי להחמיץ בתצוגה הזו.
למה זה מספיק
הגרסה המפוארת של ההארנס כוללת מעקב ניסויים בסגנון MLflow, vector store לקלטים, שירות שיפוט מבוסס LLM עם הערכה משלו, ופאנל Grafana שמתקשר לכוננות. בנינו את כולם. בקושי מפעילים אותם בפרויקט מתחת לשנה — כי הגרסה הפשוטה תופסת את אותן בעיות בעשירית מהעלות.
אם תיקחו דבר אחד מהפוסט — קחו את זה: כתבו את ההארנס ביום הראשון. לא בשבוע השלישי. לא אחרי הרגרסיה הראשונה. יום ראשון. העלות היא חצי יום הנדסי וטבלת Postgres; האלטרנטיבה היא מייל מלקוח בעוד שלושה חודשים שמתחיל ב-״נדמה לי שמשהו השתנה?״
- טבלת Postgres — לא קובץ CSV ב-S3.
- ג'וב CI — לא מחברת ידנית שאף אחד לא מריץ.
- דשבורד small-multiples — לא הודעת סלאק.
- מקרי מבחן מתוחזקים ידנית — לא מקרים שמודל אחר ייצר.
ההארנס הוא החלק בבנייה של AI שמרוויח למערכת את שמה. בלעדיו יש לכם דמו.


