Создание чат-бота технической поддержки

,

Добавить AI-чатбота в Discourse несложно (благодаря двум отличным плагинам). А вот создать чатбота, способного оказывать техническую поддержку, — задача гораздо сложнее! В этом посте мы делимся опытом настройки чатбота для технической поддержки на support.suretyhome.com: чего мы хотели, с какими проблемами столкнулись, как их решили и куда двигаться дальше.

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

  • Доступен 24/7, включая ночи и выходные, так же как и наш форум
  • Отвечает мгновенно, тогда как наша человеческая команда поддержки тратит на это немного больше времени
  • Может отвечать на вопросы, на которые пользователи не смогли бы найти ответы через поиск по форуму

Вот наш опыт.

Выбор плагина

Существует два действительно хороших плагина, предлагающих AI-чатбота:

  1. Discourse AI
  2. Discourse Chatbot

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

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

Мы получили много полезной помощи. В итоге мы выбрали Discourse Chatbot, так как он более гибкий как чатбот и предлагает больше возможностей («фишек») для настройки. Наш сценарий использования имел специфические требования, которые пока казались невыполнимыми в Discourse AI. Оба варианта могут быть отличным выбором. Какой из них подходит именно вам, зависит от конкретных потребностей вашего форума.

Первоначальная настройка

Первоначальная настройка Discourse Chatbot может стать целым проектом, поскольку существует множество опций и возможностей для кастомизации. Внимательно следуйте инструкциям по настройке и обязательно изучите все параметры.

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

  • Настройка Discourse Chat (Discourse Chatbot зависит от него)
  • В настройках Discourse Chatbot: параметр chatbot permitted in chat (чатбот разрешен в чате) — включен

Инженерия промптов

Discourse Chatbot невероятно настраиваем. Всё, что не является отдельной настройкой, кастомизируется через раздел Customize > Text (Настройка > Текст). Именно здесь происходит вся работа по инженерии промптов. В разделе Customize > Text выполните поиск по chatbot.prompt, чтобы отфильтровать все настраиваемые тексты промптов.

Чтобы заставить бота вести себя так, как мы хотим, нам нужно отредактировать системный промпт. Но их два: один для публичных обсуждений, другой — для приватных. Поскольку мы используем бота только в приватных каналах чата, нам нужно было отредактировать chatbot.prompt.system.rag.private.

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

  • Кто ваш бот? Какую роль он должен играть?
  • Какая фоновая информация или контекст ему необходимы?
  • Какие темы он должен обсуждать? Какие темы ему никогда не следует затрагивать?
  • Какой стиль письма или тон он должен использовать?
  • Что он должен делать, когда пользователь расстроен?

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

Температура и Top P

Еще один инструмент для того, чтобы сделать бота более консервативным и менее склонным к выдумыванию фактов, — это настройка температуры. По умолчанию значение температуры составляет 100, что равно 50% от максимального значения. Вы можете снизить её ещё больше, чтобы сделать бота более консервативным или детерминированным, уменьшив вероятность ошибок. Но при очень низком значении температуры (например, 0) LLM звучит не так впечатляюще. Это компромиссное решение, которое вам придется принять.

Помимо температуры, существует настройка Top P. Вероятно, она вам не понадобится, но она есть, если вдруг потребуется. Обратитесь к документации OpenAI для получения дополнительной информации.

Настройки Discourse Chatbot для этого раздела:

  • chatbot request temperature
  • chatbot request top p

Проблема: неточность и устаревание данных LLM

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

RAG будет искать дополнительную информацию на форуме перед ответом пользователю. Как бот технической поддержки, мы не можем полагаться только на обученные знания LLM; нам нужно, чтобы бот искал техническую информацию на нашем форуме перед ответом.

Для работы RAG плагин Discourse Chatbot должен создать базу данных «векторных представлений» (embeddings), представляющих каждый пост на форуме как вектор семантических «признаков». Это нужно включить, но я рекомендую подождать с включением до настройки стратегии embeddings, о которой мы поговорим в следующем разделе.

Настройки Discourse Chatbot для этого раздела:

  • chatbot bot type high trust: RAG
  • chatbot bot type medium trust: RAG
  • chatbot bot type low trust: RAG
  • chatbot embeddings enabled: enabled (после настройки стратегии embeddings)

Проблема: многие посты на форуме бесполезны

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

В Discourse Chatbot для этого используется стратегия categories embeddings (стратегия категорий embeddings). Стратегия embeddings определяет, какие посты доступны чатботу при поиске по форуму. Наш подход заключается в использовании одной непубличной категории в качестве базы знаний чатбота, поэтому мы выбираем categories в качестве стратегии embeddings. Категория базы знаний также должна быть указана в настройке embeddings categories.

Мы используем непубличную категорию (видимую только сотрудникам), потому что дублируем в ней множество публичных тем и не хотим, чтобы пользователи видели эти дубликаты. Дублирование тем в приватную категорию создает несколько других проблем.

  1. Это требует больших усилий для копирования, а ещё сложнее поддерживать копии при обновлении тем или получении новых ответов.
  2. Темы, которые находит бот при поиске по форуму, не являются публичными темами, ссылки на которые следовало бы давать пользователям в качестве справочного материала. Нам нужно отправлять LLM ссылки на публичные темы.

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

Инструменты KB импортируют целую публичную тему в приватную категорию KB как новую тему с одним постом, объединяя все посты публичной темы и добавляя ссылку на каждый публичный пост перед его содержимым. Таким образом, когда бот находит пост в приватной KB во время поиска RAG, он получает содержимое всей публичной темы и URL-адреса публичных постов, которые может включить в ответ в качестве ссылок.

Настройки Discourse Chatbot для этого раздела:

  • chatbot embeddings strategy: categories
  • chatbot embeddings categories: (ваша приватная категория KB)
  • chatbot forum search function include topic titles: disabled (по умолчанию)

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

  • chatbot.prompt.function.forum_search.answer.topic.each.post: Удалить %{username} и %{date}
  • chatbot.prompt.function.forum_search.answer.topic.each.topic: Удалить %{title} и %{url}

Проблема: LLM недостаточно часто использует поиск RAG

Теперь, когда у нас есть приватная категория с отобранными постами, содержащими только качественную информацию в качестве базы знаний чатбота, всё должно быть в порядке, верно? Нет. Следующей проблемой, с которой мы столкнулись, было то, что функция поиска RAG использовалась LLM недостаточно часто.

Такие LLM, как GPT-4, слишком умны, чтобы быть безопасными. Они часто «думают», что уже знают ответ, и не нуждаются в помощи, хотя на самом деле им следует выполнить поиск RAG и найти ответ в базе знаний. Чтобы решить это, мы используем опцию выбора инструмента (tool choice) и заставляем LLM вызывать функцию.

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

Настройки Discourse Chatbot для этого раздела:

  • chatbot tool choice first iteration: force_a_function

Проблема: производительность поиска по форуму

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

Например, представьте, что пользователь спрашивает бота, как остановить писк принтера HP Laser Jet. LLM может выполнить поиск по форуму с запросом «HP LaserJet stop beeping». В базе знаний может быть пост, который идеально решает эту проблему, но «вопросная» часть этого поста (которая наиболее точно соответствует запросу) составляет лишь 2% текста поста. Остальные 98% текста — это шаги по устранению неполадок и ответы.

Локальный поиск по форуму в Discourse Chatbot является семантическим поиском, который использует векторные представления для нахождения поста (или нескольких постов), наиболее похожих на запрос. Вопросная часть лучшего поста очень похожа на запрос, но она составляет лишь 2% от общего текста. Остальные 98% текста делают пост менее похожим на запрос, поэтому пост не занимает высоких позиций в результатах поиска по этому запросу.

Наше решение этой проблемы — добавление «постов-приманок» (bait posts) в темы базы знаний, содержащих только текст, похожий на поисковый запрос. В нашем примере выше мы могли бы добавить пост-приманку с текстом «HP Laser Jet beeping». Функция локального поиска по форуму легко найдет пост-приманку, так как он очень похож на запрос. Затем Discourse Chatbot отправит LLM содержимое реального поста, включающее ответ, вместо поста-приманки.

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

Настройки Discourse Chatbot для этого раздела:

  • chatbot forum search function results content type: topic
  • chatbot forum search function results topic max posts count strategy: just_enough
  • chatbot forum search function results topic max posts count: 1

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

Сочетание RAG, отобранной базы знаний, принудительного вызова функции LLM и постов-приманок в итоге привело к созданию довольно хорошего чатбота технической поддержки! :boom: :tada: :partying_face:

LLM галлюцинирует URL-адреса

Хотя бот хорошо справлялся с ответами на технические вопросы, у него всё ещё была раздражающая проблема галлюцинаций. Он часто придумывал URL-адреса в ответах пользователю. Это известная проблема LLM, и общее мнение таково, что с этим просто нужно смириться. Мы не хотели, чтобы наши пользователи с этим сталкивались.

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

Наше решение — добавить ограничение для бота, чтобы он мог включать URL-адрес в свой ответ только в том случае, если этот URL-адрес был получен из результата поиска по форуму. Если LLM попытается включить URL-адрес, которого не было в результатах поиска по форуму, то Discourse Chatbot сообщит LLM о проблеме и попросит попробовать снова. Этот простой обходной путь эффективно устранил галлюцинации URL-адресов.

Настройки Discourse Chatbot для этого раздела:

  • chatbot url integrity check: enabled

Проблема: чатбот не может справиться со всем

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

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

В любой из этих ситуаций, когда бот не может решить проблему, нам нужно, чтобы он эскалировал чат нашей человеческой команде поддержки. В Discourse Chatbot есть функция для LLM, чтобы сделать именно это, она называется escalate to staff (эскалировать персоналу).

Настройки Discourse Chatbot для этого раздела:

  • chatbot escalate to staff function: enabled
  • chatbot escalate to staff groups: (группа, которой должна быть передана эскалация)

Мы уже заставляем LLM вызывать функцию перед ответом, но теперь возникает вопрос: какую функцию вызывать? Должна ли LLM вызывать функцию local forum search (локальный поиск по форуму, RAG) или функцию escalate to staff (эскалировать персоналу)? Ей приходится принимать это решение каждый раз, когда пользователь отправляет ей сообщение. В большинстве случаев мы хотим, чтобы она вызывала local forum search. Мы хотим, чтобы она эскалировала персоналу только тогда, когда не может решить проблему, замечает, что пользователь расстроен, или пользователь явно просит об этом.

Мы используем промптинг, чтобы направлять LLM в принятии решения о том, какую функцию вызывать. Тексты промптов, которые можно редактировать для этого в разделе Customize > Text:

  • chatbot.prompt.system.rag.private
  • chatbot.prompt.function.forum_search.description
  • chatbot.prompt.function.escalate_to_staff.description

Проблема: невозможность мониторинга чатов

Когда пользователи фактически используют чатбота, полезно просматривать разговоры и отслеживать плохие ответы или возможности для улучшения. Но Discourse не предоставляет администраторам возможности читать чаты, что логично, так как чаты обычно являются приватными разговорами между людьми. Однако чаты с ботом поддержки не являются приватными разговорами, и если мы не можем их просматривать, мы не можем постоянно улучшать бота.

Хорошая новость в том, что Discourse предоставляет администраторам возможность экспортировать всю историю чатов форума в файл CSV.

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

Подведение итогов

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

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

Мы видим, что около половины чатов требуют эскалации персоналу. Около половины из этих эскалированных случаев — это ситуации, с которыми бот физически не мог справиться. Другая половина (около 25% всех чатов) — это случаи, когда бот мог бы решить проблему, но не справился, что является возможностью для улучшения.

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

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

Discourse Chatbot добавил поддержку гибридного поиска (как семантического, так и текстового), пока мы работали над этим проектом, поэтому, вероятно, мы скоро попробуем это.

Спасибо @merefield за всю его тяжелую работу над плагином Discourse Chatbot! С ним было очень интересно работать, и он доказал, что справляется с задачей.

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

14 лайков

К сведению, это будет реализовано в Discourse AI согласно:

Я согласен, что это довольно важная функция для RAG: LLM часто ленивы и отказываются выполнять поиск.

6 лайков