Проблема: ИИ-боты — это удобно, но иногда они начинают писать отсебятину. Оператору приходится исправлять сообщения уже после отправки, а это убивает и скорость, и качество сервиса.
|
| |
Решение: Собрать своего ИИ-суфлёра. Бот не пишет клиенту напрямую, а предлагает оператору готовый ответ. Оператор решает: отправить, отредактировать или проигнорировать.
|
| |
В этой статье — пошаговое руководство для технических специалистов. Мы разберём архитектуру, настройку webhook, вызов LLM и отправку подсказок через API Verbox.
Если вам не нужна кастомная логика и вы хотите готовое решение — в Verbox есть встроенный режим «Подсказки» в интеграции с Copilot. Это настройка в пару кликов, без кода. Но если вы хотите контролировать всё — читайте дальше.
|
| |
Схема выглядит так:
Клиент пишет в чат
↓
Verbox отправляет webhook на ваш сервер
↓
Ваш сервер принимает данные, отвечает 200 OK
↓
Отдельный воркер забирает задачу, идёт в LLM
↓
LLM возвращает ответ
↓
Ваш сервер вызывает метод Verbox API
↓
Подсказка появляется у оператора в чате
|
| |
Ключевой момент: У Verbox есть таймаут 10 секунд на запрос. Если ваш сервер не ответит за это время — webhook считается неудачным, и Verbox не будет его повторять. Поэтому нельзя идти в LLM прямо в обработчике webhook. Сначала примите данные, ответьте 200 OK, а потом обрабатывайте асинхронно.
|
| |
Зайдите в личный кабинет Verbox: API → Webhooks.
Нажмите «Добавить» в контейнере «Online-чат» и заполните поля:
|
| |
| Поле |
Что указать |
| Название |
Любое, для удобства. Например, «ИИ-суфлёр» |
| URL |
Адрес вашего сервера, который будет принимать webhook |
| Секретный ключ |
Опционально. Verbox передаст его в запросе — вы можете проверить, что запрос от нас |
| Basic Authorization |
Опционально. Дополнительная защита |
| Источник событий |
Выберите ваш сайт (проект) |
| События |
Только «Новое сообщение от клиента» ( newMessageFromClient ) |
|
| |
После сохранения Verbox начнёт отправлять POST-запросы на ваш URL при каждом новом сообщении клиента.
|
| |
Verbox отправляет POST-запрос с JSON в теле. Вот пример payload для события newMessageFromClient:
|
| |
{
"eventId": "newMessageFromClient",
"data": {
"site": {
"id": "acbd18db4cc2f85cedef654fccc4a4d8",
"domain": "site.com"
},
"client": {
"searchId": 123,
"clientId": "sw9dzztkdbec7y8jvfzo9ixs4o6wfp5n",
"name": "Иван",
"phone": "79001234444",
"email": "test@gmail.com"
},
"dialog": {
"id": 33,
"createTimestamp": 1790843869
},
"message": {
"id": 123,
"text": "Добрый день!",
"content": {
"text": "Добрый день!",
"attachments": []
},
"dialogId": 33,
"isVisibleForClient": true
},
"operator": "my_operator",
"whoSend": "client",
"dateTime": "2026-10-01 11:37:49"
},
"secretKey": "2d16c21c6231ef1a698df5238b08ef82"
}
|
| |
Что здесь важно:
- data.message.id — уникальный идентификатор сообщения. Его нужно передать в replyToMessageId, когда будете отправлять подсказку.
- data.message.text — текст сообщения клиента. Это то, что вы отправите в LLM.
- data.message.content — структурированный контент. Если клиент прислал картинку или файл, в text будет ссылка, а в content.attachments — массив вложений.
- data.client.clientId — идентификатор клиента. Его нужно передать в объект client, когда будете вызывать API.
- data.dialog.id — идентификатор диалога. Пригодится, если захотите запросить историю переписки.
- secretKey — тот самый секретный ключ из настроек webhook. Проверьте его на своей стороне, чтобы убедиться, что запрос от Verbox.
|
| |
Пример обработчика на Python (FastAPI):
|
| |
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
import json
import redis
app = FastAPI()
r = redis.Redis(host='localhost', port=6379, db=0)
VERBOX_SECRET_KEY = "ваш_секретный_ключ"
@app.post("/webhook/verbox")
async def verbox_webhook(request: Request):
payload = await request.json()
# Проверяем секретный ключ
if payload.get("secretKey") != VERBOX_SECRET_KEY:
raise HTTPException(status_code=403, detail="Invalid secret key")
# Проверяем событие
if payload.get("eventId") != "newMessageFromClient":
return JSONResponse({"status": "ignored"})
# Кладём задачу в очередь и сразу отвечаем 200 OK
r.lpush("suggestions_queue", json.dumps(payload))
return JSONResponse({"status": "accepted"})
|
| |
Почему так: Мы отвечаем 200 OK мгновенно, а всю тяжёлую работу делаем в отдельном воркере. Это гарантирует, что мы уложимся в 10-секундный таймаут Verbox.
|
| |
Шаг 3. Обработка и вызов LLM
|
| |
Теперь воркер забирает задачу из очереди и идёт в LLM.
Как передать контекст:
LLM можно передать только последнее сообщение клиента. Но для качественных подсказок лучше передать историю диалога. Есть два способа:
- Запросить историю через API Verbox. Используйте метод /chat/message/getDialog, передав dialogId из webhook. В ответе result.messages будут все сообщения диалога.
- Хранить историю на своей стороне. Если вы уже сохраняете переписку, просто используйте её.
|
| |
Пример запроса в LLM (псевдокод):
|
| |
import openai
def get_suggestion(dialog_id, message_text, context_messages=None):
prompt = f"""
Ты — вежливый и компетентный оператор службы поддержки.
Ответь клиенту кратко и по делу.
Клиент: {message_text}
"""
if context_messages:
history = "\n".join([f"{m['whoSend']}: {m['text']}" for m in context_messages])
prompt = f"История диалога:\n{history}\n\n{prompt}"
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
max_tokens=200
)
return response.choices[0].message.content
|
| |
Рекомендации:
- Промпт на ваше усмотрение. Verbox не регламентирует стиль ответов. Хотите лаконично — пишите «отвечай одним предложением». Хотите развёрнуто — просите подробный ответ.
- Ограничения по длине. Формально лимитов нет, но если подсказка идёт в Telegram, там ограничение около 1024 символов. Да и оператору неудобно читать «простыни». Оптимально — 1–3 предложения.
- Обработка не-текстовых сообщений. Если клиент прислал картинку, в message.text будет ссылка. Вы можете либо проигнорировать такое сообщение, либо отправить в LLM текст ссылки (но это малоэффективно).
|
| |
Шаг 4. Отправка подсказки оператору
|
| |
Когда LLM вернула ответ, вызовите метод Verbox API:
POST https://admin.verbox.ru/json/v1.0/chat/message/setSuggestedAnswerToClient
|
| |
Заголовки:
X-Token: ваш_api_токен
Content-Type: application/json
|
| |
Тело запроса:
{
"client": {
"clientId": "sw9dzztkdbec7y8jvfzo9ixs4o6wfp5n"
},
"message": {
"text": "Добрый день! Да, всё верно: заказ 480204 выкуплен, магазин Hyperice уже отправил товар."
},
"replyToMessageId": 123,
"rate": {
"likeUrl": "https://ваш-сервер.com/rate/like?messageId=123",
"dislikeUrl": "https://ваш-сервер.com/rate/dislike?messageId=123",
"isAutoLikeOnUsage": true,
"autoLikeOnUsageSimilarityPercent": 90
}
}
|
| |
Разбор полей:
| Поле |
Описание |
| client.clientId |
Идентификатор клиента из webhook |
| message.text |
Текст подсказки, который сгенерировала LLM |
| replyToMessageId |
ID сообщения клиента, на которое отвечаем. Если клиент написал два сообщения, а LLM думала долго — оператор поймёт, на какое именно сообщение дана подсказка |
| rate.likeUrl |
URL, который Verbox дёрнет, если оператор поставит лайк на подсказке. Если не указать — кнопка лайк не будет показана |
| rate.dislikeUrl |
URL, который Verbox дёрнет, если оператор поставит дизлайк на подсказке. Если не указать — кнопка дизлайк не будет показана |
| rate.isAutoLikeOnUsage |
Если true и есть likeUrl — Verbox автоматически вызовет likeUrl, когда оператор отправит подсказку без изменений (или с изменениями, но процент схожести по Левенштейну выше autoLikeOnUsageSimilarityPercent) |
| rate.autoLikeOnUsageSimilarityPercent |
Порог схожести (в процентах). По умолчанию 100 |
|
| |
Важно: При вызове likeUrl и dislikeUrl Verbox не отправляет payload. Все нужные данные (ID подсказки, ID сообщения) вы должны «зашить» в саму ссылку.
|
| |
Можно ли отправить несколько подсказок на одно сообщение?
Да. Количество не ограничено. Если ваша LLM сгенерировала три варианта — вызовите метод трижды. Оператор увидит все три подсказки в чате.
|
| |
Что если оператор уже ответил?
Подсказка всё равно появится в истории чата, но будет отмечена как «не использованная». Это сделано специально: клиенты просили показывать, какие подсказки генерировала LLM, даже если оператор их не использовал.
|
| |
Шаг 5. Как это выглядит у оператора
|
| |
Подсказка отображается в чате как отдельное сообщение с заголовком «Подсказка» и пометкой «Видна только оператору».
|
| |
Оператор может:
- Отправить — текст подсказки уйдёт клиенту.
- Изменить — текст скопируется в поле ввода, оператор отредактирует и отправит.
- Проигнорировать — подсказка останется в истории как неиспользованная.
|
| |
Если вы настроили likeUrl и dislikeUrl, появятся кнопки «палец вверх» и «палец вниз».
|
| |
Шаг 6. Обратная связь и аналитика
|
| |
Как работает лайк/дизлайк
|
| |
- Если оператор отправил подсказку без изменений и isAutoLikeOnUsage: true — Verbox автоматически вызовет likeUrl.
- Если оператор изменил подсказку и процент схожести по Левенштейну ниже autoLikeOnUsageSimilarityPercent — ничего не отправляется. Дизлайки в авторежиме не отправляются.
- Оператор может вручную поставить лайк или дизлайк — тогда Verbox вызовет соответствующий URL.
|
| |
В личном кабинете Verbox есть готовый виджет «Подсказки для операторов» (в разделе «Отчёты → Сводка», группа AI). Он показывает количество использованных и неиспользованных подсказок.
|
| |
Если нужно больше — используйте конструктор отчётов. Можно собрать отчёт, который покажет:
- Количество использованных подсказок с процентом схожести > X.
- Количество использованных подсказок с процентом схожести < X.
- Диапазоны: 0–50%, 51–70%, 71%+.
|
| |
Best practices и подводные камни
|
| |
- Не идите в LLM синхронно. Примите webhook, ответьте 200 OK, обработайте асинхронно. Иначе не уложитесь в 10 секунд.
- Проверяйте секретный ключ. Verbox передаёт его в payload. Если ключ не совпадает — отклоняйте запрос.
- Не полагайтесь на повтор webhook. Verbox не повторяет запросы, если ваш сервер ответил ошибкой или не ответил. Дедупликация не обязательна, но если у вас несколько webhook на один URL — стоит подстраховаться.
- Учитывайте нестабильность связи. Если ваш сервер находится за рубежом, могут быть проблемы с доступностью из РФ. Размещайте сервер в РФ или используйте прокси.
- Rate limit. Verbox допускает 100 вызовов API в минуту. Если у вас много операторов и высокая нагрузка — предусмотрите очередь.
- Обработка ошибок LLM. Если LLM недоступна — можно ничего не отправлять или отправить комментарий от виртуального оператора через /chat/message/sendToOperator с message.type = "notification".
- Тестовый стенд. Отдельного стенда нет, но вы можете отсеивать запросы не от тестового пользователя на своей стороне.
|
| |
Собрать своего ИИ-суфлёра через API Verbox — задача для технического специалиста, но она вполне решаема. Ключевые моменты:
- Настроить webhook на событие newMessageFromClient.
- Принять данные, ответить 200 OK, обработать асинхронно.
- Отправить текст в LLM, получить ответ.
- Вызвать /chat/message/setSuggestedAnswerToClient, чтобы показать подсказку оператору.
В результате оператор получает готовый ответ, который можно отправить в один клик. Клиент получает быстрый и качественный сервис. Вы получаете контроль над логикой и промптами.
Если что-то осталось неясным — обратитесь в поддержку Verbox.
|
|