<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">40Ants</title><id>https://40ants.com/</id><updated>2026-06-08T14:10:03.476847Z</updated><link>https://40ants.com/</link><subtitle type="text">Just an example of the static file generated by StatiCL.</subtitle><entry><title type="text">Как работает AI ассистент</title><id>https://40ants.com/ru/posts/kak-rabotaet-ai-assi-73/</id><updated>2026-06-08T14:10:03.413470Z</updated><link>https://40ants.com/ru/posts/kak-rabotaet-ai-assi-73/</link><summary type="text">&lt;p&gt;В прошлом посте я писал о том, что хочу в качестве эксперимента сделать визуализацию работы своего кодового ассистента &lt;a href=&quot;https://github.com/codabrus/codabrus&quot;&gt;Codabrus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;И вот настали долгожданные выходные, и я объединил код фронта с бэком. Получилось как на демке.&lt;/p&gt;

&lt;p&gt;Сообщения от пользователя отображаются синенькими блоками, ответы LLM - зелеными, а вызовы тулов - оранжевым. На блоки можно кликать чтобы видеть больше информации. Если блоки вызова тулов размещаются друг под другом - значит они выполняются параллельно. Использование акторной системы позволяет легко параллелить выполнение любой логики и у меня за выполнение каждого тула отвечает отдельный актор.&lt;/p&gt;

&lt;p&gt;Тул у агента пока один - вызов bash команды. Для экспериментов этого достаточно, но для реальной работы надо будет добавить редактирование и прочее. А так же хочу в интерфейс добавить отдельное окно со стримингом размышлений агента - чтобы было видно чем он занят прямо сейчас.&lt;/p&gt;
</summary><content type="text">&lt;p&gt;В прошлом посте я писал о том, что хочу в качестве эксперимента сделать визуализацию работы своего кодового ассистента &lt;a href=&quot;https://github.com/codabrus/codabrus&quot;&gt;Codabrus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;И вот настали долгожданные выходные, и я объединил код фронта с бэком. Получилось как на демке.&lt;/p&gt;

&lt;p&gt;Сообщения от пользователя отображаются синенькими блоками, ответы LLM - зелеными, а вызовы тулов - оранжевым. На блоки можно кликать чтобы видеть больше информации. Если блоки вызова тулов размещаются друг под другом - значит они выполняются параллельно. Использование акторной системы позволяет легко параллелить выполнение любой логики и у меня за выполнение каждого тула отвечает отдельный актор.&lt;/p&gt;

&lt;p&gt;Тул у агента пока один - вызов bash команды. Для экспериментов этого достаточно, но для реальной работы надо будет добавить редактирование и прочее. А так же хочу в интерфейс добавить отдельное окно со стримингом размышлений агента - чтобы было видно чем он занят прямо сейчас.&lt;/p&gt;
</content></entry><entry><title type="text">Собираюсь использовать в Codabrus визуализацию работы AI ассистента</title><id>https://40ants.com/ru/posts/sobirayus-ispolzova-72/</id><updated>2026-06-08T14:10:03.417135Z</updated><link>https://40ants.com/ru/posts/sobirayus-ispolzova-72/</link><summary type="text">&lt;p&gt;Хочу сделать в своем AI-ассистенте Codabrus визуализацию того, как работает AI-ассистент. Традиционные кодовые ассистенты показывают интерфейс в виде чата. Я же хочу сделать некую диаграмму, которая каждое сообщение от ассистента и от пользователя будет показывать в виде отдельного блока. Вызовы тулов будут ответвлениями, а также, наверное, будет прикольно подобным же образом визуализировать запуски сабагентов.&lt;/p&gt;

&lt;p&gt;Так можно будет проанализировать, насколько много работы сделал кодовый ассистент, что происходило в процессе - всё это будет более наглядно.&lt;/p&gt;

&lt;p&gt;Пока что в виде заглушки сделал такой простенькую штуку - подключил JavaScript библиотеку &lt;a href=&quot;https://github.com/antvis/x6&quot;&gt;X6&lt;/a&gt; от Alibaba для отрисовки диаграмм. Плюс подключил туда &lt;a href=&quot;https://github.com/40ants/clack-sse&quot;&gt;CLACK-SSE&lt;/a&gt; для того, чтобы можно было новые элементы добавлять, пуша их с сервера. Таким образом, когда что-то происходит во время работы кодового ассистента, я смогу обновлять диаграмму в веб-интерфейсе.&lt;/p&gt;

&lt;p&gt;Вот такая пока идея. Наверное, в выходные доберусь до того, чтобы связать этот интерфейс с реальным ассистентом.&lt;/p&gt;
</summary><content type="text">&lt;p&gt;Хочу сделать в своем AI-ассистенте Codabrus визуализацию того, как работает AI-ассистент. Традиционные кодовые ассистенты показывают интерфейс в виде чата. Я же хочу сделать некую диаграмму, которая каждое сообщение от ассистента и от пользователя будет показывать в виде отдельного блока. Вызовы тулов будут ответвлениями, а также, наверное, будет прикольно подобным же образом визуализировать запуски сабагентов.&lt;/p&gt;

&lt;p&gt;Так можно будет проанализировать, насколько много работы сделал кодовый ассистент, что происходило в процессе - всё это будет более наглядно.&lt;/p&gt;

&lt;p&gt;Пока что в виде заглушки сделал такой простенькую штуку - подключил JavaScript библиотеку &lt;a href=&quot;https://github.com/antvis/x6&quot;&gt;X6&lt;/a&gt; от Alibaba для отрисовки диаграмм. Плюс подключил туда &lt;a href=&quot;https://github.com/40ants/clack-sse&quot;&gt;CLACK-SSE&lt;/a&gt; для того, чтобы можно было новые элементы добавлять, пуша их с сервера. Таким образом, когда что-то происходит во время работы кодового ассистента, я смогу обновлять диаграмму в веб-интерфейсе.&lt;/p&gt;

&lt;p&gt;Вот такая пока идея. Наверное, в выходные доберусь до того, чтобы связать этот интерфейс с реальным ассистентом.&lt;/p&gt;
</content></entry><entry><title type="text">Итерация которую можно прервать</title><id>https://40ants.com/ru/posts/iteraciya-kotoruyu-mozh-71/</id><updated>2026-06-08T14:10:03.420458Z</updated><link>https://40ants.com/ru/posts/iteraciya-kotoruyu-mozh-71/</link><summary type="text">&lt;p&gt;&lt;video src=&quot;images/71.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;Итерация которую можно прервать. С акторами не всё так просто.&lt;/p&gt;

&lt;p&gt;Вот вам небольшая демка того, как в системе акторов можно реализовать итерацию таким образом, чтобы её можно было безопасно прервать. Я собираюсь использовать этот подход для того, чтобы организовать работу с код-ассистентом и тулами, которые он запускает. Это нужно сделать так, чтобы код-ассистента можно было прервать в любой момент и сделать это безопасно.&lt;/p&gt;

&lt;p&gt;В этом демо используется фреймворк Sento, реализующий актеры для Common Lisp.&lt;/p&gt;

&lt;p&gt;Вот полный код примера:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
(defun make-interruptable-actor-loop-example ()
  (ac:actor-of *sys*
               :destroy (lambda (&amp;amp;rest args)
                          ;; По сообщению :stop актор будет полностью
                          ;; остановлен и его нельзя будет запустить ещё раз
                          (log:info &amp;quot;Destroy called with ARGS = ~A&amp;quot; args))
               :receive (let ((stopped nil))
                          (lambda (message)
                            (log:info &amp;quot;Processing&amp;quot; message)
                            (case message
                              ;; Но с помощью :break итерацию можно приостановить,
                              ;; а потом продолжить заново с помощью :run.
                              (:break
                                 (log:info &amp;quot;Stopping&amp;quot;)
                                 (setf stopped t))
                              (:run
                                 (log:info &amp;quot;Running&amp;quot;)
                                 (setf stopped nil)
                                 (act:tell act:*self* :next-iteration))
                              (t
                                 (unless stopped
                                   (log:info &amp;quot;Sleeping&amp;quot;)
                                   (sleep 3)
                                   (log:info &amp;quot;Going to next iteration&amp;quot;)
                                   (act:tell act:*self* :next-iteration))))))))
&lt;/code&gt;&lt;/pre&gt;
</summary><content type="text">&lt;p&gt;&lt;video src=&quot;images/71.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;Итерация которую можно прервать. С акторами не всё так просто.&lt;/p&gt;

&lt;p&gt;Вот вам небольшая демка того, как в системе акторов можно реализовать итерацию таким образом, чтобы её можно было безопасно прервать. Я собираюсь использовать этот подход для того, чтобы организовать работу с код-ассистентом и тулами, которые он запускает. Это нужно сделать так, чтобы код-ассистента можно было прервать в любой момент и сделать это безопасно.&lt;/p&gt;

&lt;p&gt;В этом демо используется фреймворк Sento, реализующий актеры для Common Lisp.&lt;/p&gt;

&lt;p&gt;Вот полный код примера:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
(defun make-interruptable-actor-loop-example ()
  (ac:actor-of *sys*
               :destroy (lambda (&amp;amp;rest args)
                          ;; По сообщению :stop актор будет полностью
                          ;; остановлен и его нельзя будет запустить ещё раз
                          (log:info &amp;quot;Destroy called with ARGS = ~A&amp;quot; args))
               :receive (let ((stopped nil))
                          (lambda (message)
                            (log:info &amp;quot;Processing&amp;quot; message)
                            (case message
                              ;; Но с помощью :break итерацию можно приостановить,
                              ;; а потом продолжить заново с помощью :run.
                              (:break
                                 (log:info &amp;quot;Stopping&amp;quot;)
                                 (setf stopped t))
                              (:run
                                 (log:info &amp;quot;Running&amp;quot;)
                                 (setf stopped nil)
                                 (act:tell act:*self* :next-iteration))
                              (t
                                 (unless stopped
                                   (log:info &amp;quot;Sleeping&amp;quot;)
                                   (sleep 3)
                                   (log:info &amp;quot;Going to next iteration&amp;quot;)
                                   (act:tell act:*self* :next-iteration))))))))
&lt;/code&gt;&lt;/pre&gt;
</content></entry><entry><title type="text">Итерация которую можно прервать</title><id>https://40ants.com/ru/posts/iteraciya-kotoruyu-mozh-70/</id><updated>2026-06-08T14:10:03.423501Z</updated><link>https://40ants.com/ru/posts/iteraciya-kotoruyu-mozh-70/</link><summary type="text">&lt;p&gt;Итерация которую можно прервать. С акторами не всё так просто.&lt;/p&gt;

&lt;p&gt;Вот вам небольшая демка того, как в системе акторов можно реализовать итерацию таким образом, чтобы её можно было безопасно прервать. Я собираюсь использовать этот подход для того, чтобы организовать работу с код-ассистентом и тулами, которые он запускает. Это нужно сделать так, чтобы код-ассистента можно было прервать в любой момент и сделать это безопасно.&lt;/p&gt;

&lt;p&gt;В этом демо используется фреймворк Sento, реализующий актеры для Common Lisp.&lt;/p&gt;

&lt;p&gt;Вот полный код примера:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
(defun make-interruptable-actor-loop-example ()
  (ac:actor-of *sys*
               :destroy (lambda (&amp;amp;rest args)
                          ;; По сообщению :stop актор будет полностью
                          ;; остановлен и его нельзя будет запустить ещё раз
                          (log:info &amp;quot;Destroy called with ARGS = ~A&amp;quot; args))
               :receive (let ((stopped nil))
                          (lambda (message)
                            (log:info &amp;quot;Processing&amp;quot; message)
                            (case message
                              ;; Но с помощью :break итерацию можно приостановить,
                              ;; а потом продолжить заново с помощью :run.
                              (:break
                                 (log:info &amp;quot;Stopping&amp;quot;)
                                 (setf stopped t))
                              (:run
                                 (log:info &amp;quot;Running&amp;quot;)
                                 (setf stopped nil)
                                 (act:tell act:*self* :next-iteration))
                              (t
                                 (unless stopped
                                   (log:info &amp;quot;Sleeping&amp;quot;)
                                   (sleep 3)
                                   (log:info &amp;quot;Going to next iteration&amp;quot;)
                                   (act:tell act:*self* :next-iteration))))))))
&lt;/code&gt;&lt;/pre&gt;
</summary><content type="text">&lt;p&gt;Итерация которую можно прервать. С акторами не всё так просто.&lt;/p&gt;

&lt;p&gt;Вот вам небольшая демка того, как в системе акторов можно реализовать итерацию таким образом, чтобы её можно было безопасно прервать. Я собираюсь использовать этот подход для того, чтобы организовать работу с код-ассистентом и тулами, которые он запускает. Это нужно сделать так, чтобы код-ассистента можно было прервать в любой момент и сделать это безопасно.&lt;/p&gt;

&lt;p&gt;В этом демо используется фреймворк Sento, реализующий актеры для Common Lisp.&lt;/p&gt;

&lt;p&gt;Вот полный код примера:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
(defun make-interruptable-actor-loop-example ()
  (ac:actor-of *sys*
               :destroy (lambda (&amp;amp;rest args)
                          ;; По сообщению :stop актор будет полностью
                          ;; остановлен и его нельзя будет запустить ещё раз
                          (log:info &amp;quot;Destroy called with ARGS = ~A&amp;quot; args))
               :receive (let ((stopped nil))
                          (lambda (message)
                            (log:info &amp;quot;Processing&amp;quot; message)
                            (case message
                              ;; Но с помощью :break итерацию можно приостановить,
                              ;; а потом продолжить заново с помощью :run.
                              (:break
                                 (log:info &amp;quot;Stopping&amp;quot;)
                                 (setf stopped t))
                              (:run
                                 (log:info &amp;quot;Running&amp;quot;)
                                 (setf stopped nil)
                                 (act:tell act:*self* :next-iteration))
                              (t
                                 (unless stopped
                                   (log:info &amp;quot;Sleeping&amp;quot;)
                                   (sleep 3)
                                   (log:info &amp;quot;Going to next iteration&amp;quot;)
                                   (act:tell act:*self* :next-iteration))))))))
&lt;/code&gt;&lt;/pre&gt;
</content></entry><entry><title type="text">Зачем мне CLOS объекты как состояние акторов в Sento?</title><id>https://40ants.com/ru/posts/zachem-mne-clos-obuek-69/</id><updated>2026-06-08T14:10:03.425098Z</updated><link>https://40ants.com/ru/posts/zachem-mne-clos-obuek-69/</link><summary type="text">&lt;p&gt;&lt;video src=&quot;images/69.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;На этой небольшой демке хочу показать, как я собираюсь использовать CLOS-объекты как состояние акторов в моем кодовом ассистенте Кодабрус. Для реализации акторов я использую библиотеку Sento, а CLOS-объекты в качестве состояния мне нужны для того, чтобы это состояние можно было сериализовать на диск и потом продолжить работу системы с того же места, на котором остановился пользователь.&lt;/p&gt;
</summary><content type="text">&lt;p&gt;&lt;video src=&quot;images/69.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;На этой небольшой демке хочу показать, как я собираюсь использовать CLOS-объекты как состояние акторов в моем кодовом ассистенте Кодабрус. Для реализации акторов я использую библиотеку Sento, а CLOS-объекты в качестве состояния мне нужны для того, чтобы это состояние можно было сериализовать на диск и потом продолжить работу системы с того же места, на котором остановился пользователь.&lt;/p&gt;
</content></entry><entry><title type="text">Демка нового поиска на Ultralisp</title><id>https://40ants.com/ru/posts/demka-novogo-poiska-68/</id><updated>2026-06-08T14:10:03.429023Z</updated><link>https://40ants.com/ru/posts/demka-novogo-poiska-68/</link><summary type="text">&lt;p&gt;&lt;video src=&quot;images/68.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;Демка нового поиска на Ultralisp.org&lt;/p&gt;

&lt;p&gt;Не так давно я обновил Ultralisp и сделал там поддержку фреймворка reblocks-ui2, а теперь настало время очередных изменений. Вчера я выкатил обновленный поиск. Если раньше поиск по Ultralisp находил только символы и искал он по докстрингам этих символов, то теперь поиск работает также по ASDF системам и по проектам.&lt;/p&gt;

&lt;p&gt;То есть поиск идет по трем сущностям:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;проектам;&lt;/li&gt;
&lt;li&gt;ASDF системам;&lt;/li&gt;
&lt;li&gt;символам.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;При этом проект включает в себя ASDF системы, а каждая ASDF система включает в себя набор символов. Пакеты я индексировать не стал, потому что для них почему-то редко пишут докстринги.&lt;/p&gt;

&lt;p&gt;Примечательно, что всё это реализовано нейронкой GLM 5.1 под моим чутким руководством! Надеюсь в будущем добраться и до других улучшений, которые давно планировал - нейронки реально разгружают от рутины написания большей части кода, оставляя мясным хозяевам самое интересное - дебаг неправильно проставленных скобочек! :))))&lt;/p&gt;
</summary><content type="text">&lt;p&gt;&lt;video src=&quot;images/68.mp4&quot; controls=&quot;&quot; style=&quot;width: 100%&quot;&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;Демка нового поиска на Ultralisp.org&lt;/p&gt;

&lt;p&gt;Не так давно я обновил Ultralisp и сделал там поддержку фреймворка reblocks-ui2, а теперь настало время очередных изменений. Вчера я выкатил обновленный поиск. Если раньше поиск по Ultralisp находил только символы и искал он по докстрингам этих символов, то теперь поиск работает также по ASDF системам и по проектам.&lt;/p&gt;

&lt;p&gt;То есть поиск идет по трем сущностям:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;проектам;&lt;/li&gt;
&lt;li&gt;ASDF системам;&lt;/li&gt;
&lt;li&gt;символам.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;При этом проект включает в себя ASDF системы, а каждая ASDF система включает в себя набор символов. Пакеты я индексировать не стал, потому что для них почему-то редко пишут докстринги.&lt;/p&gt;

&lt;p&gt;Примечательно, что всё это реализовано нейронкой GLM 5.1 под моим чутким руководством! Надеюсь в будущем добраться и до других улучшений, которые давно планировал - нейронки реально разгружают от рутины написания большей части кода, оставляя мясным хозяевам самое интересное - дебаг неправильно проставленных скобочек! :))))&lt;/p&gt;
</content></entry><entry><title type="text">Циклическая зависимость в mgl-pax</title><id>https://40ants.com/ru/posts/ciklicheskaya-zavisimo-67/</id><updated>2026-06-08T14:10:03.449713Z</updated><link>https://40ants.com/ru/posts/ciklicheskaya-zavisimo-67/</link><summary type="text">&lt;p&gt;&lt;img src=&quot;https://40ants.com/ru/posts/images/67.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;В эти выходные решал проблемку с отвалившейся named-readtables на UltraLisp.&lt;/p&gt;

&lt;p&gt;Named-readtables библиотека довольно много где используется, и то что она стала недоступна - большая проблема.&lt;/p&gt;

&lt;p&gt;Дебажить пришлось долго, и вот что оказалось.&lt;/p&gt;

&lt;p&gt;Звёзды так сошлись, что:&lt;/p&gt;

&lt;p&gt;• Ultralisp выкидывает из диста проект при ошибках проверки очередного коммита (это стоит починить
• Gábor Melis намутил в своих либах циклическую зависимость, когда mgl-pax зависит от свежей версии dref и наоборот и попытался это решить с помощью либы autoload.
• Процесс, проверяющий проекты в Ultralisp сам по себе зависел от старой версии mgl-pax, которая была притянута как транзитивная зависимость
• Новый mgl-pax конфиликтовал со старым и не мог просто подгрузиться в образ где уже была старая версия.
• Из-за этого не мог провериться dref которому нужна новая версия mgl-pax.
• То есть, эти три либы mgl-pax, dref и autoload надо было обновлять все разом, а Ultralisp так не умеет.&lt;/p&gt;

&lt;p&gt;В итоге, чтобы обновить эту пачку либ пришлось пересобрать сам Ultralisp так, чтобы там была вкомпилирована свежая версия mgl-pax. Теперь всё заработало.&lt;/p&gt;

&lt;p&gt;Вывод - надо уменьшать количество зависимостей в бинаре, который чекает загрузку других библиотек. В идеале - до нуля!&lt;/p&gt;
</summary><content type="text">&lt;p&gt;&lt;img src=&quot;https://40ants.com/ru/posts/images/67.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;В эти выходные решал проблемку с отвалившейся named-readtables на UltraLisp.&lt;/p&gt;

&lt;p&gt;Named-readtables библиотека довольно много где используется, и то что она стала недоступна - большая проблема.&lt;/p&gt;

&lt;p&gt;Дебажить пришлось долго, и вот что оказалось.&lt;/p&gt;

&lt;p&gt;Звёзды так сошлись, что:&lt;/p&gt;

&lt;p&gt;• Ultralisp выкидывает из диста проект при ошибках проверки очередного коммита (это стоит починить
• Gábor Melis намутил в своих либах циклическую зависимость, когда mgl-pax зависит от свежей версии dref и наоборот и попытался это решить с помощью либы autoload.
• Процесс, проверяющий проекты в Ultralisp сам по себе зависел от старой версии mgl-pax, которая была притянута как транзитивная зависимость
• Новый mgl-pax конфиликтовал со старым и не мог просто подгрузиться в образ где уже была старая версия.
• Из-за этого не мог провериться dref которому нужна новая версия mgl-pax.
• То есть, эти три либы mgl-pax, dref и autoload надо было обновлять все разом, а Ultralisp так не умеет.&lt;/p&gt;

&lt;p&gt;В итоге, чтобы обновить эту пачку либ пришлось пересобрать сам Ultralisp так, чтобы там была вкомпилирована свежая версия mgl-pax. Теперь всё заработало.&lt;/p&gt;

&lt;p&gt;Вывод - надо уменьшать количество зависимостей в бинаре, который чекает загрузку других библиотек. В идеале - до нуля!&lt;/p&gt;
</content></entry><entry><title type="text">Жизненные уроки</title><id>https://40ants.com/ru/posts/zhiznennye-uroki-66/</id><updated>2026-06-08T14:10:03.460920Z</updated><link>https://40ants.com/ru/posts/zhiznennye-uroki-66/</link><summary type="text">&lt;p&gt;Последнее время я вернулся к работе над &lt;a href=&quot;https://github.com/codabrus/codabrus&quot;&gt;своим проектом кодового ассистента&lt;/a&gt;. Идея в том, чтобы сделать такого ассистента, которого можно расширять и интерактивно отлаживать в процессе его работы. Конечно, я его делаю на CommonLisp, но многие вещи делаю с помощью другого кодового ассистента - OpenCode. Мой проект, кстати, называется Codabrus. Если интересно, подписывайтесь на обновление этого проекта на GitHub, ставьте ему звездочки, шерьте с друзьями.&lt;/p&gt;

&lt;p&gt;Так вот, для разработки я сейчас использую OpenCode, и у него есть один инструмент, позволяющий сделать eval внутри работающего Lisp процесса. А в качестве модели я использую подписку на GLM 5.1. В целом, GLM неплохо справляется с разработкой на CommonLisp, лишь чуть хуже, чем Claude Sonnet, я бы сказал.&lt;/p&gt;

&lt;p&gt;Единственное, с чем у него частенько возникают проблемы, это со скобками. Тут он часто косячит и потом не может правильно выставить скобки. Ну, есть и другие проблемки, которые там, тут, здесь всплывают. Но, что удивительно, есть один трюк, который почти все эти проблемы может полечить, если его планомерно использовать.&lt;/p&gt;

&lt;p&gt;Этот трюк я подсмотрел на стриме у одного из коммон-лиспера - Николая Матюшева. Заключается трюк в том, что модель нужно научить учиться. Да, многие модели у себя в памяти как бы и так хранят какие-то знания о вашем проекте, окружении и прочем, но я предпочитаю сохранять знания явно.&lt;/p&gt;

&lt;p&gt;Как это делается? Вы просто в промпте внутри файлика AGENT.md просите модель выписывать те важные уроки, которые она получила в ходе работы над каждой сессией. И модель выписывает эти уроки в файлик &lt;a href=&quot;https://github.com/codabrus/codabrus/blob/master/lessons-learned.md#как-избежать-проблем-со-скобками-в-lisp&quot;&gt;lessons-learned.md&lt;/a&gt;. Так, например, когда у меня случилась проблема с тем, что модель никак не могла расставить скобочки в коде, я попросил ее разобраться, в чем была проблема и придумать решение на будущее так, чтобы этой проблемы больше не возникало.&lt;/p&gt;

&lt;p&gt;Модель проанализировала всю историю текущей сессии и выписала несколько важных пунктов. Таких, например, как она поняла, что если функция слишком большая и имеет большой уровень вложности, то модели сложнее правильно расставить скобки. И значит функцию надо делать короче и поменьше. Кроме того, она взяла и написала для себя кусочек кода, который позволяет ей валидировать открывающиеся и закрывающие скобки. Все это моделька сохранила в файлик lessons-learned.md. И после этого я не замечал, чтобы она зацикливалась, пытаясь правильно поставить скобки в коде.&lt;/p&gt;

&lt;p&gt;Так что, приём очень полезный. Единственное, чего я опасаюсь, это того, что этот файлик lessons-learned будет разрастаться. Кроме того, не очень понятно, что делать с шерингом этих знаний, потому что многие лайфхаки, которые модель для себя выписывает, были бы полезны и в других проектах со схожим стэком. А значит, шерить знания как-то надо. Таскать из проектов проект файлики lessons-learned.md не очень хорошо, потому что тогда будет сложно эти знания обновлять.&lt;/p&gt;

&lt;p&gt;И вот я думаю, что в своем кодовом ассистенте Codabrus я, наверное, придумаю какую-то структурную память, которая позволит шерить такие знания между проектами, над которыми работает кодовый ассистент. А может быть, даже и шерить их куда-то наружу в виде лайфхаков для других AI-ассистентов. &lt;/p&gt;
</summary><content type="text">&lt;p&gt;Последнее время я вернулся к работе над &lt;a href=&quot;https://github.com/codabrus/codabrus&quot;&gt;своим проектом кодового ассистента&lt;/a&gt;. Идея в том, чтобы сделать такого ассистента, которого можно расширять и интерактивно отлаживать в процессе его работы. Конечно, я его делаю на CommonLisp, но многие вещи делаю с помощью другого кодового ассистента - OpenCode. Мой проект, кстати, называется Codabrus. Если интересно, подписывайтесь на обновление этого проекта на GitHub, ставьте ему звездочки, шерьте с друзьями.&lt;/p&gt;

&lt;p&gt;Так вот, для разработки я сейчас использую OpenCode, и у него есть один инструмент, позволяющий сделать eval внутри работающего Lisp процесса. А в качестве модели я использую подписку на GLM 5.1. В целом, GLM неплохо справляется с разработкой на CommonLisp, лишь чуть хуже, чем Claude Sonnet, я бы сказал.&lt;/p&gt;

&lt;p&gt;Единственное, с чем у него частенько возникают проблемы, это со скобками. Тут он часто косячит и потом не может правильно выставить скобки. Ну, есть и другие проблемки, которые там, тут, здесь всплывают. Но, что удивительно, есть один трюк, который почти все эти проблемы может полечить, если его планомерно использовать.&lt;/p&gt;

&lt;p&gt;Этот трюк я подсмотрел на стриме у одного из коммон-лиспера - Николая Матюшева. Заключается трюк в том, что модель нужно научить учиться. Да, многие модели у себя в памяти как бы и так хранят какие-то знания о вашем проекте, окружении и прочем, но я предпочитаю сохранять знания явно.&lt;/p&gt;

&lt;p&gt;Как это делается? Вы просто в промпте внутри файлика AGENT.md просите модель выписывать те важные уроки, которые она получила в ходе работы над каждой сессией. И модель выписывает эти уроки в файлик &lt;a href=&quot;https://github.com/codabrus/codabrus/blob/master/lessons-learned.md#как-избежать-проблем-со-скобками-в-lisp&quot;&gt;lessons-learned.md&lt;/a&gt;. Так, например, когда у меня случилась проблема с тем, что модель никак не могла расставить скобочки в коде, я попросил ее разобраться, в чем была проблема и придумать решение на будущее так, чтобы этой проблемы больше не возникало.&lt;/p&gt;

&lt;p&gt;Модель проанализировала всю историю текущей сессии и выписала несколько важных пунктов. Таких, например, как она поняла, что если функция слишком большая и имеет большой уровень вложности, то модели сложнее правильно расставить скобки. И значит функцию надо делать короче и поменьше. Кроме того, она взяла и написала для себя кусочек кода, который позволяет ей валидировать открывающиеся и закрывающие скобки. Все это моделька сохранила в файлик lessons-learned.md. И после этого я не замечал, чтобы она зацикливалась, пытаясь правильно поставить скобки в коде.&lt;/p&gt;

&lt;p&gt;Так что, приём очень полезный. Единственное, чего я опасаюсь, это того, что этот файлик lessons-learned будет разрастаться. Кроме того, не очень понятно, что делать с шерингом этих знаний, потому что многие лайфхаки, которые модель для себя выписывает, были бы полезны и в других проектах со схожим стэком. А значит, шерить знания как-то надо. Таскать из проектов проект файлики lessons-learned.md не очень хорошо, потому что тогда будет сложно эти знания обновлять.&lt;/p&gt;

&lt;p&gt;И вот я думаю, что в своем кодовом ассистенте Codabrus я, наверное, придумаю какую-то структурную память, которая позволит шерить такие знания между проектами, над которыми работает кодовый ассистент. А может быть, даже и шерить их куда-то наружу в виде лайфхаков для других AI-ассистентов. &lt;/p&gt;
</content></entry><entry><title type="text">Некоторое время назад один из коллег опубликовал свою поделку, которая...</title><id>https://40ants.com/ru/posts/nekotoroe-vremya-naza-65/</id><updated>2026-06-08T14:10:03.468470Z</updated><link>https://40ants.com/ru/posts/nekotoroe-vremya-naza-65/</link><summary type="text">&lt;p&gt;&lt;img src=&quot;https://40ants.com/ru/posts/images/65.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Некоторое время назад один из коллег опубликовал свою поделку, которая показывает, сколько осталось квоты на использование нейросетей. Она была написана на Python с отдельной библиотекой для встраивания в тулбар на OS X. Я подумал, что это хороший проектик, чтобы попробовать переписать его на Common Lisp с помощью нейросетей.&lt;/p&gt;

&lt;p&gt;► Как нейросеть писала код&lt;/p&gt;

&lt;p&gt;У меня были исходники коллеги на Python. Я дал LLM простой запрос — переписать программу на Common Lisp, используя существующие библиотеки, найденные через &lt;code&gt;ql:system-apropos&lt;/code&gt;. В качестве ассистента использовал Claude Code + модель Opus 4.6.&lt;/p&gt;

&lt;p&gt;Нейронка написала код. В процессе она даже нашла библиотеку для работы с Objective-C, потому что для отображения пунктов меню и иконки в macOS нужно использовать фреймворк на Objective-C. Нейронка оценила библиотеку, решила, что она недостаточно хороша, отказалась от неё и написала свою обёртку над Objective-C через CFFI.&lt;/p&gt;

&lt;p&gt;► Отладка и запуск&lt;/p&gt;

&lt;p&gt;Конечно, с первого раза программа не заработала. Я сделал несколько итераций. К сожалению, такие графические программы неудобно запускать через мой MCP-сервер для разработки на Common Lisp, потому что при неправильном создании биндингов программа крэшится и роняет вместе с собой весь MCP-сервер. Пришлось запускать программу вручную и скармливать тексты ошибок ассистенту.&lt;/p&gt;

&lt;p&gt;После нескольких итераций ассистент допилил программу до состояния, когда она начала запускаться и работать достаточно стабильно. Теперь у меня есть полный аналог той программы, которую написал коллега, но на Common Lisp. Её очень удобно расширять, добавляя новый функционал прямо через REPL.&lt;/p&gt;

&lt;p&gt;► Что дальше&lt;/p&gt;

&lt;p&gt;Но интереснее другое. Раньше у меня была похожая программка для встраивания в тулбар macOS под названием Barista. Она была написана на LispWorks с его фреймворком CAPI. Там было ограничение: при распространении программы через компиляцию в LispWorks отключаются возможности компилятора, то есть нельзя подгружать динамические плагины.&lt;/p&gt;

&lt;p&gt;Теперь я могу переписать Barista так, чтобы использовался SBCL, и там не будет таких ограничений. Программа станет полностью расширяемой с помощью Lisp-скриптов.&lt;/p&gt;
</summary><content type="text">&lt;p&gt;&lt;img src=&quot;https://40ants.com/ru/posts/images/65.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Некоторое время назад один из коллег опубликовал свою поделку, которая показывает, сколько осталось квоты на использование нейросетей. Она была написана на Python с отдельной библиотекой для встраивания в тулбар на OS X. Я подумал, что это хороший проектик, чтобы попробовать переписать его на Common Lisp с помощью нейросетей.&lt;/p&gt;

&lt;p&gt;► Как нейросеть писала код&lt;/p&gt;

&lt;p&gt;У меня были исходники коллеги на Python. Я дал LLM простой запрос — переписать программу на Common Lisp, используя существующие библиотеки, найденные через &lt;code&gt;ql:system-apropos&lt;/code&gt;. В качестве ассистента использовал Claude Code + модель Opus 4.6.&lt;/p&gt;

&lt;p&gt;Нейронка написала код. В процессе она даже нашла библиотеку для работы с Objective-C, потому что для отображения пунктов меню и иконки в macOS нужно использовать фреймворк на Objective-C. Нейронка оценила библиотеку, решила, что она недостаточно хороша, отказалась от неё и написала свою обёртку над Objective-C через CFFI.&lt;/p&gt;

&lt;p&gt;► Отладка и запуск&lt;/p&gt;

&lt;p&gt;Конечно, с первого раза программа не заработала. Я сделал несколько итераций. К сожалению, такие графические программы неудобно запускать через мой MCP-сервер для разработки на Common Lisp, потому что при неправильном создании биндингов программа крэшится и роняет вместе с собой весь MCP-сервер. Пришлось запускать программу вручную и скармливать тексты ошибок ассистенту.&lt;/p&gt;

&lt;p&gt;После нескольких итераций ассистент допилил программу до состояния, когда она начала запускаться и работать достаточно стабильно. Теперь у меня есть полный аналог той программы, которую написал коллега, но на Common Lisp. Её очень удобно расширять, добавляя новый функционал прямо через REPL.&lt;/p&gt;

&lt;p&gt;► Что дальше&lt;/p&gt;

&lt;p&gt;Но интереснее другое. Раньше у меня была похожая программка для встраивания в тулбар macOS под названием Barista. Она была написана на LispWorks с его фреймворком CAPI. Там было ограничение: при распространении программы через компиляцию в LispWorks отключаются возможности компилятора, то есть нельзя подгружать динамические плагины.&lt;/p&gt;

&lt;p&gt;Теперь я могу переписать Barista так, чтобы использовался SBCL, и там не будет таких ограничений. Программа станет полностью расширяемой с помощью Lisp-скриптов.&lt;/p&gt;
</content></entry><entry><title type="text">Портируем microGPT на Common Lisp с помощью LLM</title><id>https://40ants.com/ru/posts/portiruem-microgpt-n-64/</id><updated>2026-06-08T14:10:03.476838Z</updated><link>https://40ants.com/ru/posts/portiruem-microgpt-n-64/</link><summary type="text">&lt;p&gt;Смотрите чего я навайбкодил: &lt;a href=&quot;https://github.com/40ants/microgpt&quot;&gt;https://github.com/40ants/microgpt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Это порт на Common Lisp скрипта microgpt, который недавно опубликовал Andrej Karpathy.&lt;/p&gt;

&lt;p&gt;Эта штука включает в себя код трансформера и инференс. То есть она может обучиться на каких-то входных текстах, а потом генерировать похожие тексты. Всё как у больших LLM, только буквально в одном Python-скрипте. Ну и, конечно, эта штука больше создана для обучения, а не для того, чтобы показывать хорошую производительность.&lt;/p&gt;

&lt;p&gt;В этом примере она учится на корпусе русских имен и может генерить новые, похожие по написанию:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
% ./microgpt.py
num docs: 484
vocab size: 57
num params: 5152
step 1000 / 1000 | loss 2.3474
--- inference (new, hallucinated names) ---
sample  1: Небромир
sample  2: Миловета
sample  3: Милана
sample  4: Свеладр
sample  5: Милана
sample  6: Ратевоба
sample  7: Миловисла
sample  8: Крана
sample  9: Бородосл

./microgpt.py  54.06s user 0.82s system 99% cpu 55.011 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Я подумал, что это хороший пример, чтобы попробовать, как LLM справится с переписыванием этого кода на Common Lisp.&lt;/p&gt;

&lt;p&gt;Промпт для переписывания был очень простой. Буквально я сказал LLM: &amp;quot;Вот тебе код на Python, сделай мне то же самое, но на Common Lisp, для загрузки датасета используй либу Dexador&amp;quot;. При этом я использовал в качестве агента Claude Code и нейросеть Claude Sonnet 4.6.&lt;/p&gt;

&lt;p&gt;Что меня удивило - то что нейросеть сама создала ASDF систему, а так же решила декомпозировать код на модули, а не склеила всё в один большой скрипт.&lt;/p&gt;

&lt;p&gt;Первоначальная версия которая получилась, работала аналогично питоновской, но в 5 раз быстрее:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
% time roswell/microgpt.ros

num docs: 484
vocab size: 57
num params: 5152
step 1000 / 1000 | loss 1.9185

--- inference (new, hallucinated names) ---
sample  1: Велослав
sample  2: Бореслав
sample  3: Любра
sample  4: Влавослав
sample  5: Добран
sample  6: Любегост
sample  7: Светисл
sample  8: Вирослав
sample  9: Зослав

roswell/microgpt.ros  9.41s user 0.61s system 99% cpu 10.038 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Дальше я просил LLM проанализировать что можно сделать чтобы повысить производительность и в итоге было сделано следующее:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;CLOS классы педеланы на структуры:
*&lt;/em&gt;
```&lt;/p&gt;

&lt;p&gt;roswell/microgpt.ros  6.00s user 0.47s system 99% cpu 6.489 total&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
То есть, после этого программа стала **быстрее python** оригинала **почти в 10 раз**.

А вот после объявления ftype и inline для некоторых функций, производительность улучшилась незначительно:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;roswell/microgpt.ros  5.70s user 0.51s system 99% cpu 6.232 total&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;У меня не было цели упарываться в оптимизацию, но думаю можно выжать ещё больше скорости если захотеть. Основной темой эксперимеынта было - проверить, как LLM справится с подобным проектом. Ведь иногда так бывает, что для Common Lisp какой-то библиотеки нет, но она есть для другого языка. Переписывать вручную - занятие грустное, но если можно сделать это автоматически с помощью LLM и сэкономить себе много часов работы, то почему нет?&lt;/p&gt;
</summary><content type="text">&lt;p&gt;Смотрите чего я навайбкодил: &lt;a href=&quot;https://github.com/40ants/microgpt&quot;&gt;https://github.com/40ants/microgpt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Это порт на Common Lisp скрипта microgpt, который недавно опубликовал Andrej Karpathy.&lt;/p&gt;

&lt;p&gt;Эта штука включает в себя код трансформера и инференс. То есть она может обучиться на каких-то входных текстах, а потом генерировать похожие тексты. Всё как у больших LLM, только буквально в одном Python-скрипте. Ну и, конечно, эта штука больше создана для обучения, а не для того, чтобы показывать хорошую производительность.&lt;/p&gt;

&lt;p&gt;В этом примере она учится на корпусе русских имен и может генерить новые, похожие по написанию:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
% ./microgpt.py
num docs: 484
vocab size: 57
num params: 5152
step 1000 / 1000 | loss 2.3474
--- inference (new, hallucinated names) ---
sample  1: Небромир
sample  2: Миловета
sample  3: Милана
sample  4: Свеладр
sample  5: Милана
sample  6: Ратевоба
sample  7: Миловисла
sample  8: Крана
sample  9: Бородосл

./microgpt.py  54.06s user 0.82s system 99% cpu 55.011 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Я подумал, что это хороший пример, чтобы попробовать, как LLM справится с переписыванием этого кода на Common Lisp.&lt;/p&gt;

&lt;p&gt;Промпт для переписывания был очень простой. Буквально я сказал LLM: &amp;quot;Вот тебе код на Python, сделай мне то же самое, но на Common Lisp, для загрузки датасета используй либу Dexador&amp;quot;. При этом я использовал в качестве агента Claude Code и нейросеть Claude Sonnet 4.6.&lt;/p&gt;

&lt;p&gt;Что меня удивило - то что нейросеть сама создала ASDF систему, а так же решила декомпозировать код на модули, а не склеила всё в один большой скрипт.&lt;/p&gt;

&lt;p&gt;Первоначальная версия которая получилась, работала аналогично питоновской, но в 5 раз быстрее:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
% time roswell/microgpt.ros

num docs: 484
vocab size: 57
num params: 5152
step 1000 / 1000 | loss 1.9185

--- inference (new, hallucinated names) ---
sample  1: Велослав
sample  2: Бореслав
sample  3: Любра
sample  4: Влавослав
sample  5: Добран
sample  6: Любегост
sample  7: Светисл
sample  8: Вирослав
sample  9: Зослав

roswell/microgpt.ros  9.41s user 0.61s system 99% cpu 10.038 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Дальше я просил LLM проанализировать что можно сделать чтобы повысить производительность и в итоге было сделано следующее:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;CLOS классы педеланы на структуры:
*&lt;/em&gt;
```&lt;/p&gt;

&lt;p&gt;roswell/microgpt.ros  6.00s user 0.47s system 99% cpu 6.489 total&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
То есть, после этого программа стала **быстрее python** оригинала **почти в 10 раз**.

А вот после объявления ftype и inline для некоторых функций, производительность улучшилась незначительно:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;roswell/microgpt.ros  5.70s user 0.51s system 99% cpu 6.232 total&lt;/p&gt;

&lt;p&gt;```&lt;/p&gt;

&lt;p&gt;У меня не было цели упарываться в оптимизацию, но думаю можно выжать ещё больше скорости если захотеть. Основной темой эксперимеынта было - проверить, как LLM справится с подобным проектом. Ведь иногда так бывает, что для Common Lisp какой-то библиотеки нет, но она есть для другого языка. Переписывать вручную - занятие грустное, но если можно сделать это автоматически с помощью LLM и сэкономить себе много часов работы, то почему нет?&lt;/p&gt;
</content></entry></feed>