Содержание
Коротко
Когда текст не влезает в окно контекста, агент обычно читает файл ломтями и надеется, что ответ попал в один из них, либо ищет по заранее нарезанному указателю. На стыках кусков смысл пропадает. Проект с открытым кодом Matryoshka на TypeScript оставляет документ целиком на сервере — как книгу в хранилище читального зала — и выдаёт агенту не страницы, а короткий ярлык: где лежит ответ. Автор заметки на Dev.to сам писал команды, без ключа к языковой модели и без локальной Ollama. Буквальные подсчёты сошлись с отдельной проверкой, едва стала ясна семантика. Цифры экономии токенов из описания проекта он не мерил.
Что произошло
Matryoshka написал Дмитрий Сотников (yogthos, автор каркаса Luminus для Clojure). Идея опирается на статью о рекурсивных языковых моделях Алекса Л. Чжана, Тима Краски и Омара Хаттаба из MIT CSAIL. Это независимая реализация, не код авторов статьи. На 4 октября 2026 года в репозитории было 149 звёзд, 20 копий и ни одного открытого сообщения об ошибке. Лицензия Apache-2.0. Последний выпуск в npm — matryoshka-rlm 0.2.40 от 17 мая 2026 года.
Модель здесь не пишет JavaScript или Python. Она пишет команды на Nucleus, маленьком скобочном языке: (grep "ERROR"), фильтр по предыдущему результату, подсчёт, сумма. Движок Lattice разбирает команду, проверяет типы и выполняет её по документу. Ответы остаются в SQLite в оперативной памяти, а клиент получает заглушку вроде $grep_error со счётчиком и коротким началом списка. Настоящие строки забирают отдельно, командой lattice_expand. В описании проекта сказано про «экономию токенов больше 97%» и «больше 80% по сравнению с прямым чтением файла» для сервера MCP. Это цифры проекта. Автор их не проверял.
Сервер lattice-mcp как раз не требует языковой модели. Поэтому тест говорит о движке и об инструментах, а не о том, сумеет ли модель сама выбрать команды. На машине стояли Linux x86_64, 8 виртуальных ядер, около 15 ГБ памяти, Node 20.19.2 и pnpm 10.33.4. Пакет поставили локально рядом с официальным SDK протокола MCP, а не глобально, как советует описание: установка заняла 2,5 секунды и 220 МБ каталога зависимостей. pnpm 10 пропустил сборку грамматик tree-sitter. Их оставили несобранными, и список символов в коде всё равно заработал.
Клиент на TypeScript соединился за 409 мс и увидел сервер lattice 0.2.40 с двенадцатью инструментами: загрузка, запрос, раскрытие ярлыка, закрытие, статус, список имён, сброс, заметки, справка и два вызова, которые готовят вопросы для модели.
Почему это важно
Три файла. «Война и мир» в переводе Мод с Проекта Гутенберг: 3,36 МБ, 66 041 строка, 566 333 слова, около 770 тысяч токенов (769 825 по токенизатору tiktoken, словарь o200k_base). Это больше окна большинства моделей. Журнал доступа Apache из примеров Elastic: 10 000 строк, 2,37 МБ, трафик мая 2015 года. Плюс собственные исходники Matryoshka, чтобы проверить работу с кодом. Ответы заранее посчитали обычным поиском по тексту и коротким скриптом на Python.
Роман загрузился примерно за 0,75–0,8 секунды. Дальше запросы занимали от 1 до 430 мс.
| Вопрос | Команда, по смыслу | Ответ | Сверка |
|---|---|---|---|
| Заголовки глав | поиск и подсчёт | 365 | 365 |
| Заголовки книг | тот же приём | 17 | 15, пока шаблон широкий |
| Упоминания Наташи | подсчёт совпадений | 1 213 | 1 213 (на 1 197 строках) |
| Строки про Пьера, где есть и Наташа | фильтр | 44 | 44 |
| «Генуя» | поиск и раскрытие | строки 840, 1573, 9153 | те же |
| Начало романа | строки 840–846 | семь строк цитаты | дословно |
| Бородино | подсчёт | 108 | 108 |
Поиск без учёта регистра и считает совпадения, а не строки. Лишние две «книги» оказались обычными фразами со строчной book. Флаги поиска в исходнике — gmi. Более узкий шаблон ^BOOK [A-Z]+: вернул верные 15. После этого подсчёты совпали с поиском без учёта регистра по одному совпадению.
Ранжирование упирается в написание. Запрос про «битву при Бородино» без ударения вернул пять строк, где просто сказано «битва». С ударением, как в переводе, пять строк уже содержали нужное сочетание. Нечёткий поиск Natasha Rostova ничего не нашёл, а с ударениями, как в книге, нашёл сразу. Команда, которую описание называет смысловым поиском, — это косинусное сходство по частотам слов, не векторные представления. Фраза про раненого при Аустерлице, который смотрит в небо, не вытащила известное место. Ближайшее попадание — been looking at. на строке 15862, на семь строк раньше. Обычный поиск lofty sky нашёл пассаж на строке 15869.
На журнале ответы 404 нашлись 213 раз, запросы Googlebot — 543, ответы 200 — 9 126. Сумма по сырым строкам дала бессмыслицу 1 067 060,464: берётся первое число в строке, а это начало адреса клиента. Если сначала вытащить поле размера ответа, сумма байт совпала: 2 735 455 845.
Первый сеанс по роману — 27 вызовов инструментов, ответы вместе 5 625 знаков. Это собственный подсчёт автора, не сравнительный тест. Книга осталась на сервере. Наружу вышли ярлыки и те строки, которые попросили принести.
На практике
Путь «файл слишком большой» здесь устроен как заказ в читальном зале: вы называете полку, получаете карточку, и только потом просите принести том. Карточка бесполезна, если не знать правил каталога.
Команда npx lattice-mcp из папки, где пакет не установлен, скачала чужой npm-пакет lattice-mcp версии 1.6.2. Тот попросил LATTICE_API_URL и LATTICE_API_TOKEN. Нужен двоичный файл из matryoshka-rlm. Настоящий сервер печатает lattice-mcp v0.2.40.
Дальше автор упёрся в правила, которые легко принять за поломку:
- Пишите слова так, как они стоят в документе, включая ударения. Ранжирование их не складывает.
lattice_expandждёт именованный ярлык. СловоRESULTSвнутри запроса работает, а как имя для раскрытия — нет: «неверный ярлык». Имена вроде$grep_genoaпоказываетlattice_bindings. Шаблоны с кавычками получают общие имена, поэтому список стоит запрашивать часто.- Сумма по сырым строкам журнала берёт первое число. Сначала выделите нужное поле, потом суммируйте.
- Загрузка
/etc/hostnameотказана: путь вне рабочей папки. Заметка, сохранённая черезlattice_memoпри открытом романе, раскрылась и после перехода на журнал. - Без поддержки выборки со стороны клиента пакетный вопрос к модели по трём строкам с ошибкой 500 вернул одну заготовку с тремя готовыми инструкциями. Автор сам вписал ответы
bot,bot,humanи отправил их черезlattice_llm_batch_respond. Фильтр поbotнасчитал 2. Модель эти строки не судила. - В
lc-solver.ts(2 658 строк) список функций вернул 20 штук — столько же, сколько поиск объявлений верхнего уровня, — с диапазоном строк и сигнатурой. Телоevaluateпришло целиком, 64 311 знаков, и не как ярлык: большая функция сразу попадает в контекст. - Граф вызовов на версии 0.2.40 не собрался ни на одном из четырёх исходных файлов: «граф символов недоступен». В журнал сервера падало
Graph.addEdge: источник и цель совпадают. Библиотека графа не принимает петлю на себя, и рекурсия или вызов с тем же именем, похоже, обрывает построение. Насколько это часто, по четырём файлам не сказать. - В
lattice-replпоискAusterlitzи подсчёт дали 51, как отдельная сверка. Склеить загрузку и запрос в одном потоке не вышло: запрос пришёл раньше, чем файл открылся. Передача файла аргументом сработала. Командная оболочкаrlm, где команды уже пишет модель, без настройки идёт наOllamaпо локальному адресу, трижды повторяет вызов и примерно через 9 секунд останавливается: три неудачи подряд, сеть не ответила. Так и должно быть, модели не было.
Автор не проверял живого агента, который сам выбирает команды Nucleus, запуск с моделью, вложенные запросы, выборку протокола, уплотнение контекста, пределы ресурсов, подключение к Claude Code, адаптеры по HTTP и каналу, синтез программ, дополнительные режимы ранжирования, несколько документов сразу и любые цифры экономии токенов из описания или из статьи.
Итог
На буквальных задачах движок был точен: подсчёт, поиск и цитата совпали со сверкой, когда семантика стала понятна. Документ остаётся в хранилище, на стол приносят карточку и только запрошенные строки. Ошибка здесь чаще в правилах каталога, чем в синтаксисе: поиск без регистра и сумма по первому числу уверенно сообщат семнадцать книг и бессмысленный объём байт. Ранжирование лексическое. Граф вызовов в 0.2.40 на проверенных файлах — слабое место, список символов при этом работал.
Имеет смысл пробовать, если агент ходит по большим журналам, стенограммам или книгам и ответы нужно сверять, а не вытаскивать кусками из указателя. Следующий шаг автора — посадить в контур настоящую модель и посмотреть, обойдёт ли она эти ловушки сама.



Комментарии