AI

QMD — поиск по Markdown

Периодически AI-комьюнити (в самом широком смысле) подвергается нашествию моды. В какой-то момент весь твиттер начинает писать про одно и то же решение или функцию, все советуют одно и то же и все от этого в восторге. Я не имею в виду типичный мусор вида “Recently {smth} released new feature and this changes everything…” — нет, речь о вполне интересных вещах, как, например, OpenClaw.

Вот так в очередной раз донеслась мода на qmd. Это проект CEO Shopify Тоби Люке, который выпустил его несколько месяцев назад — минипоисковик по локальным файлам (в основном markdown, не проверял, что он еще поддерживает), который работает в командной строке и может использоваться AI-агентами. Уже есть и плагины, например, к Obsidian. У меня много документов в Markdown, да и Obsidian использую, поэтому решил попробовать наконец.

Технически это RAG, только без чат-обертки. Остальные компоненты присутствуют — файлы режутся на чанки, индексируются для поиска по ключевым словам, преобразуются в вектор, всё это хранится в SQLite базе и дальше в зависимости от оператора запроса либо делается поиск по ключевым словам, либо по эмбеддингам, либо гибридный поиск, то есть собираются результаты по ключевым словам и эмбеддингам, переранжируются совместно и выдается результат.

Движок при первом использовании скачивает необходимые модели для эмбеддингов, переранжирования и расширения ключевых слов, это порядка 2-2,5 гигабайт.

В общем, всё знакомо и понятно, но, если честно, пользоваться этим сложно.

Поиск по ключевым словам быстрый и хороший. Правда, он не уникальный — даже для Obsidian есть несколько плагинов, решающих эту задачу и решающих хорошо. Но для CLI это хорошая штука, агенты смогут использовать.

Поиск по эмбеддингам меня начал удивлять — во-первых, для того, чтобы эти эмбеддинги создать, движок загрузил модель и распух в памяти до 28 гигабайт. Если в первой итерации я ему подсунул около 10 тысяч документов, то потом решил тестировать более щадяще и дал только 300 — не помогло, свои 28 гигабайт он кушал в любом случае. Я честно не понимаю, зачем ему столько — для эмбеддингов используется модель с 600М параметров, ей даже с контекстом не нужно больше пары гигабайт памяти. 28 гигабайт — это больше половины вообще всей памяти на моем MacBook Pro и системе становится тяжело, то есть в фоне эту индексацию не проделаешь. Я решил потерпеть, все же индексация делается один раз. Но при поиске он опять распух до 28 гигабайт, впрочем, после ответа память освободил.

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

ОК, я запустил гибридный поиск. Движок привычно занял 28 гигабайт оперативной памяти и начал работу. Да, это классический RAG, я и сам так подошел в разработке — взять запрос пользователя, выделить ключевые слова, добавить синонимы, поискать по нескольким запросам, преобразовать их в векторы, поискать все векторы, все это переранжировать и выдать результат.

55 секунд на один небольшой запрос по очень небольшой коллекции. И, поскольку я такое делал, тут ничего особо не ускоришь — много операций, много транзакционных расходов (времени). Плюс к тому это все сделано на Typescript и node.js, что скорости не добавляет. К примеру, мой бот прокручивает на порядок больше информации — ищет в обоих поисках по 50 документов, результат (100 документов) отдает во внешнюю LLM для переранжирования, забирает Top25, отдает с большим промптом во внешнюю LLM для формулирования ответа и 95% ответов укладываются в 53 секунды.

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

Но для не такой уж большой базы документов, пожалуй, это излишне. Оставлю пока как замену grep, но только в режиме поиска по ключевым словам — эмбеддинги и переранжирования подождут.

Как реорганизовать память в Claude Code

Одна из главных проблем работы с кодинг-агентами — это контекст. Во-первых, размер контекста не бесконечный, во-вторых, даже очень большой контекст (как, например, 1 млн токенов у Gemini) не гарантирует, что модель с ним хорошо работает. Как тут не вспомнить принцип Шерлока Холмса, который сравнивал человеческий мозг с чердаком, где всё должно быть аккуратно разложено, чтобы им можно было воспользоваться.

Есть много способов организовать работу того же Claude Code, чтобы не захламлять контекст лишними токенами. Но так или иначе, по мере развития проекта, над которым вы работаете с агентом, в нем накапливается большое количество информации, которое хорошо бы держать доступной для агента. А если проектов много, какая-то информация, конфигурации, субагенты и скиллы начинают выноситься на уровень пользователя (не говоря о том, что часто типичная установка MCP серверов или скиллов норовит вписать себя именно на уровень пользователя) и присутствовать в результате в контексте вообще всех проектов.

Недавно Anthropic выложили очень полезную статью, подробно описывающую то, как Claude Code работает с памятью. Плохая новость — это не приводит к автоматической перестройке всех проектов. Этим придется заняться самому пользователю.

Хорошая новость — для этого можно привлечь сам Claude Code. Попробуйте для начала на одном проекте. Запустите Claude Code в проекте и дайте ему следующую инструкцию:

Прочитай https://code.claude.com/docs/en/memory. Проанализируй текущую память проекта и дай предложения в соответствии с рекомендациями статьи.

Claude Code прекрасно воспринимает инструкции на любом языке, можно не заморачиваться обязательным английским — тем более, что память он в итоге перепишет на английском. Скорее всего, он предложит превратить память проекта (~/.claude/projects/projectID/memory/MEMORY.md) в некое оглавление, а текущее содержание разделить на специфические файлы по темам — в этом случае на старте загружаться будут только несколько десятков строк основного файла, а файлы по темам будут подгружаться по необходимости. Кроме того, он увидит дублирующие инструкции в этих файлах и CLAUDE.md проекта и в итоге дойдет до ваших основных файлов (~/.claude/CLAUDE.md) и предложит переделать и их.

Вот тут удержитесь от полной переделки — проверьте, как это пройдет с одним проектом. Если он не предложит сделать бэкап текущих файлов, напомните про это, дайте сделать все правки. Перезайдите в сессию — claude –resume, — и посмотрите на результат.

Мне на довольно развесистом проекте с десятками сессий и большому количеству данных в памяти удалось снизить начальную занятость контекста до 11% от общего окна — это очень неплохой результат, в среднем без подобной реорганизации легко обнаружить начальный контекст на уровне 25-30%. Учитывая, что после 140-150k токенов (при общем окне в 200k) модели становится тяжело помнить начало сессии, выигрыш сразу становится ощутим в практической работе.

Оставайтесь с нами, у меня еще много всяких соображений накопилось на эту тему и не только.

Бот жалуется

Чей-то бот сошел с ума и начал открывать issues (багрепорты) в репозитории Claude Code. Там таких несколько, про Etihad спрашивает, про аэропорты. Интересно, что его заставило так свихнуться?

Скриншот issue

Пара недель с OpenClaw

Я, конечно, поддался модному веянию и завел себе OpenClaw — фреймворк, состоящий из персонального агента и большого количества обвязок вокруг. Не могу сказать, что использую его на полную мощность, но все же наблюдения уже можно оформлять.

У меня есть достаточное количество не очень активной техники Apple, куда можно было бы поставить OpenClaw — ну, знаете, как народ вдруг повально начал покупать базовую версию mac mini специально для бота. Но я все же не стал этого делать — я не вижу особых проблем с безопасностью, но и особых причин разворачивать бота именно так тоже не заметно. Разве что немалое количество скиллов, которые идут в комплекте с ботом, рекомендуется ставить через Homebrew, ну так совершенно необязательно следовать этим рекомендациям, бинарники везде бинарники.

За две недели использования я нашел только одну проблему, которая бы решилась использованием macos — если хочется, чтобы бот работал с хранилищем Obsidian, то это хранилище не должно находиться в iCloud, как у меня было. Впрочем, я перенес пока хранилище на Cloudflare R2 с достаточно щедрым бесплатным планом — посмотрим, что будет.

Проект выходного дня — правила украинского языка

Должен признаться — я пользуюсь спеллчекером, когда пишу на украинском. Я никогда не изучал язык — когда я впервые в жизни пошел в школу в Украине, то спросил у учительницы украинского «Как мне догнать остальных в классе?». В ответ я услышал примерно то, что знают все — «Где вы были восемь лет», то есть «А как вы догоните, если у вас оценок со второго по десятый класс нет?». Это понятно, потому что еще за месяц до этого я изучал в школе азербайджанский.

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

Нет, как можно услышать, я на украинском говорю, конечно, понимаю его, да, как видите, даже пишу — однако делаю ошибки, а это невыносимо, потому что в других языках я очень быстро вижу ошибки и вообще перфекционист. Поэтому я пользуюсь спеллчекером и тщательно проверяю любой текст, даже комментарии — потому что перепутаю «и» с «і» и сразу вспомнят и об Одессе, и о Яндексе.

Я пользуюсь LanguageTool — это очень мощная штука, но она проверяет орфографию, пунктуацию и почти не ловит русизмы. Более того — в некоторых случаях именно моя самая большая проблема с «і» и «и» пролазит, поскольку само слово может правильно писаться и так, и так (такій, такий, это соответственно женский и мужской род местоимения). В общем, я помучился и решил посмотреть, что с этим и русизмами можно сделать.

Оказалось, что LanguageTool — это открытый продукт, который можно расширять, правда, только если вы разворачиваете его у себя. Это меня никогда не пугало, поэтому Claude получил задание и начал выполнять.

Мы (меня уже спрашивали, почему “мы” — скромный я, не могу приписать себе заслугу нескольких LLM) взяли корпус UA-GEC — это корпус ошибок, составленный Grammarly и выложенный в open-source. Из него вытащили разделы, где собраны ошибки по стилю, беглости, сочетаемости и калькам. Кроме того, добавили правила по согласованию. Первый вариант содержал более 1000 правил и давал кучу false positives. Пришлось переделывать, тестировать, но в итоге вроде бы получилось неплохо. Впрочем, конечно, не идеально.

Если кому-то интересно попробовать или даже пользоваться постоянно — вот репозиторий, содержащий и сами правила, и инструкцию по локальному развертыванию (вам понадобится Docker). Если найдете ошибки или есть что добавить — там можно отправить issue или даже сделать PR.

Немного дегтя

Я, пожалуй, немного компенсирую вчерашний отзыв о работе OpenClaw — не то, чтобы ложкой дёгтя, но наблюдениями противоположного характера.

Внутри неплохо спроектированного продукта находятся все те же современные модели со всеми их недостатками. И на них я тоже уже наткнулся.

Например, как не ухищряйся и не придумывай новые прекрасные методы работы с памятью, перешибить собственные знания модели очень сложно. Я и в обычном использовании регулярно страдаю от того, как модель — совершенно все равно какая именно, хоть Opus 4.5, хоть Gemini 3 Pro, — настаивает, что её не существует, а актуальная версия либо Claude Haiku 3.5, либо Gemini Flash 2.0. У меня давно есть дополнение к промпту, где явно сказано, что перед упоминанием любой версии продукта, модели или библиотеки надо проверить фактически актуальную версию — даже в таком виде модель регулярно мне сообщает, что я ошибся и указал не вышедшую еще модель. В OpenClaw я сразу указал, что проверять надо и даже отдельно сказал “Заведи себе файл с версиями, запиши туда актуальные и раз в две недели проверяй” — и все равно в очередном скрипте он вписал google flash 2.0. Причем, когда я послал исправлять — он исправил в конфиге и оставил захардкоженной модель в скрипте. Когда я пнул еще раз — он исправил в скрипте и дописал fallback — до google flash 2.0!

Это, как понятно, я уже нарушил чистоту эксперимента, глазами глядя на каждую редакцию скрипта.

Вообще, модели фантастически плохо знают две вещи — собственный API и собственные возможности. И в очередной задаче это проявилось — сначала OpenClaw написал скрипт, который не учитывал параметры reasoning в запросе к LLM, а потом я понял, что агент решил не ту задачу. Я ставил задачу проверять пачку RSS и присылать мне дайджест, а он написал скрипт, который проверяет RSS и присылает дайджест — но это не agentic решение, с тем же успехом я мог бы написать такой скрипт и без него.

Собственно, с этим я сталкивался и в Claude Code — когда ему говоришь “сделай это скиллом”, он пишет очень правильный промпт, но это не скилл, поскольку он даже не оформлен правильно.

Так что оптимальное использование OpenClaw — очень внимательно его посмотреть, проанализировать и вытащить хорошие наработки в собственные настройки. Именно так я и сделал еще на прошлой неделе. Так что у меня уже какая-то своя версия Claude Code, которой я и работаю.

Выходные с OpenClaw

Два дня возился с OpenClaw (он же Moltbot, он же Clawdbot).

Я не стал его ставить на мак — у меня есть и mac mini, и mac Studio, которые можно задействовать, но пока я не готов давать ему доступ ко всем аккаунтам и логинам, а VPS в облаке справится не хуже. Пришлось, правда, повозиться — доступ к управлению ботом предусматривает либо ssh-туннель, либо использование Tailscale, а я давно для приватного доступа использую Cloudflare Tunnel. Но настроить получилось — и я оказался в очень знакомой ситуации, когда инструмент есть, а попробовать не на чем.

Бот, активно мне помогающий

Интересные задачи: перевод сложного документа

Пожалуй, главное изменение, которое у меня произошло в связи с обширным использованием LLM — исчезли невозможные задачи. Любая сложность или задача, связанные с большим количеством информации или автоматизацией чего-то рутинного, теперь воспринимаются как своеобразный вызов — а ну, как с этим справиться?

С другой стороны, конечно, иногда в разгар боев с Claude Code ощущаешь себя героем мультика про крылья и ноги — “лучше день потерять, потом за два часа долететь”. На гораздо чаще получается наоборот.

Вот довольно скромный пример. Попался тут большой файл с техническим руководством, который надо было перевести. Попался он не мне, но, глядя на утомительный процесс перевода docx-файла с картинками, выносками и таблицами, сложно было не захотеть помочь.

Итоги года в вайб-кодинге

В общем, мне кажется конец года лучшим моментом, чтобы еще раз поговорить о вайб-кодинге. О нем пишут, ему учат и пытаются отучить, о нем говорят все подряд и даже выбрали словом года. Коллеги по подкасту Радио-Т весь год с угасающим энтузиазмом обещали, что вот-вот всё то, что не соответствующие высокому званию программиста навайбкодили, наконец-то перестанет работать и весь мир придет к ним на поклон за исправлениями — ну, и раз уж я закончил год выпуском уже третьей версии интересного проекта, где весь код написан и отлажен разными версиями AI, то вполне можно и подвести итоги.

Иллюстрация того, как должна измениться работа программиста (prompt: Claude Opus 4.5, picture: IMAGEN 4
Иллюстрация того, как должна измениться работа программиста (prompt: Claude Opus 4.5, picture: IMAGEN 4

Гипотетически, ответ такой…

Я уже примерно год занимаюсь несколькими AI-проектами, в том числе RAG-ботом (Retrieval-Augmented Generation), и всё время выясняю для себя что-то новое. Почему бы не поделиться?

Разработка RAG-чатбота считается простой задачей — многие облачные платформы, от OpenAI до Cloudflare, предлагают даже готовые решения, где все можно настроить кликами в веб-интерфейсе. Да и для собственной разработки не заметно особых проблем — возьмите базу знаний, порежьте ее на небольшие фрагменты, однородные по смыслу (например, вопрос-ответ или раздел в большом документе), вычислите для этих фрагментов векторное представление (embeddings, в самом простом случае это очень дешево делается через запрос к API, например, OpenAI или Google), сохраните в специальный вид базы, которая называется “векторной” и ждите вопроса пользователя. Полученный вопрос тоже превращаете в эмбеддинг и теперь на запрос с ним векторная база вернет вам результаты, наиболее похожие (similar) на заданный вопрос. Остается сформулировать запрос к LLM буквально следующего содержания “Ты специалист службы поддержки (или консультант, смотря что за задача), вот вопрос пользователя, вот что мы знаем на эту тему, сформулируй ответ”.

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

Будущее SEO

На выходных попалась статья в блоге Semrush про то, что золотая эра SEO заканчивается, AI в результатах поиска Googel даёт всё больше ответов без клики на сайты, а AI-чаты (ChatGPT или Claude) предпочитают давать ссылки на крупные бренды. В результате малому бизнесу, который до сих пор уповал на поисковую оптимизацию и контент-маркетинг, достаётся все меньше трафика и что дальше делать — неизвестно.

Разумеется, крупный сервис, ориентированный в том числе на этот малый бизнес, не может просто поднять проблему — он должен рассказать, что сделать, и рекомендации там достаточно понятные. Займитесь, пишут, нормальным маркетингом, стройте бренд, наращивайте социальное присутствие и оффлайн-активность и вас начнут искать по названию, а тут уж любой поиск вас и найдет.

Возможно, общость рекомендаций связана в том числе и с отсутствием у Semrush готового сервиса, в который можно ткнуть пальцем и сказать “пользуйтесь!”. Но в целом, я бы назвал развитие ситуации справедливым.

Чем, по сути, было поисковое продвижение для малого бизнеса последние, пожалуй, лет 10, если не больше? Буквально два направления, оба в меру сомнительные — расстановка ссылок и контент-маркетинг. Со ссылками примерно и так понятно — то, что начиналось с совершенно добровольного обмена или цитирования, давно выродилось в агрессивную тактику задалбывания предложениями разместить гостевой пост, разместить ссылку где-то в тексте, поменять ссылку в тексте 10 летней давности и поставить там вместо оригинала ссылку на другой сервис “почти такой же точно, но другой” — в общем, наверняка знаете, о чем речь. Но что не так с контент-маркетингом?

Да всё не так примерно. Вот есть сайт небольшого магазина или небольшой компании. Контента на нем в обычном случае не то, чтобы много — страницы товаров, оплата/доставка, “О нас”, что еще может быть в магазине? Но тут приходит контент-маркетолог и рассказывает, что не будет никаких продаж без контент-маркетинга — то есть новых статей пару раз в неделю на темы, связанные со сферой магазина. Без этого, авторитетно объясняет маркетолог, не будет ни репутации магазина, как выдающегося в своей нише, ни поискового трафика, поскольку что тут индексировать поиску?

Но поставьте себя на место владельца магазина. Где он возьмет материал на две статьи в неделю? О чем писать? Хорошую статью написать не очень просто, даже если у вас есть материал. А у какого количества магазинов и бизнесов вообще есть какой-то уникальный опыт, достойный статьи? Вы знаете, что получается в итоге — многочисленный статейный мусор “Топ-10 чего угодно”, где на первом месте приведен не имеющий недостатков продукт автора, а дальше всякие недостойные конкуренты, или “Советы начинающим кому угодно”, хоть сантехникам, хоть ядерным физикам. Пройдитесь по сайтам SaaS-продуктов — они все забиты регулярными статьями на совершенно общеобразовательные темы, часто скопированные либо у других, либо из википедии. Это была эпоха великого рерайта, что уж тут скрывать?

Вот теперь она справедливо заканчивается — если речь идет об ответе на вопрос, то AI хоть в чате, хоть в выдаче даст ответ лучше и быстрее, без излишней рекламы. А если продукт, сервис, магазин имеет что сказать, как обладатели уникального опыта, он не пропадет. Я вот в большом количестве поисков про клавиатуры встречаю один украинский магазин, у которого и хороший набор товаров, и глубокое знание темы, и много собственных тестов с подробными обзорами. Жаль, что он такой у нас один, но он заслужил свой поисковый трафик и меня в качестве покупателя.

Вот еще бы соцсети подобным образом очистить — но это прямо противоречит как бизнес-модели, так и интентам пользователей. Так что лучше туда просто не ходить. Шучу.

Редизайн блога

Я не думаю, что кто-то даже из постоянных читателей этого блога вдруг заметит изменение дизайна, поэтому лучше расскажу.

Собственно, рассказать стоит только то, что весь процесс — от макетирования до полной имплементации и исправления багов, — занял у меня часа полтора. Конечно, благодаря AI — я взял привычный Claude Code, применил уже проверенный на паре мелких задач скилл frontend-design и так всё и сделал. Claude расспросил, какие стили я предпочитаю, какой шрифт для чего лучше использовать, что лучше сохранить из существующей темы (а тут стояла Mainroad, довольно старая тема) и нарисовал три макета в разном стиле.

Мне оставалось выбрать один из трех и через минут 15 можно было тыкать его на локальном сервере. Возможно, Claude Code и сам бы справился с вылизыванием верстки, но я предпочитаю держать минимальное количество MCP серверов, лучше уж я ему скриншотов накидаю.

Не обошлось без казусов — например, исправляя ширину поста, он вдруг заявил “А еще я убрал красную линию в заголовке” и на самом деле её убрал. Пришлось сказать, чтобы вернул.

Но результат мне нравится. Надеюсь, аудитории тоже будет лучше.

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

Не даем заснуть колонкам

На выходных задумался, что за последний год у меня сильно изменился шаблон поведения в совершенно стандартных сценариях использования продуктов. Если раньше, встречая какое-то мелкое неудобство, я пробовал его решить настройками или чьим-то готовым решением, то сейчас я начинаю думать — “А нельзя ли это устранить вообще? Что посоветует AI?”. И по результатам небольшого чата вполне может последовать радикальная перенастройка системы или даже написание программы, которая решит проблему.

История про долгую историю окупаемости

В очередной раз встретил выступления “экспертов” про то, что AI — это пузырь, компании глубоко убыточны, инвестиции никогда не окупятся, ну, вы тоже встречали, — и вспомнил прекрасную историю из прошлого.

На четвертом курсе института нам читал лекции по экономике железнодорожного транспорта профессор Бондаренко и на лекции, посвященной расчету окупаемости капвложений (сейчас бы сказали — “инвестиций”), рассказал о том, что он входил в рабочую группу экономистов, занимавшихся разработкой ТЭО (технико-экономического обоснования) системы “Экспресс” — автоматизированной системы продаж билетов на пассажирские поезда в СССР. Кажется, речь шла о системе “Экспресс-2”, запущенной во всесоюзном масштабе в середине 80-х годов прошлого века.

Приятный сеанс вайбкодинга

Я в последнее время практически большую часть работы делаю с использованием AI-агентов, которые при этом что-то программируют. На меня за это регулярно сердятся “настоящие” программисты, мол, я ничего не понимаю, что там AI пишет, будет масса проблем потом, кто это сможет поддерживать и вообще… Я, правда, честно отвечаю, что меня не волнует, кто это сможет поддерживать, пока с этим справляется даже нынешний AI, тем более, что большинство вещей, которые в итоге получаются — это прототипы, которые используются для разовой или нерегулярной задачи. Если в итоге станет понятно, что идея, алгоритм или последовательность операций даёт нужный результат — “правильной” разработкой займутся живые люди, которые сделают “правильный” проект. Хотя при этом я неплохо представляю, что откуда берется, что с данными происходит и как проверить итоговый результат — а вот какой алгоритм сортировки применен или как не по канонам названы методы, меня и волновать не должно, я такого и про результат работы живых людей не знаю.

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