Опыт построения ИИ-продукта в соло-режиме

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

До этого у меня был опыт использования агентской разработки для создания специализированного ЯП, но это был узконаправленный исследовательский интерес. Ну и на работе, будучи тимлидом, активно использую труд агента в SDLC. При этом опыта создавать с нуля приложение, проектировать UX/UI/CUI, чат-бота, безопасность, расписывать пользовательские сценарии и реализовывать различные схемы работы с моделью, у меня ещё не было.

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

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

Расскажу про саму решаемую задачу

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

Если простой TODO-лист пишется не приходя в сознание минут за 15 на любом современном фреймворке, то как только мы пытаемся сделать что-то более сложное и минимизировать когнитивную нагрузку на пользователя, то будто бы утыкаемся в бетонную стену. Моя проблема со всеми приложениями, которые я пробовал, заключается в том, что в какой-то момент мне нужно тратить слишком много времени на поддержание запланированного. Я же хочу планировать так, будто я общаюсь с ассистентом, причём в тех каналах, где я уже привык общаться текстом или голосом. В моём случае это Telegram и Алиса. Пользовательский интерфейс нужен скорее для того, чтобы проконтролировать, посмотреть прогресс или эпизодически, когда есть подходящее настроение, плотно поработать над планами.

Тут вы можете сказать: возьми OpenClaw или другого агента и общайся сколько хочешь. Я соглашусь, но частично. Действительно, возможность вести личные дела в Obsidian и подключить к агенту Telegram многое решает. У меня всё это и так настроено. Но такое взаимодействие нельзя назвать полноценным продуктом. Это скорее некий DIY-проект, который может дать впечатляющие результаты, но требует времени на настройку и вовлечение. В продукте можно задать онтологию предметной области, закрепить интеграции и контракты, сделать специализированный UI и разбор сложных кейсов. В общем, нарастить обвязку, целиком заточенную под решение конкретных продуктовых задач. Например, мне важно, чтобы приложение обеспечивало быстрые и правильные ответы, точно ловило мои интенции и имело при этом низкую себестоимость.

Если смотреть под таким углом, то планировщик, который я задумал, должен дополнять вещи типа OpenClaw, а не конкурировать с ними: персональный ИИ-помощник может использовать API планера для создания задач, загружать и выгружать сущности, и это, на мой взгляд, только дополняет картину. Но и без ассистента у меня должна быть возможность быстро запланировать задачу, скорректировать планы и получить о них детальную информацию.

С точки зрения компонент приложения всё выглядит так:
1. Основное веб-приложение
2. Админка (prompt-studia)
2. HTTP API
3. MCP (WIP)
4. Чат-бот для ТГ
5. Обвязка для Алисы (WIP)

По языкам: фронтенд на TypeScript, весь бек на питоне
Агент: Codex (GPT-5.5 High)
Навыки для ИИ: superpowers и несколько своих навыков для контура знаний и продуктовой разработки.

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

Немного упрощённая итоговая онтология

Немного упрощённая итоговая онтология

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

Далее я хотел, чтобы у приложения была возможность:

  1. создавать планы с привязкой к дате и без неё;

  2. задавать минимальный интервал между событиями («переворачивать матрас каждые две недели»);

  3. привязываться к порядковому номеру временной сущности («последнюю субботу месяца планировать вылазки на следующий месяц»);

  4. создавать события, которые длятся несколько дней, и при этом я могу быть занят постоянно в эти дни (командировка) или частично (фестиваль/конференция в моём городе), а расписание занятости может изменяться в зависимости от дня;

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

  6. записывать практики — действия, для которых важны непрерывность и отслеживаемость. Например, занятия йогой;

  7. связывать планы с людьми и местами. Например: «Пойти с женой в кино»;

  8. создавать текстовые заметки, связанные с планами;

  9. использовать русский язык со всей его вариативностью.

Наглядный пример:

Раз в две недели по средам вечером созваниваться с мамой

В этой фразе есть несколько разных смысловых слоёв:

  1. это регулярное действие, а не разовая задача;

  2. интервал — раз в две недели;

  3. день недели — среда;

  4. время — вечер, то есть мягкое окно, а не точное 19:30;

  5. человек — мама, и это может быть важным контекстом для будущих запросов;

  6. действие относится к личной сфере, а не к работе;

  7. если пользователь пропустит созвон и сделает его позже, возможно, следующий повтор должен считаться от фактического выполнения.

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

Ещё несколько примеров:

Фраза пользователя

Наивная трактовка

Что нужно хранить на самом деле

Каждую первую субботу месяца покупать корм коту и сначала проверять остатки

Ежемесячная задача

Рутину с правилом «первая суббота месяца» и отдельный подготовительный шаг «проверить остатки», потому что порядок действий важен.

Поменять фильтр в октябре

Событие в октябре или заметка

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

Завтра вечером купить лампочки для кухни

Календарное событие с точным временем

Дело, а не событие: дата «завтра», мягкое время «вечером», без фиксации точного начала и конца.

Пойду на парную йогу с женой 17 марта в 16:00 в Namastation, 2 часа

Текстовая заметка или простой reminder

Событие: точное начало, длительность 2 часа, человек жена, место Namastation, вероятная сфера здоровье.

Перенеси встречу с Сергеем на завтра

Создать новое событие «встреча с Сергеем»

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

Уточни встречу с Сергеем: встречаемся в офисе

Создать новую встречу в офисе

Обновить место существующей встречи, не потеряв время и участника.

Созвон с поддержкой

Человек поддержка

Дело или событие с ролью/командой в тексте; поддержка не должна автоматически становиться персоной.

Реализация

Первая ("наивная") версия

Первая («наивная») версия

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

Очень быстро я пришёл к тому, что мне нужна качественная обвязка — то, что в статьях по ИИ называется harness. Тащить LangChain/Graph казалось усложнением, и я решил сделать узкозаточенный инструмент — так появился PromptStudio. Это админка, которая позволяет динамически задавать промпты, работать с моделью напрямую, смотреть трейсы, работать с инструментами, задавать сценарии для проверки и вести статистику по связкам «модель + промпт». Всё это можно было собрать из открытых решений, но это казалось и до сих пор кажется сложнее, чем завайбкодить за пару дней своё решение.

Существенный фактор в пользу вайбкодинга — я сразу понимал, что нужно и что я собираюсь делать: хранить в YAML весь пайплайн, редактировать его в UI, иметь возможность варьировать запросы к моделям в пайплайнах и прогонять разные пайплайны на разных моделях с наборами тестов, чтобы в итоге автоматически получить скор. Также студия умеет использовать сервисы планера как инструменты модели и привязывать пайплайны к API.

Как это всё выглядит
 PromptStudio — интерфейс топорный, но все нужные мне функции тут есть

PromptStudio — интерфейс топорный, но все нужные мне функции тут есть

Я загрузил в неё набор из 64 базовых сценариев и стал проверять их на бесплатных моделях (локально и через OpenRouter) и яндексовских моделях. Само облако мне знакомо по прошлым проектам, плюс есть начальный грант. Так я определил круг моделей, которые достаточно выразительны, чтобы пройти все кейсы без ошибок.

Сценарии устроены следующим образом: они определяют, что отсылать и какой дополнительный контекст передавать, а затем проверяются статус ответа, тип сущности, действие, ключевые поля, отсутствие лишних уточнений, сохранение в БД, отсутствие дублей, чистота контракта и иногда задержка с токенами. Сейчас всё устроено так, что почти каждая найденная ошибка автоматически превращается в сценарий, в котором выделяются части, отличающие его от существующих сценариев, и таким образом база проверок ежедневно растёт.

Пример простого сценария — один запрос + немного контекста:

{
  "text": "Встретиться с Сергеем сегодня в 19:00",
  "quick_add": true,
  "user_context": {
    "language": "ru",
    "timezone": "Europe/Moscow",
    "known_spheres": [
      "Жизнь",
      "Работа",
      "Здоровье"
    ]
  },
  "shortlists": {
    "goals": [
      "Запустить MVP продукта",
      "Ремонт"
    ],
    "milestones": [
      "Согласовать словарь",
      "Разработка"
    ],
    "people": [
      "Сергей — коллега",
      "Сергей — тренер",
      "Мария",
      "Анна"
    ],
    "locations": [
      "Офис",
      "Namastation"
    ]
  },
  "context_ids": {}
}

Есть более сложные варианты, где пользователь может уточнить уже сделанный запрос и, например, отметить прогресс. Для каждого варианта можно оценить, насколько модель справилась: вызвала ли нужный инструмент, смогла ли заполнить итоговую структуру. Баллы за каждый пункт проставляет SOTA-модель. Я пока не встречал кейс, где она бы ошиблась и сделала что-то неправильное.

Когда я только начал экспериментировать, наиболее комфортной из открытых моделей была Qwen 235B A22B. Какое-то время я был ею доволен: модель прощала много ошибок, на моих тестах с отрывом набирала большое количество очков, и в целом выглядело так, что по соотношению цены и качества — самое то. Минуса было два:

  1. Цену хотелось ещё ниже: эксперименты быстро высасывают выданный грант, а мне хотелось проверить как можно больше гипотез за как можно меньше денег. Один прогон на всех сценариях выходил в 500–800 рублей, в зависимости от количества пайплайнов.

  2. Скорость. Модель работала сильно медленно, около 30 секунд на ответ, и это ставило саму идею проекта под угрозу. Дело в том, что основной интерфейс должен быть чат/войсы, а в таком режиме 30 секунд — слишком ощутимая задержка.

Тогда я стал исследовать быстрые модели и смотреть, кто что предлагает на российском рынке, и быстро обнаружил, что довольно неплохие результаты показывает яндексовская Alice AI LLM Flash, которую я отмёл на первом отсеве из-за того, что она стабильно игнорировала часть инструкций. Но к этому моменту я наигрался с бесплатными и локальными моделями, и у меня был развитый repair-слой, который позволял не замечать некоторые вольности в формировании JSON и доводил вывод модели до необходимого контракта. При этом «флешка» отвечала остальным критериям: низкая цена и высокая скорость работы. Большая часть ответов укладывалась в 5 секунд даже с корректирующими запросами.

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

Нужно сказать, что в некоторых случаях для классификации намерения модель вообще не нужна: справляются комбинация dateparse, pymorph3 и rapidfuzz. Были большие надежды на Natasha, но они не оправдались: тесты сходу не показали качественного улучшения, и я отложил эту идею, по крайней мере на время.

Вторая версия, актуальная

Вторая версия, актуальная

Процесс регистрации для упрощения сделан вокруг Telegram. Почему нет MAX? Я скажу. Признаюсь, подумал, что сделать поддержку MAX было бы разумно: это потенциально увеличит охваты. Но внезапно оказалось, что национальный мессенджер надёжно защищен от таких опасных мыслей: физическому лицу делать ботов не положено. Не буду это комментировать тут, попридержу для тг.

Вынос проекта за пределы личного ноутбука

Мне хотелось выкатываться сразу в что-то публичное, но при этом хочется чтобы это был сразу MWP. С другой стороны, психологически хотелось иметь доказательство что это всё может быть выкачено. В итоге я остановился на публичной бете — так я контролирую свои расходы с одной стороны и могу собрать обратную связь от заинтересованных людей с другой. Пару вечеров потратил на то чтобы понять как именно выкатывать и… долгожданный первый деплой.

Прохожу регистрацию, сам себя апрувлю и создаю первую задачу. Чувствую радость и гордость. Радость была недолгой, но это ожидаемо: мои сценарии бот проходил с лёгкостью, но в первый же день я столкнулся с осознанием того, что много реальных запросов не учтено и нужно ещё изрядно поработать, прежде чем вывести всё это в публичную историю. При этом сам я уже вовсю пользуюсь своим детищем: переношу туда планы и заодно добираю тестовые сценарии.

Про деплой особо нечего рассказывать: попросил нейронку сгенерировать мне Ansible и, собственно, им и деплою. На текущем этапе за глаза.

Примеры диалогов через ТГ
Тут видна ошибка — чат создал заметку, а не задачу. Но дальше корректно среагировал на исправление.

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

Пример поиска по существующим планам
Вот так происходит создание дела

Вот так происходит создание дела

Монетизация и юридическая сторона

Как подключать платежи, я разузнал, но перспектив по монетизации особо не вижу. Я буду рад, если проект будет отбивать себестоимость облака и токенов. С другой стороны, есть несколько идей для развития: совместное планирование, покупки, голосовое общение. Я допускаю, что в какой-то момент это может вырасти в классный подписочный сервис.

Юридический вопрос — отдельная неувлекательная история. Мы отсылаем персональные данные в LLM и Telegram, и это могут быть довольно чувствительные данные, если кто-то захочет запланировать врача и прикрепить к плану заметку с детальными вопросами. На все такие операции нужны явные согласия. А ещё нужно стать оператором ПДн. Кроме того, недавно принятый 149-ФЗ тоже потенциально осложняет жизнь. Потихоньку читаю законы и пытаюсь понять, можно ли в этой стране вообще делать такие сервисы.


Если вдруг есть желание помочь или узнать больше о проекте, то самый простой способ — написать об этом мне в Telegram

UPD1 Сайт: https://planitforme.ru/ — есть ограниченный демо-режим и лист ожидания — на текущий момент это закрытая бета. Я планирую её открыть, но какое-то время это займёт. Как минимум по причине того, что аутентификация через ТГ теперь объявлена вне закона.

UPD2 Изменил заголовок, раньше была добавка «от идеи до MWP». Но использование такого сокращения (которое в тексте было расшифровано как minimal wowable product) вызывало не совсем те реакции, на которые я рассчитывал.

Автор: 0ex0

Источник

Обсуждение закрыто.