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

LLM Caching

אחת הדרכים הפשוטות לחסוך הרבה כסף ולהאיץ תגובה: לא לשלם פעמיים על אותו חישוב. שלושה סוגי caching ומתי כל אחד.

שלושה דברים שנקראים "מטמון"

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

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

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

בשורה אחת

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

מטמון פרומפט: הזול והבטוח

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

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

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

הכלל שנגזר: הקבוע קודם, המשתנה אחרון

# ✗ הורס את המטמון בכל בקשה
messages = [
    {"role": "system", "content": f"היום {today}. " + INSTRUCTIONS},
    {"role": "system", "content": SCHEMA},
    {"role": "user",   "content": question},
]

# ✓ כל מה שקבוע בהתחלה, כל מה שזז בסוף
messages = [
    {"role": "system", "content": INSTRUCTIONS},   # לא משתנה
    {"role": "system", "content": SCHEMA},         # לא משתנה
    {"role": "system", "content": f"היום {today}."},
    {"role": "user",   "content": question},
]

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

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

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

מתי זה בכלל משתלם

חישוב פשוט שמכריע: כמה מהבקשה קבוע וכמה משתנה.

מערכת A — עוזר על מסמכי החברה
  קבוע:   הנחיות + סכימה   ≈ 2,000 טוקן
  משתנה:  שאלה + קטעים     ≈ 3,000 טוקן
  → 40% מהקלט נשמר. שווה מאוד.

מערכת B — סיווג הודעה קצרה
  קבוע:   הנחיה קצרה       ≈ 150 טוקן
  משתנה:  ההודעה           ≈ 200 טוקן
  → כמעט אין מה לשמור. דלג.

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

התאמה מדויקת: פשוט, ומוגבל

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

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

import hashlib, re

def key(q, model, prompt_version):
    q = q.strip().lower()
    q = re.sub(r"[^\w\s\u0590-\u05FF]", "", q)  # פיסוק
    q = re.sub(r"\s+", " ", q)                    # רווחים
    raw = "%s|%s|%s" % (prompt_version, model, q)
    return hashlib.sha256(raw.encode()).hexdigest()

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

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

מטמון סמנטי: איפה זה נשבר

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

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

"מה מדיניות ההחזרות למוצרי חשמל?"
"מה מדיניות ההחזרות למוצרי הלבשה?"
  → דמיון גבוה מאוד. משמעות שונה.

"כמה עולה המסלול הבסיסי?"
"כמה עולה המסלול העסקי?"
  → אותו דבר. ותשובה שגויה כאן עולה כסף.

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

איך להשתמש בזה בלי להישרף

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

מפתח המטמון: מה חייב להיכנס

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

מה שחייב להיות בפנים:

ההיקף הוא לא אופציונלי

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

מה אסור לשמור

פסילה: מתי לזרוק

שתי גישות, ואחת מהן נכונה כמעט תמיד.

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

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

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

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

בסוכנים זה מתנהג אחרת

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

מה ששווה לשמור בסוכן:

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

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

לשמור את השליפה, לא רק את התשובה

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

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

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

סדר היישום: מה לעשות בשבוע הראשון

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

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

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

ושתי אפשרויות שאינן מטמון ולעיתים עדיפות

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

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

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

איפה לשים את זה בפועל

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

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

def cached_answer(k, compute):
    try:
        hit = store.get(k)
        if hit:
            log("cache_hit", key=k)
            return hit, True
    except StoreError as e:
        log("cache_unavailable", err=e)   # ממשיכים

    out = compute()
    try:
        store.set(k, out, ttl=3600)
    except StoreError:
        pass                              # לא נכשלים על כתיבה
    return out, False

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

למדוד, ולא רק את מה שנוח

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

מה שכדאי לעקוב אחריו:

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

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

מטמון והזרמה לא מסתדרים לבד

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

שתי דרכים לטפל:

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

מתי לא

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

הצעד הבא

Caching הוא חלק מבקרת עלות רחבה. שלב אותו עם ניתוב מודלים ותמחור חכם.