Пам'ять
Те, що агент зберігає між розмовами, на відміну від вікна, яке він читає всередині однієї. Цим словом називають дві різні речі, і поводяться вони достатньо по-різному, щоб їхня плутанина коштувала пів дня:
- Нотатки — те, що агент записав про людину і про роботу. Рядки, довговічні, подаються в кожен хід.
- Пошук по розмові — доступ до того, що було сказано, за горизонтом вікна. Це взагалі не сховище: це пошук по сховищу чату.
Нотатки: курована сторінка і датовані записи
Пам'ять агента — це markdown, який він написав, а не нарізані повідомлення. Одна курована сторінка — його постійний звіт про людину і про роботу — плюс датовані нотатки, по одній на день. Будь-який окремий елемент обмежений 2 000 знаками; шлях запису відхиляє довший, а не підрізає його мовчки: нотатка, обірвана на середині фрази, гірша за відмову, на яку агент може відреагувати.
Нотатки пишуть троє, і четвертого немає: імпорт пакета, власний інструмент запам'ятовування в агента і куратор — фоновий прохід, який перечитує розмову, коли та вже пішла вперед, і вирішує, що заслуговує її пережити. Куратор іде за порогом, а не після кожного ходу (приблизно кожні чотири обміни або 8 000 знаків розмови), бо платити за перечитування кожного ходу — це приблизно стільки ж, скільки коштує сам хід.
Помилка запису дорожча за помилку читання. Неправильно прочитане забудеться з наступним ходом, а неправильно записане подаватиметься в кожен хід, доки хтось не помітить, — а помітити важко: агент упевнено посилається на факт, якого не було.
Що отримує хід, і єдина стеля над цим
Композитор рівно один, викликається один раз за хід, і його викликають обидва мозки. Він повертає і шари промпта, і префікс повідомлень, і те, чим за них заплатили, — бо торгувати одним шаром проти іншого може лише той, хто бачить усе одразу.
До нього було два — один для нотаток, інший для розмови, — у кожного своя стеля, і суми не тримав ніхто. Саме так промпт виростає на тисячу знаків, хоча ніхто цього не вирішував.
персона → останній обмін → зведення → нотатки → витяги → глибше вікноЦе порядок витіснення: коли стеля зв'язує, місце поступаються справа. Перші два не ріжуться ніколи — персона взагалі не береться з бюджету, а останній обмін видається раніше, ніж хтось встигає витратити. Зведення стоїть вище за нотатки, бо воно про цю розмову.
Стеля — 18 000 знаків на весь префікс, це сума того, що просять шари, тому сьогодні нікому насправді не відмовляють. Рахується у знаках, а не в токенах: токенайзера тут немає, а блок їде в кожному ході — це постійна ціна, а не разова.
Читання робиться за можливості. Сховище, яке не відповіло, коштує ходу його нотаток, але ніколи самого ходу.
Упорядкування нотаток за змістом — побудовано і не запускалося жодного разу
Нотатки можна впорядкувати за тим, про що хід, а не за датою: питання перетворюється на вектор, найближчі нотатки знаходяться у векторному сховищі, а їхні оцінки стають порядком. Стеля і запит кожного шару при цьому не змінюються — змінюється те, на які нотатки витрачається їхній бюджет.
Вектори живуть в infra/vector як L2-нормовані байти float32 з ключем-простором імен, який несе команду, тому нотатки одного орендаря навіть не порівнянні з чужими. Вектор зараховується лише при збігу моделі ембеддингів і ширини; вектор, що розійшовся хоч в одному з двох, — не слабкий збіг, а невидимка.
І нічого з цього ніколи не виконувалося. Жодне середовище в цьому репозиторії не задає ключа ембеддингів, тому виклик падає раніше за пошук, а в базі розробки лежить нуль векторів. Без упорядкування нотатки приходять новими вперед — і це не деградований режим, а рівно та поведінка, яка була до появи можливості. Нотатка, яка не потрапила в ранжування, не виключається ніколи: вона сортується після оцінених, за датою серед своїх.
Тому ж поріг відсікання не налаштований, а не налаштований погано: щоб його налаштувати, потрібна колонка оцінок того постачальника, який постачається, а виробити її тут нічим.
З наявності індексу випливають два обов'язки, і обидва забезпечені механічно, а не пам'яттю:
- Усе, що пише нотатку, зобов'язане її переіндексувати. Письменник, який забув, лишає нотатку, яка є в базі і яку не можна згадати ніколи, — найгірший вид поломки, бо нічого не падає. Перевірка відхиляє нового письменника, який цього не робить.
- Видалення нотатки прибирає її вектор. Інакше людина видаляє нотатку, екран погоджується, що її більше немає, а пошук продовжує її повертати — тобто агент пам'ятає те, що йому веліли забути.
Пошук по розмові
Два читальні інструменти дістають увесь тред: останні повідомлення і пошук по листуванню (повнотекстовий пошук Postgres, з ранжуванням). Обидва обмежені агентом, у чиєму ході їх викликано, і людиною в цій розмові — ніколи чужим листуванням.
Але інструмент спрацьовує лише тоді, коли модель запідозрить, що чогось бракує, — а дефект, який цим закривають, рівно той, де вона не підозрює. Виміряно: на питанні, відповідь на яке лежала дванадцятьма днями раніше, відповідь була правильною в кожному прогоні, де модель потягнулася за інструментом, і неправильною в кожному, де не потягнулася, і більше їх ніщо не розрізняло.
Тому перший пошук робить хід, а не модель. Усе повідомлення користувача шукається раніше, ніж модель щось побачить, влучання, вже показані вікном, викидаються, а з ходом їдуть не більше чотирьох витягів (2 000 знаків) — у промпті, але ніколи в історії: рядок, вирваний з порядку, не є попереднім повідомленням, і підстановка його як такого ламає чергування, на яке чекає провайдер. Питання, у якому менше двох справжніх слів, не шукається зовсім, тому «дякую» не коштує нічого.
Інструменти лишаються: модель, якій потрібен інший запит, має мати змогу його поставити.
Пам'ять vs знання
- Пам'ять = те, що цей агент знає про людину і про роботу (ця сторінка) →
agent/memory. - Знання = каталог і документи магазину, залиті в LightRAG →
agent/knowledge.
Див. також
- Сховище — розмова, з якої беруться ці нотатки й витяги.
- Коротка пам'ять — вікно всередині однієї розмови.
- Що агент робив — де написана агентом нотатка видно як подію.