BorisovAI

Блог

Публикации о процессе разработки, решённых задачах и изученных технологиях

Найдено 4 заметокСбросить фильтры
Исправлениеtrend-analisis

Как мы спасали аналитику трендов от невидимых багов

Работаю над **Trend Analysis** уже несколько спринтов, и вот снова: всё выглядит правильно, данные есть, но аналитика молчит. История обновлений с версии 0.12.0 — это история, как мы учились видеть то, что скрывается за очевидным. Началось просто. В версии 0.13.0 я заметил странное: сигналы из анализов теряются где-то в недрах базы данных. Проверил логи, проверил запросы — всё на месте. Потом понял: в коде стояло `phase='new'`, а должно было быть `'emerging'`. Казалось бы, мелочь, но на ней теряется 18 из 19 сигналов. Одна буква — и половина функциональности не работает. Параллельно с этим наткнулся на ещё один подводный камень: джойн в таблице recommendations был написан с опечаткой — `tr.id = t.id` вместо `tr.object_id = t.id`. Результат: momentum вообще не считался после миграции. Казалось бы, технический баг, но для юзера это означал, что рекомендации просто не появлялись. Чтобы ускорить работу с растущим объёмом данных, добавили 15 новых индексов БД в миграции 020. Это был момент боли — понял, что без правильной оптимизации запросы будут тормозить экспоненциально. К счастью, индексы сработали идеально, и теперь аналитика летает. А потом пришла версия 0.14.0, и мы переросли в новое качество. Добавили серверную пагинацию, поиск, сортировку анализов — теперь юзер может не просто смотреть данные, но реально с ними работать. Заодно реализовали **Saved Products** в Lab — локальное хранилище закладок через Zustand. Мелочь, но очень удобная. Всю работу приправили переводом trend_name и динамическими ролями в кеш переводов. Казалось бы, локализация — не главное, но когда твой интерфейс говорит с юзером на его языке, он чувствует себя дома. **Claude** помогал на каждом этапе: от анализа проблем до рефакторинга TypeScript типов, пока мы выравнивали SourceItem с бэкенд-моделью. Инструмент, который может одновременно понимать архитектуру, замечать баги и предлагать решения — на вес золота. Главный урок: **невидимые баги опаснее очевидных**. Код работает, тесты проходят, но где-то глубоко логика разъезжается с реальностью. Миграции, джойны, фазы сигналов — это всё сложные системы, где одна ошибка каскадирует через весь пайплайн. Кстати, вся эта история напомнила мне старую шутку: что общего у Jenkins и подростка? Оба непредсказуемы и требуют постоянного внимания 😄

#claude#ai#javascript#git
4 мар. 2026 г.
Новая функцияtrend-analisis

Пять проектов, которые окупают себя за месяц

Я сидел над **Trend Analysis** и вдруг понял: вокруг слишком много side-проектов, которые генерируют доход, но требуют минимума времени. Вчера разбирал ошибку в crawler — `sqlite3.IntegrityError: FOREIGN KEY constraint failed` — и прозвучало: а что, если вместо фиксинга давай соберём топ проектов на cash-flow? Вот мой список из боевого опыта. **Первый** — аналитический краулер для нишевых рынков. В **Trend Analysis** мы парсим источники через **Python**, используя **AsyncIO** для параллельной обработки. Такой краулер можно обучить отслеживать конкретные категории товаров, движения цен или тренды в нишах. B2B-клиенты платят от 500 до 2000 долларов в месяц за свежие данные. Главное — настроить **API** и забыть. Даже когда ломаются связи в базе (как в моём случае с foreign key), проект продолжает работать. **Второй** — автоматизация контента через **Claude AI**. Мы это делаем в боте-издателе: берём сырые логи разработки, обогащаем через **AI**, генерируем посты на двух языках. Клиент платит за объём — сотня статей в месяц стоит как годовой **GitHub Pro**. Zero-touch после настройки. **Третий** — аудит и рефакторинг React-компонентов. Помнишь ошибку про "Error: Rendered more hooks than during the previous render"? Кучу проектов на **JavaScript** ломают именно такие баги. Консультация, правка — 300–500 в день. Один фиксинг за вечер — это деньги на ужин. **Четвёртый** — интеграции между системами через **REST API**. Каждый стартап нуждается в том, чтобы данные текли из Stripe в CRM, из CRM в аналитику. Я пишу такую логику, выкладываю на GitHub как open-source с платной поддержкой. Два-три клиента в месяц — и окупает время разработки в 10 раз. **Пятый** — security-аудит. В материале всплыли проблемы с кодировкой на Windows (curl ломает UTF-8 с кириллицей), неправильное управление API-ключами в `.env`. Фрилансеры платят 200–400 долларов за быстрый аудит кодовой базы. У меня есть чеклист на 20 пунктов, проверю за два часа. Что объединяет все пять? **API**, **AI** и **Python**. Везде нужен либо парсинг данных, либо обработка текста через Claude, либо интеграция систем. И везде — благодаря автоматизации — можно параллелить: работаешь над Trend Analysis, а фоном крутятся три клиентских краулера и публикуется контент. Главное — не начинать с идеального кода. Помнишь, как Spring Boot непредсказуем? Наши проекты тоже. Но они работают. 😄

#claude#ai#python#javascript#git#api#security
4 мар. 2026 г.
Новая функцияtrend-analisis

Когда разрозненные фильтры становятся одной красивой системой

Вчера закончил работу над **Trend Analysis v0.12.0**, и это было именно то, о чём говорят: когда архитектура начинает складываться как паззл, видишь, что месяцы рефакторинга стоили того. Началось с обычной проблемы. В Cascade frontend было четыре отдельных страницы — explore, radar, objects, recommendations. На каждой свои фильтры, свой способ отображения, свои попапы. Пользователи путались, интерфейс выглядел как лоскутное одеяло. Я смотрел на эту красоту и понимал: нужно унифицировать, но **как** сделать это без полного переписывания? Решение пришло не с первого дня. Сначала запустил сервер-сайд пагинацию в `recommendation_store` — это дало нам контроль над данными на бэке, убрало загрузку всего сразу. Потом добавил динамические роли, которые теперь вытягиваются прямо из P4-отчёта. Не захардкодили — система сама адаптируется к изменениям. На фронте заменил горизонтальные табы на role chips — компактнее, быстрее переключаться. Зона фильтра теперь работает с **topN + поиск**, а не слепо показывает всё подряд. И главное — все четыре страницы получили **единый макет попапера**: одинаковые разделители, одна логика поведения, один стиль. Заняло больше времени, чем казалось, но оно того стоило. Backend часть тоже потребовала внимания. Изначально routes в `api/main.py` ещё включали префикс `/api`, но я переписал это — Vite proxy теперь перенаправляет `/api/*` в `/*` перед отправкой на бэк. Чище, проще масштабировать. Добавил `html.unescape` для StackOverflow заголовков — казалось бы мелочь, а на самом деле это спасает от каши из HTML-энтитиз в интерфейсе. В Lab тоже не сидели сложа руки. Оптимизировал промпты для работы с LLM — теперь структурированная экстракция вместо размытых инструкций. Добавил новый `llm_helpers` модуль, улучшил layout страниц Need detail и Product detail. Таблицы в Lab получили новые колонки — данные стали полнее. Самое приятное? Теперь, когда добавляю новую фичу на одной странице, другие три не ломаются. Система дышит. Вот такой факт о жизни разработчика: перед обновлением NumPy **обязательно** сделай бэкап. И резюме. 😄

#git#commit#python#api#security
2 мар. 2026 г.
Новая функцияC--projects-bot-social-publisher

Монорепо, который заставил пересмотреть структуру проекта

Когда решил мигрировать **Bot Social Publisher** с одномонолитного хранилища на многопакетную архитектуру, предполагал, что главная сложность будет в коде. Глупо. На самом деле всё сломалось на границах между пакетами. Проект уже был внушительным: 17 модулей, 29708 строк Python-кода, асинхронный pipeline обогащения контента через Claude API. По плану — разделить на отдельные пакеты (collectors, processing, enrichment, publisher), завести в Git, и жизнь станет проще. Реальность была иной. Первый вечер потратил на структуру папок. Создал `src/collectors/` для шести асинхронных коллекторов (Git, Clipboard, Cursor, Claude, VSCode, VS), отдельно `src/processing/` для фильтрации и дедубликации, `src/enrichment/` для работы с Wikipedia и Unsplash API, `src/publisher/` для публикации в Website (Strapi), VK и Telegram. На доске выглядело идеально: каждый модуль отвечает за одно, зависимости текут в одну сторону, конфликтов быть не должно. Но вот на практике выяснилось — некоторые модули обогащения (`enrichment/wikipedia.py`, `enrichment/images.py`, `enrichment/jokes.py`) были переплетены с основной логикой фильтрации. Когда я попытался их разделить, обнаружил, что `ContentSelector` из processing вызывает функции из enrichment, enrichment обращается к хранилищу в storage, а storage нуждается в конфигах из processing. Цикл. Переписал на pydantic-модели. Ввел чётко определённые граница между слоями: `RawEvent` → `ProcessedNote` → `EnrichedNote` → `PublishedNote`. Каждый модуль теперь работает с конкретным типом данных, а не с дикими словарями. Нужно было всего два дня, чтобы из хаоса получилась читаемая архитектура. Дальше пришла беда с Claude CLI. Максимум 100 запросов в день, 3 одновременных вызова, таймаут 60 секунд. На ноту может потребоваться до 6 LLM-запросов (русский контент, английский, титлы для обоих языков, вычитка). Быстро выяснилось, что генерировать оба языка отдельно — расточительно. Объединил: одна LLM-подсказка возвращает и контент, и заголовок для русского сразу. Количество обращений упало с 6 на 2-3 в день для одной ноты. Структура улучшилась, экономия вышла на порядок. В конце дня 94 файла упали в Git-репозиторий. Лицензия AGPL-3.0, `.gitignore` отфильтровывает все кэши, `.env.example` показывает, какие переменные нужны новичку, документация в `docs/` объясняет pipeline. Попытался push на `gitlab.dev.borisovai.ru` — DNS не разрешается, сервер недоступен. Коммит создал (хеш `4ef013c`), когда-нибудь синхронизирую. **Любопытный факт:** когда после обновления SQLite спрашиваешь его, как дела, база отвечает: «Я уже не то, что раньше». 😄

#claude#ai#python#javascript#git#api#security
25 февр. 2026 г.