ИИ-ассистент для ЖКХ без разработчиков: архитектура и подводные камни

Руководитель продукта «Домиленд» Михаил Михайлов за два месяца в одиночку собрал ИИ-продукт для ЖКХ. Разбираем, какие слои ему пришлось построить вокруг языковой модели и почему без них прототип не дошёл бы до продакшена.

Краткий пересказ YandexGPT
  • PropTech-платформа «Домиленд» внедрила ИИ-ассистента для упрощения взаимодействия жителей с домом.
  • Ассистент умеет принимать показания счётчиков (в том числе по фотографии), информировать о расходе ресурсов и событиях в ЖК, находить заявки жителей.
  • Около 15% обращений, которые должны были дойти до управляющей компании, ассистент перехватывает на себя.
  • Продакшен-версия включает сложный цикл инструментов, MCP-сервер, API конкретного сервиса и контур контроля качества.
  • Реализовали строгую систему авторизации, чтобы предотвратить доступ к данным о соседних квартирах.
  • Создали инфраструктуру для тестирования синтетических и полусинтетических корзин запросов и логирования — это позволяет быстро выявлять и исправлять проблемы.
  • Агент сохраняет контекст диалога, чтобы не терять нить разговора и не переспрашивать о уже упомянутых данных.
  • Выстроили иерархию доверия источникам информации, чтобы избежать ошибок в ответах модели.
  • Ответы ассистента шаблонизированы для обеспечения детерминизма и предсказуемости. Чётко описали запреты для агента, чтобы избежать нежелательных действий.
  • Используют адаптер для работы с различными API управляющих компаний, что позволяет агенту обрабатывать заявки любой УК. Верификацию данных осуществляют на уровне API, а не через системный промпт.
  • Реализовали собственный цикл вызова функций (function loop) для контроля порядка вызовов и расхода токенов.
  • Языковая модель в сервисе используется в основном для понимания запроса пользователя и выбора действия, а остальные процессы контролируются кодом.

Yandex Scale 2026

24 сентября, Москва и онлайн.
Главная технологическая конференция
Yandex Cloud.

Хочу прийти!

Эту статью мы написали на основе доклада «От идеи до прода за два месяца: ИИ-продукт своими руками без разработчиков» на фестивале решений Yandex AI Studio Series Summer Edition.

Зачем PropTech-платформе Яндекса ассистент

«Домиленд» — это приложение для жителей, сервисы для управляющих компаний (УК) и системы умных зданий, которые собирают всё это в одну экосистему. У приложения больше полутора миллионов пользователей. Житель может на ходу попросить Яндекс Станцию заказать пропуск гостю, и тот попадёт на ресепшен жилого комплекса, если территория закрытая, или открыть домофон голосом, пока руки заняты.

Причин запускать ассистента было три:

  • Позиционирование. Мы изначально ищем и осваиваем сценарии, в которых житель взаимодействует с домом самым коротким способом.
  • Запрос партнёров и жителей. Управляющие компании и пользователи всё чаще просят текстовые и голосовые интерфейсы вместо мобильного приложения: люди хотят решать бытовые вопросы там, где им удобно.
  • Короткий вход в продукт. Вместо навигации по разделам приложения человек пишет «у меня авария» — и модель сама заполняет форму заявки в управляющую компанию. Или присылает фотографию счётчика, а показания распознаёт тоже модель.

Что умеет ИИ-ассистент

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

  • Принимает показания счётчиков. Самый популярный сценарий — передача по фотографии. Раньше такое фото приходило на почту, и оператор вручную считывал цифры и вносил их в систему. Теперь это делает ассистент.
  • Видит расход и подсказывает, когда откроется окно передачи показаний или когда отключат холодную воду.
  • Знает, что происходит вокруг дома. Например, может найти заявку жителя и сказать, когда в ЖК будут мыть окна. Эти данные ассистент берёт у управляющей компании.

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

Полноэкранное изображение

Ассистент сам находит на фотографии серийный номер счётчика и определяет, к какой квартире он относится. Пользователю остаётся подтвердить намерение.

Ассистентом регулярно пользуются больше 20 тыс. жителей. Главное наблюдение пилота: около 15% обращений, которые должны были дойти до управляющей компании, ассистент перехватывает на себя. Написать в чат оказалось удобнее, чем дозваниваться в УК или искать нужную форму в приложении.

Почему прототип на MCP не становится продуктом

Первая версия выглядела так же, как у всех, кто пробует собрать агентское решение: агентский цикл, MCP-сервер, API и клиент — у нас это был телеграм-бот. Такой продукт можно поднять с любой языковой моделью за пару дней в Yandex AI Studio.

Для продакшена это не годится: передача показаний и заявки в УК — критичные для человека задачи. Если агент ошибётся, передаст не те цифры или не отправит их вовсе, житель заплатит лишнее.

Продакшен-версия устроена принципиально сложнее: цикл инструментов, MCP-сервер, API конкретного сервиса и отдельный контур контроля качества. По сути, мы построили вокруг модели харнес — обвязку из кода, которая удерживает модель на задаче и забирает на себя всё, что нельзя доверить генерации. Дальше разберём его по слоям: с чего начинали, что показали прогоны и какие решения дошли до продакшена.

Полноэкранное изображение

Авторизация: слой, который закрывают первым

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

  • Не передаются через модель, то есть не проходят по цепочке «промпт → ответ → API → MCP» и дальше.
  • Регулярно сбрасываются и недоступны даже внутри «тёплых» MCP-соединений. Иначе такое соединение теоретически может подхватить данные другого пользователя и создать заявку от чужого имени.

Переделывать этот слой, когда цепочка вызовов уже собрана, дороже, чем построить его сразу.

Тестовые корзины и логирование: строим раньше, чем кажется нужным

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

Рядом с прогонами обязательно нужен полный стек логирования: от сообщения пользователя в чате до полного ответа API. Без него нельзя быстро итерировать.

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

Память и контекст: почему агент не должен переспрашивать про квартиру

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

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

Кроме предсказуемости диалога инъекция контекста экономит вызовы инструментов.

Иерархия доверия: какому источнику модель верит в первую очередь

Даже самая дорогая модель в Yandex AI Studio может ошибаться. В сервисе вроде передачи показаний нельзя закладывать даже один процент неверных данных.
Контекст агента складывается из нескольких слоёв:

  • ответ инструмента;
  • контекст текущего диалога: ID дома, доступные и недоступные показания;
  • история диалога.

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

Чтобы этого не было, мы выстроили иерархию доверия источникам. Её можно задать прямо в системном промпте, но модель должна явно понимать, какой источник важнее.

Детерминизм: почему все ответы шаблонизированы

Вторая половина той же задачи — детерминизм ответов, включая идемпотентность операций записи.

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

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

Запреты: что агенту нельзя — описываем так же явно, как и то, что можно

К агенту подключено около 20 инструментов, и здесь есть неочевидный риск. Если в описании инструмента не сказано прямо, что каких-то действий делать нельзя, модель додумает лишнее. Написано, что можно передать заявку в УК и прочитать сообщение через другой инструмент, — и модель решает, что можно и отправить сообщение в заявку. Хотя это не предусмотрено.

На ручном тестировании такие случаи почти не видны. Их вылавливает только регулярный прогон тестовой корзины.

Реальные API: адаптер вместо переписывания

Когда на MVP есть два месяца, никто не будет переписывать существующий API под агента. Приходится встраиваться поверх.

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

Отдельная история — заявки. У каждой управляющей компании они собраны в своём конструкторе форм: один и тот же вызов сантехника у одного партнёра выглядит простой формой, у другого — многошаговым выбором времени и слота. Формат заявки приходил нам HTML-разметкой, подготовленной под вёрстку в мобильном приложении. Модель видела элементы формы — например, радиокнопки, — но не всегда могла корректно упаковать их в вызов инструмента записи.

Пришлось написать адаптер, который приводит разные типы заявок к нормализованному формату. С моделями, которыми мы пишем код, это заняло один день. После этого агент справляется с заявкой любой УК за один заход.

Верификация: только на уровне API, а не системного промпта

Человек может ошибиться и поставить точку не в том месте — значит, нужна верификация ввода.

В ранних версиях на MCP мы пробовали делать ограничители через системный промпт. Было любопытно наблюдать, как они работают. В общем, никак. На более сильных моделях надёжность выше, но даже 10% ошибок в таком сервисе критичны. Поэтому вся верификация и все операции записи в итоге живут на уровне API, а не на усмотрении модели.

Свой function loop: контроль порядка вызовов

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

За фразой «закажи сантехника на ближайшее время» стоит несколько шагов: узнать доступное время, доступного мастера, тип заявки. Без строгого контроля результаты этих вызовов внутри одного раунда путаются между собой, и агент совершает не то действие.

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

Агент — это харнес, а модель — его часть

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

Решение полностью в продакшене и уже продаётся партнёрам. Календарно ушло два месяца, при этом проектом мы занимались не на полную ставку. Быстро развернуть инфраструктуру и собрать прототип помогло облако.

Вайб-кодингом это назвать нельзя: вайб-код — это когда написал промпт, и вдруг появилось что-то большое. Здесь была планомерная архитектурная работа, для неё ближе термин AI-driven development. И требовать от модели стоит больше, чем кажется на старте: собрать прототип и поиграться с ним легко, а дальше начинается харнес.

ИИ-ассистент для ЖКХ без разработчиков: архитектура и подводные камни

Войдите, чтобы сохранить пост