מבוא: למה סוכני AI בלי זיכרון הם כמו עובד שמתחיל מחדש כל יום
דמיינו לרגע עובד מצוין שכל בוקר שוכח את כל מה שקרה אתמול. כל פגישה, כל משימה, כל העדפה של לקוח — פשוט נמחקים. נשמע אבסורדי, נכון? אז זה בדיוק מה שקורה עם רוב סוכני ה-AI שאנחנו בונים היום. ה-LLM מקבל שאילתה, מעבד אותה, מחזיר תשובה — ומיד שוכח הכל. בשיחה הבאה? מתחיל מאפס.
ב-2026 הבעיה הזאת כבר לא סתם מעצבנת — היא קריטית. סוכני AI כבר לא רק עונים על שאלות. הם מנהלים תהליכים מורכבים, לומדים מאינטראקציות, ומשרתים משתמשים לאורך שבועות וחודשים. לפי מחקר של Mem0 שפורסם ב-arXiv, שכבת זיכרון חכמה מספקת שיפור של 26% בדיוק, הפחתה של 91% בזמן תגובה ו-חיסכון של 90% בטוקנים בהשוואה לגישת הקשר מלא. המספרים האלה הם לא תיאורטיים — הם משנים את התמונה לגמרי.
אז במדריך הזה נבנה יחד מערכת זיכרון ארוך-טווח מלאה לסוכני AI. נתחיל מהבנת הארכיטקטורה, נעבור למימוש מעשי עם Mem0 ו-Letta, ונסיים עם שיטות עבודה שבאמת עובדות בייצור. יאללה, נצלול.
סוגי זיכרון בסוכני AI: מיפוי מלא
בדומה לזיכרון האנושי (ויש פה באמת הקבלה מעניינת), גם זיכרון של סוכני AI מחולק לכמה סוגים. ההבנה של ההבדלים ביניהם היא הבסיס לבניית מערכת זיכרון שעובדת.
זיכרון לטווח קצר (Short-Term Memory)
זה חלון ההקשר (Context Window) של ה-LLM — כל מה שנמצא ישירות בפרומפט. הודעות אחרונות, הוראות מערכת, תוצאות כלים. היתרון ברור: גישה מיידית, אפס זמן חיפוש. החיסרון? מוגבל בגודל (גם ב-2026, עם חלונות של מיליון טוקנים, זה עדיין לא אינסופי), ונמחק בסוף השיחה.
זיכרון אפיזודי (Episodic Memory)
שומר מה שקרה — אירועים ספציפיים, אינטראקציות קודמות, תוצאות של פעולות. למשל: "ב-15 במרץ המשתמש ביקש לשנות את הפורמט לטבלה ואהב את התוצאה". זיכרון אפיזודי מאפשר לסוכן ללמוד מניסיון ולהימנע מטעויות שחזרו בעבר. בעיניי, זה אחד הסוגים הכי חשובים — בלי זה הסוכן חוזר על אותם טעויות שוב ושוב.
זיכרון סמנטי (Semantic Memory)
מאחסן מה שהסוכן יודע — עובדות, ידע כללי, העדפות משתמש. בניגוד לזיכרון אפיזודי, הוא לא קשור לאירוע ספציפי. למשל: "המשתמש הוא מפתח Python שמעדיף קוד תמציתי". לא משנה מתי זה נלמד, זה תמיד רלוונטי.
זיכרון פרוצדורלי (Procedural Memory)
מקודד איך לעשות דברים — דפוסי התנהגות, תהליכי עבודה מועדפים, כללים שנלמדו. למשל: "כשהמשתמש מבקש ניתוח נתונים, תמיד התחל בויזואליזציה לפני הסבר טקסטואלי". זה הזיכרון שהופך סוכן מ"כלי שעובד" ל"עוזר שמבין אתכם".
זיכרון עבודה (Working Memory)
שכבת ביניים שמחזיקה מידע רלוונטי למשימה הנוכחית. חשבו על זה כ-RAM — לא הכל נטען בו-זמנית, אלא רק מה שצריך עכשיו. מערכות מתקדמות יודעות לדרג פריטי זיכרון לפי חשיבות ולהחליט מה נכנס לזיכרון העבודה ומה נשאר באחסון.
הארכיטקטורה: איך זורם מידע בין חלון ההקשר לאחסון חיצוני
האתגר המרכזי בעיצוב זיכרון לסוכני AI הוא בעצם שאלה אחת: איך מעבירים מידע בין חלון ההקשר של ה-LLM לבין אחסון חיצוני? לפי מסגרת CoALA (Cognitive Architectures for Language Agents) מאוניברסיטת פרינסטון, יש שלושה דפוסים עיקריים.
דפוס 1: חילוץ אוטומטי (Automatic Extraction)
המערכת מנתחת כל שיחה אוטומטית, מחלצת עובדות והעדפות, ושומרת אותן לאחסון חיצוני. בשיחה הבאה, מידע רלוונטי נשלף באמצעות חיפוש סמנטי ומוזרק לפרומפט. זו הגישה של Mem0 — פשוטה ליישום ועובדת טוב עבור רוב מקרי השימוש.
דפוס 2: ניהול עצמי על ידי הסוכן (Agent-Managed Memory)
כאן הסוכן עצמו מחליט מה לזכור, מה לעדכן ומה למחוק — באמצעות כלים (tools) ייעודיים לניהול זיכרון. זו הגישה של Letta, שמתייחסת לחלון ההקשר כ-RAM ולאחסון חיצוני כדיסק. האנלוגיה למערכת הפעלה היא מדויקת להפליא.
דפוס 3: גרף ידע (Knowledge Graph Memory)
זיכרונות נשמרים כצמתים ויחסים בגרף — ישויות (אנשים, מושגים, פרויקטים) מחוברות בקשתות עם תוויות. הגישה הזו מאפשרת הבנת קשרים מורכבים ושאילתות כמו "מי עבד עם מי על איזה פרויקט". Zep ו-Mem0g (הגרסה המתקדמת של Mem0) משתמשות בדפוס הזה.
מימוש מעשי עם Mem0: שכבת זיכרון חכמה בארבע שורות קוד
Mem0 (מבוטא "מם-זירו") הוא פריימוורק קוד פתוח שמוסיף שכבת זיכרון אינטליגנטית לכל סוכן AI. הוא מחלץ עובדות אוטומטית משיחות, שומר אותן באחסון וקטורי, ושולף מידע רלוונטי כשצריך. הכל בלי שתצטרכו לנהל את הלוגיקה בעצמכם — וזה החלק שהכי אהבתי בו.
התקנה והגדרה ראשונית
pip install mem0ai
# הגדרת מפתח API — Mem0 משתמש ב-LLM לחילוץ עובדות
export OPENAI_API_KEY="sk-your-key-here"
דוגמה בסיסית: סוכן עם זיכרון מתמשך
from openai import OpenAI
from mem0 import Memory
openai_client = OpenAI()
memory = Memory()
def chat_with_memory(message: str, user_id: str = "user_1") -> str:
# שלב 1: שליפת זיכרונות רלוונטיים
relevant = memory.search(query=message, user_id=user_id, limit=5)
memories_str = "\n".join(
f"- {entry['memory']}" for entry in relevant.get("results", [])
)
# שלב 2: בניית פרומפט עם הקשר מזיכרון
system_prompt = f"""אתה עוזר AI חכם עם זיכרון ארוך-טווח.
להלן מידע שאתה זוכר על המשתמש:
{memories_str if memories_str else "אין זיכרונות קודמים."}
השתמש במידע הזה כדי לתת תשובות מותאמות אישית."""
# שלב 3: יצירת תשובה עם ה-LLM
response = openai_client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": message}
]
)
assistant_reply = response.choices[0].message.content
# שלב 4: שמירת השיחה בזיכרון
memory.add(
messages=[
{"role": "user", "content": message},
{"role": "assistant", "content": assistant_reply}
],
user_id=user_id
)
return assistant_reply
# שימוש — שיחה ראשונה
print(chat_with_memory("אני מפתח Python, עובד בחברת סטארטאפ בתחום הפינטק"))
# Mem0 מחלץ אוטומטית: "המשתמש הוא מפתח Python בסטארטאפ פינטק"
# שיחה שנייה — יום אחר כך
print(chat_with_memory("יש לי באג בקוד, אתה יכול לעזור?"))
# הסוכן כבר יודע שאתה מפתח Python בפינטק ומתאים את התשובה
אז מה קורה מאחורי הקלעים? Mem0 משתמש ב-LLM (ברירת מחדל: gpt-4.1-nano) כדי לחלץ עובדות מהשיחה. הוא לא שומר את כל הטקסט — הוא מזקק אותו לייצוגים תמציתיים. כשמגיעה שאילתה חדשה, הוא מבצע חיפוש סמנטי ומחזיר רק את הזיכרונות הרלוונטיים ביותר. פשוט ואלגנטי.
הגדרת זיכרון מתקדמת עם אחסון מותאם
בסביבת ייצור, בטוח תרצו לקנפג את שכבות האחסון. הנה הגדרה עם Qdrant כמסד וקטורי ו-PostgreSQL להיסטוריה:
from mem0 import Memory
config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4.1-mini",
"temperature": 0.1
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
"vector_store": {
"provider": "qdrant",
"config": {
"host": "localhost",
"port": 6333,
"collection_name": "agent_memories"
}
},
"version": "v1.1"
}
memory = Memory.from_config(config)
# הוספת זיכרון עם metadata
memory.add(
messages=[{"role": "user", "content": "אני צריך לסיים את הפרויקט עד סוף אפריל"}],
user_id="user_42",
metadata={"project": "dashboard-v2", "priority": "high"}
)
# חיפוש עם סינון metadata
results = memory.search(
query="מה הדדליינים שלי?",
user_id="user_42",
limit=10
)
# עדכון זיכרון קיים
memory.update(memory_id="mem_abc123", data="הדדליין הוזז ל-15 במאי")
# מחיקת זיכרון שלא רלוונטי יותר
memory.delete(memory_id="mem_old456")
היקפי זיכרון: משתמש, סשן וסוכן
Mem0 תומך בשלושה היקפים (scopes) שמאפשרים שליטה מדויקת על מי רואה מה:
- זיכרון משתמש (user_id): מתמשך בין כל השיחות עם משתמש ספציפי. אם מישהו מזכיר שהוא מעדיף לימוד בבוקר — זה נשאר זמין בכל סשן עתידי.
- זיכרון סשן (session_id): עוקב אחרי הקשר בתוך שיחה בודדת. למשל, המתכון הנוכחי שמדברים עליו.
- זיכרון סוכן (agent_id): שומר מידע ספציפי לאינסטנס מסוים של סוכן AI. שימושי כשיש לכם כמה סוכנים עם תפקידים שונים (וזה מצב נפוץ יותר ממה שחושבים).
# שילוב של היקפים שונים
memory.add(
messages=[{"role": "user", "content": "תמיד תענה לי בעברית"}],
user_id="user_42", # העדפה אישית — מתמשכת תמיד
agent_id="support_bot" # רק הסוכן הזה ידע את זה
)
memory.add(
messages=[{"role": "user", "content": "אני מחפש טיסות לניו יורק"}],
user_id="user_42",
session_id="session_789" # רלוונטי רק לשיחה הנוכחית
)
מימוש עם Letta: כשהסוכן מנהל את הזיכרון שלו
Letta (לשעבר MemGPT) לוקחת גישה שונה לחלוטין, וכאן זה נהיה מעניין באמת. במקום שכבת זיכרון חיצונית שמחלצת עובדות אוטומטית, Letta היא סביבת ריצה שלמה לסוכנים שבה הסוכן עצמו מנהל את הזיכרון — בדיוק כמו שמערכת הפעלה מנהלת RAM ודיסק.
הארכיטקטורה: LLM כמערכת הפעלה
Letta מחלקת את הזיכרון לשלוש שכבות:
- Core Memory (זיכרון ליבה): תמיד בתוך חלון ההקשר — בלוקים של מידע שהסוכן יכול לערוך ישירות. כמו RAM.
- Archival Memory (זיכרון ארכיוני): אחסון ארוך-טווח שניתן לחיפוש. הסוכן יכול לכתוב ולקרוא ממנו דרך כלים ייעודיים. כמו דיסק קשיח.
- Recall Memory (זיכרון שליפה): היסטוריית שיחות מלאה שניתנת לחיפוש. הסוכן יכול לחזור אחורה ולמצוא מה נאמר בשיחות קודמות.
התקנה והגדרה
pip install letta-client
export LETTA_API_KEY="your-api-key"
יצירת סוכן עם זיכרון מובנה
from letta_client import Letta
client = Letta(api_key="your-api-key")
# יצירת סוכן עם בלוקי זיכרון ליבה
agent = client.agents.create(
model="openai/gpt-4.1-mini",
embedding="openai/text-embedding-3-small",
memory_blocks=[
{
"label": "human",
"value": "שם המשתמש: דנה. מפתחת Full-Stack. מעדיפה Python."
},
{
"label": "persona",
"value": "אני עוזר AI עם זיכרון ארוך-טווח. אני זוכר העדפות ולומד מאינטראקציות."
},
{
"label": "project_context",
"value": "הפרויקט הנוכחי: מערכת המלצות מבוססת AI. טכנולוגיות: FastAPI, Qdrant, LangChain."
}
]
)
print(f"Agent created: {agent.id}")
# שליחת הודעה — הסוכן משתמש בזיכרון הליבה אוטומטית
response = client.agents.messages.create(
agent_id=agent.id,
input="מה אתה יודע עליי ועל הפרויקט שלי?"
)
for msg in response.messages:
print(msg)
והנה הנקודה הקריטית: הסוכן ב-Letta יכול לערוך את בלוקי הזיכרון שלו בעצמו. אם המשתמש אומר "דרך אגב, עברתי לעבוד עם TypeScript", הסוכן יעדכן את בלוק ה-human בעצמו — בלי שום קוד חיצוני. זה פשוט עובד.
כלי זיכרון מובנים
Letta מספקת לסוכן כלים ייעודיים לניהול זיכרון:
core_memory_append— הוספת מידע לבלוק זיכרון ליבהcore_memory_replace— עדכון מידע קיים בבלוק ליבהarchival_memory_insert— שמירת מידע לזיכרון ארוך-טווחarchival_memory_search— חיפוש בזיכרון הארכיוניconversation_search— חיפוש בהיסטוריית שיחות
# הסוכן קורא לכלים האלה אוטומטית, למשל:
# כשהמשתמש אומר "אני עובר לפרויקט חדש בתחום הבריאות"
# הסוכן יקרא ל-core_memory_replace כדי לעדכן את project_context
# ול-archival_memory_insert כדי לשמור את פרטי הפרויקט הקודם
# ניטור פעולות זיכרון
response = client.agents.messages.create(
agent_id=agent.id,
input="אני עובר לפרויקט חדש — אפליקציית בריאות דיגיטלית עם React Native"
)
# הסוכן יבצע אוטומטית:
# 1. archival_memory_insert — שמירת הפרויקט הישן
# 2. core_memory_replace — עדכון הפרויקט הנוכחי
# 3. תשובה למשתמש עם אישור שהזיכרון עודכן
Mem0 מול Letta: מתי להשתמש במה
הבחירה בין Mem0 ל-Letta היא לא שאלה של "מי יותר טוב". בכנות, שני הכלים מצוינים — זו שאלה של מה מתאים למקרה השימוש שלכם.
| קריטריון | Mem0 | Letta |
|---|---|---|
| גישת זיכרון | חילוץ אוטומטי + חיפוש סמנטי | ניהול עצמי על ידי הסוכן |
| אינטגרציה | נוסף כשכבה לכל פריימוורק (LangChain, CrewAI, LangGraph) | סביבת ריצה שלמה — מחליף את הסטאק |
| מורכבות הגדרה | 4 שורות קוד למינימום עובד | דורש הבנה של ארכיטקטורת הזיכרון |
| שליטה בזיכרון | אוטומטי ברובו — קל אבל פחות גמיש | הסוכן שולט — גמיש אבל דורש אמון בשיפוט הסוכן |
| מתאים ל- | צ׳אטבוטים, עוזרים אישיים, תמיכת לקוחות | סוכנים אוטונומיים מורכבים, משימות ארוכות-טווח |
| רישיון | Apache 2.0 (קוד פתוח) | Apache 2.0 (קוד פתוח) |
| זיכרון גרף | זמין בתוכנית Pro ($249/חודש) או self-hosted | לא נתמך ישירות |
כלל אצבע לבחירה
- בחרו Mem0 אם אתם רוצים להוסיף זיכרון לסוכן קיים במינימום שינויים. מתאים בעיקר כשמקרה השימוש הוא התאמה אישית והתמדה של העדפות משתמש.
- בחרו Letta אם אתם בונים סוכן מורכב מאפס ורוצים שהוא ינהל את הזיכרון בעצמו — במיוחד לסוכנים אוטונומיים שרצים לאורך זמן.
- שקלו Zep אם הזמניות חשובה לכם. למשל, אם אתם צריכים לענות על שאלות כמו "מי היה אחראי על החשבון לפני מרץ?".
מימוש עצמאי: בניית שכבת זיכרון בלי ספריות חיצוניות
לפעמים אתם פשוט צריכים שליטה מלאה. אולי מסיבות פרטיות, אולי בגלל דרישות ייחודיות, ואולי כי אתם סוג המפתחים שאוהבים לדעת מה קורה מתחת למכסה המנוע (ואני מבין את זה לגמרי). הנה מימוש של שכבת זיכרון בסיסית ב-Python טהור:
import json
import os
from datetime import datetime, timezone
from openai import OpenAI
client = OpenAI()
MEMORY_FILE = "agent_memory.json"
def load_memories() -> dict:
"""טעינת זיכרונות מקובץ."""
if os.path.exists(MEMORY_FILE):
with open(MEMORY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {"user_facts": [], "episodic": [], "preferences": []}
def save_memories(memories: dict) -> None:
"""שמירת זיכרונות לקובץ."""
with open(MEMORY_FILE, "w", encoding="utf-8") as f:
json.dump(memories, f, ensure_ascii=False, indent=2)
def extract_facts(conversation: list[dict]) -> list[str]:
"""חילוץ עובדות מהשיחה באמצעות LLM."""
extraction_prompt = """Analyze this conversation and extract key facts about the user.
Return a JSON array of strings, each being a concise fact.
Focus on: preferences, background, goals, constraints.
If no new facts found, return an empty array.
Respond ONLY with the JSON array."""
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{"role": "system", "content": extraction_prompt},
{"role": "user", "content": json.dumps(conversation, ensure_ascii=False)}
],
response_format={"type": "json_object"}
)
try:
result = json.loads(response.choices[0].message.content)
return result.get("facts", result) if isinstance(result, dict) else result
except (json.JSONDecodeError, KeyError):
return []
def find_relevant_memories(query: str, memories: dict, limit: int = 5) -> str:
"""מציאת זיכרונות רלוונטיים באמצעות LLM-based ranking."""
all_memories = (
memories.get("user_facts", []) +
memories.get("preferences", []) +
[ep["summary"] for ep in memories.get("episodic", [])]
)
if not all_memories:
return "אין זיכרונות קודמים."
ranking_prompt = f"""Given this query: "{query}"
Rank these memories by relevance (most relevant first).
Return the top {limit} as a JSON array of strings.
Memories:
{json.dumps(all_memories, ensure_ascii=False)}"""
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[{"role": "user", "content": ranking_prompt}],
response_format={"type": "json_object"}
)
try:
result = json.loads(response.choices[0].message.content)
ranked = result.get("memories", result) if isinstance(result, dict) else result
return "\n".join(f"- {m}" for m in ranked[:limit])
except (json.JSONDecodeError, KeyError):
return "\n".join(f"- {m}" for m in all_memories[:limit])
def chat(message: str, user_id: str = "default") -> str:
"""שיחה עם זיכרון."""
memories = load_memories()
# שליפת זיכרונות רלוונטיים
relevant = find_relevant_memories(message, memories)
# יצירת תשובה
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{"role": "system", "content": f"אתה עוזר AI עם זיכרון.\nזיכרונות:\n{relevant}"},
{"role": "user", "content": message}
]
)
reply = response.choices[0].message.content
# חילוץ ושמירת עובדות חדשות
conversation = [
{"role": "user", "content": message},
{"role": "assistant", "content": reply}
]
new_facts = extract_facts(conversation)
for fact in new_facts:
if fact not in memories["user_facts"]:
memories["user_facts"].append(fact)
# שמירת אירוע אפיזודי
memories["episodic"].append({
"timestamp": datetime.now(timezone.utc).isoformat(),
"summary": f"משתמש: {message[:100]}",
"user_id": user_id
})
# שמירה לקובץ
save_memories(memories)
return reply
חשוב להבהיר: המימוש הזה מעולה ללמידה ולניסוי, אבל לא לייצור. בסביבה אמיתית תרצו מסד וקטורי (Qdrant, Pinecone, Weaviate), מנגנון נעילה למניעת race conditions, ומערכת ניטור לאיכות הזיכרונות. אם אתם בונים משהו שצריך לעבוד ברצינות — תעשו לעצמכם טובה ותשתמשו ב-Mem0 או Letta. תחסכו שבועות של פיתוח.
שיטות עבודה מומלצות לזיכרון בייצור
אחרי שבחרתם כלי ומימשתם את שכבת הזיכרון, הנה העקרונות שעושים את ההבדל בין דמו מרשים למערכת שבאמת עובדת:
1. הפרידו בין RAG לזיכרון
RAG מתאים לידע אוניברסלי — דברים שנכונים לכל המשתמשים (מסמכי מוצר, מדיניות חברה). זיכרון מתאים להקשר אישי — דברים שנכונים למשתמש ספציפי. רוב מערכות הייצור צריכים את שניהם במקביל, ולהפריד ביניהם זה הצעד הכי חשוב.
2. זקקו לפני שמירה
שמירת שיחות גולמיות כיחידות זיכרון? זה מתכון לשליפה רועשת. במקום זאת, זקקו אינטראקציות לאובייקטי זיכרון תמציתיים — עובדות מפתח, העדפות מפורשות, תוצאות של פעולות. Mem0 עושה את זה אוטומטית, אבל כדאי לוודא שאיכות החילוץ מספיקה למקרה שלכם.
3. תנו לסוכן לשלוט מתי לשלוף
שליפה אוטומטית לפני כל תור סוכן היא יקרה ולא יעילה. דפוס טוב יותר: תנו לסוכן את השליפה ככלי (tool) שהוא מפעיל כשהוא מזהה צורך בהקשר מהעבר. זה חוסך קריאות מיותרות ומשפר את הרלוונטיות בצורה משמעותית.
4. הטמיעו מנגנוני שכחה
זיכרון שרק גדל ולא מצטמצם? הופך לרועש עם הזמן. הנה מה שעובד:
- דעיכה זמנית (Temporal Decay): מידע ישן מקבל ציון נמוך יותר בשליפה
- ציון רלוונטיות (Relevance Scoring): מידע שמעולם לא נשלף — כנראה לא כזה חשוב
- מדיניות מותאמת: "שכח העדפות אוכל אחרי 6 חודשים", "שמור העדפות עבודה לנצח"
5. נטרו איכות זיכרון
הוסיפו מדדים לניטור שכבת הזיכרון. בלי ניטור, אתם טסים עיוורים:
- דיוק שליפה: האם הזיכרונות שנשלפו באמת רלוונטיים?
- כפילויות: כמה זיכרונות כפולים או סותרים יש במערכת?
- שימוש: כמה זיכרונות מעולם לא נשלפו?
- השפעה: האם תשובות עם זיכרון טובות יותר מתשובות בלי?
6. הגנו על פרטיות
זיכרון ארוך-טווח שומר מידע אישי, וזה אומר שאתם חייבים להתייחס לזה ברצינות:
- הצפנת נתונים במנוחה ובמעבר
- יכולת מחיקת זיכרון לפי בקשת משתמש (GDPR/Right to be Forgotten)
- הפרדה מוחלטת בין זיכרונות של משתמשים שונים
- רישום (audit log) של כל פעולות הזיכרון
דוגמה מלאה: סוכן תמיכה עם זיכרון Mem0
בואו נשלב את כל מה שלמדנו לדוגמה אחת מלאה — סוכן תמיכה שזוכר לקוחות, היסטוריית בעיות, והעדפות תקשורת:
from openai import OpenAI
from mem0 import Memory
openai_client = OpenAI()
# הגדרת Mem0 עם אחסון מתמשך
memory = Memory.from_config({
"llm": {
"provider": "openai",
"config": {"model": "gpt-4.1-mini", "temperature": 0.1}
},
"vector_store": {
"provider": "qdrant",
"config": {
"host": "localhost",
"port": 6333,
"collection_name": "support_memories"
}
},
"version": "v1.1"
})
SYSTEM_PROMPT = """אתה סוכן תמיכה מקצועי עם זיכרון ארוך-טווח.
אתה זוכר אינטראקציות קודמות עם הלקוח ומשתמש במידע הזה
כדי לתת שירות מותאם אישית ויעיל.
זיכרונות על הלקוח:
{memories}
הנחיות:
- אם הלקוח חזר עם בעיה דומה לעבר, התייחס לזה
- השתמש בהעדפות שנלמדו (שפה, רמת טכניות, ערוץ מועדף)
- אם זיהית דפוס של בעיות חוזרות, הצע פתרון מניעתי
"""
def support_agent(message: str, customer_id: str) -> str:
# שליפת זיכרונות רלוונטיים
results = memory.search(query=message, user_id=customer_id, limit=10)
memories_str = "\n".join(
f"- {r['memory']}" for r in results.get("results", [])
)
# יצירת תשובה
response = openai_client.chat.completions.create(
model="gpt-4.1",
messages=[
{"role": "system", "content": SYSTEM_PROMPT.format(memories=memories_str or "לקוח חדש — אין היסטוריה")},
{"role": "user", "content": message}
]
)
reply = response.choices[0].message.content
# שמירת האינטראקציה בזיכרון
memory.add(
messages=[
{"role": "user", "content": message},
{"role": "assistant", "content": reply}
],
user_id=customer_id,
metadata={
"channel": "web",
"category": "support",
}
)
return reply
# שימוש
# פנייה ראשונה
print(support_agent(
"האפליקציה קורסת כשאני מנסה לייצא PDF",
customer_id="cust_1001"
))
# פנייה שנייה — שבוע אחר כך
print(support_agent(
"שוב הבעיה עם ייצוא PDF, הפעם בדפדפן אחר",
customer_id="cust_1001"
))
# הסוכן יזהה את הבעיה החוזרת ויציע פתרון שורש
שאלות נפוצות
מה ההבדל בין זיכרון לסוכן AI לבין RAG?
RAG (Retrieval-Augmented Generation) שולף מידע ממאגר מסמכים קבוע שרלוונטי לכל המשתמשים — כמו תיעוד מוצר או מדיניות חברה. זיכרון סוכן, לעומת זאת, שומר מידע ספציפי למשתמש שנלמד מאינטראקציות: העדפות, היסטוריה, והקשר אישי. מערכת ייצור טובה משלבת את שניהם — RAG לידע כללי וזיכרון להתאמה אישית.
האם Mem0 דורש שרת GPU?
לא. Mem0 משתמש ב-APIs של ספקי LLM (כמו OpenAI ו-Anthropic) לחילוץ עובדות ובמסד וקטורי לאחסון. אין צורך ב-GPU מקומי. אפשר גם להריץ מקומית לחלוטין עם Ollama כ-LLM ו-Qdrant כמסד וקטורי — אבל תצטרכו מכונה עם לפחות 16GB RAM.
איך מונעים שהסוכן "יזכור" מידע שגוי?
שלוש שכבות הגנה: (1) אימות בעת חילוץ — שימוש ב-LLM חזק יותר לבדיקת אמינות עובדות מחולצות; (2) מנגנון עדכון — כשמידע סותר מגיע, Mem0 מעדכן אוטומטית את הזיכרון הקיים במקום ליצור כפילות; (3) ניטור שוטף — בדיקות תקופתיות של איכות הזיכרון וניקוי זיכרונות לא עדכניים.
כמה זיכרונות אפשר לשמור לפני שהביצועים נפגעים?
תלוי במסד הווקטורי. Qdrant ו-Pinecone תומכים במיליוני וקטורים בלי בעיות ביצועים משמעותיות. אבל החסם האמיתי הוא לא כמות האחסון — זו איכות השליפה. ככל שיש יותר זיכרונות, החיפוש הסמנטי צריך לעבוד קשה יותר למצוא את הרלוונטיים. לכן מנגנוני שכחה חשובים: הגבילו זיכרון פעיל ל-1,000-10,000 פריטים לכל משתמש והעבירו ישנים לארכיון.
האם אפשר לשלב Mem0 עם LangGraph או CrewAI?
בהחלט. Mem0 נועד לעבוד כשכבה נוספת על כל פריימוורק סוכנים קיים — יש אינטגרציות רשמיות ל-LangChain, LangGraph, CrewAI ו-LlamaIndex. בפועל, מדובר בהוספת קריאת memory.search() לפני הרצת הסוכן ו-memory.add() אחרי. שתי שורות קוד שהופכות סוכן חסר מצב לסוכן עם התמדה אמיתית.