(java || kotlin) && devOps
342 subscribers
13 photos
2 videos
7 files
420 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Третий репозиторий Java разработчика

Изначально был Maven Central.
Потом появился Docker Hub.
Теперь ещё и Hugging Face - хранилище opensource моделей.

И с ним возникают свои нюансы.
Например:
1) у некоторых моделей нужно зайти в UI и запросить доступ, явно согласившись с лицензией. Чем это принципиально отличается от License.md - не понятно

2) если JVM и Docker скрывают от нас железо, то LLM модели - нет. От того, что у вас - CPU, GPU или NPU - зависит выбор модели. Базовая модель может быть одинаковой, но появляется новое измерение - оптимизация под железо. Кроме того, у разных NPU - Intel, AMD, Qualcomm, Google, anyone else?)- разные SDK. А NPU выглядит перспективной штукой, так как он специализированный и более дешёвый. В общем, напрашивается новый слой абстракции.

#ai #llm #infrastructure
Локальный LLM

Тема локальных LLM последнее время начала развиваться, т.к. не все хотят или могут зависеть от дяди "в облаке".
Нет интернета, конфиденциальные данные, стоимость...

Но с запуском модели локально есть два препятствия - доступность хороших моделей и отсутствие мощного GPU.
С моделями подвижки есть - особенно с выкладыванием достаточно мощных моделей Qwen и DeepSeek в opensource. В общем смотри https://huggingface.co.
А вот с GPU все сложнее.
Все больше людей переходят на ноуты - как на работе, так и дома. И там видеокарта встроенная и слабая.
Что делать?
В последнее время появляются ноуты, а точнее процессоры со встроенным AI ядром.
Например: https://www.intel.com/content/www/us/en/products/sku/241751/intel-core-ultra-7-processor-255h-24m-cache-up-to-5-10-ghz/specifications.html
Чип как я понял у всех процессоров Intel пока один, называется NPU 3720.

Попробовал я запустить на таком чипе нормальную LLM - нормальную, в смысле LLM общего назначения, а не заточенную под embedding, обработку картинок или голоса...
Сразу наткнулся на ряд подводных камней:
1) широкоизвестная (в узких кругах запускателей LLM моделей) ollama NPU не поддерживает. Надеюсь, это временно, но сейчас так. Зато Intel сделал свой SDK - OpenVINO, с похожим функционалом.
Поддерживаются Windows и Ubuntu 22 https://docs.openvino.ai/2025/openvino-workflow/running-inference/inference-devices-and-modes/npu-device.html
2) в WSL, и далее Docker Desktop NPU не пробрасывается, работает только в native режиме. Я про Windows, но подозреваю проблемы и на Ubuntu

Ну ок, пробуем OpenVINO, благо на huggingface есть коллекция LLMs optimized for NPU, в документации к модели есть инструкция по запуску, например: https://huggingface.co/OpenVINO/gemma-3-4b-it-int4-cw-ov
Но и тут сплошные нюансы:
1) обязательно нужен последний драйвер от Intel, у моего кажется версия от 25.12.2025, что намекает на то, что "тема горячая". На исходной версии драйвера, поставленной Windows, запуск LLM падал с ошибкой компиляции. Об фазе активной разработки говорит раздел "Supported Features and properties" по ссылке ниже.
2) нельзя так просто взять и запустить модель на NPU (c). Требуются модели с квантизацией - это по сути сжатая модель, когда веса преобразуются из Double в Int с минимальным влиянием на точность ответа (так обещают). В случае NPU лучше даже в int4, чем в int8, цифры приведу позже.
Список моделей можно найти тут: https://docs.openvino.ai/2025/documentation/compatibility-and-support/supported-models.html или вот так https://huggingface.co/OpenVINO
3) модели с числом параметров больше 4b (4 млрд) лучше не брать. Они возможно запустятся, но время ответа уйдет за 1 минуту
4) рекомендую внимательно прочитать https://docs.openvino.ai/2025/openvino-workflow-generative/inference-with-genai/inference-with-genai-on-npu.html, оттуда станет ясно, что сейчас при запуске модели через NPU происходит долгая компиляция. Я к чему - кэширование обязательно, оно раза в 3-4 увеличивает скорость запуска. Второго и последующих естественно.
Другие опции - performance hints и AOT (Ahead of Time) компиляция пока сыроваты, а там, где они у меня завелись AOT Weightless - результат был примерно такой же, как с кэшем.
Кэш и AOT по сути являются альтернативами. AOT должен быть быстрее, но он еще сырой и требует двух запусков с разными параметрами, в то время как подключение кэша прозрачно.

Еще что интересно.
Если вернуться с списку моделей от Intel - https://docs.openvino.ai/2025/documentation/compatibility-and-support/supported-models.html, то там порядка 1000 моделей совместимы с NPU. Это сильно меньше, чем CPU\GPU, но много.
А вот если посмотреть на категорию этих моделей, то Large Language Model будет меньше чем у сотни.
Остальные - это Object Detection, Speech Recognition, Image\Video classification, Text To Speech, Natural Language Processing, Audio, Image generation, Image to Image. Вообще говоря классификация интересна сама по себе, но я бы хотел заострить внимание на том, что LLM меньше 10%.
Это говорит о том, для чего Intel делала свой чип.
1
И о главном - скорость ответа.
Тестировал на двух типах моделей, Python, OpenVINO 2025.4.1 GenAi API, Windows 11, Intel Core Ultra 7 255H:
1) анализ изображения, модель gemma-3-4b-it-int4-cw-ov, пайплайн openvino_genai.VLMPipeline
CPU 30c
CPU+cache 22c
NPU 80c
NPU+cache 25c
GPU 20c
GPU+cache 14c

2) режим чата, модель qwen2.5-1.5b-instruct-int4-ov, пайплайн openvino_genai.LLMPipeline
CPU 6c
CPU+cache 5c
NPU 40c
NPU+cache 10c
NPU+AOT 9c
GPU 9c
GPU+cache 5c

Это не полноценный бенчмарк, но пару прогонов делал.

Итог: для картинок быстрее GPU, для текста - паритет CPU и GPU. Чуда не произошло.
Но. Одним NPU ядром разгрузить 14 ядер CPU - в целом уже неплохо.
И кэширование гораздо важнее для NPU, не понимаю почему.

P.S. Интересный момент - железо сильно влияет на ответ на одной и той же модели и промте. Т.е. смысл везде похож, но текст ответа сильно отличается:

Here's what's unusual in the picture:
The cat is lying completely flat inside a cardboard box! It's a very relaxed and adorable pose for a cat, but it’s not typical behavior – cats usually prefer to be curled up or have some space around them.
Let me know if you want to analyze the picture further!

Here's what's unusual about the picture:
* **The cat is in a box!** It's not just *near* a box, but it's completely curled up and lying down *inside* a cardboard box. It’s a classic, adorable, and slightly unusual behavior for cats.
Let me know if you'd like me to elaborate on why it’s unusual!

Here's what's unusual in the picture:
* **The cat is lying in a cardboard box.** Cats are known for enjoying boxes, but it's particularly amusing to see one completely relaxed and stretched out inside one!
Let me know if you'd like to analyze another image!

Повторяемость на одном и том же типе железа при этом хорошая.

#ai #hardware
🔥1
Я вот прямо зауважал Русскую редакцию Microsoft после прочтения этой фразы в Совершенном коде Макконела.
Жаль имя переводчика не указали)

#book_review
😁7🔥1
Продолжение по Совершенному коду Макконела.

Надо сказать, что хорош конечно же не только переводчик, но в первую очередь сам автор.
Цитата:
Убедитесь, что всем известна цена изменения требований
Думая о новой функции, клиенты приходят в возбуждение.
Кровь у них разжижается, переполняет продолговатый мозг, и они впадают в эйфорию, забывая обо всех собраниях, посвященных обсуждению требований... и всех документах.
Угомонить таких одурманенных новыми функциями людей проще всего заявив:
«Ого, это действительно прекрасная идея!
Но ее нет в документе требований, поэтому я должен пересмотреть график работы и смету, чтобы вы могли решить, хотите ли вы реализовать это прямо сейчас или позднее».
Слова «график» и «смета» отрезвляют куда лучше, чем кофе и холодный душ, и многие требования быстро превращаются в пожелания.


P.S. заметки по книге еще будут)

#book_review
😁6
AI и Совершенный код - видишь связь?)

А она есть)
Одна из важных вещей, которую "с порога" подсвечивает Макконнелл (да, оказывается двойных согласных там целых три) - собственно программирование делится на несколько этапов: детальное проектирование, кодирование и отладка, модульные и интеграционные тесты, интеграция на стенде.
Возможно даже отладку стоило бы выделить отдельно, т.к. часто по факту так и происходит. Но не суть.

Важно, что это все такие же полноправные этапы большого процесса разработки, как и сбор требований, проработка архитектуры, тестирование, сопровождение...
Особо интересно проектирование. Объем его может варьироваться - от размера проекта или итерации при Agile разработке, от детальности проработки архитектуры, но такой этап есть.
И важно о нем не забывать.

Так вот, если применять AI в разработке - забыть о проектировании становится сложнее.
Если сразу попросить агента сделать что-то - результат будет каким-то)
Даже простейшая задачка типа: "обнови Gradle wrapper" - может привести к непредсказуемому результату.
Например, агент попытается вытянуть Gradle с родного сайта, хотя это может быть запрещено политикой компании (ака кровавый enterprise).
Или обновить до такой версии, которая потребует обновления Java.
Да и заодно и обновить код под новую версию Java)
Не даром некоторые AI агенты в IDE имеют два режима - Plan и Act.

Второй важный момент - как раз тут вырисовывается водораздел: проектирование - ведет человек, возможно совместно с AI. Кодирование и отладку вполне можно оставить AI.

И последнее - возможно AI не ускорит разработку, а сделает ее более качественной, за счет большего упора на проектирование и снятие рутины с разработчика.

#ai #book_review
👍2
На самом деле грустная новость - Stack overflow умирает.
Окей - решения существующих проблем уже проиндексированы различными LLM, и ответы достаточно точные.

А что делать с новыми?

#ai #troubleshooting
Forwarded from /g/'s Tech Memes
RIP

StackOverflow provided data to LLMs, LLMs replaced StackOverflow, and now no new Q&A hub exists to provide fresh data
😭2
И снова к Совершенному коду)

Там есть раздел про выбор языка.

Интересный аспект: язык влияет на мышление, и, следовательно, на процесс проектирования. Точнее на его уровень - более высокоуровневое или низкоуровневое. Нужно ли думать про удаление мусора, закрытие ресурсов, безопасностью работы с памятью ...

И в итоге язык влияет на скорость разработки, причем несколькими путями:
1) на незнакомом языке происходит замедление разработки до 30%
2) в разных языках объем полезной работы, которую в среднем производит одна строка кода, отличается. Это не только и не столько про скорость написания кода, но и про скорость чтения и понимания. Данный показатель как раз иллюстрирует табличка из поста.

Из таблицы видно, что Java никогда не была лидером по выразительности. Но надо отметить - в последние лет 10 работа над этим ведется.

Kotlin я думаю даже выше 6-ки будет.

#lang #book_review
Немного разбавлю серию про Совершенный код, но обязательно к ней вернусь)

У меня было много постов про собеседования - и по типовым вопросам, и по ошибкам, и по разным этапам (live coding, алгоритмы). Можно найти по тэгу #interview.
Появилась мысль оценить важность разных этапов интервью разработчика. IMHO конечно же)

1) code review - как по мне самый полезный этап, т.к. разработчик чаще всего приходит в существующую команду с каким-то кодом, и с этим кодом ему придется работать. Brownfield другими словами.
Этап показывает и навыки чтения кода, и практическое применение теоретических знаний при исправлении ошибок, и способность кандидата рассуждать, уверенность в своих знаниях объясняя ошибку и способ ее исправления.

2) разбор проблем\инцидентов из практики нанимающей команды. Полезно, т.к. позволяет понять понять навыка кандидата по решению проблем и "примерить" опыт кандидата на команду. А возможно - получить "инсайты" по улучшению архитектуры\кода)
Разработка - это не только лишь код, проблемы часто съедают больше времени, чем собственно работа с кодом.

3) live coding не (!) алгоритмических задач. Ну или простых алгоритмических. Позволяет понять, как кандидат подходит к решению задач, соотношение проектирование vs кодирование, и конечно как пишет код.
Не забыл он еще с AI агентом или тимлидством, как это делать?)

4) теория. Хотя многие ругают, я считаю полезной, как показатель кругозора и\или опыта. Lazy Load, индексы, как работает GC, Atomic, как работает Spring (а это важно, есть компании его запрещающие на основании того, что никто не знает до конца, как он работает).
Тут важно докручивать вопросы, чтобы этап не превратился в проверку памяти кандидата. Не так важно, сталкивался кандидат сам с проблемой или посмотрел ролик Борисова. Важно понял ли)

5) system design - с уровня Senior обязательно, но есть нюанс. Главное противоречие этого этапа - необходимость за условный час спроектировать систему. Т.е. сделать за час то, что у обычного архитектора занимает дни, возможно неделю.
Но польза конечно же есть: как кандидат задает ли кандидат вопросы, правильные ли они - показывает способность работы с бизнесом. Все ли аспекты архитектуры затронул, как рассуждает - навыки архитектуры и проектирования.
Главное не требовать спроектировать 100% системы за час) Тогда это превратится в проверку натасканности на задачу, как часто происходит алгоритмической секцией. Или с заучиванием теории.
Второе важное замечание - практическая применимость. Если собес на архитектора - окей, но даже архитектор не проектирует систему целиком по методикам system design.
Но что важно: да, эталонного сеанса system design я в реальной работе не встречал. При этом все его части сами по себе полезны для разработчика уровня Senior+

6) алгоритмическая секция - по сути это такая "олимпиада 2.0". Или тест на IQ 120+. Если пытаемся сделать команду спецназовцев от разработки - да, иначе стоит подумать над необходимостью) Главная проблема секции - на практике алгоритмы пишут единицы процентов разработчиков.

7) знакомство с ИТ лидом и\или командой - это софт-скилы, тоже важно, один в поле не воин.

#interview
👍1
И снова минутка цитат, подтверждающая мысль, что Стив (Макконнелл) умеет жечь глаголом сердца людей:

Наследование — мощный и... довольно опасный инструмент. В некотором смысле наследование похоже на цепную пилу: при соблюдении мер предосторожности оно может быть невероятно полезным, но при неумелом обращении последствия могут оказаться очень и очень серьезными.

Если наследование — цепная пила, то множественное наследование — это старинная цепная пила с барахлящим мотором, не имеющая предохранителей и не поддерживающая автоматического отключения. Иногда такой инструмент может пригодиться, но большую часть времени его лучше хранить в гараже под замком.


P.S. Справедливости ради отдельно обсуждается кейс mixin - классов, не являющихся самостоятельной сущностью, а лишь содержащих какой-то общеупотребительный функционал. Пример: Comparator. То, что в Java реализуется как интерфейс с методами по умолчанию. Этот вариант - ок, но здесь множественное наследование лишь средство подмешать данный функционал в класс

#book_review
Небольшое дополнение по принципу Liskov к https://t.me/javaKotlinDevOps/182

Краткое содержание предыдущей серии - основной способ нарушить это принцип в Java - сломать семантический контракт метода.

А еще нарушение этого принципа может подсветить плохую абстракцию, выбранную для класса.
Пример: кто-то решил сделать один базовый класс для вклада и кредита. В этом случае метод monthlyPayment() покажет, что это была плохая идея. Т.к. в вызывающем классе нам в зависимости от конкретного потомка - вклада или кредита - придется брать знак минус или плюс для вычислений. Что нарушает принцип Liskov.

P.S. Это тоже Совершенный код)

#solid #book_review
Нужно ли читать чужой код?
Я не про код-ревью, а про процесс разработки.

С одной стороны я всегда топлю за то, что если есть проблемы с внешней библиотекой - не понятно, почему метод возвращает такой результат или ошибку - залезь в ее код, и посмотри.
Но Стив Макконнелл (да, снова Совершенный код) подсвечивает один интересный момент - разницу между синтаксической и семантической инкапсуляцией внутренностей класса.
С синтаксической все просто - объявил по максимуму все private и профит.
А вот семантическая, а точнее ее нарушение - это наши догадки насчет внутреннего устройства чужого класса, влияющие на наш код.
А догадки эти обычно возникают после чтения кода...
Тут еще хорошая аналогия с работой разработчика и тестировщика. Для тестировщика код - это черный ящик. А для разработчика - нет. Или все же да?)

Я для себя решил так. Если найдено неочевидное\неправильное поведение внешней библиотеки, ее автор доступен и готов к сотрудничеству - стоит по советам Стива зайти к нему и попросить поправить.
А если хотя бы одно из этих условий не выполняется - можно и нужно залезть в код. И возможно даже завязаться на его внутренние детали реализации. Да, да, я про костыль.
Но с обязательными условиями:
1) proxy слой
2) с подробным комментарием что делается и почему.
И с заведением техдолга если все же есть возможность поправить эту проблему прямым образом.

#book_review #code
👍1💯1
assert в боевом коде?

На всякий случай напомню https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html

Пример:

Connection conn = getConnection();
assert conn != null;


Важной особенностью assert-ов является тот факт, что по умолчанию проверки, выполняемые в assert, выключены.
Для включения нужно передать опцию -ea (-enableassertions) при запуске, просто или с указанием пакета.
И как раз этот факт является одним из двух гвоздей, убивающих данную фичу.
Второй гвоздь - позиционирование assert-ов примерно такое же, как и у отладочных логов.
Это я читаю как в Совершенном коде (да, он спонсор данного поста))), так и в статье выше обсуждается как бы их удалить из кода.

Теперь на отойдем на шаг назад.
Все ошибки во входящих данных можно разделить на две категории - ожидаемые и нет.
Это деление не дискретное, а непрерывное, но в любом случае приводит к вопросу - как проверять данные на неожиданные ошибки? Нужно ли это делать вообще?
С ожидаемыми все понятно - пишем проверку, if и далее возврат кода ошибки\exception\запись в лог.
А неожиданные - что с ними делать?
Самый яркий пример - проблема nullability в Java. Объекты у нас везде, тогда в теории почти в любом методе нужна проверка на null.
Или не нужна, т.к. это сильно увеличивает объем кода и ухудшает читаемость.

Тут как раз предлагается использовать assert - для ошибок, которых при нормальной работе программы быть не должно.
Почему мне это не нравится.
Как раз по двум причинам выше - мы решили проверить данные и вроде закрылись assert-ом.
А потом кто-то убрал -ea в ПРОМе. И вообще говоря такой путь часто рекомендуют - разработка с assert, ПРОМ - без.
Или кто-то удалил assert посчитав его отладочным. Проект то живет долго, люди меняются.

Решением проблемы является созданием слоя валидации (или расположение валидации на сервисном слое). До того, как данные прошли этот слой считаем, что там может быть что угодно.
После - минимум проверок.
Да, часть валидации происходит в API (маппинг API в объекты), но не вся и не всегда только API является поставщиком данных.

Еще предлагаемый кейс для assert - pre-condition, post-condition, инварианты - т.е. реализация контрактов для методов и классов в коде.
Причем часто основная идея здесь не проверка условий, а именно документирование контракта с помощью assert.
И тут снова вступает в силу ненулевая вероятность удаления assert-ов, т.к. в боевом коде они выглядят чужеродно.
Я тут за JavaDoc, т.к. по JavaDoc можно построить отдельный jar с документацией, который может использовать IDE.
С контрактами есть отдельный важный момент: контракт - это часть класса, выносить его в слой валидации плохо.
Но в таком случае лучше его реализовать или обычным кодом или JavaDoc.

Итого остается редкий кейс разработки кусочка монолита, когда нет уверенности, что контракты соблюдаются. Условно разработка чего-то уровня JDK.

Используете ли assert в боевом коде? Для чего?

#book_review #contracts #validations
"Цените легкость чтения кода выше, чем удобство его написания"

Я постоянно топлю за то, что код должен легко читаться.
И цитата из сами понимаете какой книжки как нельзя лучше иллюстрирует данный принцип.

Т.к. если не задумываться об удобстве чтения кода, то мы получаем:
1) дублирование - проще же скопировать, чем выделить новую абстракцию
2) вечный техдолг из-за не проведенного вовремя рефакторинга
3) божественные классы: пусть новый метод Y не вписывается в абстракцию класса Х, но чтобы это заметить - надо выйти за рамки текущей задачи
4) огромные иерархии классов, длинные методы - проще добавить код по аналогии
5) слабое покрытие тестами - код работает, мне он на данный момент абсолютно понятен. Зачем тесты писать - ради тестов?
6) методы и классы с неактуальными названиями
7) все методы в классе являются public - они же вызываются из public метода, да и вдруг кому-то пригодятся
8) спагетти-код
...
и получаем легаси в итоге.

#book_review
Рубрика "Загадки от Стива".

Если объект класса создается в коде всего один раз - стоит заменить такой класс объектом.
О чем речь?

Пример:
у нас есть разные виды карт: Мир, Мир Supreme, Visa Classic, Visa Digital..
Можно завести под каждый тип отдельный подкласс, но в большинстве случае достаточно параметризовать все отличия разных типов карт и просто создавать объекты одного класса.


#book_review #oop
Ещё один элемент AI-пазла.

Сделаю паузу по книжке.

У нас есть стандарт для получения данных из внешних источников (MCP), потенциальный протокол для запросов в LLM (TOON, хотя тут борьба ещё впереди), паттерн локальной БД (RAG), стандарт памяти для контекста (GAM), навыков агентов (Agent Skills), реестр opensource-моделей (HuggingFace).

Если смотреть на агентов и их локальные возможности, в частности для разработки и смежных активностей, то тут можно найти место для стандарта. Что делает такой агент: читает файлы (код), создаёт и меняет их, запускает команды в консоли и анализирует вывод, возможно запускает браузер. Также — запуск скилов и вызов MCP. Плюс мультиагентность — отдельно агенты для планирования, правки кода, возможно тестирования...

Вот всё это реализует OpenCode https://opencode.ai/. Плюс работа с сессиями, аутентификация у разных провайдеров LLM, выбор модели и даже sharing сессии. Обещают, что, кроме режима sharing, на сервер ничего не шлют.На свой сервер, на сервер LLM конечно же шлют.
Но есть поддержка Ollama для запуска моделей локально. Ещё интересно, что инструмент поддерживает три типа взаимодействия: консоль, web и TUI. TUI — Terminal User Interface. И это реальный консольный UI. Вспоминается MS DOS и  Norton Commander. Попробовал — мне понравилось. Удобно.

Минусы:
- для установки и шаринга сессии нужен VPN;
- кроме основной модели есть ещё так называемая small model, в качестве которой у меня OpenCode сам выбрал платную модель OpenRouter (а основную модель я выбрал там же бесплатную) и втихаря сожрал 5 центов за час.

А вообще классная штука, в первую очередь для разработки, но вижу пользу и для анализа данных, тестирования...

P. S. Вот только в стане фреймворков разработки агентов всё ещё разброд и шатание, хотя для Python выделяется пара LangChain/LangGraph.

#ai #llm
Еще одна загадка "от Стива":

Цитата:
"В одном исследовании 450 методов было обнаружено, что дефекты отсутствовали у 50% методов, обладающих высокой связностью,
и только в 18% методов с низкой связностью (Card, Church, and Agresti, 1986).
Другое исследование методов (это просто совпадение, хотя и весьма необычное) показало,
что в сравнении с методами, имеющими самое низкое отношение «сопряжение/связность» (coupling-to-cohesion),
методы с максимальным отношением «сопряжение/связность» содержали в 7 раз больше ошибок,
а исправление этих методов было в 20 раз более дорогим (Selby and Basili, 1991)."

Речь про то, что в методах с высокой связностью кода - single responsibility по сути - меньше ошибок.
Почему?

Мой ответ:
низкая связность может иметь одну из двух причин:
1) плохое проектирование = больше ошибок
2) плохо проведенный\не проведенный вовремя рефакторинг, когда в метод добавили новый функционал, "гвоздями прибив" его к существующему без нормального тестирования
Ну и банально - больше функционала в методе = больше метод = больше вероятность ошибки. Но тут зависимость не линейная, при нормальном проектировании.


#book_review #quest
🔥1
И еще один вопрос от Стива, попроще:
"Используйте утвердительные имена булевых переменных"
Почему?

Ответ:
чтобы избежать вот такого кода:

if ((!notFound) && ... )

затрудняющего чтение.

А кстати в Python все еще хуже:

if (not notFound) and ...:



#book_review
Долговременное хранение контекста AI агента - можно ли попроще?

Я уже писал про GAB - систему хранения контекста диалога https://t.me/javaKotlinDevOps/495.
Напомню тем кто забыл - там два компонента Memorizer (фоновое сохранение данных) и Researcher (компиляция ответа под конкретный запрос пользователя) и два вида памяти: весь диалог и короткие сводки (кэш).
И в целом GAB - это научная работа без практического внедрения.
Когда появится реализация - это будет отдельный сервис а-ля RAG.

Так вот - как можно сделать примерно тоже самое проще? Например, в контексте агента для разработки

Краткий ответ - можно. Подробный - давайте напишем промт для агента с просьбой собрать, сохранить и поддерживать актуальность информации по проекту внутри проекта в текстовых файлах.
Пусть это будет Markdown как некий стандарт, сложившийся не только в AI.
Т.е. процесс выглядит так:
1) инициализируем память собрав всю информацию по проекту и сохранив ее
2) при старте любого диалога подтягиваем информацию
2) после успешного выполнения любых действий над проектом обновляем\чистим информацию в долговременной памяти

Как говорится - ближе к делу.
Встречаем Cline Memory Bank https://docs.cline.bot/prompting/cline-memory-bank

На что стоит обратить внимание:
1) лично я когда говорил о долговременной памяти - я подразумевал контекст сессии.
На самом деле не обязательно им ограничиваться.
В случае разработки - сессия = таска, а контекст по проекту имеет смысл хранить постоянно.
Т.е по сути он разделяется на постоянную часть и текучку.

На примере Cline Memory Bank постоянная часть:
`projectbrief.md`
- Foundation document that shapes all other files
- Created at project start if it doesn't exist
- Defines core requirements and goals
- Source of truth for project scope

`productContext.md`
- Why this project exists
- Problems it solves
- How it should work
- User experience goals

`systemPatterns.md`
- System architecture
- Key technical decisions
- Design patterns in use
- Component relationships
- Critical implementation paths

`techContext.md`
- Technologies used
- Development setup
- Technical constraints
- Dependencies
- Tool usage patterns


Текучка:

`activeContext.md`
- Current work focus
- Recent changes
- Next steps
- Active decisions and considerations
- Important patterns and preferences
- Learnings and project insights

`progress.md`


2) Является ли такая структура памяти оптимальной? Хз, но я бы с нее начал.

3) что с поддержкой данной штуки в других агентах? без проблем, т.к. по сути memory bank = промт + способность агента читать и писать в файл.
Пример для Cursor https://www.youtube.com/watch?v=azXNHRtzd5s
Roo Code решили обвернуть это в MCP сервер https://skywork.ai/skypage/en/roo-code-memory-bank-ai-agent/1980851096638783488
Почему бы и нет, поможет при разработке других агентов, причем это могут быть агенты с разным назначением.

4) в Memory Bank хранится информация по архитектуре\структуре проекта, его стек, команды запуска, code style и прочие правила работы.
И если они уже есть в проекте - можно просто их переиспользовать, стандартизировав место хранения.

5) что из этого хранить в git? постоянную часть точно, текучку - наверное нет, т.к. у каждого она своя, но надо смотреть

В общем - рекомендую, сам буду настраивать на всех проектах.

P.S. если сравнить два подхода GAB vs Memory Bank - это как JIT и AoT компиляция

#ai #ai_agents #mcp
Что не докрутили в record-ах?

Для начала кратко о том, что докрутили:
1) компактное объявление, типовые методы из коробки
2) иммутабельность
3) минимально необходимая расширяемость - дополнительные конструкторы, интерфейсы, обычные методы, статические поля, методы и внутренние классы.

Получаем аналог data class в Kotlin. Или структур из древних языков типа C.

Но с небольшим отличием - не хватает метода копирования "из коробки".

Почему так сделали? Есть же Cloneable интерфейс. И его даже можно добавить в record руками.

Думаю, причина в иммутабельности record и скажем так скомпрометированности clone().

Для иммутабельной сущности нет смысла в полной копии - можно использовать текущий объект.

С clone() основная проблема в том, что "из коробки" он делает поверхностную копию, но при переопределении может дать полную. И вообще полную копию автоматически сделать сложно. А это приводит к путанице - метод один, а поведение может отличаться.

В итоге приходим к тому, что иметь возможность быстро сделать поверхностную копию записи с изменением пары полей было бы неплохо. И такой JEP есть https://openjdk.org/jeps/468
Надеюсь внедрят.

#java #иммутабельность