Memory

תזכורת: זיכרון קצר טווח מול ארוך טווח

בנושא AI Agents ראינו את ההבחנה העקרונית בין זיכרון קצר טווח (מה שנשאר בתוך שיחה אחת) לזיכרון ארוך טווח (מה שנשמר גם אחרי שהשיחה נגמרת ומשמש שיחות עתידיות) — ראו פרק ה-Memory שם. בפרק הזה נראה איך LangChain ממש את שני הסוגים בקוד.

עד עכשיו כבר השתמשנו בזיכרון קצר טווח בלי לקרוא לו כך: כל thread_id שהעברנו ב-configurable מאז פרק 2 הוא בדיוק זה — היסטוריית ההודעות שנשמרת ומוזרמת חזרה למודל בכל קריאה נוספת לאותו thread.

זיכרון קצר טווח: מעבר להודעות בלבד

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

המשותף לכל מה שב-state הזה: הוא קשור ל-thread_id הספציפי. ברגע שעוברים ל-thread חדש — גם אם זה אותו משתמש בדיוק — ה-state הזה לא קיים יותר. בשביל מידע שצריך לשרוד מעבר לשיחה בודדת צריך את הסוג השני.

זיכרון ארוך טווח: חנות שחוצה threads

זיכרון ארוך טווח נשמר במבנה נפרד — store — שלא קשור לשום thread_id ספציפי. שומרים בו ערכים לפי namespace (למשל מזהה משתמש) ומפתח (למשל "preferences"), וכל agent שמקבל גישה לאותו store יכול לקרוא את הערך הזה, בלי קשר לאיזה thread השתמשו בו כדי לכתוב אותו מלכתחילה.

TypeScript
import { InMemoryStore } from "langchain";

const store = new InMemoryStore();

await store.put(["users", "user-42"], "preferences", { unit: "celsius" });

const memory = await store.get(["users", "user-42"], "preferences");
// → { value: { unit: "celsius" }, ... }

איך agent קורא וכותב לזיכרון ארוך טווח

מעבירים את ה-store ל-createAgent, ומגדירים כלי שקורא ל-store.put/store.get בתוך הפונקציה שלו — ה-userId מגיע מ-config בדיוק כפי שראינו עם getUserOrders בפרק ה-Tools, כדי שהמודל לא יצטרך (ולא יוכל) להמציא מזהה משתמש בעצמו.

TypeScript
const rememberPreference = tool(
  async ({ key, value }: { key: string; value: string }, config) => {
    const userId = config?.configurable?.userId;
    await store.put(["users", userId], key, value);
    return "נשמר";
  },
  {
    name: "remember_preference",
    description: "שומר העדפה של המשתמש לשימוש עתידי, גם בשיחות הבאות",
    schema: z.object({ key: z.string(), value: z.string() }),
  }
);

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

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

TypeScript
const agent = createAgent({
  model: "anthropic:claude-sonnet-5",
  tools: [getWeather, rememberPreference],
  store,
});

// שיחה 1, thread-a
await agent.invoke(
  { messages: [{ role: "user", content: "תזכור שאני מעדיף מעלות צלזיוס" }] },
  { configurable: { thread_id: "thread-a", userId: "user-42" } }
);

// שיחה 2, thread-b — thread שונה לגמרי, אבל אותו משתמש
await agent.invoke(
  { messages: [{ role: "user", content: "מה מזג האוויר בתל אביב?" }] },
  { configurable: { thread_id: "thread-b", userId: "user-42" } }
);
// ה-agent עדיין "זוכר" את ההעדפה מ-thread-a, כי היא הגיעה מה-store ולא מהיסטוריית ה-thread