Цель лекции
Объяснить, в каком виде память существует внутри системы и почему модель данных важнее выбора базы.
Ожидаемый результат
Читатель понимает, какие поля нужны воспоминанию, чтобы оно было управляемым: content, type, scope, source, timestamp, confidence, importance, provenance, temporal metadata, links, status, soft delete и superseded records.
Зачем это нужно
В предыдущей лекции мы обсуждали, где хранить память: prompt, files, KV, SQL, document store, vector DB, search index, graph, object storage и cache. Но выбор storage не спасает систему, если сама запись памяти плохо спроектирована.
Плохая запись:
Пользователь любит краткость.
На первый взгляд это полезно. Но для memory layer не хватает почти всего:
- какой пользователь;
- для каких задач;
- кто это сказал;
- когда;
- это постоянное предпочтение или временная просьба;
- насколько мы уверены;
- можно ли это показывать другим агентам;
- что делать, если пользователь позже попросит подробные объяснения;
- устарела ли запись;
- есть ли старая версия.
Хорошая память - это не просто текст. Это структурированная запись с жизненным циклом.
Основная идея
Качество памяти сильно зависит от representation: как система моделирует записи, факты, события, навыки, связи, источники, время и статусы.
Storage отвечает на вопрос "где лежит память?".
Representation отвечает на вопрос "что именно мы храним и как этим управлять?".
Если representation слабая, появляются проблемы:
- retrieval не может фильтровать по scope;
- update не знает, что заменить;
- confidence не учитывается;
- source теряется;
- deletion не затрагивает derived records;
- facts и hypotheses смешиваются;
- old и active versions попадают в один context;
- permissions невозможно применить точно.
Memory record должен быть достаточно структурированным, чтобы поддерживать весь lifecycle: write, retrieve, inject, update, consolidate и forget.
Ключевые термины
| Термин | Короткое определение |
|---|---|
MemoryRecord |
Базовая единица памяти в системе. |
Content |
Текстовое или структурированное содержание записи. |
Type |
Вид записи: fact, event, skill, reflection, document chunk, summary, policy. |
Scope |
Область применимости: user, session, project, team, organization, agent. |
Source |
Откуда появилась запись: user, tool, document, model extraction, human review. |
Provenance |
История происхождения и преобразований записи. |
Confidence |
Насколько система доверяет записи. |
Importance |
Насколько запись важна для будущего поведения. |
Temporal metadata |
Временные поля: created_at, observed_at, valid_from, valid_until, last_confirmed_at. |
Link |
Связь между memory records или entities. |
Status |
Состояние записи: active, draft, superseded, stale, archived, deleted. |
Soft delete |
Логическое удаление без немедленного физического удаления. |
Superseded record |
Запись, замененная более новой или scoped версией. |
Базовый MemoryRecord
Концептуальная запись может выглядеть так:
MemoryRecord
id: mem_123
type: semantic_fact
content: "Project uses Vitest as test runner."
scope:
project: billing-service
source:
kind: file
reference: package.json
confidence: high
importance: medium
status: active
created_at: 2026-08-07T12:00:00+03:00
observed_at: 2026-08-07T11:58:00+03:00
last_confirmed_at: 2026-08-07T12:00:00+03:00
entities:
- billing-service
- Vitest
- package.json
links:
- relation: supersedes
target: mem_098
permissions:
visibility: project
Это не универсальная схема для всех систем. Это mental model. В конкретной реализации часть полей будет таблицами, часть JSON, часть индексами, часть derived metadata.
Главная мысль: запись должна быть управляемой.
Content: текст и структура
Content может быть natural language, structured data или оба варианта.
Текст:
User prefers concise final reports after file edits.
Структура:
subject: user
predicate: prefers_response_style
object: concise_final_reports
scope:
task_type: file_edit_final_response
Текст удобен модели. Структура удобна системе.
Практичный подход часто комбинирует оба:
summary: "User prefers concise final reports after file edits."
structured:
subject: user_123
relation: prefers
object: concise_final_reports
applies_to: file_edit_final_response
Так запись можно вставить в prompt и одновременно искать, обновлять, фильтровать и проверять.
Type: зачем памяти нужен тип
type определяет, как запись использовать.
Примеры:
| Type | Что хранит | Как используется |
|---|---|---|
semantic_fact |
Устойчивый факт | Context, reasoning, project/user profile. |
episodic_event |
Событие и outcome | Debugging, audit, replay, reflection. |
procedural_skill |
Workflow или навык | Планирование действий. |
policy |
Обязательное правило | Ограничение поведения. |
reflection |
Lesson learned | Warning, strategy adjustment. |
document_chunk |
Фрагмент внешнего источника | RAG и grounding. |
summary |
Сжатое состояние | Session continuity, handoff. |
entity |
Объект системы | Linking и graph retrieval. |
Если type не задан, retrieval может смешать event, fact и procedure. Модель получит "что произошло" как "что всегда делать" или hypothesis как verified fact.
Scope
Scope говорит, где запись применима.
Примеры:
scope:
user: user_123
scope:
project: ai-agent-memory-guide
task_type: lecture_writing
scope:
organization: acme
policy_domain: security
Без scope агент вспоминает правильные данные в неправильном месте. Preference одного пользователя применяется к другому. Workflow одного репозитория используется в другом. Временная session instruction становится долговременной привычкой.
Scopes подробно разберем в следующей лекции. Здесь важно: scope должен быть частью representation, а не внешним комментарием.
Source и provenance
Source отвечает на вопрос: откуда взялась запись?
Примеры source:
- direct user instruction;
- tool result;
- project file;
- official documentation;
- CRM record;
- model extraction;
- human review;
- consolidation of episodes;
- imported knowledge base.
Provenance шире source. Она показывает историю:
Raw conversation -> extracted fact -> human confirmed -> indexed -> superseded older fact
Пример:
source:
kind: user_instruction
conversation_id: conv_2026_08_07
message_id: msg_42
provenance:
extracted_by: memory_writer_v2
reviewed_by: user
derived_from:
- msg_42
Provenance нужна для:
- проверки;
- объяснимости;
- conflict resolution;
- deletion;
- audit;
- confidence scoring;
- human correction.
Запись без source со временем становится опасной: агент помнит, но не знает, почему.
Confidence и importance
Confidence и importance отвечают на разные вопросы.
Confidence:
Насколько запись надежна?
Importance:
Насколько запись важна для будущего поведения?
Примеры:
| Запись | Confidence | Importance |
|---|---|---|
| "Пользователь сказал 'ок'." | High | Low |
| "Возможно, причина бага в кешировании." | Low | Medium |
| "Security policy запрещает раскрывать secrets." | High | Critical |
| "Тест упал один раз." | High как событие, low как причина | Medium |
| "Проект использует Vitest согласно package.json." | High | Medium |
Retrieval и action должны учитывать оба поля. Low-confidence memory может быть полезной как hypothesis, но не как fact. High-importance policy должна иметь высокий приоритет в context assembly.
Temporal metadata
В memory systems важно различать несколько моментов времени.
| Поле | Что означает |
|---|---|
created_at |
Когда запись создана в memory store. |
observed_at |
Когда событие было замечено агентом. |
event_time |
Когда событие реально произошло, если известно. |
valid_from |
С какого момента факт считается действительным. |
valid_until |
До какого момента факт действителен. |
last_confirmed_at |
Когда запись последний раз подтверждалась. |
last_used_at |
Когда запись последний раз использовалась retrieval/action. |
expires_at |
Когда запись должна перестать быть active. |
Пример:
created_at: 2026-08-07
observed_at: 2026-08-07
valid_from: 2026-07-20
last_confirmed_at: 2026-08-07
Агент мог узнать сегодня, что проект перешел на Vitest 20 июля. Это разные даты.
Temporal metadata нужна для freshness, historical retrieval, contradiction detection, TTL и decay.
Fact representation
Факт удобно представлять как relation:
subject -> predicate -> object
Пример:
subject: ai-agent-memory-guide
predicate: primary_language
object: Russian
scope:
project: ai-agent-memory-guide
source:
kind: project_instruction
confidence: high
Или:
subject: user_123
predicate: prefers
object: concise_final_reports
scope:
project: ai-agent-memory-guide
task_type: file_edit
Такая форма помогает:
- находить противоречия;
- обновлять object;
- связывать entities;
- строить graph;
- объяснять факт;
- фильтровать по subject или predicate.
Не каждый факт нужно превращать в строгий RDF-like triple. Но mental model subject-predicate-object помогает избегать расплывчатых записей.
Event representation
Event record отвечает на вопрос "что произошло?"
Поля:
- actor;
- action;
- target;
- result;
- time;
- context;
- artifacts;
- source;
- importance;
- related entities.
Пример:
type: episodic_event
actor: coding-agent
action: ran_tests
target: invoice_totals.test.ts
result: failed
event_time: 2026-08-07T16:10:00+03:00
context:
changed_file: src/pricing/discount_helper.ts
artifacts:
- test_log_uri: object://logs/test_run_123
source:
kind: tool_result
importance: medium
Event representation важна для audit, replay, debugging и reflection.
Ошибка: сохранять event как semantic fact.
"invoice_totals.test.ts fails"
Это может быть true в конкретный момент, но не обязательно всегда. Лучше:
"invoice_totals.test.ts failed after change X at time Y."
Skill representation
Procedural memory требует другой структуры.
Skill или workflow может иметь:
- name;
- trigger или applies_when;
- goal;
- steps;
- constraints;
- required tools;
- expected outcome;
- failure modes;
- source;
- scope;
- priority;
- status.
Пример:
type: procedural_skill
name: write_full_markdown_lecture
applies_when:
- user asks to write or expand a lesson
scope:
project: ai-agent-memory-guide
steps:
- read target lesson plan
- read adjacent course files
- preserve title, goal and expected result
- add terms, diagram, examples, risks, summary and self-check questions
constraints:
- write in Russian
- keep the guide conceptual
expected_outcome:
- complete Markdown lecture
source:
kind: project_instruction
Если хранить skill как один text chunk, агенту труднее понять trigger, constraints и priority.
Reflection representation
Reflection record должен отличать outcome, evidence и lesson.
Пример:
type: reflection
summary: "Lesson plans should be checked against final lecture sections."
trigger:
kind: draft_review
evidence:
- first draft missed SOUL.md from source bullet list
lesson:
When expanding lesson plans, verify that required bullets are represented or intentionally omitted.
applicability:
project: ai-agent-memory-guide
task_type: lecture_writing
confidence: high
Так representation не сохраняет chain-of-thought, но сохраняет полезный урок.
Links между записями
Память редко состоит из независимых строк.
Links могут выражать:
derived_from;supersedes;conflicts_with;supports;contradicts;related_to;mentions_entity;caused_by;part_of;depends_on.
Пример:
reflection_123 derived_from event_456
fact_789 supersedes fact_101
procedure_222 supported_by reflection_123
document_chunk_333 mentions_entity service_billing
Links помогают:
- объяснять происхождение;
- делать graph search;
- удалять derived records;
- разрешать конфликты;
- строить summaries;
- проводить audit.
Soft delete и superseded records
Не каждая запись удаляется физически сразу.
Soft delete:
status: deleted
deleted_at: 2026-08-07
delete_reason: user_request
Superseded:
status: superseded
superseded_by: mem_456
Разница:
- deleted запись не должна использоваться и может подлежать физическому удалению из индексов и derived records;
- superseded запись остается историей, но не должна быть active;
- archived запись может быть доступна для audit или historical retrieval;
- stale запись требует проверки перед использованием.
Статус - обязательная часть representation, если memory layer поддерживает update и forgetting.
Представление как graph
Даже если storage не graph database, полезно думать о памяти как о графе.
Граф помогает увидеть связи между user, project, documents, lessons, skills и reflection. Даже если физически данные лежат в SQL и JSON, relation model улучшает retrieval и update.
MemoryRecord schema: пример
MemoryRecord
id: string
type: enum
status: enum
summary: string
content: text_or_json
scope:
user_id: optional
session_id: optional
project_id: optional
team_id: optional
organization_id: optional
agent_id: optional
source:
kind: enum
reference: string
observed_by: optional
scores:
confidence: low | medium | high
importance: low | medium | high | critical
temporal:
created_at: timestamp
observed_at: optional timestamp
event_time: optional timestamp
valid_from: optional timestamp
valid_until: optional timestamp
last_confirmed_at: optional timestamp
expires_at: optional timestamp
entities:
- entity_id
links:
- relation: string
target_id: string
permissions:
visibility: enum
read_roles: list
write_roles: list
Это учебная схема, не готовая миграция базы. В реальной системе поля будут зависеть от продукта, privacy requirements и storage choice.
Мини-кейс: user preference
Плохая запись:
User likes short answers.
Управляемая запись:
id: pref_001
type: semantic_fact
status: active
summary: User prefers concise final reports after file edits.
structured:
subject: user_123
predicate: prefers
object: concise_final_reports
scope:
project: ai-agent-memory-guide
task_type: file_edit_final_response
source:
kind: user_instruction
confidence: high
importance: medium
created_at: 2026-08-07T13:00:00+03:00
last_confirmed_at: 2026-08-07T13:00:00+03:00
Теперь агент может правильно применить preference: кратко ответить после редактирования файла, но не сокращать саму лекцию.
Мини-кейс: coding event
Плохая запись:
Tests failed.
Управляемая запись:
id: event_401
type: episodic_event
status: active
summary: invoice_totals.test.ts failed after editing discount_helper.ts.
actor: coding-agent
action: ran_tests
target: invoice_totals.test.ts
result: failed
context:
changed_file: src/pricing/discount_helper.ts
source:
kind: tool_result
confidence: high
importance: medium
event_time: 2026-08-07T16:10:00+03:00
entities:
- file:src/pricing/discount_helper.ts
- test:invoice_totals.test.ts
Такую запись можно использовать для debugging, reflection и future retrieval.
Типичные ошибки
Ошибка 1: хранить только text blob.
Текст удобен, но без type, scope, source и status память трудно обновлять.
Ошибка 2: не различать content и metadata.
Metadata не должна прятаться внутри произвольной фразы.
Ошибка 3: не хранить source.
Факт без источника трудно проверить, объяснить и удалить.
Ошибка 4: смешивать event и fact.
"Тест упал" - событие. "Тест всегда падает" - другое утверждение и обычно неверное.
Ошибка 5: не хранить temporal fields.
Без времени невозможно понять freshness, TTL и historical validity.
Ошибка 6: не моделировать links.
Без связей трудно понять, какие records derived from source и что удалить при correction.
Ошибка 7: не иметь status.
Active, stale, superseded, archived и deleted записи должны вести себя по-разному.
Ошибка 8: проектировать representation только под одну базу.
Модель памяти должна отражать lifecycle, а не ограничения первого выбранного storage.
Краткое резюме
Memory Representation определяет, чем является запись памяти внутри системы. Хорошая запись содержит content, type, scope, source, provenance, confidence, importance, temporal metadata, entities, links, permissions и status.
Факты, события, навыки и reflection требуют разных структур. Text summary полезен для LLM, но structured fields нужны для retrieval, update, conflict detection, deletion и governance.
Хорошая representation делает память управляемой. Плохая representation превращает память в набор заметок, которые невозможно надежно искать, обновлять и забывать.
Вопросы для самопроверки
- Почему memory record не должен быть только текстовой строкой?
- Чем
confidenceотличается отimportance? - Какие временные поля могут быть нужны записи памяти?
- Почему event representation отличается от fact representation?
- Зачем memory records нужны links и status?
Что дальше
В следующей лекции мы разберем Memory Scopes: как определить, кому и где применима запись памяти, как защищать multi-tenant системы и как решать конфликты между user, session, project, team и organization memory.