מנהל פיתוח: ״ישנתי שנת חורף והתעוררתי ל Agentic Coding, מה עלי לדעת?״

בכל טרנד חדש ״שכולם כבר אימצו״, יש את הרוב השקט שמאמץ אותו מאוחר יותר. לפעמים קצת יותר, לעתים – הרבה יותר. גם שנים לאחר שהיה נדמה ש״כולם״ כבר עברו ל Agile או עברו לענן – עדיין הייתה קבוצה גדולה (ושקטה), אולי אפילו רוב – שעדיין לא עשה את זה.

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

מה עליכם לדעת?

בגדול: ארגונים נכשלים באימוץ Agentic Coding לא בגלל שהכלים לא טובים, אלא בגלל שילוב של בחירות לא טובות, אימוץ אנושי חלש, וחסמים ארגוניים.

כמנהלים בארגון – זה התפקיד שלכם לפתור את זה.

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

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

  • פתיחה דרמטית: "יצא כלי AI חדש" / "This new AI tool just dropped…"
  • הבטחה ענקית: "שמשנה את כל הכללים" / "game changer" / "changes everything" / "שבר את כל המוסכמות" / "מגדיר מחדש את המשחק"
  • סופרלטיבים תומכים: "הלסת שלי גירדה את הרצפה" / "mind blowing" / "jaw dropping", וכו׳.
  • ״הוכחה״ קצרה: – סרטון קצר / דמו / תמונות before-after / סיפור כזה או אחר
  • קריאה לפעולה – ״עזבו ברגע זה את כל מה שאתם עושים״ / "חייבים לנסות" + לינק + אימוג'יז

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

מה באמת משפיע על היכולת להגיע Agentic Coding מוצלח?

1. גישה למודלים חזקים לעבוד איתם

הרבה ארגונים רוצים לעשות Agentic Coding אבל משיקולי עלות / אבטחה קיצונית – מונעים מהמפתחים את המודלים החזקים. זה לפעמים מתבטא בתקציב, ולפעמים דרישה ל hosting on-premises של המודלים.

יש ארגונים שמאוד רוצים שהארגון יתייעל בעזרת Agentic coding אבל מארחים רק מודלים on-premises ולא מודלים חזקים במיוחד. זו גישה שמאוד מקשה על אימוץ מוצלח – במיוחד בהתחלה. כמו שנראה בהמשך, יש לארגון עקומת-למידה, ודווקא בהתחלה (כדי לבנות הצלחות, trust, והבנה איך עובדים עם המודלים) – חשוב להתחיל עם מודלים חזקים, גם אם הם עולים יותר. התייעלות כספית בכמות השימוש tokens – היא חשובה, אבל מוטב שתבוא אחרי שהארגון עבר את שלב האימוץ הראשוני.

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

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

גם כאשר אתם מארחים מודלי OSS, חשוב לוודא ש:

א. אתם עובדים בגרסאות עדכניות (Kimi K2, למשל, אינו רלוונטי מרגע שיצא Kimi-2.5 המוצלח בהרבה).

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

אלו דברים שתלויים בארגון, וגם ארגונים בטחוניים / פיננסיים יכולים לאפשר אותם.

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

הנה לדוגמא מאמר כיצד מודלים חזקים יותר הצליחו משמעותית יותר במציאת באגים בלינוקס. עבור משימות של Planning ו troubleshooting – מודלים חזקים יותר עושים עבודה משמעותית יותר טובה. Planning פחות מוצלח – משפיע אח״כ על כל העבודה. Troubleshooting טוב יותר יכול להיות ההבדל בין שעות לימים של עבודה. המודלים החזקים מצדיקים את עצמם לגמרי במקומות הללו.

נזכיר שבין השחרור של Opus 4.1 ל Opus 4.6 עברה רק חצי שנה. פער דרמטי.

הערה: Benchmarks של מודלים חשוב לקחת עם קרטוב מלח. כולם עושים תרגילים לצאת טוב יותר, ולפרסם את ה benchmarks שבהם המודל שלהם הצליח יותר. אני מסתכל כיום בעיקר על ה Code Arena Benchmark, עם היתרונות והחסרונות שלו.

הערה 2: גודל ה Context Window לא כל-כך חשוב כפי שניתן לחשוב מקריאה ראשונית. אפשר לעבוד בסדר גמור גם עם context window של 100K. אל תלחצו אם אין למודל שלכם context windows של 1M טוקנים.

2. פתיחות אמיתית בקרב המהנדסים / התלהבות

בארגונים רבים מתרחש הפרדוקס הבא:

  • Senior Engineers (בממוצע) יכולים להוציא מה Agents את המירב – אבל הם יותר מדי ביקורתיים לגבי עבודת הסוכן (לא אהבתי את העימוד), אולי חוששים למקום שלהם בארגון, לא פעם הם מקובעים, זהירים מדי – ומגוון סיבות אחרות שמקשות עליהם להטמיע Agentic Coding בכח מלא.
  • Junior Engineers (בממוצע) יצליחו פחות עם Agents כי אין להם מספיק נקודות ייחוס לאמת / לבקר את העבודה של הסוכן ולהכווין אותו – אבל הם הרבה יותר פתוחים לניסיון.

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

״אם הותיקים נגד + מי שבעד לא מביא תוצאות מדהימות – אולי זו באמת לא טכנולוגיה בשלה? אולי שווה לחכות עוד שנה-שנתיים?״ – היא מסקנה לוגית, אך שגויה לחלוטין.

אני לא מכיר את הארגון שלכם, אני לא מכיר את האנשים והתרבות – אבל אתם **חייבים** לייצר דרייב שבו האנשים החזקים בארגון מתחילים להשתמש ב Agentic Coding מכל הלב, להשיג תוצאות מדהימות (זה אפשרי) – וכך גורמים לכולם בארגון לנסות ולהבין איך עושים את זה גם.

דברים שארגונים עושים שמעכב את ההגעה לשלב הזה:

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

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

ג. מקדמים את הגישה שסוכן הוא "Co-pilot״ או ״משלים קוד״ / יועץ / מבקר מהצד. עד שלא תתנו לסוכן לכתוב את הקוד – לא תצליחו להתקדם באמת.

3. פתיחות ארגונית

בארגון יש יחסי כוחות שה Agentic Coding עומד לערער. ההנדסה עובדת עם אנשי מוצר, עם אנשי UX, אנשי אבטחה, IT, שיווק / GTM ועוד. אם הפיתוח יעבוד משמעותית יותר מהר, אבל כל הגופים מסביבו לא יסתגלו / ידרשו לעבוד בדיוק כפי שעבדו עד עכשיו – הרכבת תיתקע. מכונית מירוץ לא עוזרת כשהיא באיילון בפקק.

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

למשל: המהנדסים משתמשים ב Google Stitch להוציא UX ראשוני סביר – בלי לחכות לאנשי ה UX. זה עוזר להם להתקדם מהר יותר. הגיוני לארגון שאנשי ה UX יקחו את עבודת ה UI / עיצוב הראשונית של הסוכן וימשיכו משם. יתקנו ויידייקו. סוכני הקוד ידעו לעשות מהר את כל השינויים הנדרשים בקוד.

האם אנשי ה UX יסכימו לכך? האם לא יעלבו? יעשו escalation / ישברו את הכלים?

זו עבודה ארגונית / ניהולית לטפל בה – אבל זה חסם אמיתי למעבר לפיתוח בעזרת סוכנים.

4. הכלים הנכונים – זה לא כל-כך חשוב

ה Agentic IDEs (או command line) הכי פופולאריים בעת כתיבת הפוסט בשעה המדוברת הם כנראה: Claude Code ו Codex, אולי גם Anti-Gravity.

לאחר שעבדתי גם עם Claude Code, Cursor ו Windsurf (ויש לי העדפות אישיות, ודעות על כולם) – אני משוכנע שאפשר להצליח עם כולם.

כל עוד אתם לא עובדים עם כלים מיושנים (אני מחשיב את GitHub copilot ככזה, לא ניסיתי בשנה האחרונה) או כלים שלא באמת מיועדים למפתחים (כמו B44 או Lovable) – זה לא משנה הרבה. זה כמו הדיון בין IntelliJ ו Eclipse. עבודה מצויינת ניתן לעשות בשניהם.

פרק משמעותי בכלים הוא MCP integrations לכלים בארגון: Jira, Wiki, GitHub, גוגל דרייב ועוד. זה משפר פריון אמיתי, אולי אפילו ב 10% (משמעותי). ארגונים גדולים נזהרים מאוד מהטמעה של MCP (הרי ה S ב MCP הוא עבור Security) – אבל באמת שאפשר גם בלעדיהם. למשל, כתיבת Skills / rule ל IDE שמפעילים כלי command line.

המלצתי היא להפעיל קצת גמישות אישית ויצירתיות על פני מלחמה ב ״רק Claude Code״ (שעוד חודש תהפוך ל ״רק Codex״). החלפה של כלים היא לא דבר קל לארגון, והעיקר שיהיו לכם כלים ״מספיק טובים״.

4ב. Closing the feedback loop

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

במקום שהסוכן רק יכתוב קוד, אתם רוצים שהוא יקבל גם את התוצאות של ה Linting או קומפילציה. של הרצת הטסטים או המדדים בפרודקשיין. כמו שאתם מצפים ממפתח להריץ (ולתקן לפי הצורך) טסטים לפני שהכריז ״סיימתי״ – כך אתם רוצים גם שיפעל הסוכן. אם יש בעיות בפרודקשיין – אתם רוצים להטריג אוטומטית (trigger) את הסוכן ולבקש ממנו לנתח את הבעיה, לחשוב על תיקון, ולממש אותו. תפקידכם לבוא ולבדוק את הניתוח וה PR. לא לקבל את הלוגים מפרודקשיין ולהעביר ידנית לסוכן (או חלילה: לבצע ניתוח ראשוני בעצמכם).

כדי שלולאת הפידבק תעבוד הסוכן צריך גישה לכלים השונים: בדיקות, לוגים, CI/CD וכו׳. זה דורש השקעה. גם ליישם אינטגרציות לסביבה הייחודית שלכם, גם לייצר לסוכן מספיק rules ו knowledge base מה עליו לעשות, וגם להעניק לו הרשאות גישה (בארגונים מסוימים זה החלק הכי מורכב).

יש פה התייעלות והתבגרות חשובה שאני לא רוצה להפחית בערכה, אבל היא מגיעה אחרי כל השאר.

5. חסכון ב tokens

אחרי ש:

  • אתם עובדים עם סוכנים בצורה שוטפת, הם כותבים את רוב הקוד. זה עובד!
  • אתם מפעילים גם Background Agents שיעבדו ברקע.
  • חיברתם את הסוכנים ללוגים וה monitors / alerts של המערכת לסגור feedback loop.

תגלו שאתם משתמשים בהמון tokens – וזה יקר למדי.

העתיד לא ברור פה:

  • אמנם עלויות ייצור ה token פוחתות באמצעות טכניקות של caching וחומרה ייעודית, אך יש שאלה כמה זמן השיפור המשמעותי ימשיך.
  • חברות ה AI מסבסדות בצורה מאסיבית את עלות ה tokens – יש שאומרים שהעלות האמיתית היא פי 3-5 ממה שאנחנו משלמים היום.
  • יש הערכות שהזינוק בצריכה ייצור מחסור בכח מיחשוב עולמי – ויתגלגל לעלויות גבוהות יותר לכל token.

לא דמיוני שעוד שנה או שנתיים עלות ה token תהיה גבוהה משמעותית מהעלות שלה היום.

בקיצור: אחרי שהצלחתם ״לגרום למכונה לנוע״ – חשוב גם לעבוד ביעילות. לחסוך ב tokens. למשל:

  • כל מה שניתן לעשות ב script רגיל (קוד) – תעשו בסקריפט ולא בעזרת LLM.
    • (ברור שהסוכן יכתוב עבורכם את הסקריפט).
  • מודלים גדולים זה מצוין, אבל 80-90% מהזמן תלמדו לעבוד עם מודלים קטנים ויעילים יותר. יש לא מעט דיבור על מודלים קטנים ממוקדי-משימה. אני עושה את רוב העבודה שלי על Gemini-Flash – מודל בסיסי למדי.

סיכום

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

יש שיאמרו ש Agentic Coding מצליח פחות ב Backend מאשר ב Frontend או במערכות גדולות / מורכבות פחות ממערכות קטנות / חדשות. אולי יש בזה אמת, אבל זה לא משנה.

Agentic Coding מצליח הרבה פחות טוב למי שלא נפל לו האסימון עדיין איך לעבוד איתו. זה העובדה המעניינת.

אני מפציר בכם לא להישאר מאחור, יש פה טכנולוגיה שומטת לסת שאתם רוצים לרוץ ולאמץ מיד!

שיהיה בהצלחה!

תהליכי בדיקה של מערכות LLM (או Evaluations)

בפוסט הזה נדבר על ״הטסטים״ של מערכות LLM, הרי הם ה Evaluations.

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

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

מדוע Evaluations ולא טסטים? מה נשתנה?

מערכות LLM (או LLM Apps) דורשות כמובן גם testing – כמו כל מערכת קוד. החלק שפונה ל LLM הוא החלק שלא ניתן לבדוק בעזרת מתודולוגית הבדיקה הרגילה:

  • אי-דטרמניזם: אותו הקלט יכול להחזיר פלט שונה בכל פעם. במתודולוגיות בדיקות רגילות אנו יודעים לכל היותר להתמודד עם סבילות (tolerance), נניח לבדוק שהערך יהיה בין 5.5 ל 7.5.
  • אין תמיד הגדרה חד־משמעית ל“נכון”: נניח בתשובה של סוכן-שירות-לקוחות ללקוח אין תשובה ״נכונה״. יש תשובות טובות יותר, וטובות פחות – במגוון פרמטרים.
    • גם כשנדמה שהבעיה “סגורה” עם פלט בינארי (true/false) – עדיין חסרה ההגדרה החשובה באמת: מה מחיר הטעות, ואיזה סוג טעות גרוע יותר. האם עדיף לומר מדי פעם true כשהתשובה false או להיפך? מה ה tradeoff בין האופציות?
    • ככל שמרחב הפלט שלנו מורכב יותר – כך בעיית הגדרת ה success היא מורכבת יותר.
  • מרחב קלט/פלט עצום: לעתים מגוון האפשרויות הוא לא עשרות או מאות אופציות משמעותיות, אלא מרחב שלצורך העניין הוא אין-סופי. במקרים כאלו אי אפשר לעשות "test coverage״.
    • שבירות: לא פעם שינוי קטן בקלט או בפרומפט יכול מאוד לשנות את התוצאה. זו סיבה חשובה נוספת לבדוק – אבל היא לא מקילה על הבדיקות. זה אומר שאם בדקתי קלט מאוד דומה עשרות פעמים והתוצאה היא טובה – זה לא מבטיח ששינוי קטן בקלט לא ישנה משמעותית את התוצאה.
  • שחזור (Reproducibility) הוא קשה – נניח זיהיתי תסריט שבו המערכת נתנה תוצאה לא טובה. אני מתקן את ה prompt/RAG/מה שזה ורוצה להריץ מחדש.
    • א. אני חייב לוודא שכל ה prompts, הגדרות tools או skills, גרסאת המודל (מתעדכנים כל כמה חודשים), ה context הכל זהה – אחרת אני לא בודק אותו הדבר.
    • ב. אקראיות המודל עדיין משחקת תפקיד.
    • למשל: פרקטיקה מקובלת היא לקבוע את ה temperature ל 0 בזמן eval (אפילו אם המודל ירוץ בסוף בטמפ׳ גבוהה יותר) – וכך לצמצם את האקראיות.

אפשר להעלות עוד בעיות, אבל זה הבסיס.

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

מה עושים? יש כבר מתודוליה מבוססת וידועה. מדענים/חוקרים עם הדילמות האלו כבר עשורים. בעצם אנו זקוקים לשילוב בין Empirical Evaluation ל Statistical Evaluation או בקיצור Evaluations. זו הבשורה הטובה.

הבשורה הפחות נוחה, היא שאין ״EUnit״ (על משקל JUnit) או JasmineEval מוכן, לא כי קשה לבנות framework כזה אלא מכיוון שצריך להתאים את שיטת הבדיקה הספציפית למערכת הספציפית. אין one-size-fits-all.

עבור כל מערכת LLM תצטרכו לתפור Evaluation המתאים למידותיה. זה לא מסובך כמו שזה עשוי להישמע בתחילה – אבל זה בהחלט מציב אתכם בעולם של ניהול סיכונים תמידי שאולי פחות הייתם רגילים לו בתור מהנדסים.

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

תהליכי האימות הם לא קלים ולא זולים, אבל בלעדיהם:

  • לא נדע באמת כמה טובה/מדויקת המערכת שלנו.
  • לא נדע לזהות במהירות רגרסיות בביצועים.
  • יהיה מאוד קשה להשתפר, או לדעת היכן / מתי צריך להשתפר.
  • לא נדע להעריך כמה מסוכנות ״תשובות לא טובות״. האם הן ״לא טובות״ או מהוות סיכון ממשי (חושפות מידע רגיש, סיכוניים משפטיים, או הטעייה קשה של המשתשמש).
חווית פיתוח מערכות LLM בדיוק גבוה. סליחה שלא מצאתי/יצרתי גרסה בלי הכיתוב ״CSS״

אז איך מתמודדים עם כל חוסר השלמות / ודאות הזה? האם נידונו לתסכול ושחיקה?

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

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

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

Guardrails מול Evaluation

כדי לכסות מערכת מורכבת, ובצורה יעילה ולא יקרה מדי אנחנו משלבים את האימות שלנו בכמה רמות. כמו שבתוכנה ״רגילה״ יש בדיקות יחידה/רכיב/אינטגרציה כך בבדיקה של מערכת LLM נהוג להשתמש ברמה רמות של בדיקה.

בגדול* יש לנו שתי קטגוריות עיקריות של שיטות אימות:

  • Evaluations – מריצים את המערכת על סט דוגמאות מוכנות מראש, נותנים ציונים לתוצאות, ומצפים לרף מסוים (משתנה) של תוצאות כדי להחשב הצלחה. למשל: ציון ממוצע 80 ומעלה.
  • Guardrails – אלו בדיקות שמתבצעות כחלק מכל בקשה, בזמן ריצה: לבדוק ששלבים שונים בתהליך הם מספיק טובים ולא מעידים על תקלה. למשל: כשלון מסוים של Retrieval יכול להשבית את הסיכוי למודל לספק תשובה טובה, ולכן עדיף לנסות מחדש חלק או את כל התהליך.

* ניתן להגדיר עוד כמה קטגרויות, וכמה תתי-קטוגוריות – אבל בואו נתקדם שלב-שלב.

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

תכונהEvaluationsGuardrails (או SafeGuards)
מתי רציםתקופתית / לפני השקת גרסה.בכל בקשה (request) בפועל.
זמני ריצהדקות עד שעות. Batch / Offline.
כל הפעלה מפעילה מודל LLM (עקרונית).
עשרות מילי-שניות עד שניות בודדות (וידוא מול מקורות חיצוניים). גם אם נשתמש במודל LLM זה לרוב יהיה מודל קטן ויעיל.
Online/realtime.
אתגריםיקרות לפיתוח, תחזוקה, והרצה.
״היכן ניתן לעשות פחות?״
למצוא את המינון הנכון של אפשור / חסימה.
מה עושים כאשר הבדיקה נכשלת?חוקרים מהיכן נובע ה drift – ואיך לתקן אותו. חקירה = עבודה.החלטת זמן-ריצה (fallback/חסימה/הורדת יכולת/תיעוד).
ניתוח אנושי תקופתי גם כאן.
כלים נפוצים (לא חובה)DeepEval, LangSmith, TruLensGuardRails AI, NeMo Guardrails, various imperative validations

דוגמה קצרה לתהליך Evaluation

בשלב הזה אני רוצה להדגים דוגמה פשוטה לתהליך Evaluation. דוגמה קונקרטית ולא תאוריה.

הצורך: כחלק מהגשת תביעה במערכת שלנו, לקוחות מעלים מסמכים. המסמכים נמצאים ב pool אחד (אינם מסווגים) – מה שגורם לעבודה רבה יותר על הטיפול בתביעה. אנחנו רוצים לקחת מסמכים בפורמט תמונה / PDF ולסווג אותם לאחת מ 4 קטגוריות:

  • הצעת מחיר Estimate
  • קבלה Receipt
  • חשבונית Invoice
  • תצהיר Declaration

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

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

אנשי הפרודקט יירצו כנראה לדעת כמה אנחנו מדויקים. מה הסיכוי לטעות – וכמה גדולות הטעויות? יש גם AI Compliance שרוצים את זה בכתב ועם בקרה רבעונית (בארגונים יותר גדולים). מה עושים?

המקרה שלנו מרגיש לא כל-כך מסובך:

  • ״הטעות הכי גדולה הוא המרחק בין 2 קטגוריות: הנחנו מסמך אחד והתקבל אחר״.
  • ״התוצר משפיע בעיקר על פרודקטיביות של הטיפול בתביעה (נזק קל) ואפשר לתקן בדיעבד (סרקתי את המסמכים וגיליתי שמה שסומן כ״חשבונית״ הוא בעצם ״קבלה״)״.

שווה לציין שמשימת Classification היא ברורה יחסית לתהליך ה Eval. לבדוק Generation (טקסט חופשי) – הרבה יותר מורכב.

שלב ראשון: בניית Golden Dataset

ברור שגם אדם שמסווג מסמך לקטגוריה עלול לטעות. אולי לא תמיד ניתן לסווג את המסמך בצורה חד-חד ערכית: נניח חשבונית שהיא גם קבלה. שאנחנו בונים Golden Dataset אנחנו רוצים:

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

לכמה דוגמאות אנחנו זקוקים?
עבור בדיקת התכנות ראשונית? לפחות 50 דוגמאות.
עבור יציאה לפרודקשיין 200-1000 דוגמאות.

מדוע אלו המספרים? אלו כללי-אצבע להתחיל איתם. כמובן שכל מקרה לגופו.

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

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

  • לבחור מגוון אקראי של דוגמאות, נניח 90% מה dataset הן רשומות אקראיות מהשנה האחרונה.
  • לברר עם מומחי הדומיין מהם מקרי הקצה בעלי משמעות עסקית גבוהה – ולברור מגוון של מקרים כאלו (ה 10% הנותרים).

ה Golden Dataset שלנו הוא לא רק ״נתונים לצורך בדיקות״, הוא בעצם המיקוד שלפיו נאפטם את ה pipeline. הבחירה היא משמעותית.

את ה golden dataset צריך לתייג. מישהו צריך לעבור ידנית על 200 המסמכים הללו ולתייג אותם בדייקנות. דיוק התיוג חשוב לא פעם יותר מגודל ה dataset. פרקטיקה מקובלת היא לעשות שני מעברים – שני מתייגים כך שאם יש סתירה – הם יושבים ומבלנים את הפער – וכך הדיוק איכותי יותר.

כמובן שזו הרבה עבודה, ולכן יש גם טכניקות להוזלת עלויות. למשל: LLM as a judge, ניתן חלק מהתיוג או בדיקת התיוג – למודל LLM נוסף; לרוב: הכי חזק שנגיש לנו, לא זה שנשתמש בו בזמן ריצה.
יש כלים שונים שעוזרים לבצע ולבדוק את התיוק, להצליב תוצאות וכו׳. למשל SuperAnnotate for Data Trainers.

במהלך התיוג, סביר שניתקל במקרי קצה שלא לקחנו בחשבון. למשל חשבונית שהיא גם קבלה. מה נעשה? יש שתי גישות עיקריות:

  • נחליט לתייג קבלה+חשבונית כחשבונית – ו״נַטֶּה״ את ה pipeline לטעות העדיפה מבחינתו (מבלי להוסיף עוד קטגוריה – שתסבך את הכל).
  • נוסיף קטגוריה נוספת Unknown ונלמד את ה pipeline שלנו להודות שהוא לא בטוח. זה עדיף, הרבה פעמים, על לנחש לא נכון.

שלב שני: קביעת מדדי הצלחה

חשוב להבין מה התסריט העסקי. לא רק ״מקסימום דיוק״ אלא ״אלו טעות יותר כואבת מטעות אחרת״. למשל אמרנו קודם (חוסר-דיוק):

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

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

כלומר: התוצאה יכולה להיות משהו כזה:

  • הכי חשוב לנו לא לפספס תצהירים. עדיף לסווג מסמך שאינו תצהיר – כתצהיר, ולטעות (הבוחן יתקן את ההגדרה) מאשר לפספס את התצהירים ולסווג אותם כמסמכים שונים. זה נקרא recall(Declaration).
  • חשוב גם כן להבחין נכון בין חשבוניות וקבלות. זה מבלבל גם אנשים, ואנחנו רוצים לחסוך להם את הזמן בהבחנה בינהם. צד אחד לא חשוב יותר מהשני. זה נקרא pair confusion(Invoice,Reciept).

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

שלב שלישי: יישום (איטרציה ראשונה)

אז יש לנו dataset איכותי ומדדי הצלחה. נממש את ה pipeline שלנו: Prompt, אולי קצת context building (הדוגמה הזו נראית פשוטה), בחירת מודל, temperature וכו׳ – ונריץ את 200 הדוגמאות. נחשב את הפערים בין התוצאות של ה pipeline (קרי: ה LLM) מה שנקרא גם prediction מול המתייגים האנושיים (שאנחנו מחשיבים כאמת, מה שנקרא ground truth). במקום ה ״assert״ יהיה לנו חישוב שתוצאתיו יראו משהו כזה:

  • recall(Declaration) = 0.77
  • pair confusion(Invoice,Reciept) = 0.68

האם זה מספיק טוב לביזנס? – זאת שאלת המפתח. בכל מקרה, מכיוון שזו איטרציה ראשונה, ואחרי שהשקענו כל-כך הרבה זמן בבניית ה golden dataset שווה לנסות עוד כמה איטרציות נוספות: שינויים ב prompt, בפרמטרים למודל, מודלים שונים, וכו׳. אולי אחרי כמה עשרות איטרציות נגיע לתוצאה כמו:

  • recall(Declaration) = 0.74
  • pair confusion(Invoice,Reciept) = 0.81

האם זה טוב יותר? זו כמובן שאלה עסקית לאנשי המוצר. אלו הדילמות שתתקלו בהן שוב ושוב. קשה לשפר הכל – ולא פעם צריך לקבל פשרות.

כיצד מריצים את החישובים הנ״ל? אנחנו משתמשים בכלי פנימי להרצה וחישוב (על בסיס scikit-learn – הכלי מקובל לחישובי נכונות ססטיסטית). יש גם פתרונות יותר שלמים – סוויטות שלמות של איסוף נתונים, בדיקה, וניתוח (בעיקר כלים מסחריים). פחות חשוב הכלי, יותר חשוב שהתהליך יהיה מבוקר ו reproducible.

להשוואת התוצאות (מהר מאוד יצטברו עשרות ניסויים שתרצו לברור ביניהם) הכלי המקובל הוא MLOps.

חשוב להזכיר שהרצה של LLM pipeline הוא פעולה יקרה:

  • כל הרצה יכולה לקחת דקות עד שעות.
  • כל הרצה יכולה לעלות בדולרים – במיוחד אם יש LLM as a judge. נניח: 4$~ להרצה.

כדי לבדוק יציבות, לפעמים אנחנו מריצים את אותו ה pipleline כמה פעמים, ננניח 3-5 פעמים ועושים ממוצע.

זה לא נשמע הרבה – אבל זה מצטבר. כנראה שלא תרצו להריץ את ה evaluation כחלק מה CI/CD pipeline שלכם, אלא רק כאשר אתם עושים שינוי רלוונטי (נניח: ב prompt) או פעם בשבוע כדי למצוא רגרסיות.

סיכום

קיבלנו הצצה על איך נראה תהליך Evaluation ובמה הוא שונה מ Automated Testing.

יש עוד הרבה מה לכסות בנושא ה Evaluations:

  • אלו מטריקות קיימות, ואיך בוחרים ביניהן? single class vs. multi-class וממוצעים (micro/macro/weighted)? אופרציונליזציה (הפיכת תוצאות כלליות – למדידות).
  • סטטיסטיקה ל LLM App Engineers: מובהקות, טעויות סטטיסטיות אפשריות (biases) ואיך להיזהר מהן, וכו׳.
  • LLM-as-a-Judge: איך עושים ומנהלים את ה tradeoff בין הוזלת עלויות – לדיוק/ניהול סיכונים.
  • Context/Retrieval Evalaution: כאשר ה RAG מורכב, יתכן ונרצה לעשות Eval גם לו.
  • Post-Deployment Evaluation: איך לאסוף ולייצר פידבק מפרודקשיין שנוכל להשתמש כדי לשפר את המודל?

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

שיהיה בהצלחה!

כל מה שצריך לדעת בכדי להישמע כמו מומחה LLM Apps

כשהרבה אנשים מסביב נשמעים כמו מומחי LLM Apps, אולי לגיטימי שהצעד הראשון יהיה ליישר קו – ולהישמע גם, ורק משם להמשיך?!

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

סוכן אחד אינו מספיק

מערכות של סוכן אחד הן מוגבלות. כשהמשימה מורכבת (למשל: ביצוע מחקר שוק רב-שלבי) סוכן אחד עלול לא לעמוד במשימה. נרצה אם כן לחלק את המערכת לכמה סוכנים כל אחד עם מומחיות משלו (Prompt, RAG) שיתמקד בחלק שלו.

  • Agentic Workflow היא ארכיטקטורה פשוטה יותר, בה מספר סוכנים מבצעים שרשרת של שלבים, באופן שהוגדר מראש. למשל: Planner Agent => Market Scanning Agent => Competitive Analyzer Agent => Summarizing Agent.
    • ה Workflow לא חייב להיות ליניארי, אפשר לתכנן חזרות לשלבים מוקדמים יותר, אבל חוקי ה workflow מוגדרים מראש.
  • Multi Agents System (MAS) היא מערכת אוטונומית בה יש סוכן אחד שהוא Orchestrator שכל פעם בוחן את המצב ומחליט דינמית איזה סוכן להפעיל בשלב הבא. מתחיל עם Planner ואז מבצע את התוכנית, אבל אם נראה לו שמשהו בתוכנית שגוי – יכול להחזיר את הפידבק ל Planner שיתקן את התוכנית, למשל.

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

יתרונות מובהקים של מערכות Multi-Agent:

  • אי ערבוב context בין משימה למשימה (יש context שונה לכל סוכן). ידוע ש Context Dilution (״התפזרות ההקשר״) על מגוון נושאים היא בעיה אמיתית ל Attention. כל סוכן – מנהל context ממוקד ו memory רלוונטי למשימה שלו.
  • בדיקה הדדית – מודלי LLM נוטים לטעות תוך כדי שימור ביטחון עצמי גבוה. בדיקה הדדית של התוצאות שלהם היא קריטית. לסוכן אחר, על בסיס מודל שונה / context שונה – יש סיכוי מוגבר (מול אותו המודל עצמו) לאתר טעויות בתשובה.

חסרונות של מערכות Multi-Agent:

  • מערכות מורכבות, יקרות יותר (יותר tokens ו latency), וקשות לניטור / troubleshooting
  • כמות האפשרויות להרכבת מערכת כזו כמעט ואינה מוגבלת – מה שמקל עלינו כמהנדסים שבונים אותן להתברבר ולבזבז זמן רב בשינויים שלא בהכרח ישפרו את הביצועים.
  • יש הרבה תיאוריה וארכיטקטורות שמפורסמות – פחות הצלחות מובהקות בשטח. תחום עם סיכון גבוה לאי-הצלחה.

Context is King

או Context is Everything או Context Engineering is Key, וכו׳.

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

״Good Context wins Intelligence״ – הוא ביטוי שהגעתם אליו בעצמכם. כלומר: context מוצלח עם מודל חלש (נניח GPT-5, חחח איזו היסטוריה) יגבר על מודל חזק בהרבה (למשל Opus 4.5 Pro) עם context פחות מוצלח. קל להחליף מודלים, אבל הרבה פעמים זה לא עוזר – מה שעוזר זה לבנות context נכון.

Context נכון משמע:

  • להבין את ה user query / הבעיה שמנסים לפתור בצורה עמוקה.
  • להביא ל context מידע ייחודי (שאינו world knowledge שיש כבר למודל), רלוונטי, ואיכותי
  • לא להביא יותר מדי מידע, כדי לא לפגוע ב Attention / לגרום ל Context Dilution.
  • לא להביא / להסיר מידע סותר או מבלבל – שיגרום לסוכן להתבלבל / לאבד מיקוד.
  • כמובן טוב שיהיו instructions טובים (קרי: prompt Engineering) שיאגדו את כל מכלול ה context.

עכשיו אתם יכולים לבחור באחת משתי גישות פופלריות של מומחיות:

גישה ראשונה: RAG איכותי עושים עם Vector DB ו Embedding אבל זו מומחיות שלמה.

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

גישה שנייה: RAG גנרי על בסיס Vector DB ו Embedding הוא לעצלנים / בורים – יש לעשות Custom RAG לבעיה הספציפית.

רק שילוב חכם בין בסיסי-נתונים רלציוניים (נתונים עסקיים מובנים), בסיסי נתונים של Graph (ידע של דומיין) ו Vector DB (מאמרים כלליים) תוך תכנון קפדני. אתם באופן אישי מאוד התרגשתם מהשחרור של pg_textsearch שתומך ב BM25 לפי פרמטרים בתוך ה DB עצמו. עכשיו לא נדרש מכם לעבוד גם עם ElsaticSearch (שבנינו: הוא די מיושן).

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


אפשר לבחור בכל אחת מהגישות – כל אחת נחשבת מקצועית ומובילה.

אפשר כמובן לשלב ביניהן – אבל זה דורש מעט יותר מיומנות אישית.

Observability, Governance, and Safety

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

ההבדל בין ילד למקצוען בעולם ה LLM הוא היכולת להבטיח שהמערכת מתנהגת בצורה תקינה וטובה – שווה ערך או טוב יותר מהמקבילה האנושית.

כן, זה כולל דברים לכאורה לא סקסיים כמו Security ו Legal ו HITL (קרי Human-in-the-loop – משמע גם עבודה ידנית) – אבל זה בעצם המומחיות האמיתית במערכות LLM.

כן, תנו למהנדס הג׳וניור לבנות סירת מירוץ ולהשיט אותה בשיא המהירות. בסוף, מה שעושה את ההבדל בין עסק כושל לעסק מצליח בעולם הזה – זה לעשות Safety ו Governance, לוודא שסירת המירוץ לא מתרסקת על סלע (רגולציה) – וזה התבלין המיוחד שאתם מביאים לשולחן.

מה שחשוב עכשיו הוא לשלוט במערכת. להוסיף OpenTelemetry (ועליה: OpenInference – ההתאמה לעולמות ה AI) כדי לדעת לעקוב אחרי ה flows של ה agents ולהבין היכן הם כושלים.

כלים כמו Nemo Guardrails של אנבידיה או Presidio (זיהוי וניקוי של PII) הם ה infra החדש.
כן, לאנוידיה לא תמיד הייתה תדמית טובה בפיתוח תוכנה – אבל הם השתפרו!

יש המון סטארט-אפים חדשים בקטגוריה של Safety ו Guardrails (שם גנרי להגנות שונות) – ואתם יכולים לציין כל שם שנשמע אמין ולא מאוד קליט. אף אחד לא מצליח לעקוב גם ככה. אני עובד עם ב״איקרוס״, אם אתם רוצים לדעת. משהו משהו.

xLM משנה הכל, לכולם – בכל מקום

LLM (שפה) או VLM (חזותי) או SLM (מודל קטן – נושא חם!) או MMLM (מולטי-מודל) או RLM (קרי Reasoning Language model), וכו׳.

אתם כבר הבנתם שמשהו בין 600% ל 1000% מהמשרות בארה״ב יוחלפו בשנים הקרובות ע״י LLM.

תכנות הוא מקצוע שעבר מהעולם, ואין טעם בכלל ללמוד לכתוב קוד – רק specs שה LLM יבצע, או meta specs שה Agents החכמים יהפכו ל specs.

אתם מחכים לחברה (company) של עובד בודד שתהפוך לחד-קרן. רק עניין של זמן. אתם ידעתם.

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

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

ה AI זו בועה אחת גדולה!

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

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

דוח של BCG (רוב החברות לא מצליחות להפיק ערך מוחשי מ LLM)

  • רוב החברות לא מצליחות להפיק ערך מוחשי מ-LLM: רק 26% פיתחו יכולות שמאפשרות לעבור מעבר ל-PoC ולהניב ערך, ו-74% עדיין לא מציגות ערך מוחשי מהשימוש ב-AI.
  • רק 4% מהחברות מצליחות לייצר ערך משמעותי מ LLM באופן עקבי. אלו בעיקר חברות תוכנה ופיננסים.

דוח של MIT (״95% מהפיילוטים של LLM נכשלים״)

  • רק 5% מהפיילוטים מבוססי LLM מגיעים להאצת הכנסות מהירה. כל ה 95% האחרים כושלים, או מדשדשים.
  • הדו״ח ״מאשים״ יישום לא נכון של LLM, הן בבחירת המטרות והן בלמידה של הארגון איך להשתמש בו.
  • מה מצליח יותר: לרכוש מוצרים שכבר הצליחו – ממי שכבר ״הצליח לעשות את זה״

רויטרס (AI promised a revolution. Companies are still waiting)

  • פורסטר: רק 15% מהחברות שיישמו LLM ראו שיפור במרווחי רווח בשנה האחרונה בזכות ה LLM.
  • פורסטר צופה שב 2026 חברות יידחו כ 25% מההשקעות המתוכננות ב LLM.
  • השוק מבין ש LLM זה לא ״כפתור קסם״ אלא מיומנות שצריך ללמוד ולפתח.

ועוד… לא חסרים דוח״ות באופי הנ״ל.

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

LLM זקוק לנתונים טובים (Context is King, אמרנו?) ולמומחיות והבנה בארגון היכן LLM באמת מתאים. הוא נהדר ב 80%, אבל להביא אותו ל 90%+ – זו לפעמים עבודה מאוד קשה. רק לאבחן מתי הוא לא עובד – ולהעביר לטיפול אנושי – זה לא פשוט.

אתם הרי אמרתם את זה – איי שם עוד לפני לפני התפוצצות בועת הדוט-קום (במידה ונולדתם כבר).

באופנה הנוכחית של שילוב נבון בין מיסאינפורמציה ודיסאינפורמציה – אני בטוח שתסתדרו.

מצד שני, זה רק עניין של זמן, ו 2027 תהיה שנת ה Baby Boom של פתרונות LLM. או שלא.

סיכום

הפוסט הזה משלב קצת ידע High-Level, סרקזם, והומור – כי זה מה שאני יכול לתת לכם בשלב הזה.

אני מקדיש הרבה מזמני ללמוד, להבין, להתייעץ ולשמוע – ועדיין יש הרבה יותר שאלות טובות – מתשובות טובות.

זה עניין של זמן, אבל כנראה זה יגיע. האם נאהב את כל התשובות? בוודאי שלא.

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

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

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

שיהיה בהצלחה!

נ.ב. זיהיתם טענות מופרכות בפוסט? ״סופגניות חנוכה״ (easter eggs)? כתבו בתגובות.

טכניקות NLP בסיסיות – חלק ב׳

בפוסט הראשון (לינק) הצגנו תהליך Canonicalization והכרנו כמה כלי NLP בסיסיים וחשובים – אבל היו כמה שלא הזכרנו – שחשוב להכיר. לכך מוקדש הפוסט הזה.

Lemmatization (או Morphological Normalization)

בבלשנות, מורפולוגיה היא תחום העוסק באופן שבו מילים נוצרות ומוטות (משתנות לפי זמן, מספר, מין וכו’). למשל:
• run → running, runs, ran — פּוֹעַל בצורות שונות.
• service → services, servicing — שם עצם ופּוֹעַל הנגזרים מאותו שורש.
• good → better → best — שינוי מדרגת תואר.

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

ExplanationPart of Speech (POS)LemmaToken
Irregular plural normalized to singularNounchildchildren
Past tense → base verb “be”Auxiliary Verbbewere
Present participle → base “run”Verbrunrunning
No change; already base formADVfastfast
No change for prepositionsADPinin
Determiner, unchangedDETthethe
Noun in singular form, stays sameNounparkpark

שווה לציין מונח דומה בשם Stemming תהליך דומה ל Lemmatization אבל מבוסס-חוקים / יוריסטיקות – לא ניתוח תחבירי או מורפולוגי. הוא מהיר הרבה יותר, ומשמעותית פחות מדויק. מתאים בעיקר לכמויות גדולות של טקסט כאשר הדיוק חשוב פחות. לדוגמה Stemmer הוא חלק מתהליך ניתוח הטקסט של ה Indexing של Elasticsearch.

בואו נראה קצת קוד:

from rapidfuzz import fuzz
import spacy

nlp = spacy.load("en_core_web_sm") # small vector english model. Included.

def lemmatize(text):
    return " ".join([t.lemma_ for t in nlp(text.lower())])

text1 = "children were running fast in the park"
text2 = "a child in the park ran fast"

fuzz.WRatio(text1, text2) # score: ~70
fuzz.WRatio(lemmatize(text1), lemmatize(text2)) # score: ~92

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

חשוב לציין שלמטיזציה (lemmatization) מטפלת רק בצורה של המילה, לא במשמעות שלה. במקרה של Good vs. Best – צפויה לנו אכזבה.

print(fuzz.WRatio("good", "better")) # score: 0.0
print(fuzz.WRatio("good", "best")) # score: 0.0
print(fuzz.WRatio(lemmatize("good"), lemmatize("better"))) # score: 0.0

במקרה שאנחנו רוצים להשוות משמעות, אנחנו משתמשים ב semantic similarity, למשל:

import spacy

nlp = spacy.load("en_core_web_lg") # LARGE vector english model

print(nlp("good").similarity(nlp("better"))) # score: ~81
print(nlp("good").similarity(nlp("bad"))) # score: ~73; note we didn't get a negative number since the algorith directional closeness, not semantic opposition.
print(nlp("good").similarity(nlp("best"))) # score: 70

שימו לב שכדי שזה יצליח, עברנו לעבוד במודל הוקטורי הגדול של Spacy (צריך להוריד כ 400MB).

יש מגוון כלים/אלגוריתמים ל Semantic Similarity, ספציפית Spacy משתמשת ב cosine similarity – עליו ארצה להרחיב ולהסביר בפוסט המשך.

הפונקציה nlp() מריצה pipeline של עיבוד שפה:

  • Tokenizer – חלוקת טקסט למלים / יחידות בעלות משמעות. במקרה שלנו, token יחיד.
    • כל אלגוריתם שמנסה “להבין” טקסט, בין אם זה מנוע חיפוש, מודל Transformer, או סתם regex — צריך לדעת מהן יחידות המשמעות שעליהן לעבוד. ללא Tokenization, כל הטקסט הוא רק רצף תווים חסר גבולות.
    • הערה: מודלי שפה גדולים (LLM) token הוא לא בהכרח מילה. לפעמים מחלקים מילה לכמה tokens, למשל: unbelievable ל ["un", "believ", "able"].
  • Token to Vector (קרי embedding) – הופך את ה tokens לייצוג וקטורי (מערך של מספרים, למשל בין 1.0- ל 1.0). נרחיב עליו בהמשך.
  • רכיבים שונים שמוסיפים metadata על ה tokens.
    • Tagger -סיווג Part of Speech (POS).
    • Parser – מנתח תלויות תחביריות במשפט. מי קשור למי.
    • NER – סיווג יישויות בטקסט: ״חברה״, ״מדינה״ וכו׳.

האובייקט שחוזר מפונקציית ה nlp() הוא doc המכיל את ה tokens ו metadata (סיווגים). ניתן לקסטם את ה pipeline ולהשבית / להוסיף שלבים. במקרה שלנו אנחנו מסתמכים על רק על ה embedding.

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

Sentence Segmentation (או Sentence Boundary Detection בקיצור SBD)
פונקציית ה nlp() של SpaCy כוללת רכיב בשם dependency parser המפרק טקסט למשפטים. בסוג של tokenization, אנו יכולים לגשת ל doc.sents (בפייטון ובשפת C אוהבים לקצר שמות משתנים, לדעת) – רשימת המשפטים בטקסט. פירוק למשפטים הוא לא מלאכה קלה, ולא כל המודלים תומכים ביכולת הזו. בתוך אובייקט ה doc ה source of truth של החלוקה למשפטים הוא ברמת ה token, בתכונה token.is_sent_start ועריכת הערך שלו, קובעת את חלוקת המשפטים במסמך.

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

Embedding

תהליך ה embedding הוא תהליך שהופך tokens לוקטור (מערך מספרים עשרוניים). לכל וקטור יש מימדים, ו token נתון ממופה במרחב בכל מימד בנפרד. המרחקים במרחב מבטאים דמיון סמנטי, למשל:

  • ״חתול״ ממופה ל [0.7, 0.5, 0.1]
  • "כלב״ ממופה ל [0.8, 0.3, 0.1]
  • ״אבטיח״ ממופה ל [0.1, 0.2, 0.8]

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

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

מדוע עושים embedding? רשתות ניורונים עובדות רק על מספרים, לא על טקסט. הייצוג הוקטורי מאפשר לנו לעבד את הטקסט ברשתות ניורוניות. אלגוריתמים כמו זיהוי סנטימנט או כוונה, סיכום, תרגום, זיהוי יישויות ועוד משיגים תוצאות טובות בהרבה על גבי רשתות ניורוניות מאשר בכלי NLP קלאסיים. ה Embedding הוא התרגום הנדרש כדי להפעיל טקסט על רשתות ניורונים לצורך הפעלת האלגוריתמים האלו. בעצם embedding הוא הייצוג הטבעי (״שפת המכונה״) של רשתות הניורונים.

יש מעט embeddings סטנדרטיים (למשל Word2Vec או GloVe) אבל רוב הפעמים שנעשה embedding נעשה אותם ל״שפה״ של מודל ספציפי, למשל BERT, GPT-4, GPT-5. כל embedding מגדיר:

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

נסווג את המודלים הזמינים לנו לשלוש קבוצות:

  • מודלים קלאסיים – SpaCy (או ספריות דומות) מכילה מגוון מודלים, עם תכונות שונות, לשפות שונות (אנגלית, גרמנית, וכו׳). הם מיועדים בעיקר לניתוח ותיוג טקסט בשיטות NLP קלאסיות. יש מודלים לשפה כללית (web), משפטית, רפואית, וכו׳. המודלים משתמשים בעיקר ב embedding סטנדרטיים כגון GloVe שהם סטטים – כלומר לכל מילה יש וקטור קבוע מראש, ב 300 מימדים (במקרה של GloVe).
    • מודלים סטטיים לא ידע לסווג אחרת את המילה Apple במשפטים ״Apple release a new iPhone״ ו "He ate an apple״. למילה מסוימת, למשל "Apple״, יש משמעות קבועה.
    • מודל סטנדרטי אומר שניתן לעשות לטקסט embedding פעם אחת – ולהשתמש בו בכמה מודלים.
  • מודלים קונטקסטואליים – במודלים האלו ה embedding הוא חלק מובנה במודל (ולכן לא יכול להיות סטנדרטי). המודל בוחן את הטקסט ולומד בצורה דינאמית את משמעות המילים ובונה להם וקטורים במרחב. פלטפורמה פופולארית למודלים קונטקסטואליים היא Hugging Face Transformers המספקת מודלים של Deep Learning (מסוג Transformers). יש מודלים למשימות שונות כגון ניתוח סנטימנט, תרגום, סיכום, OCR, וכו׳. המודלים הללו איטיים יותר, אבל מספקים תוצאות מדויקות יותר ממודלים קלאסיים. לרוב הם עובדים בייצוג של 500 עד 1000 מימדים.
    • במודלים קונטקסטואליים, ה־embedding הוא חלק אינטגרלי מהמודל עצמו, ולכן אינו סטנדרטי או ניתן להפרדה. המודל מנתח את הטקסט ולומד באופן דינמי את משמעות המילים בהתאם להקשר שלהן, ובונה עבורן ייצוגים וקטוריים במרחב רב־ממדי.
    • למשל, כאשר נעשה embedding לשני מסמכים, א׳ וב׳:
      • במסמך א': "Apple announced a new iPhone" המודל רואה את המילים "announced" ו-"iPhone". הוא מבין שההקשר הוא טכנולוגיה, ולכן הוא ממקם את "Apple" בנקודה על המפה שהיא:
        • גבוהה בציר "טכנולוגי" (ציר 17).
        • נמוכה בציר "אכיל" (ציר 250).
      • במסמך ב': "She ate an apple" המודל רואה את המילים "ate" ו-"an". הוא מבין שההקשר הוא אוכל, ולכן הוא ממקם את "apple" בנקודה אחרת לגמרי על אותה מפה:
        • נמוכה בציר "טכנולוגי" (ציר 17).
        • גבוהה בציר "אכיל" (ציר 250).
    • כלומר, שומרים על ״חוקי הפיסיקה״ של כל embedding: יחסי הקירבה עובדים לפי אותם כללים, מרחקים נמדדים בצורה זהה, ויש אותו מספר מימדים – אבל המיקום של אותן מילים במימדים – שונה.
    • עבור משימות מסוימות, כמו השוואת משעות של הטקסט – חיבור וקטורים יכול לעבוד (צירוף של רשימת הוקטורים של מסמך א׳ לוקטורים של מסמך ב׳). המילים המקוריות לא משנות – רק המשמעות שלהן.
    • עבור משימות אחרות, למשל סיכום טקסט או זיהוי סנטימנט – פתאום המילים מטשטשות משמעות. למילה ״Apple״ אין כבר משמעות יחידה. מכאן שחיבור embedding יגרום לפגיעה קשה בתוצאות.
      • הפתרון הפשוט הוא לחבר את המסמכים א׳+ב׳ – ולבצע embedding מחדש לאיחוד שלהם.
      • יש אלגוריתמים שמאחדים embedding שונים שנוצרו בהקשרים שונים – אך יש בהם פשרות.
  • מודלים ענקיים (LLM) אלו מודלים מסוג Transformers אבל עצומים בגודלם (ולכן איטיים הרבה יותר – לרוב מריצים אותם על שרת מרוחק). הם קונטקסטואליים וכוללים גם ידע עולמי, ולא רק הקשר מקומי מתוך הטקסט. המודלים הללו הם general-purpose ולרוב יכולים להתמודד עם כל הבעיות (ברמת הצלחה כזו או אחרת), או לפחות לנסות.
    • למשל (דוגמה רגישה), ״ישראל״ במודל קונטסטואלי רגיל ≈ מדינה, מופיעה יחד עם מילים כמו “מזרח”, “תל־אביב”, “ממשלה”. “ישראל” תשב קרוב ל־“ירדן”, “לבנון”, “סוריה”, “ארה״ב” ו״אירופה״ – פשוט כי אלו מופיעים יחד הרבה בטקסטים שעליהם אומן.
    • מודל LLM יידע ש״ישראל״ יושבת במזרח התיכון (עובדה) ולא באמריקה. שיש בה קונפליקטים ביטחוניים מתמשכים, שהיא מזוהה עם טכנולוגיה, דמוקרטיה, דתות, צבא, ועוד. כלומר הוא ימפה את הידע הזה בתוך מימדים ב embedding (בשונה למשל מ״מונטנגרו״ – בעלות מאפיינים אחרים).
    • מודלי LLM לרוב משתמשים ביותר מימדים, לרוב 1500-4000 מימדים (בעת כתיבת הפוסט).
המודלים של SpaCy אינם יודעים לעשות זאת – ועוד ב 24 שניות..

סיכום

אם לפני הפוסט הזה (חלק א׳+ב׳) לא היה לכם מושג מהו NLP (מלבד מושג כללי) ואיך משתמשים בו – הרי בסוף הפוסט אמור להיות לכם את ה״א״, וחצי ה״ב״.

ייתכן ומומחי NLP יכעסו על הפוסט – שלא פתחתי בהגדרות כמו תחביר, פונולוגיה, סמנטיקה, ופרגמטיקה. שאני בכלל לא מומחה NLP בעצמי. נו… שיכעסו 🤷.

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

שיהיה בהצלחה!

טכניקות NLP בסיסיות לפיתוח LLM – חלק א׳

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

כאשר אנחנו מפתחים מערכות LLM, פרוטוקול שאנחנו עומדים לעסוק בו הרבה הוא ״טקסט של שפה אנושית״, אפילו בתסריטים של Machine to Machine. בפוסט הזה אני רוצה לדבר על כמה כלי NLP בסיסיים שעוזרים לעבוד עם טקסט, ועל השימושים שלהם במערכות LLM. בואו נתחיל להבין איפה הכלים האלו יכולים לשמש אותנו:

  1. custom) RAG) – כדי להגיע לתוצאות מצוינות הרבה פעמים נצטרך לנהל את ה context retrieval בעצמנו ולתפור אותו ל use-case, לא סתם להשתמש ב RAG Framework מהמדף. לשלב טכניקות כגון vector similarity, hybrid search ו BM25.
  2. Safety / Validation – כאשר אנחנו רוצים לבדוק את ה output של ה LLM שהוא סביר / לגיטימי / בגבולות שאנו מצפים ולא פוגע / לא-חוקי / מעבר לגבולות האחריות שלנו – אנחנו צריכים לאתר תבניות מסוימות בטקסט. איך עושים את זה? בעזרת כלי NLP כמובן. NER (קרי Named Entity Recognition – זיהוי אלמנטים כמו כתובת, שם עסק, עיסוק, וכו׳) למשל לאיתור PII או, Text Classification (סיווג טקסט לקטגוריה, למשל ״עצה ביטוחית״ או ״תוכן רעיל״).
  3. Evaluation – כאשר אנחנו רוצים לאמוד כמה מוצלחות התשובות של ה LLM שהפעלנו. לזהות מגמות של רגרסיה כדי לטפל בהן. יש מדדי הערכה קלאסיים כגון F1 או ROUGE, טכניקות חדשות יותר כגון LLM-as-a-Judge ו Pairwise Comparison.
  4. ניקוי נתונים בתהליך ה ingest ל Knowledge Base – נרצה לצמצם כפילויות סמנטיות, ולצמצם טקסט מיותר שלא שווה לאנדקס. כאן יש שימוש ב Canonicalization, Stemming, Lemmatization, Deduplication ועוד.
  5. Intent extraction / routing – אנחנו רוצים לאבחן את סוג הבקשה (intent) של המשתמש (אנושי או מכונה) ולנתב אותו ל branch הנכון של ה LLM. נשתמש בכלים כגון SVM (Support Vector Machine) או LLM Chains.

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

את רוב הפונקציות הנ״ל תוכלו למצוא בספריות כגון SpaCy או NLTK (קרי Natural Language Toolkit) לעיבוד טקסט + scikit-learn ל intent/safety ו evaluation בפייטון או Apache OpenNLP בעולמות הג׳אווה.
חשוב לציין שה ecosystem בעולם הפייטון מוביל על פני כל stack טכנולוגי אחר בעולמות הללו.

ניתן למצוא גם יכולות NLP חלק ממוצרים מוכרים המטפלים בטקסט, בעיקר Apache Lucene / Elasticsearch/OpenSearch אבל גם בסיסי נתונים כמו Postgres או אורקל (שממנו הושפע רבות) – בעזרת plugins כמו pg_bm25 או pgvector אבל גם SQLite (בסיס נתונים embedded – קטן ופשוט) עם כמה יכולות. במהלך הדרך התוודעתי לבסיס נתונים קטן ו embedded נוסף בשם DuckDB (הוא Columnar, vectorized, multi-threaded DB) המצוין לאבטיפוס בעולמות ה retrieval ומאפשר להריץ דירוג לשוני (BM25) ודירוג סמנטי (וקטורי) במנוע אחד.

Use case פשוט להתחלה

אנחנו רוצים לזהות במערכת שלנו לקוחות B2B שמנסים להרשם פעמיים. הם מספקים כתובת אימייל ושם העסק (Business Name). אם המייל + שם העסק זהים – נודיע להם שיש משתמש במערכת ונציע להם retrieval email (קרי ״forgot my password״).

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

  • שגיאות כתיב. Dainel ולא Daniel
  • אותיות גדולות/קטנות, רווחים, או סימני פיסוק A.C.M.E., Inc. מול ACME Inc.
  • קיצורים שונים, למשל: Ezra&Sons International מול Ezra and sons Intl.

לשמחתנו, אנחנו מכירים גוגל/פרפלקסיטי ויכולנו למצוא בקלות ספרייה כגון RapidFuzz (פייטון) שעושה Fuzzy matching לטקסט. יש שם מגוון פונקציות, אבל הטובה ביותר (לפי GPT) היא WRatio. נשתמש בה!

> fuzz.WRatio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
95.0
> fuzz.WRatio("ACME international", "ACME INTERNATIONAL")
34.54
>>> fuzz.WRatio("AIG", "AIF") # keyboard-adjastant typo
66.66
>>> fuzz.WRatio("AIG", "AI±") # keyboard-distant typo
66.66

כלומר, אני מבין ש Fuzzy Match מחזיר מספר בין 0 ל 100, ואני צריך לקבוע מעל איזו ציון אני מקבל תוצאה כחיובית – זה מובן, אבל הספריה המובילה הזו, שגם GPT וגם Claude המליצו לי עליה – לפעמים דיי מפגרת!

אולי שווה להשתמש בפונקציות אחרות ולא דווקא WRatio?
weighted ratio מריץ כמה ״אלגוריתמים״ שונים ונותן את התוצאה הגבוהה ביותר. לפעמים יש אלגוריתם ״אופטימי״ שיקפיץ תוצאות וייתן false positive, אז כן – כדאי להכיר מה הספרייה עושה.

אולי צריך להבין טיפה NLP גם כאשר משתמשים בספרייה ״מובילה״?
בהחלט. Fuzzy match הוא אלגוריתם שמכסה תחומים מסוימים – ולא מכסה אחרים. הוא יידע לזהות חילופי מילים, מילים בודדות שנוספו לטקסט, או שגיאות כתיב מסוימות (אות חסרה) – אבל יש אלמנטים שלמים של טקסט (אפילו בסיסיים כמו UPPERCASE vs. lowercase) שהוא לא בנוי להתמודד איתם.

בדומיין כמו שמות עסקים (לא אביא דוגמאות – אבל האמנו לי, בבקשה) – יש הרבה תצורות של שוני שמחוץ ל״רדאר״ של fuzzy match. אז מה עושים? Canonicalization.

כמפתחים, אנו רגילים לעשות normalization בטקסט, קרי יצירת ייצוג עקבי לצורת הטקסט כגון ״ CAFÉ״ ו "cafe״.
כעת נרצה קצת להתקדם ולבצע canonicalization שמשמעו ייצוג עקבי למשמעות הטקסט (בדומיין) כגון ״Acme LLC״ ו ״acme״ (למי שלא מכיר LLC ≈ ה ״בע׳מ״ של ארה״ב).

יישום canonicalization לצורך השוואת טקסט

נתחיל ב normalization:

import spacy
import unicodedata 

tokenizer = spacy.blank("en") # english-only

def normalize_text(text: str) -> str:
  
    text = text.lower() #lowercase

    # Unicode normalization
    text = unicodedata.normalize("NFKD", text) # **1** Unicode normalize (NFKD)
    text = "".join(character for character in text if unicodedata.combining(character) == 0) # **2** remove combining characters

    # Tokenize with spaCy **3**
    doc = tokenizer(text)

    # Strip punctuation/whitespace **4**
    tokens = []
    for token in doc:
      if token.is_punct or token.is_space:
        continue
      tokens.append(token.text)

    # Join back
    return " ".join(tokens)
  1. זו נורמליזציה של Unicode כפי שהסברתי בפוסט על תוכנה רב-לשונית (תחת חיפוש ו Normalization). ייתכן והטקסט שמגיע אלינו, גם ממשתמשי קצה לא אחיד בצורה שלו. למשל:  מרכאות ניטראליות ( " ) מול מרכאות בעלות כיוון (  , ‟ ). או בגרמנית Fuβ שזו צורת כתיבה שקולה ל Fuss. נרמול NFKD הוא לרוב הנרמול המומלץ.
  2. זה שלב נוסף של הסרת סימנים מסוימים, כמו accent (נפוץ בשפות אירופאיות).
    למשל café ל cafe.
  3. כאן אנחנו משתמשים בספרייה בשם SpaCy (מקור השם: space – מרחב בין מילים/לשוני + Cy כי מומשה ב Cython גרסה מהירה של פייטון) לביצוע tokenization – חלוקת טקסט ליחידות בסיסיות הנקראות tokens — לרוב מילים, סימני פיסוק, מספרים וכו’. לדוגמא:
    "I love NLP." → [ "I", "love", "NLP", "." ]
  4. אנחנו משתמשים ב tokenization על מנת לנקות whitespace (זה קל, אפשר גם ב Regex), וסימני פיסוק (נקודה, פסיק וכו׳).
    ״אבל ליאור, אפשר בקלות לעשות את זה ב Regex״ – זה דיי נכון, אבל לא מדויק. למשל, אנחנו רוצים להוריד גרשיים ׳ מסביב למילה, אבל לא בתוך המילה "don't״. או למשל לא לשבור את "U.S.A״ ל ["U","S","A"]. בעוד Regex ייפול במקרי הקצה אלו, SpaCy לא.
    כמובן שזה קצה הקרחון של היכולות של SpaCy – אבל זה הרגל טוב להשתמש בו – ואז ניתן להרחיב ולהשתמש ביכולות נוספות.

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

למשל, בשמות חברות בארה״ב נהוג (אבל לא חובה) להוסיף LLC או INC (המקביל ל״בע׳מ״ בישראל). נרצה להסיר את הביטויים האלו על מנת שאם נרשם השם פעם עם, ופעם בלי – עדיין נדע להשוות אותם. למשל:
["llc", "inc", "corp", "co", "pc", "lp", "llp"]

שימו לב ש llc מופיע בטקסט לרוב כ L.L.C – אבל מכיוון שכבר הסרנו סימני פסוק, אין צורך לבדוק את המקרים הללו.

השלב הבא הוא לנקות Stop Words. אלו מילים מאוד נפוצות, אך שלא מוסיפות משמעות לתוכן הטקסט (ולכן מקשות על השוואה יעילה). למשל: the, a, an, and, or, is, was, are, to, from, for, of

אנחנו יכולים להשתמש ברשימה מוכנה / גנרית כמו spacy.lang.en.stop_words.STOP_WORDS (המכילה 326 מילים) אבל בד״כ התוצאות טובות / נשלטות יותר אם ננהל את הרשימה בעצמנו. במקרה שלנו, בחנתי את הטקסט* ומצאתי ש and ו the הן המילים הנפוצות שארצה להגדיר ב STOP WORDS.

בנוסף, ארצה להחליף את הטקסט "&" ב " and ״ – כחלק מהתהליך. כמובן שחשוב לעשות זאת, לפני הסרת סימני הפיסוק. הכל מצפייה בטקסט*

* האמת, מאז שיש LLM – הוא עושה הרבה מהעבודה הזו. אני שולף מבסיס הנתונים כ 10K רשומות של שמות עסקים, לוקח מודל חזק (כיום: GPT5-thinking-high) ומבקש ממנו לעזור לי לנתח את הטקסט. מה ה stop words? מה ה designations הנפוצים? מה ה synonyms (נדבר עליהם מיד)? מה עוד פספסתי? כמובן שאני חושב ומבקר את מה שהוא אומר וגם בודק בעצמי – אבל הוא בהחלט מאוד עוזר. (למשל את קיצורי החברות lp ו pc הוא זיהה – ואני לא הייתי מודע אליהם).

השלב האחרון שנשתמש בו הוא Synonym expansion.
synonym הן מילים נרדפות, ושוב – הרשימה הרלוונטית היא לרוב מבוססת דומיין. הנה מונחים לדוגמא שזיהיתי:

synonyms:
  service:
    - services
    - solutions
  construction:
    - contruction # very common spelling mistake
    - constrcution # a common spelling mistake
    - builders
    - contractors
  consulting:
    - advisory
  cleaning:
    - janitorial
 ...

אני אעבור על הטקסט ואחליף כל ערך ברשימת המילים הנרדפות, למילה המובילה (למשל: services ל service). שימו לב ש:

  1. יש מקרים בודדים של יחיד <=> רבים. לא טיפלתי בזה בצורה גורפת כי לא ראיתי שזה נפוץ בדוגמאות הטקסט. כמו כן, בסוף אשתמש ב RapidFuzz שהאלגוריתמים שלו מתמודדים טוב עם יחיד-רבים בשפה האנגלית.
  2. הכנסתי שגיאות כתיב נפוצות במקרה של construction. הכנסה של שגיאות כתיב כ synonym הוא לא לגמרי סטנדרטי ונתון להחלטה ספציפית. במקרה שלי, הטקסט להשוואה מוקלד ע״י משתמש במובייל – קרקע פורייה לשגיאות כתיב נפוצות. הוספתי את האפשרות יותר כדוגמא, כי היעד הסופי של ה canonicalization במקרה הזה, RapidFuzz, ״אוכל״ היטב גם שגיאות כתיב מהסוג הזה.

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

סיכום

גם בעולם בו יש את ה״קסם״ של LLM – עדיין יש מקום ל NLP ״קלאסי״.

אפשר לומר שדווקא ה־LLM החזיר (חלק מ) ה־NLP למרכז. בכל מקרה שבו המודל לא מצליח “במכה אחת” וללא עזרה (מה שנקרא ״zero-shot״), אנו נדרשים לעבד טקסט: לנקות, להבין, למיין, וכו׳ — בדיוק שם נכנס ה־NLP הקלאסי לתמונה.

בדוגמה, ראינו ש Fuzzy Matching לא תמיד עובד Out of the Box, ללא הכנת הטקסט. עשינו Canonicalization והכרנו כמה מושגים חשובים ושימושיים בעיבוד טקסט כמו Stop Words ו Synonyms Expansion. לא הזכרנו Lemmatization ו Embedding – מה שיחייב אותי לכתוב פוסט המשך 😅.

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

שווה גם לציין שחלק מהשימושים בכלים שראינו הם ספציפיים Use Case. למשל Synonyms expansion הוא לא תמיד החלפה של רשימת מונחים בערך קאנוני. זה תלוי במקרה. למשל, עבור חיפוש טקסט, ייתכן ונרצה להרחיב ערך מהרשימה לכל ה synonyms המוגדרים. דוגמה: אם הופיעה ב query המילה ״service״ נרחיב את החיפוש לכל הערכים [״service״, ״services״, ״solutions״] כי כל אחד מהם רלוונטי פוטנציאלית לחיפוש שלנו.

שיהיה בהצלחה!