דילוג לתוכן
תפריט

המוצר

פתרונות

אינטגרציות

מפתחים

שפה

המוצר

קובץ בינארי אחד, קובצי markdown, אינדקס נגזר

ה-hooks לוכדים את מה שהסוכן עושה. ה-markdown ב-git מחזיק את מה שנלמד. SQLite הוא אינדקס חיפוש שאפשר לזרוק ולבנות מחדש. הדף הזה עובר על הדרך מ-hook ועד התדריך של הסשן הבא, ואומר איפה התכנון עדיין דק.

קובץ בינארי אחד, תיקיית נתונים אחת.

SQLite מגיע בפנים, libgit2 הוא vendored וה-embedder כתוב ב-Rust טהור. אין sidecar, אין שרת מסד נתונים ואין תור שצריך להריץ. כל מה שהוא יודע נמצא בתיקייה אחת.

<data_dir>/

wiki/דפי markdown עם YAML frontmatter, ב-repository של git. מקור האמת.
db/memory.sqliteהאינדקס הנגזר: טקסט מלא, ישויות, קישורים, embeddings, סשנים, ביקורת. מצב WAL.
raw/מקטעי JSONL שעברו ניקוי ואינם משתנים, מסשנים מנוהלים של ai-memory run.
models/מודל ה-embeddings המקומי, all-MiniLM-L6-v2, בערך 87 MB ומקובע ב-SHA-256.
logs/פלט לוג יומי מתגלגל.
config.tomlנקרא פעם אחת בעלייה. לכל ערך יש override מסוג AI_MEMORY_*.

השרת מאזין כברירת מחדל על 127.0.0.1:49374. גיבוי הוא ai-memory backup, או git push של הוויקי יחד עם rsync של התיקייה.

מ-hook ועד התדריך הבא.

שבעה משמונת הצעדים האלה רצים בלי מודל ובלי מפתח API. צעד ה-LLM כבוי עד שמגדירים ספק.

תרשים: hook שולח אירועים שעוברים דרך שער sanitize אל כותב יחיד, נשמרים כתצפיות, הופכים לדף סשן, מתפצלים אופציונלית לדפים נוספים דרך LLM, ונכנסים ב-commit לוויקי ב-git. חץ חוזר עם התווית Briefing יוצא מהוויקי אל ה-hook הבא.
רק השלב המקווקו צריך LLM. החץ החוזר הוא התדריך שמוזרק ב-SessionStart הבא.
  1. Hookאפס LLM

    ה-CLI של הסוכן מפעיל hook של מחזור החיים. זה fire and forget עם תקציב של 200 ms: hooks נייטיב שומרים את האירוע ב-spool מקומי, ותהליך עזר מנותק מעביר אותו הלאה. השרת עונה 202, או 429 כשהוא רווי.

  2. ניקויאפס LLM

    ה-router של /hook מסיר סודות ומגביל גדלים. זה הנתיב היחיד מטקסט לא מהימן אל ה-store.

  3. כותב יחידאפס LLM

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

  4. תצפיותאפס LLM

    האירועים נשמרים ב-SQLite בתור audit trail תפעולי. זו השלכה מוגבלת של הסשן, ואף פעם לא תמלול מלא.

  5. סוף הסשןאפס LLM

    כללים, בלי מודל, הופכים את התצפיות ל-sessions/<id>.md ופותחים שורת Handoff לסוכן הבא, בטרנזקציה אחת.

  6. איחודLLM אופציונלי

    כשמוגדר ספק, LLM כותב מחדש את הסיכום או מפצל אותו ל-concepts/, decisions/, gotchas/ ו-procedures/. זה רץ מתוך תור עם ניסיונות חוזרים, מחוץ להשהיה של ה-hook.

  7. Commit ואינדוקסאפס LLM

    כל כתיבת דף היא אטומית (tmp, rename, fsync), נכנסת ב-commit ל-git, ומאונדקסת באותה טרנזקציית SQLite שבה נכתבת השורה שלה.

  8. שאילתה ותדריךאפס LLM

    memory_query מחפש באינדקס. ב-SessionStart הבא ה-hook מביא את ההעברה הפתוחה ותדריך מובנה לאותה תיקייה.

שתי שכבות, מקור אמת אחד.

אם הקבצים והאינדקס לא מסכימים, הקבצים מנצחים.

תרשים: מדף של דפי markdown ב-git, עם הסימון Source of truth, נמצא מעל אינדקס SQLite עם הסימון Derived. הכותב מזין את שניהם. חץ מקווקו של file watcher וחץ רציף של reindex מצביעים שניהם מה-markdown למטה אל האינדקס.
  • הקבצים הם האמת

    הדפים הם markdown עם YAML frontmatter תחת wiki///. אפשר לפתוח אותם ב-Obsidian, להריץ עליהם grep ולדחוף אותם ל-remote.

  • SQLite הוא נגזר

    כל מה שמתאר דף בתוך memory.sqlite אפשר לבנות מחדש מהקבצים עם ai-memory reindex. אינדקס פגום ניתן לשחזור.

  • הכתיבות שייכות לשרת

    כתיבות רגילות עוברות דרך שכבת הוויקי, שמעדכנת יחד את הקובץ, את היסטוריית ה-git ואת האינדקס.

  • watcher תופס את השאר

    עריכות מ-vim או מ-Obsidian נקלטות על ידי file watcher. diff מלא כל 30 שניות תופס אירועים שהוא פספס.

אחזור: ארבעה ערוצים, דירוג אחד.

תרשים: שאילתה מתפצלת לארבעה מסלולים עם התוויות FTS5, Entities, Graph ו-Vectors, ומסלול הווקטורים מקווקו כי הוא אופציונלי. המסלולים מתמזגים בצומת עם התווית RRF k=60, עוברים דרך סולם Authority, ומסתיימים ברשימת תוצאות מדורגת.
מסלול הווקטורים מקווקו כי החיפוש עובד גם בלעדיו.
  • טקסט מלא

    SQLite FTS5 על כותרות הדפים והגוף שלהם, עם סינון stopwords משאילתות חשופות.

  • התאמת ישויות

    אינדקס לקסיקלי של שמות מתוך entities ו-tags ב-frontmatter, משוקלל לפי שכיחות דפים הפוכה.

  • שכנים בגרף

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

  • וקטורים, אופציונלי

    דמיון קוסינוס על embeddings מהמודל המקומי שרץ בתוך התהליך. מופעל כברירת מחדל מאז 2.0, אף פעם לא חובה, ו-brute force בכוונה.

אחרי המיזוג

  • Reciprocal Rank Fusion עם k=60 ממזג את הערוצים לפי דירוג, כך שאף ערוץ לא צריך כיול של ציונים.
  • אחר כך מכפיל סמכות מוגבל מטה תחרויות צמודות לטובת כללים, החלטות, נהלים ומלכודות מתוחזקים. דפים אפיזודיים והיסטוריים נשארים בחיפוש, ושום דבר לא מוצא החוצה לגמרי.
  • LLM rerank אופציונלי: קריאה אחת לכל שאילתה, על עד 30 כותרות וקטעים. בכל כשל נשמר הסדר המקומי. עדיין אין reranker מקומי, וזה הפער של הפרויקט שמזכירים הכי הרבה.
  • אם הדפים המקומפלים לא מחזירים כלום, חיפוש מוגבל בתצפיות הגולמיות מחזיר raw_hits.
  • מעבירים explain=true כדי לראות לכל תוצאה את הדירוג בכל ערוץ, את תרומות ה-RRF ואת המכפיל.

זמן: as_of

  • מעבירים תאריך ISO כדי לשאול מה הוויקי אמר על משהו באותו זמן.
  • הוא רושם רק את זמן ההזנה: מתי ai-memory למד עובדה ומתי החליף אותה, ואף פעם לא מתי היא הייתה נכונה בעולם.
  • הוא לא משחזר את הדירוג שחיפוש היה מחזיר באותו תאריך.
תקפות בזמן, בתיעוד

קשתות מטופסות (typed edges)

  • השדה relations: ב-frontmatter מקבל קבוצה סגורה: causes, fixes, contradicts. שגיאת הקלדה לא יכולה לייצר סוג חדש.
  • contradicts מזין את lint בלי LLM, ומדווח עד שמישהו מיישב את הסתירה.
  • בחיפוש הן מופיעות ב-explain בלבד: הן מצטרפות לגרף כקישורים רגילים ולא משפיעות על הדירוג, כי הבנצ'מרק לא נתן בסיס למשקל. memory_read_page יכול לעבור עליהן כדי להציג דפים קשורים.
קשתות מטופסות, בתיעוד

תופס אחד, כותב אחד.

שני כללים נושאים את רוב הנכונות: העברה אפשר לתפוס פעם אחת, ורק thread אחד כותב ל-SQLite.

העברות הן פרוטוקול

  • העברה היא רשומה מטופסת: סוכן מקור וסוכן יעד, פרויקט, cwd, סיכום, שאלות פתוחות, קבצים שנגעו בהם, צעדים הבאים.
  • הקבלה היא compare and set אטומי. סוכן שני שמבקש לא מקבל כלום.
  • ה-cwd מותאם לפי גבולות נתיב: /repo מכסה את /repo/api ואף פעם לא את /repo-other.
  • העברה ידנית גוברת על האוטומטית. הקבלה מפקיעה מועמדות אוטומטיות ישנות יותר באותה טרנזקציה.
  • בשרת משותף העברה שייכת לבעלים שלה, אלא אם היא נשלחה עם shared=true.

כלל הכותב היחיד, במדידה

כל הכתיבות עוברות דרך תור אחד, מוגבל ל-1024, אל thread אחד של מערכת ההפעלה. קריאות משתמשות ב-pool נפרד לקריאה בלבד. פרץ כתיבות מאט את היצרנים שלו, ואף כתיבה לא נזרקת.

  1. כותב 142 לשנייה23.9 ms
  2. 8 כותבים295 לשנייה3.4 ms
  3. 32 כותבים698 לשנייה1.43 ms
  4. 128 כותבים700 לשנייה1.43 ms
  • התקרה היא בערך 700 כתיבות בשנייה, והיא שטוחה מ-32 כותבים ומעלה. כותב אחד מוגבל על ידי fsync ולא על ידי ה-CPU.
  • נמדד על דיסק מקומי מהיר. volume ברשת או volume איטי יתנו מספרים נמוכים משמעותית.
  • הבדיקה מפעילה את ה-store ישירות ומדלגת על שכבת ה-HTTP שבחזית.
  • אפשר לשחזר עם cargo test -p ai-memory-store --test writer_throughput -- --ignored --nocapture.

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

הקוד, לפי crate.

תשעה crates, לכל אחד תפקיד אחד ו-API מטופס, בלי תלויות מעגליות.

Crateאחריות
ai-memory-coreטיפוסי דומיין, שגיאות, מזהים. בלי IO.
ai-memory-storeSQLite, ה-actor של הכותב, pool הקוראים, חישובי הדעיכה.
ai-memory-wikiכתיבות markdown אטומיות, ה-file watcher, git.
ai-memory-mcpה-transport של MCP ו-router הכלים.
ai-memory-hooksסכמות ה-payload, ה-sanitizer, הכניסה של /hook.
ai-memory-llmגבול האימות מול ספקים, ה-traits של LLM ושל embedder.
ai-memory-consolidateingest, lint, sweep וצינור השיפור האוטומטי.
ai-memory-workstreamמתאמים לקריאה בלבד לתמלולים נייטיב ולהרצות.
ai-memory-cliהקובץ הבינארי ai-memory ותתי-פקודות ה-HTTP הדקות שלו.

23 כלי MCP, מצומצמים בכוונה

ה-hooks עושים את הלכידה השגרתית, כך שסוכנים כמעט לא צריכים לקרוא לכלים האלה ידנית.

שליפה (7)

  • memory_query
  • memory_recent
  • memory_read_page
  • memory_read_session_observations
  • memory_briefing
  • memory_explore
  • memory_status

העברות (4)

  • memory_handoff_begin
  • memory_handoff_list
  • memory_handoff_accept
  • memory_handoff_cancel

הודעות בין פרויקטים (4)

  • memory_message_send
  • memory_message_list
  • memory_message_pop
  • memory_message_cancel

כתיבה ותחזוקה (8)

  • memory_write_page
  • memory_delete_page
  • memory_consolidate
  • memory_auto_improve
  • memory_feedback
  • memory_lint
  • memory_forget_sweep
  • memory_install_self_routing

ARCHITECTURE.md, עם כל 15 האינווריאנטיםהחלטות תכנון ואפשרויות שנדחו

שאלות ותשובות

איפה ai-memory שומר את הנתונים שלו?

בתיקיית נתונים אחת: repository git של דפי markdown תחת wiki/, אינדקס SQLite נגזר תחת db/, מקטעי רצף עבודה שעברו ניקוי תחת raw/, מודל ה-embeddings המקומי תחת models/, ולוגים.

האם ai-memory צריך LLM?

לא. לכידה, סיכומי סשנים, העברות, אינדוקס, חיפוש והתדריך רצים בלי שום ספק מוגדר. איחוד עם LLM, שיפור אוטומטי ו-rerank הם opt-in.

מה קורה אם אינדקס ה-SQLite אבד או נפגם?

קובצי ה-markdown הם מקור האמת. ai-memory reindex בונה מהם מחדש את אינדקס הדפים. אין טרנזקציה משותפת למערכת הקבצים ול-SQLite, ו-reindex הוא גם הדרך לסגור חלונות של קריסה.

איך האחזור מדרג תוצאות?

ארבעה ערוצי מועמדים (טקסט מלא ב-FTS5, התאמת ישויות, שכנים בגרף ווקטורים אופציונליים) מתמזגים עם Reciprocal Rank Fusion ב-k=60, ואז מותאמים עם מכפיל מוגבל של סמכות המקור. LLM rerank הוא אופציונלי, ותצפיות גולמיות הן fallback.

בכמה כתיבות בשנייה הוא עומד?

ב-store נמדדו 42 כתיבות בשנייה עם כותב אחד, 295 עם 8, ותקרה של קרוב ל-700 מ-32 כותבים ומעלה. המספרים נמדדו על דיסק מקומי מהיר, והבדיקה מפעילה את ה-store ישירות בלי שכבת ה-HTTP שבחזית.

לקרוא את הקבצים שהוא כותב.

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