- BrainTools - https://www.braintools.ru -
Переговоры начались стандартно: рукопожатия, слайды. Потом пошли возражения: «Зачем нам менять наш офис на ваш?», «Сможете пояснить нестыковки в документации?», «А чем докажете, что ваше решение лучше?» — и Рома «поплыл».
Меня зовут Вадим Бадиков, я специалист по анализу данных и я работаю в «Синимекс». Как вы возможно уже догадались по заголовку и небольшому спойлеру выше, я буду рассказывать что-то про продажи — точнее, про нашего ИИ-тренера по продажам. Берите поп-корн, наливайте кофе — поехали.
Создать ИИ-тренажер для менеджеров по продажам нас заставил провал на одной встрече. В целом, эта история будет о разработке, ошибках и о том, как мы в итоге научили машину тренировать людей.
Чтобы было понятнее, начну с вымышленного примера. Дано: условная компания «Докбокс», молодой IT-стартап, который создает свой «умный офис» — пакет корпоративных приложений, призванный заменить привычные решения от Microsoft или Google.
У «Докбокса» уже есть несколько внедрений, но для роста нужны новые клиенты, и как можно больше. Для этой цели в команду наняли Романа, нового менеджера по продажам.
Роман — начинающий специалист с минимальным практическим опытом [1] в B2B. Взяли его, что называется, на вырост — развивать продажи с нуля. Общительный, отзывчивый, он производил впечатление [2] человека, созданного для этой работы. Оставалось проверить теорию практикой.
Переговоры начались стандартно: рукопожатия, слайды. Все шло по плану, пока клиенты не начали задавать вопросы. А потом пошли возражения: «Зачем нам менять наш офис на ваш?», «В документации есть моменты, которые надо бы прояснить», «Не вызывает доверия». На эти и подобные выпады менеджер не смог дать убедительного ответа, его реакция [3] была неуверенной, и Рома «поплыл».
Итог был предсказуем: продажа не состоялась. И всё же Роман неглупый парень — проанализировал встречу, выделил три ключевые ошибки [4]. Первая — неумение работать с возражениями. Вторая — как следствие, недостаток уверенности в диалоге. И третья, фундаментальная — слабое знание продукта и сопроводительной документации, что и стало первопричиной провала.
Казалось бы, в чем проблема? Отправляй новичка «в поля», пусть набивает шишки, общается с клиентами и продает. На десятой встрече, может, и получится. Но в B2B-сегменте цена такого «обучения» — это потерянные лиды и вполне реальные деньги. Приставить к каждому новичку опытного наставника — тоже не выход. У наставников свои дела и KPI, а их оценка всегда будет нести отпечаток личного опыта. Нужен был тренажер — объективный, всегда доступный и способный моделировать диалоги любой сложности. Таким решением для нас и стал ИИ-тренер.
Мы сформулировали три ключевых требования к будущей системе. Во-первых, тренажер должен уметь отрабатывать полный цикл продажи от лица клиента: начиная с приветствия и заканчивая фиксацией договоренностей. Во-вторых, он должен моделировать живой диалог: задавать вопросы, возражать и, что принципиально важно, проверять утверждения менеджера на соответствие фактам из документации. И в-третьих, по итогам симуляции — предоставлять развернутую обратную связь: где сотрудник был убедителен, а какие моменты стоит проработать.
Как и в любом проекте по машинному обучению [5], все начинается с данных. Это наше сырье.
На входе у нас было два типа артефактов: сценарии визитов и техническая документация.
Сценарий визита — это, по сути, партитура диалога: в нем прописаны цели, ключевые тезисы, которые должен донести менеджер, и типовые возражения, с которыми он может столкнуться. В качестве примера мы взяли документацию по нашему продукту «Умный офис».
Техническая документация представляла собой набор PDF-файлов, которые уже используются в работе. Современные языковые модели способны обрабатывать такие документы без сложной предварительной подготовки, что избавляет от необходимости вручную размечать огромные массивы текста.
Теперь к самому интересному — к технической реализации нашего агента. Сразу оговорюсь: собрать такую систему — это не просто взять готовый ChatGPT, скормить ему вопрос и выдать пользователю ответ. Хотя такие решения и существуют, для серьезных задач они не годятся. Мы рассматривали три архитектуры, и две из них сразу отбросили.
Первый вариант, самый очевидный, — архитектура с одним агентом (single-agent). Идея проста: берем одну большую языковую модель и ставим ее как посредника между пользователем и нашими данными. Реализовать такое решение можно быстро, и отклик системы будет моментальным. Но для сложных диалогов, как в нашем тренажере, этот подход не годится. Главный враг здесь — ограниченное окно контекста модели. Любой, кто «общался» с LLM в длинных диалогах, знает этот эффект: после нескольких обменов большими репликами контекст «забивается», модель «плывет» и начинает нести околесицу. Она попросту забывает [6], с чего начинался разговор, и теряет нить беседы.
Вторая проблема, вытекающая из первой, — это неконтролируемая генерация. Когда у модели переполняется эффективный контекст, она перестает следовать инструкциям, которые ей дали в самом начале. В итоге генерация превращается в хаос. Так что, несмотря на всю свою привлекательность и простоту, архитектура с одним агентом для нашей задачи оказалась тупиковым вектором.
Следующий вариант — мультиагентные системы. При таком подходе, набравшем популярность год-полтора назад, вместо одного «мастера на все руки» предполагается использовать команду узкоспециализированных агентов. Они сами кооперируются между собой, чтобы сформировать ответ пользователю. Такая архитектура уже больше походит на то, что мы привыкли понимать под искусственным интеллектом [7]: система автономно решает, какого из своих сотрудников привлечь к задаче или какой внешний инструмент использовать.
Главный плюс мультиагентных систем — их способность решать комплексные, многосоставные задачи. Нужно одновременно получить данные о погоде через API, проверить свежие коммиты в репозитории на GitHub и сходить в базу данных? Пожалуйста. Агенты сделают это независимо друг от друга. Можно создать сколько угодно таких «спецов», каждый со своим уникальным промптом и контекстом: один будет играть роль «педантичного» валидатора, другой — общаться с пользователем, третий — выступать в роли эксперта по конкретной теме, например, по медицине.
Простора для творчества [8] здесь хватает: можно до бесконечности плодить агентов и писать для них промпты. Но у этой гибкости есть обратная сторона — неконтролируемая генерация (и затрачиваемое на нее время), только уже на новом уровне. Взаимодействие агентов превращается в «черный ящик»:
Почему один агент в конкретный момент обратился именно к другому?
С каким вопросом?
Почему получил именно такой ответ?
Понять эту логику [9] невозможно. Система становится непредсказуемой, а ее настройка — мучительной. Можно идеально описать желаемый результат, но система просто не заработает. И для мультиагентной архитектуры такое поведение [10] — норма.
В итоге мы остановились на третьем варианте — sequential prompting, или последовательных запросах. Идея этого подхода в том, чтобы выстроить агентов в цепочку, где каждый выполняет свою узкую задачу и передает результат следующему. Получается своего рода конвейер: один агент получил «деталь», выполнил свою операцию и передал заготовку дальше. И так хоть до ста агентов в цепи (сто — тоже не предел).
Главное достоинство такой архитектуры — генерация становится полностью контролируемой. Мы можем выстроить детерминированную последовательность действий и влиять на формирование ответа на каждом этапе. При этом, как и в мультиагентных системах, сохраняется большой контекст. Основной недостаток — сложность настройки, но, в отличие от «черного ящика» мультиагентов, эта задача хотя бы имеет решение.
Если сравнить три архитектуры — одноагентную, мультиагентную и последовательные запросы, — то для нашей задачи sequential-prompting выглядит наиболее подходящим решением.
Дисклеймер: не факт, что оно подойдет вам — у вас могут быть другие требования к уровню контроля, скорости разработки или генерации ответов.
Теперь к более частным задачам. Любая деловая беседа, если отбросить детали, зачастую строится по классической трехфазовой структуре:
открытие встречи: обменяться любезностями, обсудить погоду, настроиться на диалог, начать диалог;
презентация продукта: рассказать о его пользе, ответить на вопросы, отработать возражения;
закрытие: подвести итоги, договориться о следующих шагах.
Основная идея в том, чтобы разбить определенные инструкции для каждой фазы диалога, чтобы промпты были более легковесными. Такой подход позволяет нам управлять ходом беседы, преследуя на каждом этапе свои цели: сперва — установить контакт, затем — представить продукт и, наконец, — прийти к конкретным договоренностям.
Скажем, для фазы презентации промпт содержит описание продукта, типовые возражения и желаемую структуру диалога. Это помогает модели вести предметный разговор. На этапе закрытия фокус смещается на торги и фиксацию договоренностей.
Но как модель понимает, что пора переключаться на следующую фазу? Через структурированный вывод. Современные модели умеют отвечать не просто текстом, а в формате JSON. Этот объект данных, помимо реплики, может содержать разные служебные параметры, например, команду на смену фазы диалога.
Вот пример «промышленного» промпта (Пример 1). В нем мы жестко прописываем роль («Ты — целевой клиент»), ситуацию («Текущая фаза — открытие визита»), критерии оценки поведения [11] и пример ответа. Такой детальный инструктаж — стандартная практика для реальных AI-агентов.
Пример 1. Пример промпта для открытия
Ты целевой клиент, к которому пришли на встречу …
Ситуация:
— Текущая фаза диалога: "opening" (начало визита).
— В этой фазе допустимо: краткое приветствие, уточнение цели встречи, возможно — пара фраз нейтрального small talk …
Твоя задача:
Ответить на реплику менеджера максимально реалистично … .
Предполагаемый ответ (все в рамках JSON):
{
"phrase": “Добрый вечер!”,
"mg_state_alignment": true,
"mg_next_state_opportunity": false
}
…
Ключевой элемент — требование отдать ответ в JSON. Надо сказать, еще пару лет назад большие языковые модели отвратительно справлялись с этой задачей. Но сегодня они генерируют JSON почти без ошибок, что позволяет легко интегрировать их ответы в программный код и извлекать оттуда данные для дальнейшей обработки.
Наша первая реализация агента выдавала JSON с тремя полями: реплика для пользователя (например, «Добрый вечер») и два служебных флага — MGStateAlignment и MGNextStateOpportunity. Первый флаг подтверждал, что диалог идет по плану, второй — намекал на возможность перехода к следующей фазе, скажем, от светской беседы к презентации. Казалось бы, все учли. Но тесты показали удручающий результат: из 8 диалогов только 2 можно было назвать успешными (см. Таблицу 2).
Быстрые, но беспомощные ответы ботов нас, конечно, не устроили. Проблем вырисовалось несколько:
Огромный контекст, который мы никак не могли ужать, и модель в нем попросту «тонула», выдавая несуразицу.
Неточность промптов. Каждая модель — это черный ящик со своим характером, обусловленным датасетами, на которых ее учили. «Серебряной пули» в промпт-инжиниринге не существует, только метод проб и ошибок.
Формат реплики. Они бывали то слишком детальными на банальное приветствие, то слишком короткие в случае с презентацией, у модели не было вариаций для генерации, а закрывать граничные случаи в промпте практика не очень хорошая.
Чтобы решить эти проблемы, разработали второго агента, задача которого — выбирать наилучшую реплику из нескольких предложенных. Теперь первый агент вместо одной фразы генерирует набор реплик для дальнейшего выбора, например, brief (короткая) или balanced (сбалансированная).
Второй агент, «редактор», анализирует эти варианты, сверяется с историей диалога и выбирает наиболее подходящий (Пример 2). Такая схема позволяет дать модели простор для вариативности и сохранить жесткий контроль над итоговым результатом. К тому же, мы смогли разгрузить первого агента, перенеся часть инструкций во второй, что решило проблему с раздутым контекстом и промптом.
Процесс теперь выглядит так: система определяет фазу диалога, подбирает промпт, первый агент генерирует варианты ответов, а второй — выбирает из них лучший. Этот ответ и уходит пользователю.
Результаты не заставили себя ждать: в 7 из 8 тестовых диалогов бот вел себя не просто корректно, а естественно и живо. Количество «галлюцинаций» заметно снизилось. Цена за такое качество — время ответа, которое, конечно, выросло, но результат того стоил.
Пример 2. Варианты реплик
1. Генерируем вариации реплик
{
"phrases": {
"brief": ["Добрый вечер!", "Здравствуйте"],
"balanced": ["Здравствуйте, слушаю.", "Приветствую, Вадим."]},
…
}
2. Выбираем подходящую
{
"phrase_type" : "brief",
"phrase_pos" : 0
}
Полученная двухступенчатая система стала нашим baseline — рабочей лошадкой, от которой можно было отталкиваться для дальнейших улучшений.
Система стала выглядеть следующим образом:
Выбор промпта учитывая фазу диалога.
Генерация вариаций ответа.
Выбор реплики.
Выдача выбранной реплики пользователю.
Что дальше? Решили добавить в тренажер уровни сложности: легкий, средний и хардкорный (см. рис. 1) и внедрить проверку тезисов во время диалога.
Вопрос со сложностью закрывается тюнингом промптов:
на легком уровне бот — покладистый собеседник, которого легко склонить на свою сторону.
На среднем он уже проявляет характер и требует аргументов.
На сложном уровне агент превращается в настоящего ревизора: он с дотошностью проверяет каждое слово и каждый факт, который пользователь приводит в защиту продукта.
А вот вопрос с проверкой тезисов не так тривиален…
Для примера возьмем диалог:
🤖: Какая рабочая нагрузка у вашего облачного офиса?
🙋🏻♂️: Наша облачная реализация умного офиса выдерживает до 500 пользователей единовременно!
Чтобы научить агента не принимать такие заявления на веру, а проверять их, мы вооружили его технологией RAG — Retrieval-Augmented Generation. Суть этого подхода в том, что большая языковая модель (LLM) для генерации ответа обращается не только к своим внутренним знаниям, но и к внешней, заранее подготовленной базе документов. Фактически, мы даем модели возможность «подсматривать в шпаргалку».
Процесс проверки фактов разбит на три этапа, которые должна выполнить система (рис. 2):
Выделить из реплики пользователя конкретное утверждение и понять, о каком продукте идет речь (Пример 3).
Найти в базе знаний наиболее подходящий фрагмент текста (так называемый «чанк»), который относится к этому продукту.
Передать этот чанк вместе с утверждением в LLM для вынесения вердикта: «верю» или «не верю».
Пример 3.
А. Определить утверждение и релевантный продукт
🙋🏻♂️ - Наша облачная реализация “Умного Офиса Words” выдерживает до 500 пользователей единовременно!
————————————————————————————
🤖 - {
"statements" : ["Облачная версия продукта Умный
Офис Words выдерживает до 500 пользователей"],
"products" : ["Умный Офис Words"]
}
B. Выбрать схожие чанки для продукта
документы (чанки) =
rag_engine.cosine_search
(
text = “... версия продукта Умный Офис Words
выдерживает…”,
filter = “product_name == ‘Умный Офис Words’ ”,
top_k = 5,
…
)
С. Передать чанки и получить вердикт
"
Ты эксперт по валидации утверждений
Твоя задача: сделай вердикт по утверждению на основе следующего документа
Утверждение: "Облачная версия продукта Умный
Офис Words выдерживает до 500 пользователей"
Документ: “ … нагрузочные тесты на умный Офис Words проводились с 2-мя пользователями в пике (РП и Фронтэнд разработчиком)“
"
Вердикт: Не подтверждено! ❌
Итак, наш Роман не моргнув глазом заявляет о 500 пользователях для облачного «Умного офиса». Чтобы найти релевантную информацию, мы используем векторный поиск.
Утверждение Романа преобразуется в эмбеддинг, который затем сравнивается с эмбеддингами всех чанков в нашей базе знаний. Система находит ближайший по смыслу (т.е. эмбеддингу) фрагмент из продуктовой документации и передает его вместе с исходным тезисом на суд модели. В нашем случае в документации черным по белому написано, что тестирование проводилось только для двух пользователей.
Модель, сравнив «заявлено 500» и «по факту 2», выносит вердикт: «не подтверждено». После чего агент тактично отвечает
🤖: «Роман, я бы не был так уверен в этих данных».
Таким образом, агент указывает на несоответствие.
Подведем итоги. На данный момент прототип находится на стадии тестирования. Он уже демонстрирует хорошие коммуникативные навыки, и у нас появились заинтересованные в этом AI-тренере клиенты. Мы проводим апробацию системы в различных направлениях.
Согласно расчетам KPI для компании, мы прогнозируем следующие показатели. Мы ожидаем, что у среднего сотрудника (условного «Романа»), который будет регулярно использовать нашу систему для совершенствования навыков и практики с AI-ассистентом, частота запросов на коммерческие предложения (офферы) вырастет как минимум на 15%. Кроме того, прогнозируется рост конверсии в согласованные пилотные проекты после офферов не менее чем на 20%. Подчеркну, что это расчетные показатели. Тестирование завершилось лишь неделю назад, и реальной статистики с полей у нас пока нет.
В качестве бонуса и для поднятия настроения прилагаю список проблем, которые у нас возникли при промпт-инжиниринге (мы каждый промпт переписывали в среднем по 12 раз — ниже ответы почему):
Тренер был то непроходимым, то со всем соглашался, то не соглашался.
Тренер может попытаться “блеснуть” знаниями в диалоге.
Тренер может проигнорировать прямое оскорбление или неуважение в диалоге
Тренер общался неестественно.
Подобрали другую версию GPT — тренер общается по другому (и как правило хуже) независимо от новизны версии GPT.
Слишком вежливый или дотошный.
Просил положить документы на стол.
Легко можно было увести диалог.
Не соглашался на пилот даже после отработки всех возражений.
По первой просьбе писал сортировку пузырьком.
Так что работа продолжается, оставайтесь на связи — и спасибо за ваше внимание [12].
Не забудьте подписаться на наш блог, чтобы быть в курсе.
Автор: aogo
Источник [13]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/28748
URLs in this post:
[1] опытом: http://www.braintools.ru/article/6952
[2] впечатление: http://www.braintools.ru/article/2012
[3] реакция: http://www.braintools.ru/article/1549
[4] ошибки: http://www.braintools.ru/article/4192
[5] обучению: http://www.braintools.ru/article/5125
[6] забывает: http://www.braintools.ru/article/333
[7] интеллектом: http://www.braintools.ru/article/7605
[8] творчества: http://www.braintools.ru/creation
[9] логику: http://www.braintools.ru/article/7640
[10] поведение: http://www.braintools.ru/article/9372
[11] поведения: http://www.braintools.ru/article/5593
[12] внимание: http://www.braintools.ru/article/7595
[13] Источник: https://habr.com/ru/companies/cinimex/articles/1023050/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1023050
Нажмите здесь для печати.