Skip to content

TaleEngine v2.5.0 Beta

Latest

Choose a tag to compare

@Sonicspeedfly Sonicspeedfly released this 26 Sep 03:02
· 47 commits to main since this release
c171719

Память длинных чатов стала мастер-снимком строгой схемы: он собирается пакетами,
проверяется после каждого ответа модели и пересобирается вручную с прогрессом.
Заодно исправлены две тихие потери: снимок обрезался до 6000 символов, а
выбранный вручную бюджет хода в 1 млн сбрасывался при каждой загрузке.

Добавлено — иерархическая пакетная память

Хроника длинного чата была свободным конспектом: не больше шести кусков за ход и
только после ответа ассистента, без пауз, повторов и прогресса. Большой бэклог
(импорт на тысячу сообщений) догонялся за несколько ходов, пересобрать память
вручную было нельзя, а при повторных сжатиях конспект мог молча выронить пункт
списка или персонажа второго плана.

  • Мастер-снимок строгой схемы из четырёх разделов: «Хроника и событийный
    каркас», «Активные персонажи и их статусы», «Фактологический реестр и лор»,
    «Списки и медиа-анкоры». Это Markdown: его читают во вкладке «Память» и в
    экспорте, в контекст он идёт как есть.
  • Свёртка по пакетам: снимок_N = слияние(снимок_{N−1}, пакет_N), пакеты по
    20 сообщений (не больше 80 000 символов). Один движок и один промпт — и для
    прохода после хода, и для полной пересборки. Новые модули:
    backend/hierarchical_memory.py (чистое ядро, только stdlib) и
    backend/memory_service.py (адаптер к БД).
  • Проверка каждого ответа: нет раздела, пустой ответ или снимок «сдулся»
    больше чем вдвое — модель получает корректирующий ход (до двух). Брак после
    них в память не пишется, указатель «учтено до» не двигается.
  • Обрыв лимитом вывода (обёртка <master_state> не закрыта или шлюз сообщил
    finish_reason=length у непустого ответа) — не брак, а сразу сжатие хроники с
    арками и один повтор слияния: корректирующий ход с тем же лимитом оборвался бы
    снова. Если реестр и списки сами больше лимита вывода, модель не зовётся —
    понятная ошибка вместо платных попыток.
  • Страж записей: персонаж, запись реестра или элемент списка, которые модель
    выронила, возвращаются из предыдущего снимка дословно. Обновлённую на месте или
    слегка переименованную запись страж узнаёт (регистр, ё/е и пунктуация не
    важны) и не дублирует; записи с одинаковым началом («Linkin Park — «Numb»» и
    «Linkin Park — «In the End»») друг друга не прикрывают.
  • Бюджет снимка 12 000 токенов: сверх него старые записи хроники сворачиваются
    в арки [#a–#b] Арка «…»; последние 12 записей хроники и разделы персонажей,
    реестра и списков не трогаются — из ответа сжатия берётся только хроника, а
    ответ без свежих записей хроники отвергается.
  • Пауза и повторы: 1,5 с между любыми запросами памяти (слияние, факты,
    сжатие); при 429, таймауте, 5xx и обрыве связи — до 4 повторов через 2/4/8/16 с
    (не меньше Retry-After). Отказ по ключу, неверный запрос и фильтр провайдера —
    ошибка сразу, без платных повторов. «Остановить» и «Сбросить память» обрывают
    паузы сразу. Задания памяти идут по одному на процесс, остальные ждут в очереди.
  • Сбой обновления виден и не повторяется на каждом ходу: ошибка ежеходного
    прохода записывается и показывается во вкладке «Память» («Память не
    обновилась: … Следующая попытка — после ЧЧ:ММ или кнопкой «Догнать»»), а
    следующий проход ждёт 10 мин, 20, 40… до 6 ч.
  • Лимит вывода модели памяти: max_tokens памяти и рабочий бюджет снимка
    прижимаются к тому, что модель успевает написать (по карте LiteLLM). У модели
    по умолчанию gpt-4o (вывод до 16 384) запрос с 17 824 получал бы 400 на
    каждом проходе. Модель неизвестна, а провайдер отверг max_tokens — один
    повтор с DEFAULT_MAX_TOKENS и предупреждение.
  • Вкладка «Память» → «Мастер-память этого чата»: размер снимка, до какого
    сообщения он учтён и сколько сообщений ждут сжатия; предупреждения памяти и
    ошибка последнего обновления; «Пересобрать с нуля» (подтверждение с оценкой
    числа платных запросов), «Догнать» (с подтверждением, если пакетов больше
    трёх), «Экспорт .md», «Сбросить память»; прогресс [Обработано 140/800 сообщений | Сжато до 4 200 токенов] с номером пакета и кнопкой «Остановить»;
    поля «Размер пакета», «Пауза между запросами», «Бюджет снимка» (до 40 000 — с
    предупреждением, если модель памяти столько не напишет). Итог задания честный:
    «Сжимать нечего — весь чат в окне» вместо «0 сообщений → 0 токенов».
  • Пересборка идёт в буфер, а старый снимок работает до конца — подмена одним
    коммитом. Прерванную перезапуском сервера пересборку продолжает кнопка
    «Продолжить» или обычные проходы после ходов; остановленную кнопкой — только
    «Продолжить», а проходы тем временем обновляют живой снимок.
  • Монитор токенов: из чего складывается ход — системный промпт и якоря,
    мастер-снимок и факты, дословное окно; доля от бюджета хода и от лимита модели
    (MODEL_CONTEXT_LIMIT, 1 000 000). Та же разбивка — в инспекторе хода. Для
    групповых чатов не считается (tiers: null): ход группы собирается иначе.
  • Снимок входит в бюджет хода: снимок, база знаний, аватары и статичный хвост
    резервируются до обрезки истории. Раньше они шли сверх бюджета — при бюджете
    30 000 в модель уходило до 41 тыс. токенов.
  • Факты пакета, чей запрос фактов не удался (сбой, остановка), доизвлекает
    следующий пакет.
  • В пакетах — настоящие имена авторов (персона, персонаж, говорящий в группе) и
    время в часовом поясе чата; base64, data-URI, HTML-оформление и <think>
    вырезаются, вложения подписываются типом и именем файла.
  • Сводки 2.4.x (свободный конспект) переводятся в новую схему ближайшим проходом
    без отдельных затрат; чистая конвертация — «Пересобрать с нуля».
  • API: GET/DELETE /api/sessions/{id}/memory, POST …/memory/rebuild,
    POST …/memory/cancel, GET …/memory/export, report.tiers (у групп —
    tiers_unavailable: "group") в GET /api/sessions/{id}/context; в статусе —
    snapshot.last_error, snapshot.retry_after, settings.max_snapshot_tokens,
    job.warnings, job.snapshot_tokens, staging.paused (см.
    docs/API.md; подробно — docs/HORAE.md).

Исправлено — бюджет 1M сбрасывался на 200k при каждой загрузке

В 1.12.0 сохранённое окно контекста в 1 млн токенов обещали опускать до 200 тыс.
один раз, но проверка шла при каждой загрузке интерфейса: выбранный вручную
1 000 000 в «Окне контекста» тихо возвращался к 200 000 при следующем открытии
страницы. Теперь миграция выполняется один раз (флаг ctx_budget_v: 2 в
настройках ui), и выбранный после неё 1 млн остаётся.

Исправлено — снимок памяти обрезался до 6000 символов

_adopt_summary сохранял авто-сводку слайсом [:6000], так же резался и буфер
пересборки. Хвостовые разделы — персонажи, локации, незакрытые линии — пропадали
молча, без ошибки и предупреждения, и модель «забывала» договорённости из начала
чата. Теперь снимок не режется: от мусора защищает проверка ответа (снимок
длиннее max(200 000, 8 × бюджет снимка) символов не принимается), от
раздувания — бюджет снимка и сжатие хроники в арки.

Изменено — активное окно по умолчанию 50

Дословно модель видела последние 20–23 сообщения — меньше одной связной сцены, а
всё старше видит только через снимок.

  • DEFAULT_WINDOW = 50 на сервере и в интерфейсе: дословно идут 50–53 сообщения.
  • Сохранённое прежнее значение по умолчанию 20 один раз поднимается до 50 (флаг
    memory_defaults_v: 2); выставленное после этого вручную 20 не трогается.
  • Кнопки окна во вкладке «Память»: 20 / 50 / 80 / 150 / «вся история» (было
    20 / 40 / 80 / 150).

Обновление

  • Изменился серверный код, поэтому после git pull сервис нужно перезапустить.
    В Docker код бэкенда и бота запечён в образ — нужна пересборка:
    docker compose up -d --build (простой restart оставит старый бэкенд со
    свежим интерфейсом). Без Docker — перезапуск start.sh или systemd-сервиса.
  • Новые переменные .env — все необязательные, умолчания заданы в коде:
    MEMORY_BATCH_SIZE=20, MEMORY_BATCH_CHARS=80000, MEMORY_DELAY_MS=1500,
    MEMORY_SNAPSHOT_TOKENS=12000, MEMORY_MAX_RETRIES=4, MEMORY_TEMPERATURE=0.2,
    MEMORY_MAX_BATCHES_PER_TURN=6, MODEL_CONTEXT_LIMIT=1000000 (образец — в
    .env.example). Новых зависимостей и ручных миграций БД нет.
  • summary_model («Подключение») должна выдавать длинный ответ: снимок
    переписывается целиком, и потолок вывода — max(DEFAULT_MAX_TOKENS, round(бюджет снимка × 1,4) + 1024), то есть 17 824 токена при бюджете 12 000.
    Если LiteLLM знает модель, вывод и бюджет снимка прижимаются к её лимиту сами
    (вкладка «Память» предупредит); иначе, если модель столько не выдаёт, уменьшите
    «Бюджет снимка». Если же в лимит вывода не влезают реестр и списки снимка
    (ошибка «реестр и списки больше лимита вывода»), уменьшение бюджета не поможет:
    нужна модель с большим выводом или ручная чистка этих разделов.
  • Постоянная стоимость выросла. Снимок до «Бюджета снимка» (12 000 токенов)
    идёт в каждый ход — в хвост, вне кэшируемого префикса; до 2.5.0 сводка была не
    длиннее 6000 символов (1,5–2,5 тыс. токенов). И раз в summary_every
    сообщений модель памяти переписывает снимок целиком — до 17 824 токенов вывода
    на обновление, в 5–10 раз больше, чем в 2.4.x. Снизить: меньше «Бюджет
    снимка», реже «Как часто обновлять сводку» (каждые 20 сообщений вместо 10),
    дешёвая summary_model.
  • Пересборка платная: «Пересобрать с нуля» стоит ⌈(сообщений − окно) / размер
    пакета⌉ запросов слияния (плюс изредка сжатие хроники). Факты заново не
    извлекаются там, где они уже есть: у чата с фактами пересборка запросов фактов
    не делает, а без фактов (после «Сбросить память», у сводки до 2.4.0) — до
    одного на пакет. Чат на 1 050 сообщений при окне 50 и пакете 20 — около 50
    запросов к summary_model. Оценку показывает подтверждение перед запуском.
    Сама по себе после обновления пересборка не запускается: сводки 2.4.x
    переходят на новую схему обычными проходами после ходов, а сводки до 2.4.0
    пересобираются фоном, как и в 2.4.0.
  • Окно выросло с 20 до 50 сообщений, поэтому вход длинного чата на каждом ходу
    вырастет примерно на 30 реплик. Вернуть прежнее — «Память» → «Активное окно» →
    20.