Temporal Knowledge — ניהול מידע שמשתנה לאורך זמן

מאת צוות מדיה דיל · 12.08.2026 · AI Retrieval · 5 דק׳

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

סוכן AI פנימי בחברת לוגיסטיקה קיבל שאלה: "מה היה מחיר המשלוח לאירופה כשהלקוח ביצע את ההזמנה בפברואר?" והחזיר את המחיר הנוכחי — כי מאגר הידע שלו החזיק רק את המחיר העדכני, ללא זיכרון היסטורי. זו לא תקלה נדירה; זו תוצאה ישירה של איך רוב מערכות ה-RAG בונות את מאגר הידע שלהן: כל עדכון דורס (overwrite) את הקודם, ומאגר הידע תמיד מייצג רק "עכשיו". ברגע שהעסק שלכם מעורב בחוזים, תמחור היסטורי, מבנה ארגוני משתנה, או כל תחום שבו "האמת" תלוית זמן — הארכיטקטורה הזו מייצרת תשובות שגויות שנשמעות בטוחות לגמרי.

שתי ציריי זמן: Valid Time מול Transaction Time

הפתרון המבוסס בעולם מסדי הנתונים נקרא bi-temporal modeling, והוא מבחין בין שני צירי זמן שונים לחלוטין שקל לבלבל ביניהם. Valid Time הוא מתי העובדה נכונה במציאות — "המחיר היה 50 שקל מ-1 בינואר עד 15 במרץ". Transaction Time הוא מתי המערכת ידעה על העובדה — מתי הרשומה נכתבה בפועל למסד הנתונים. השניים לא תמיד זהים: ייתכן שגילינו ב-20 במרץ (transaction time) שהמחיר השתנה כבר ב-15 במרץ (valid time) — למשל בגלל דוח שהתעדכן באיחור. מערכת שמבחינה בין הצירים האלה יכולה לענות גם על "מה חשבנו שהיה נכון בזמן X" וגם על "מה באמת היה נכון בזמן X" — שתי שאלות שונות לגמרי עם תשובות שונות.

מבחינה מעשית, זה מתורגם לכך שכל רשומה בטבלה (או קשת בגרף) מחזיקה ארבעה שדות זמן במקום שניים: valid_from, valid_to, recorded_at, ו-invalidated_at. עדכון מידע לא דורס שורה קיימת — הוא סוגר את הטווח התקף שלה (valid_to = now()) ופותח שורה חדשה. זה נשמע בזבזני, אבל בפועל זו הדרך היחידה לאפשר point-in-time queries אמינות — שאילתות מהצורה "הראה לי את מצב הידע כפי שהיה נכון ב-1 בפברואר".

גרפי ידע זמניים

כשמאגר הידע בנוי כגרף (ולא רק כטבלאות), אותו עיקרון חל על קשתות: כל קשת בין שתי ישויות ("עובד X מדווח לעובד Y", "מוצר A זמין במחסן B") מקבלת חותמת valid_from/valid_to במקום להיות עובדה בינארית קבועה. שאילתת טראברסל בגרף כזה יכולה לסנן קשתות לפי חלון זמן — "הראה לי את מבנה הדיווח הארגוני כפי שהיה ב-1 בינואר 2026" — ולקבל תת-גרף שונה משאילתה זהה על תאריך אחר. זו הרחבה טבעית של גרפי ידע רגילים, כמפורט במדריך ארכיטקטורת גרפי ידע, ומתחברת ישירות לרעיון של Context Graphs לניהול שיחה — שם כל עובדה בשיחה היא בעצם מקרה פרטי של קשת זמנית שצריך לדעת מתי היא הפכה ללא-תקפה.

איך סוכן AI צריך לשאול שאלות תלויות-זמן

הבעיה המעשית ביותר היא שרוב הסוכנים לא יודעים לשאול שאלה זמנית נכון. כדי שסוכן יענה נכון על "מה היה המחיר כשהלקוח הזמין", הוא צריך קודם לזהות שהשאלה כוללת רכיב זמני, לחלץ את התאריך הרלוונטי (מתוך הקשר ההזמנה, לא מהיום הנוכחי), ולנסח שאילתה עם פילטר valid_from <= order_date AND (valid_to IS NULL OR valid_to > order_date) — ולא סתם שאילתה על הרשומה העדכנית ביותר. הדרך הטובה ביותר להטמיע את זה היא לא לסמוך על המודל "לזכור" לעשות זאת, אלא לבנות tool ייעודי — get_fact_as_of(entity_id, field, timestamp) — שמטמיע את לוגיקת הסינון הזמני בקוד ולא בפרומפט. כך גם כשמודל השפה משתנה, ההתנהגות הזמנית נשארת דטרמיניסטית ובדוקה.

שילוב הגישה הזו עם בעיית העדכניות ההפוכה — מניעת שימוש במידע ישן מדי כשהמצב הנוכחי כן נדרש — מטופל בהרחבה במדריך Knowledge Freshness. השניים משלימים זה את זה: temporal knowledge עונה על "מה היה נכון אז", freshness עונה על "האם מה שיש לי עכשיו עדיין נכון".

סכימת טבלה מעשית ל-bi-temporal ב-PostgreSQL

מימוש בפועל של הרעיון לא דורש מנוע ייעודי. טבלת עובדות פשוטה יכולה להיראות כך: entity_id, attribute, value, valid_from, valid_to (ברירת מחדל NULL כלומר "עדיין תקף"), recorded_at. שאילתת "מה היה נכון ב-15 בפברואר" הופכת פשוטה: SELECT value FROM facts WHERE entity_id = ? AND attribute = ? AND valid_from <= '2026-02-15' AND (valid_to IS NULL OR valid_to > '2026-02-15'). אינדקס מורכב על (entity_id, attribute, valid_from) שומר על ביצועים סבירים גם כשהטבלה גדלה לאורך זמן, כי כל עדכון עובדה יוצר שורה חדשה במקום לדרוס שורה קיימת. הגישה הזו זולה למימוש בהשוואה למסד bi-temporal ייעודי, ומספיקה לרוב מקרי השימוש בפועל.

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

שכבת ה-application שכותבת לטבלה כזו צריכה גם היא משמעת: כל "עדכון" הופך בפועל לשתי פעולות אטומיות בטרנזקציה אחת — סגירת הטווח התקף של השורה הישנה (UPDATE ... SET valid_to = now()) והכנסת השורה החדשה. אם שתי הפעולות לא רצות באותה טרנזקציה, נוצר חלון קצר שבו אין אף שורה תקפה, או גרוע יותר, שתי שורות תקפות בו-זמנית — מה שמחזיר בדיוק את בעיית ה-race condition שהמודל כולו נועד למנוע. עטיפת הלוגיקה הזו בפונקציית עזר אחת ברמת ה-ORM או ה-repository, ולא מתן גישה ישירה לטבלה מכל חלק בקוד, מונעת סטייה בהתנהגות בין מקומות שונים שכותבים לאותה טבלה.

עלות המימוש מול הסיכון של להתעלם ממנה

bi-temporal modeling מוסיף מורכבות אמיתית — יותר שדות, שאילתות מסובכות יותר, וצורך במשמעת בכל נקודת כתיבה כדי לא לדרוס עובדות בטעות. לא כל מערכת צריכה את זה. עסק שבו נתונים משתנים לעיתים רחוקות ואין שום ערך עסקי לשאילתות היסטוריות יכול להסתפק ב-overwrite פשוט. אבל בכל תחום עם חוזים, תמחור, רגולציה, או שאלות ביקורת ("מה ידענו ומתי ידענו את זה") — היעדר מודל זמני נכון הוא לא חיסכון, הוא חוב טכני שמתפוצץ בדיוק ברגע שהכי כואב: כשצריך להוכיח משהו רטרואקטיבית ואי אפשר, כי המידע הישן פשוט נמחק.

תגיות: Temporal Knowledge · Bi-Temporal Modeling · Knowledge Graph · Valid Time · Point-in-Time Query · Data Modeling

← חזרה לבלוג · צור קשר