ИИ в энтерпрайзе за год: что получилось, а что нет

Превью видео «Личный опыт с ИИ в Enterprise-разработке» с канала StringConcat
Это текстовая версия видеоролика. Смотреть на YouTube (около 20 минут) или во ВКонтакте.

Введение

Сначала про контекст. Мы используем иишку в кровавом энтерпрайзе, а это немного не то же самое, что ночами клепать убыточные B2B SaaS-стартапы в режиме лудомана у игрового автомата. Суперспециалистами по ИИ мы себя тоже не считаем: просто воспользовались советами из ролика «ИИ FOMO». Вы там писали, что это всё капитанство, но, как видите, работает.

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

Сетап

Мы пользуемся и коммерческими агентами, и моделями, которые развёрнуты у нас внутри. Нам повезло: есть серверы с мощными видяхами. Прототипы, внутренние тулзы и всё, где нет коммерческой тайны и персональных данных, делаем на коммерческих моделях. Для чего-то более секретного и серьёзного, естественно, берём свои.

По качеству они, конечно, уступают, но за последний год скакнули очень сильно. Раньше результат был уровня «пук-среньк», теперь получается вполне пригодный, местами сравнимый даже с топовыми моделями. Особенно радует семейство Qwen. Проблем хватает, самая заметная: локальные модели жрут уйму токенов. Но мы над этим работаем.

Что работает хорошо

Внутренние тулзы

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

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

Разработка новых продуктов

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

Моделируем, проектируем и изучаем предметную область мы по-прежнему вручную. ИИ подключается потом и снимает с нас часть рутины. Устроено это примерно так.

Сначала мы зарываемся в предметку и моделируем её через Event Storming: выделяем модули, агрегаты, разбираем всё по винтику. В итоге получаем понятные составные части: агрегаты, объекты-значения, правила, доменные сервисы и прочее в этом духе. Такое генерировать не очень сложно. Кстати, про value-объекты у нас есть два больших видео (часть 1, часть 2), а по ним сделана большая текстовая статья, если вам удобнее читать.
Текстовая версия гайда по Value Object (объектам-значениям) на Sponsr
Дальше шаблоны, готовые библиотеки и скиллы. Например, HTTP-клиент мы каждый раз не изобретаем: подключаем свой библиотечный, а в нём уже есть мониторинг, логирование, предохранители, всё что нужно. Есть и скилл для написания value-объектов. Он описан довольно формально, и это огромный плюс, потому что формальное ИИ переваривает лучше всего.
Скилл для написания агрегатов и Value Objects: правила и структура
Сюда же добавляем проверки, линтеры, статические анализаторы и тесты. Тесты в том числе на архитектуру: да, мы тестируем даже структуру приложения.

Благодаря всему этому нормальный код получается генерировать даже на слабых моделях. Я пробовал Qwen 2.5 на 7B, куда уж скромнее, причём не агентом, а просто в чате, и с некоторыми элементами она вполне справилась.

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

Но не везде всё гладко.

С моделированием у нас не очень получилось. ИИ не знает вашу предметную область, она сидит в головах экспертов. Рассказать LLM может только про очень распространённое, например про двойную бухгалтерскую запись, которую она видела миллион раз. В терминах Domain-Driven Design такой домен называется универсальным. А с основным приходится ходить вручную и клеить стикеры. Можно поспрашивать модель про термины, пусть расскажет хотя бы то, что знает, но выхлоп меньше, чем хотелось бы.

Второй случай: границы систем. Допустим, есть класс на 50 полей, и заполнить их надо из десяти источников. Начинаешь ходить в эти сервисы и выясняется, что документация неактуальна, результат работы совсем не тот, что ожидался, и вообще валятся какие-то ошибки. Тут ИИ тоже буксует, приходится сидеть и разбирать всё руками. Хотя польза от неё в таких историях всё-таки есть, но об этом чуть позже.

Зато есть неплохой бонус. Когда всё стандартизировано и правила понятны, ИИ хорошо находит нарушения инвариантов. Недавно я писал про это в своём Telegram-канале.

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

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

Пару лет назад у нас выходил ролик про перспективы IT-рынка. Я там говорил, что уже наметилось разделение на кодеров, которые не хотят читать требования, а хотят просто программировать, и инженеров, которым нужно разобраться в процессе целиком. И что со временем кодеры станут не нужны, причём даже без всякого ИИ. Мне писали, что я неправ. Но прогресс сделал это чуть быстрее, чем я ожидал.

Реверс

Ещё одно неплохое применение: реверс. Есть исходники, и надо понять, что происходит внутри. Мы восстанавливали структуру приложений, вытаскивали эксплуатационную документацию (какие бывают параметры и на что они влияют), строили зависимости между микросервисами, рисовали схемы C4 в Structurizr. Аналитики вообще научились задавать вопросы прямо коду: «мне нужно выполнить такую-то операцию, какую апишку заиспользовать, какие они бывают, что передавать на вход?» С оговорками это работает хорошо.

Оговорки такие. Из набора правильных локальных описаний («этот класс делает вот это, этот сервис вызывает тот») ИИ может собрать неправильную картину целиком. В лапше из микросервисов ей мерещились связи, которых на самом деле нет. Причём выглядит всё убедительно: схема красивая, стрелочки на месте, а половина архитектуры живёт только в голове модели. Поэтому для нас такая схема не документация, а гипотеза, которую надо проверить. Но получить вводные данные вполне можно.

Бывают и безнадёжные случаи вроде «пара сотен хранимых процедур, и всё»: ни нормальных точек входа и выхода, ни понятных имён, одна клинопись из однобуквенных переменных. Тут не поможет никто. А вот если у сервиса есть апишка, но нет ни исходников, ни документации, и нужно понять, как ею пользоваться, ситуация интереснее. Берём Jupyter-ноутбук, и ИИ генерит гипотезы: пишет код, который дёргает апишку, перебирает варианты и ищет рабочий путь. Цикл простой: гипотеза, эксперимент, результат, новая гипотеза. Картину не всегда удаётся восстановить целиком, но это в любом случае быстрее, чем перебирать вручную.

Пользовательская документация

Заряжаем агента, и он через Playwright или DevTools сам ходит по страничкам, жмёт кнопки, делает скриншоты и складывает всё в заранее заданном виде. На выходе почти пригодная к употреблению дока со скриншотами и понятной структурой. Причём агент не пересказывает чужие описания системы, а проходит реальный интерфейс и фиксирует, что там есть на самом деле.

Нюансы, как всегда, имеются. Хитрый сценарий агент может не осилить или вообще не догадаться, что он существует. Если поведение зависит от данных или требует решения человека, он тоже начинает тупить (хотя ему можно подсказать). На тестовых стендах часть интеграций может вообще не работать. Ручная правка всё равно нужна: поменять формулировки, заменить скриншот, добавить кейсы, до которых агент не добрался. Но это совсем не то же самое, что писать доку с нуля, а такая работа, честно говоря, довольно бестолковая. Вместо «напиши мануал на двадцать страниц» получается «проверь и поправь то, что уже собрано».

Что получилось не очень

Инфраструктура

Как ни странно, на первом месте у нас инфраструктура. Нужно описать Helm-чарты для Kubernetes, собрать кластер из нескольких микросервисов, приделать Prometheus, Grafana, дашборды и сбор логов. Ничего экзотического, совершенно стандартные вещи. Я несколько раз специально собирал такие небольшие кластеры с нуля. На старте всё идёт неплохо, а через какое-то время кластер начинает разваливаться. С docker-compose, кстати, примерно то же самое, хотя задача проще.

Сначала я винил конкретного агента: ну, может, надо просто попробовать другого. Пробовал других агентов и другие модели, и все упирались примерно в один и тот же потолок, после которого всё начинает обрастать костылями. Не запускается сервис, модель говорит: «Сейчас напишу тебе скриптик, запустишь, и всё взлетит». Запускаешь, сервис взлетает. Правда, ровно до тех пор, пока под не пересоздадут или кластер не перезагрузят, и тогда всё лежит по-прежнему. В итоге в репозитории скапливается куча скриптов вроде fix_это и fix_то, и вся конструкция держится на честном слове.

Мы с такой проблемой, судя по всему, не одни. Есть исследование Microsoft Research: взяли 302 реальных инцидента в Kubernetes и проверили, как LLM справляются с восстановлением. Понять, какой сервис сломался и что за проблема, модели научились хорошо, лучшие результаты выше 90%. Но когда нужно выбрать конкретное правильное действие по починке, результат падает примерно до 40–60%. «Я понял, что сломалось» и «я знаю, как это чинить» оказались разными задачами, а связаны они довольно слабо. Это совпадает с тем, что видел я: точечную проблему мне довольно успешно удавалось пофиксить, а вот с работоспособностью кластера в целом большие вопросы.
Исследование Microsoft Research: как LLM восстанавливают микросервисы после сбоев в Kubernetes
Почему именно тут? Есть предположение. Когда ИИ пишет код, у неё есть тесты и проверка, пусть даже просто компилятор, и всё лежит рядом: открыл файл, написал тест, сразу увидел результат. В инфраструктуре появляется расшаренное нелокальное состояние. Правишь один YAML, а последствия вылезают совсем в другом месте, через сеть, несколько сервисов и контроллеры Kubernetes, иногда с задержкой. Единой точки, где видно, что происходит прямо сейчас, нет, и агенту трудно удерживать целостную картину и получать быстрый однозначный фидбэк. Без хорошей наблюдаемости и автоматических проверок он не исправляет систему, а наслаивает костыли. Может быть, у вас другой опыт, напишите в комментариях.

Большие тексты и лекции

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

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

Не только мне, кстати. Проблему длинных текстов исследуют отдельно. В работе IS-CoT показано, что по мере роста текста модели теряют связность и управляемость, поэтому авторы вместо попытки нагенерировать всё одним махом добавляют отдельный цикл планирования, написания и проверки. Большая лекция — это не набор хороших абзацев, а авторская конструкция, которую надо удерживать на десятках страниц. Модель может отлично написать каждый кусок и при этом развалить целое.
Статья IS-CoT: коллапс генерации длинных текстов у языковых моделей
Второй неприятный момент: ИИ постоянно норовит усреднить твои мысли. Пишу эмоциональный кусок, а она мне: так лучше не писать, это может кого-то задеть или обидеть. А мне этот кусок нужен для художественного замысла. В конкретном случае можно сказать «не трогай», и она послушается. Но стоит затеять рефакторинг, поменять сквозную мысль или пример, как агент незаметно подменяет твои идеи усреднёнными. На эту тему тоже есть исследование: сравнивали тексты людей и GPT-4 и нашли эффект гомогенизации, то есть меньше разнообразия идей и сдвиг к общему среднему. Может быть, я просто неправильно составлял промты, хотя вроде бы обмазался правилами, что можно трогать, а что нет.
Исследование эффекта гомогенизации текстов больших языковых моделей
Поэтому в текстах я использую иишку только для локальных вещей: красивая формулировка, логическая связка между двумя кусками. Мысли и структура мои, и двигаюсь я маленькими шагами: один кусок, один рефакторинг, одна задача за раз. Формулировки как раз самое трудоёмкое, и тут она реально экономит время. А вывод про контент-заводы простой: сотни единиц контента они вам, конечно, нагенерируют. Только кормить они вас будут говном.

Личное планирование

У меня как у руководителя, да и просто как у человека, очень много задач в течение дня. И я, поддавшись моде, решил прикрутить к этому иишку. Настроил агента, подключил планировщик через MCP, подключил Obsidian, обмазался правилами. Хотел получить «центр управления полётами» и персонального ассистента. Получилась ИИ ради ИИ: куча правил и описанных процессов, а в итоге мусорка. Вместо ассистента я получил подопечного, за которым надо постоянно присматривать.

Что пошло не так? Планирование — это не просто чатик, куда говоришь «раскидай мне день». Нужно держать в голове довольно большой контекст: что приоритетно, что нет, что от чего зависит, что нельзя потерять. А агент несколько раз просто продалбывал задачи, которые у него были записаны: забывал вытащить из бэклога, забывал сдвинуть. Сроки срывались. Как будто ему не хватало того самого контекста. В итоге у меня появилась ещё одна задача: проверять, ничего ли он не забыл. Историю я закончил тем, что всё выкинул.

Выяснилось, что я такой не один. Harvard Business Review описывал человека, который подключил агента к календарю, чтобы освободить время, а получил вторую работу: управлять самим агентом. Для этого эффекта придумали даже отдельный термин, bot-sitting. Вместо работы ты кормишь агента контекстом, проверяешь результаты, исправляешь ошибки и следишь, чтобы он опять чего-нибудь не забыл. Мой критерий простой: если стоимость контроля выше стоимости ручной работы, автоматизации не произошло. Подумайте, может, вы тоже попали в эту ловушку и просто спускаете деньги и токены, хотя вручную сделать гораздо проще.
Статья Botsitting vs Botshitting: Two New Words for the Work Around AI

Сложные программы и вайб-кодинг

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

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

Почему так происходит, хорошо описал мой товарищ и коллега Гена Круглов в статье «Восходящая спираль энтропии». Если коротко: агент неплохо решает локальную задачу, но заодно создаёт связи и техдолг, которые мешают следующей. Локальный фикс, больше связанности, система непонятнее, ещё один фикс, ещё непонятнее, и так по кругу. В какой-то момент агенту становится проще подогнать то, что он может проверить прямо сейчас (поправить тест, обойти крайний случай), чем разбираться и исправлять наверченное. Видимо, где-то мы пересекаем порог сложности. До него агент держит систему в голове, а после него чинишь один баг, и отваливаются две фичи. На выходе зелёные тесты и программа, которая не работает. Подробности лучше прочитать в самой статье, а на канале автора много интересного.
Схема «Восходящая спираль энтропии»: связанность, цикломатическая сложность, когнитивная перегрузка и взлом награды

Что нужно, чтобы ИИ заработал [вам денег]

1. Первое — процесс. Код можно сгенерировать за полчаса, а потом две недели ходить по согласованиям и ревью и постоянно разруливать конфликты. И выясняется, что дело вообще не в написании кода, а во всём, что вокруг него. С этим неплохо помогает trunk-based разработка, но её тоже надо уметь готовить. Если организация не умеет быстро интегрировать изменения, хоть десять агентов запускай, быстрее не станет.

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

3. Третье — маленькие обозримые шаги. Рецепт тот же, что и для trunk-based. Генерируйте гранулярно и отсматривайте результат. Если к вам прилетает мерж-реквест на сто файлов по сто пятьдесят строк в каждом, никто его смотреть не будет. Это уже не разработка, а лотерея, и последствия понятны. Чем меньше diff, тем проще его прочитать, понять и откатить, а накопление ошибок почти всегда начинается там, где шаг оказался слишком большим для проверки.

4. Четвёртое — независимая проверка. Раз агент умеет красить тесты в зелёный, надо отнять у него возможность их править. Нужен отдельный контур ревью и автоматической проверки: человек или другой агент, который эти тесты не писал, зафиксированные golden-кейсы, property-based тесты, то есть всё, что условно тяжело подделать. Выглядит как лишняя бюрократия, но именно это отличает «тесты зелёные» от «код работает». Заодно вы ещё сильнее сужаете пространство решений, что опять же хорошо для результата.

Итог

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

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

Ну а на этом всё. Пишите в комментариях, что всё это шляпа и я ни в чём не разбираюсь.
Больше таких разборов — в Telegram и на Спонсоре
В телеграм-канале я делюсь короткими заметками, а на Спонсоре лежат большие тексты и гайды, например по Value Object.
Читайте также