Разработка бота для автоматического ответа на FAQ Битрикс24
Половина входящих обращений в чат поддержки — это одни и те же вопросы: «Как вернуть товар?», «Где мой заказ?», «Какие условия доставки?». Оператор тратит на них время, которое дороже стоит на нетипичных проблемах. FAQ-бот закрывает типовые вопросы автоматически и передаёт нестандартные — живому оператору.
Где работает бот
Открытые линии Битрикс24 — основная точка входа. Бот подключается к открытой линии как первый оператор. Когда клиент пишет в онлайн-чат на сайте, в Telegram или VK, обращение попадает боту. Если бот отвечает — оператор не беспокоится. Если нет — передаёт человеку.
Регистрация бота в открытых линиях:
POST /rest/imopenlines.bot.register
{
"CODE": "faq_bot",
"EVENT_HANDLER": "https://your-server.com/openline/event",
"OPENLINE": "Y" // Бот для открытых линий
}
Два подхода к сопоставлению вопросов
Подход 1: Поиск по ключевым словам. Вопросы и ключевые слова хранятся в базе, бот ищет совпадения в тексте сообщения. Просто в реализации, понятно в обслуживании.
CREATE TABLE custom_faq_entries (
id SERIAL PRIMARY KEY,
question TEXT NOT NULL,
answer TEXT NOT NULL,
keywords TEXT NOT NULL, -- через запятую
category VARCHAR(100),
hits INT DEFAULT 0,
is_active TINYINT DEFAULT 1
);
function findFaqAnswer(string $userMessage): ?array {
$words = array_filter(explode(' ', mb_strtolower($userMessage)));
$results = [];
$faqs = getFaqEntries(); // из кеша
foreach ($faqs as $faq) {
$keywords = explode(',', mb_strtolower($faq['keywords']));
$score = 0;
foreach ($keywords as $kw) {
$kw = trim($kw);
if ($kw && (mb_stripos($userMessage, $kw) !== false)) {
$score += mb_strlen($kw); // длинные ключевые слова весомее
}
}
if ($score > 0) {
$results[] = ['faq' => $faq, 'score' => $score];
}
}
if (empty($results)) return null;
usort($results, fn($a, $b) => $b['score'] <=> $a['score']);
return $results[0]['faq'];
}
Подход 2: Векторный поиск (RAG). Вопросы индексируются как эмбеддинги (OpenAI text-embedding-3-small, Yandex GPT Embeddings). При новом вопросе — поиск ближайших соседей в векторной БД (pgvector, Qdrant). Работает на семантически похожих формулировках без точного совпадения слов.
Выбор: для 50–200 FAQ хватает ключевых слов. Для большой базы знаний с вариативными формулировками — RAG.
Обработка события в открытой линии
// Входящее событие от Б24
$event = json_decode(file_get_contents('php://input'), true);
if ($event['event'] === 'ONIMBOTMESSAGEADD') {
$sessionId = $event['data']['PARAMS']['SESSION_ID'];
$dialogId = $event['data']['PARAMS']['DIALOG_ID'];
$text = $event['data']['PARAMS']['MESSAGE'];
$chatId = $event['data']['PARAMS']['CHAT_ID'];
$faq = findFaqAnswer($text);
if ($faq) {
// Отвечаем и закрываем сессию
$b24->callMethod('imopenlines.session.message.send', [
'SESSION_ID' => $sessionId,
'MESSAGE' => $faq['answer'],
]);
// Увеличиваем счётчик hits
incrementFaqHits($faq['id']);
// Закрываем сессию — оператор не получает уведомление
$b24->callMethod('imopenlines.session.close', ['SESSION_ID' => $sessionId]);
} else {
// Передаём оператору
$b24->callMethod('imopenlines.session.transfer', [
'SESSION_ID' => $sessionId,
'QUEUE_ID' => 1,
]);
$b24->callMethod('imopenlines.session.message.send', [
'SESSION_ID' => $sessionId,
'MESSAGE' => 'Соединяю с менеджером, пожалуйста, подождите...',
]);
}
}
Уточняющие вопросы
Если совпадений несколько — бот показывает варианты:
if (count($topResults) > 1 && $topResults[0]['score'] < 10) {
$options = array_slice($topResults, 0, 3);
$message = "Уточните, пожалуйста, что вас интересует:\n";
foreach ($options as $i => $r) {
$message .= ($i + 1) . ". {$r['faq']['question']}\n";
}
$message .= "0. Другое (подключить менеджера)";
// Сохраняем контекст выбора в Redis
$redis->set("faq_choice:{$sessionId}", json_encode($options), 300);
}
Административный интерфейс базы FAQ
Контент-менеджер должен управлять FAQ без правки кода. Разрабатываем административный раздел в /bitrix/admin/ или как приложение в Б24:
- CRUD для вопросов и ответов.
- Категории (Доставка, Оплата, Возврат, Технические вопросы).
- Статистика: сколько раз вопрос был закрыт ботом (
hits), сколько передано операторам. - Просмотр сессий, где бот не нашёл ответ — это приоритет для пополнения базы.
Аналитика эффективности
-- Процент автоматически закрытых сессий
SELECT
DATE(created_at) AS day,
COUNT(*) AS total,
SUM(CASE WHEN closed_by = 'bot' THEN 1 ELSE 0 END) AS auto_closed,
ROUND(SUM(CASE WHEN closed_by = 'bot' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS autoclose_pct
FROM custom_faq_sessions
GROUP BY DATE(created_at)
ORDER BY day DESC;
Целевой показатель автозакрытия для зрелой базы FAQ — 60–70%.
Сроки
| Этап | Срок |
|---|---|
| Регистрация бота в открытых линиях, базовая интеграция | 1–2 дня |
| Структура БД FAQ, поиск по ключевым словам | 2–3 дня |
| Логика передачи оператору, уточняющие вопросы | 2–3 дня |
| Административный интерфейс (CRUD FAQ) | 2–3 дня |
| Аналитика и отчёты | 1–2 дня |
| Наполнение базы + тестирование | 2–3 дня |
Итого: 1.5–2.5 недели без учёта наполнения базы. Наполнение — отдельная работа, зависит от объёма документации.







