Context Compaction — דחיסת שיחות ארוכות ללא איבוד מידע קריטי
מאת צוות מדיה דיל · 12.08.2026 · Context Engineering · 5 דק׳
איך בונים מנגנון compaction שממיר היסטוריית שיחה ארוכה לתקציר קומפקטי, בלי לאבד החלטות, אילוצים ומספרים שהמשימה תלויה בהם.
סוכן קידוד שרץ על משימת refactoring גדולה עבד יפה בשעה הראשונה, ואז החל "לשכוח" החלטות שהתקבלו קודם — למשל שהוחלט לא לגעת במודול תשלומים, או ששם משתנה מסוים שונה בכוונה. הסיבה לא הייתה קסם: בשלב מסוים ה-runtime הפעיל דחיסה אוטומטית של ההיסטוריה כדי לפנות מקום, וה-summary שנוצר היה גנרי מדי — "בוצעו שינויים במספר קבצים" — ומחק בדיוק את הפרטים שהמשימה המשיכה להסתמך עליהם. Context Compaction הוא הפרקטיקה של דחיסת שיחה ארוכה לייצוג קטן יותר, וההבדל בין compaction טוב לגרוע הוא כמעט תמיד באיזה מידע נבחר להישמר במפורש, ולא רק "כמה" מצטמצם.
compaction זה לא compression
שני המונחים מתבלבלים לעיתים קרובות. Context Compression מתייחס בדרך כלל לטכניקות שמצמצמות את ייצוג המידע עצמו — ניסוח מחדש קצר יותר, הסרת redundancy, לפעמים אפילו ייצוג ברמת embedding. Compaction, לעומת זאת, הוא תהליך ברמת ניהול השיחה: בנקודת זמן מסוימת (למשל כשמגיעים ל-70% מהתקציב שהוגדר, ראו Context Budgeting) המערכת עוצרת, לוקחת את כל ההיסטוריה עד כה, ומייצרת ממנה מצב חדש וקומפקטי שממנו השיחה ממשיכה. זו לא פעולה על טקסט בודד אלא החלטה ארכיטקטונית: מה נשאר, מה נמחק, ומה עובר לאחסון חיצוני שניתן לשלוף בחזרה במידת הצורך.
מה חובה לשמר במפורש
הטעות הנפוצה ביותר היא לתת למודל לסכם "בחופשיות" בלי הנחיה מבנית, מה שמוביל לסיכומים שקולעים לטון הכללי של השיחה אבל מחמיצים פרטים קונקרטיים. compaction אמין דורש רשימת קטגוריות שחייבות הישרדות מפורשת, בפורמט מובנה ולא בפרוזה חופשית:
- החלטות שהתקבלו — כולל הנימוק הקצר, לא רק המסקנה, כדי שאפשר יהיה לערער עליה בהמשך אם נדרש.
- אילוצים ומגבלות — "אסור לגעת ב-X", "התקציב הוא Y", "הלקוח דורש Z" — אלה בדיוק הדברים שנעלמים ראשונים בסיכום גנרי.
- מזהים ומספרים מדויקים — שמות קבצים, מזהי טיקטים, מספרי גרסה. מודל שמסכם "כמה קבצים שונו" במקום לרשום את הרשימה המדויקת יוצר בור מידע שאי אפשר למלא בדיעבד.
- פעולות פתוחות (open loops) — משימות שהתחילו ולא הסתיימו, כדי שלא "ייעלמו" בלי שאיש שם לב.
דפוס עבודה שמתפקד היטב הוא לדרוש מהמודל למלא תבנית JSON קבועה בשלב הסיכום, ולא לתת חופש ניסוח — כך אפשר גם לבדוק אוטומטית שכל שדה חובה מולא, במקום לגלות בדיעבד שהסיכום "שכח" שדה שלם.
Compaction היררכי: לא כל השיחה נדחסת באותו קצב
גישה בוגרת יותר לא דוחסת את כל ההיסטוריה בבת אחת אלא בשכבות: החלק האחרון של השיחה (למשל עשרת התורות האחרונים) נשאר גולמי לגמרי, החלק שלפניו עובר סיכום ברמה בינונית, וההתחלה הרחוקה עוברת לסיכום-על תמציתי ביותר. זה מדמה את האופן שבו זיכרון אנושי עובד — אירועים אחרונים חדים, אירועים רחוקים מקוצרים לתמצית. בכל פעם שמפעילים compaction נוסף, "מקדמים" שכבה אחת קדימה: מה שהיה גולמי הופך לסיכום בינוני, ומה שהיה בינוני מתמצת עוד יותר. הגישה הזו קשורה ישירות לשאלות שנדונות במאמר על Working Memory מול Long-Term Memory, כי בפועל compaction הוא מנגנון ה"קידום" בין שתי רמות הזיכרון האלה.
אירוע לוג מלא + תצוגה דחוסה
הפרקטיקה הבטוחה ביותר היא לא למחוק אף פעם את ההיסטוריה המקורית, אלא לשמור אותה כ-append-only log חיצוני (קובץ, טבלה, או event store), ולתת ל-compaction ליצור רק "תצוגה" קומפקטית ששולחים למודל. אם מתגלה בהמשך שפרט קריטי אבד בסיכום, אפשר לחזור ללוג המקורי ולשלוף אותו ידנית או אוטומטית — למשל דרך כלי retrieval שמחפש בלוג המלא לפי מילת מפתח או embedding. גישה כזו הופכת את compaction מפעולה בלתי הפיכה למעין cache: אפשר להיות אגרסיביים בדחיסה, כי תמיד יש רשת ביטחון.
בדיקת איכות compaction
בלי בדיקה שיטתית, קל מדי לגלות בעיה בפרודקשן ולא בפיתוח. גישה מעשית היא לבנות מערך eval קטן: שיחות ארוכות עם עובדות "טמונות" בשלבים שונים (למשל אילוץ שהוזכר בתור 3 מתוך 40), ואז להריץ compaction ולבדוק אם המודל עדיין יכול לענות נכון על שאלה שתלויה בעובדה הזו אחרי הדחיסה. ציון שנופל מתחת לסף מוגדר צריך לעצור deploy, בדיוק כמו כל regression test אחר. זהו ההבדל בין מערכת שמסתמכת על "המודל בטח יזכור" לבין מערכת שמוכיחה זאת.
מתי להפעיל compaction — trigger מבוסס טוקנים מול trigger מבוסס זמן
יש שתי אסטרטגיות נפוצות להחלטה מתי בדיוק להפעיל compaction, ולכל אחת מחיר שונה. הראשונה, trigger מבוסס טוקנים, מפעילה דחיסה כשההיסטוריה חוצה אחוז מסוים מהתקציב שהוגדר — פשוטה ליישום, אבל עלולה לקטוע compaction באמצע רצף לוגי (למשל באמצע ניתוח משימה מורכבת), מה שמייצר סיכום פחות קוהרנטי. השנייה, trigger מבוסס גבולות טבעיים, מחכה לנקודת עצירה הגיונית — סיום תת-משימה, מעבר לנושא חדש, אישור מהמשתמש — ורק אז מפעילה דחיסה, גם אם התקציב עדיין לא נוצל במלואו. הגישה השנייה מייצרת תוצאה איכותית יותר אבל דורשת מנגנון שמזהה "נקודות עצירה" — לרוב סימון מפורש מהמודל עצמו ("סיימתי את השלב הזה") או מהאורקסטרטור שמנהל את הזרימה. בפרודקשן, השילוב הנפוץ ביותר הוא trigger מבוסס טוקנים כרשת ביטחון, עם ניסיון להמתין לגבול טבעי הקרוב ביותר לפני ההפעלה בפועל, ולא לחתוך בול ברגע שהתקרה נחצתה.
מי מבצע את הדחיסה: אותו מודל או מודל נפרד
שאלה ארכיטקטונית שקל לפספס היא האם compaction מתבצע על ידי אותו מודל שמנהל את השיחה, או על ידי מודל נפרד וזול יותר שמיועד רק לסיכום. שימוש באותו מודל נוח כי הוא כבר "נמצא בהקשר" ומבין את הניואנסים של השיחה, אבל הוא גם יקר יותר וגם מוסיף latency לזרימה הראשית. שימוש במודל נפרד — קטן, מהיר וזול, שמתמחה בחילוץ עובדות לפי תבנית קבועה — מפחית עלות ומאפשר להריץ את הדחיסה במקביל ברקע בלי לחסום את השיחה הפעילה, אבל דורש שהמודל הזה יקבל הנחיה מפורשת מאוד לגבי מה לשמר, כי הוא לא "מכיר" את הרגישויות של המשימה הספציפית באותה מידה. בפרודקשן עם נפח תעבורה גבוה, מודל סיכום ייעודי כמעט תמיד משתלם כלכלית, בתנאי שההנחיה שלו נבדקת שוב ושוב מול מקרי קצה — כי הוא זה שקובע בפועל מה שורד מהשיחה ומה נעלם ממנה לצמיתות.
תגיות: Context Compaction · Conversation Summarization · LLM Agents · Context Window · Memory