לדלג לתוכן

8.1 איפה AI נכשל הרצאה

שבעה פרקים למדנו איך להשתמש בagent, איך לתת לו context, איך לבנות איתו tools משלנו. עכשיו מגיע החלק הכי חשוב לקריירה שלכם: מתי לא לסמוך עליו. הagent כמו Claude Code הוא tool עוצמתי, אבל הוא לא חבר צוות שאפשר להאשים כשמשהו נשבר בפרודקשן - האחריות תמיד נשארת אצלכם. כדי לשאת באחריות הזו ברצינות, צריך להכיר את דפוסי הכשל האופייניים של מודלי שפה: מתי הם ממציאים עובדות, מתי הם בטוחים בעצמם יותר משצריך, ולמה קוד שנראה מושלם יכול להיות שגוי בדיוק. זו לא הרצאה על "AI רע" - היא הרצאה על איך להשתמש בtool חזק בלי להיפגע מהחולשות שלו.

הזיה - hallucination

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

בcontext של פיתוח, hallucination מופיעה בכמה צורות אופייניות:

  • פונקציות שלא קיימות - הagent קורא לפונקציה מספרייה, בשם הגיוני לחלוטין, שפשוט לא קיימת בגרסה הזו (או בכלל).
  • פרמטרים שגויים - קריאה נכונה לפונקציה אמיתית, אבל עם ארגומנט שאינו קיים או שם שדה שהוחלף.
  • הפניות למקורות שלא קיימים - קישור לתיעוד, מאמר או issue ב-GitHub שנשמע אמין אבל לא קיים בפועל.
  • התנהגות ספרייה מומצאת - תיאור מדויק ומשכנע של איך פונקציה "אמורה" לעבוד, שלא תואם את מה שהיא באמת עושה.
# Typical example of hallucination - the function sounds plausible, but doesn't exist in the requests library
import requests

response = requests.get_with_retry("https://api.example.com", retries=3)
# requests doesn't contain such a function. There's requests.Session() with adapters,
# but not get_with_retry directly. The model "invented" a convenient interface that it assumed would be there.

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

ביטחון עצמי מוגזם - overconfidence

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

התופעה הזו מסוכנת במיוחד בשלושה contexts:

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

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

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

Question: "Does this function correctly handle all edge cases?"

Typical model answer: "Yes, the function handles all edge cases
including empty input, null values, and integer overflow."

What actually happened: the model reviewed the code visually, didn't run any tests,
and didn't necessarily consider integer overflow because it wasn't present in the original code.

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

קוד שנשמע נכון אבל שגוי - plausible-but-wrong code

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

דוגמאות אופייניות:

# Request: "write a function that checks whether a user is allowed to access a resource"
def can_access(user, resource):
    if user.is_admin:
        return True
    if resource.owner_id == user.id:
        return True
    return False

# Looks correct, passes basic tests - but completely forgot about shared-resource permissions
# (resource.shared_with), so a user who has a resource shared with them will incorrectly get "not authorized".
# A silent bug - it doesn't crash, it's just overly restrictive, and easy to miss in review.
# Request: "write a function that computes a moving average"
def moving_average(values, window):
    result = []
    for i in range(len(values)):
        window_slice = values[max(0, i - window + 1):i + 1]
        result.append(sum(window_slice) / len(window_slice))
    return result

# The code is mathematically correct, but at the start of the list the window is smaller than requested
# (average over fewer elements than the window size), and this may or may not make
# a difference - it depends on a requirement that wasn't explicitly stated in the prompt.

שני התבניות שחוזרות שוב ושוב:

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

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

ידע מיושן - outdated knowledge

לכל מודל שפה יש נקודת חיתוך ידע - knowledge cutoff: תאריך שאחריו הוא לא ראה מידע חדש באימון. גם המודלים העדכניים ביותר של היום - Opus 4.8, Sonnet 5, Haiku 4.5 - פועלים כך. זה אומר שהמודל עלול:

  • להמליץ על גרסת ספרייה שכבר deprecated.
  • לא להכיר API חדש שהתווסף אחרי שהאימון שלו הסתיים.
  • להציע פתרון ל"בעיה" שכבר נפתרה בגרסה עדכנית של הtool, כי הוא לא יודע שהיא נפתרה.
  • לתאר "השיטה המומלצת" הישנה, כשבפועל הקהילה עברה לגישה אחרת.
Typical example:
The model suggests using package X at version 2.x, because that's the version it knew
from training. In practice, the package moved to 3.x with breaking changes,
and the API the model suggests no longer exists.

הפתרון המעשי הוא לא "לזכור שיש cutoff ולדאוג" - זה לא עוזר בפועל. הפתרון הוא שימוש בtools שמעקפים את המגבלה:

  • חיפוש באינטרנט - כשהagent או הצ'אט תומכים בחיפוש חי, זה נותן גישה למידע עדכני שלא היה חלק מהאימון.
  • שרתי MCP לתיעוד - כמו שראינו בפרק 6, חיבור לתיעוד רשמי ועדכני (למשל דרך Context7 או שרת דומה) עוקף את בעיית ה-cutoff לגמרי, כי המודל קורא תיעוד אמיתי ולא נשען על זיכרון.
  • קריאת קוד קיים בפרויקט - אם הagent קורא את ה-package.json או requirements.txt בפועל, הוא רואה איזו גרסה באמת מותקנת, ולא מנחש.
  • מודעות פשוטה - כשמבקשים המלצה על ספרייה או tool חדשים יחסית, שווה לשאול את המודל במפורש "מה נקודת החיתוך שלך" ולהצליב עם מקור עדכני לפני שסומכים.

באגים עדינים - subtle bugs

מעבר לhallucination ולקוד שגוי בגלוי, יש קטגוריה מסוכנת עוד יותר: באגים עדינים שרק מופיעים בתנאים מסוימים. אלה קשים לתפיסה גם למפתחים מנוסים, אבל agent AI נוטה לייצר אותם בתדירות גבוהה יותר כי הוא לא "מריץ" את הקוד בראש שלו באותה צורה שמפתח מנוסה עושה - הוא מייצר טקסט שסטטיסטית דומה לפתרונות נכונים.

טבלת דפוסים נפוצים:

דפוס הבאג דוגמה למה קשה לתפוס
תנאי מרוץ - race condition שתי בקשות שמעדכנות אותו רשומה בו-זמנית לא מופיע בבדיקה ידנית רגילה, רק תחת עומס
off-by-one לולאה שרצה עד len(arr) במקום len(arr) - 1 עובד נכון על רוב הקלטים, נשבר על הקצה
טיפול שגוי באזורי זמן חישוב הפרש תאריכים בלי להתחשב ב-UTC עובד במחשב המפתח, נשבר במשתמש באזור זמן אחר
השוואת מספרים עשרוניים if price == 19.99 במקום השוואה עם סף נכשל בגלל דיוק floating point
דליפת משאבים פתיחת קובץ/חיבור בלי סגירה בנתיב שגיאה עובד בהרצה קצרה, קורס אחרי שעות ריצה
הרשאות חסרות בבדיקת קצה בדיקת הרשאה רק בנתיב הראשי, לא בנתיב החלופי נראה מאובטח, יש דלת אחורית לא מכוונת

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

כשhallucination הופכת לפעולה - agentic hallucination

בצ'אט, hallucination היא משפט שגוי שאתם קוראים ובודקים לפני שאתם משתמשים בו. אצל agent שרץ בטרמינל, כמו Claude Code, hallucination יכולה להפוך ישירות לפעולה - קובץ שנכתב, פקודה שרצה, שינוי שנשמר בגיט. זה הבדל מהותי, כי הagent לא תמיד עוצר לשאול "האם אני בטוח שזה נכון" לפני שהוא ממשיך לצעד הבא בלולאה שלו.

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

זו הסיבה שמצב תכנון - plan mode, ביקורות ביניים, ותחומי הרשאה מצומצמים (רק תיקיית הפרויקט, לא כל המערכת) הם לא "חוסר אמון בagent" אלא רשת ביטחון הכרחית מול העובדה שהמודל עצמו לא תמיד יודע שהוא טועה. ככל שהמשימה נותנת לagent יותר צעדים עצמאיים ברצף, כך שווה לעצור ולבדוק תוצאות ביניים לעיתים קרובות יותר, ולא רק בסוף.

איך לזהות דפוסי כשל בזמן אמת

הידע התיאורטי לא מספיק - צריך הרגלים מעשיים שמפעילים "פעמון אזעקה" בזמן העבודה עם הagent:

  • חשדנות כלפי ודאות מוחלטת. אם הagent אומר "זה בטוח יתקן את הבעיה" בלי לנמק או להראות בדיקה, זה דגל אדום, לא הרגעה.
  • בקשו הפניה למקור. אם הagent מצטט התנהגות API, בקשו "תראה לי בתיעוד" או תנו לו גישה לחפש. הפניה שלא ניתן לאמת שווה כמעט כלום.
  • הריצו, אל תקראו בלבד. קוד שנראה נכון חייב לרוץ בפועל, כולל על קלטי קצה. זה הכלל המרכזי שחזרנו עליו כבר בפרק 3.6.
  • שימו לב לפערי גרסה. אם הagent מציע קוד עם API שאתם לא מזהים, בדקו האם הוא קיים בגרסה המותקנת בפועל - לא רק "האם הוא נשמע סביר".
  • בקשו מהמודל להצביע על אי-ודאות. אפשר לבקש במפורש בפרומפט: "אם אתה לא בטוח בהתנהגות של פונקציה מסוימת, תגיד את זה במפורש במקום לנחש." זה לא פותר את הבעיה לגמרי, אבל משפר משמעותית את הסיכוי שהמודל יסמן אי-ודאות כשהיא קיימת.
  • בדקו הנחות סמויות. לפני שמאשרים תיקון, שאלו את עצמכם: "איזו הנחה הagent עשה כאן שלא כתבתי לו במפורש?" לרוב יש כמה, וכדאי לוודא שהן נכונות.

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

סיכום

  • הזיה - hallucination היא ייצור מידע שגוי בביטחון מלא, כי המודל חוזה טקסט סביר ולא בהכרח אמת מאומתת. מתבטאת בפונקציות שלא קיימות, פרמטרים שגויים והפניות למקורות מומצאים.
  • ביטחון עצמי מוגזם גורם למודל להישמע משוכנע גם כשהוא בעצם מנחש - בדיבוג, בהחלטות ארכיטקטורה ובהערכה עצמית של עומק הבדיקה שביצע.
  • קוד "נכון למראה" מכסה את המקרה הנפוץ ומפספס קצוות, או מניח הנחה סבירה אך שגויה על הדרישה - ורק ריצה בפועל עם קלטי קצה חושפת את זה.
  • ידע מיושן נובע מנקודת חיתוך האימון - knowledge cutoff. הפתרון הוא חיפוש חי, שרתי MCP לתיעוד עדכני, וקריאת קבצי הפרויקט בפועל במקום הסתמכות על זיכרון המודל.
  • באגים עדינים כמו תנאי מרוץ, off-by-one, טיפול שגוי בזמן ודיוק עשרוני עוברים סקירה חזותית בקלות ונתפסים רק בהרצה ובבדיקת קצוות.
  • ההרגל המרכזי שמגן עליכם: חשדנות כלפי ודאות מוחלטת, דרישת הוכחה במקום הצהרה, והרצה בפועל של כל קוד לפני שסומכים עליו - במיוחד ככל שההשלכות של טעות חמורות יותר.