Files
Andrey 91fab586fa ✨ feat(deploy): сохранить override и постоянные dev-окружения
Сохранить порядок дополнительных Compose-файлов при обновлении и подключать их помощнику на чтение. Добавить проверки override, постоянных каталогов dev-данных и документацию проекта. Явно задать русский язык в тестах русских подписей.
2026-10-01 18:18:58 +03:00

359 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p align="center">
<img src="apps/internal-ui/public/favicon.svg" alt="Chatballs" width="88" height="88">
</p>
<h1 align="center">Chatballs</h1>
<p align="center"><strong>ИИ-платформа клиентской поддержки</strong></p>
<p align="center">
ИИ-платформа, которая ведёт диалоги с клиентами вместо вас: отвечает в мессенджерах, почте и на сайте и передаёт сотрудникам только сложные вопросы.
</p>
<p align="center">
<a href="README.md">English version</a>
</p>
<p align="center">
<img alt="Self-hosted" src="https://img.shields.io/badge/self--hosted-one%20command-1677ff">
<img alt="Docker Compose" src="https://img.shields.io/badge/docker-compose-2496ED?logo=docker&logoColor=white">
<img alt="Bring your own model" src="https://img.shields.io/badge/AI-bring%20your%20own%20model-6f42c1">
<img alt="License: AGPL-3.0" src="https://img.shields.io/badge/license-AGPL--3.0-blue">
</p>
---
<p align="center">
<img src=".github/assets/cover.jpg" alt="Рабочее место Chatballs: список диалогов, переписка и карточка контакта" width="1024">
</p>
<p align="center">
<a href="https://t.me/chat_balls">Телеграм-канал</a>
&nbsp;&middot;&nbsp;
<a href="https://chatballs.ru">Сайт</a>
&nbsp;&middot;&nbsp;
<a href="https://chatballs.com.edevs.tech/">Центр помощи</a>
</p>
---
## Содержание
- [Что это](#что-это)
- [Установка](#установка)
- [Требования](#требования)
- [Шаг 1. Запуск](#шаг-1-запуск)
- [Шаг 2. Мастер первого запуска](#шаг-2-мастер-первого-запуска)
- [Шаг 3. Настройка в интерфейсе](#шаг-3-настройка-в-интерфейсе)
- [Виджет на сайте](#виджет-на-сайте)
- [Звонки](#звонки)
- [Внешнее хранилище файлов (опционально)](#внешнее-хранилище-файлов-опционально)
- [Обновление](#обновление)
- [Функции](#функции)
- [Решение проблем](#решение-проблем)
- [Лицензия](#лицензия)
---
## Что это
Chatballs берёт на себя первую линию общения с клиентами. ИИ-агент отвечает по вашей базе знаний в Telegram, MAX, ВКонтакте, электронной почте и в чате на сайте. Когда агент не уверен в ответе или клиент просит человека, диалог уходит вашим сотрудникам вместе с уведомлением.
Платформа ставится на ваш сервер одной командой. Данные клиентов остаются у вас. ИИ-модель вы подключаете сами по своему ключу.
---
## Установка
### Требования
| | |
|---|---|
| **Сервер** | Linux, x86_64 |
| **ПО** | Docker и плагин Docker Compose |
| **Порты** | 80 и 443 открыты |
| **Порты для звонков** | 3478 (UDP и TCP) и диапазон UDP 49160–49999 |
Домен на старте не нужен. Установка открывается по IP-адресу сервера, домен задаётся позже в настройках.
### Шаг 1. Запуск
Скачайте `compose.yaml` со страницы релиза и поднимите стек:
```bash
curl -fsSL https://github.com/dartdavros/chatballs/releases/latest/download/compose.yaml -o compose.yaml
```
```bash
docker compose up -d --wait
```
Больше ничего настраивать не нужно. Файла `.env` у продукта нет: секреты установки генерируются при первом запуске и хранятся в томе Docker. Всё остальное настраивается в интерфейсе.
Что происходит при первом запуске:
1. Генерируются секреты установки: ключ подписи, пароли ролей базы данных, ключ шифрования, секрет TURN.
2. Поднимаются PostgreSQL с pgvector и Redis.
3. Выполняются миграции базы.
4. Стартуют приложение, фоновый воркер, фронтенд и шлюз Caddy.
### Шаг 2. Мастер первого запуска
Откройте в браузере `http://<IP сервера>/`. Мастер попросит:
- название организации;
- имя, почту и пароль владельца;
- поставить ли демо-данные, чтобы посмотреть продукт на примере.
После этого вы сразу оказываетесь в системе как владелец.
### Шаг 3. Настройка в интерфейсе
Всё дальнейшее делается в разделе **Настройки**.
| Раздел | Что сделать |
|---|---|
| **Платформа** | Укажите домен установки. Шлюз сам выпустит сертификат Let's Encrypt и переведёт работу на HTTPS. Здесь же задаётся исходящая почта по SMTP: она нужна для приглашений сотрудников и восстановления паролей. |
| **Интеграции** | Подключите провайдера ИИ-моделей: OpenRouter, любой OpenAI-совместимый сервис или локальную модель. Для первого знакомства есть демо-провайдер, которому не нужен ключ. Затем подключите точки входа: бота Telegram, бота MAX, сообщество ВКонтакте, почтовый ящик по IMAP/SMTP или веб-виджет для сайта. |
| **Агенты** | Создайте ИИ-агента: кто он, как говорит, по каким правилам работает. Выберите модель. Прикрепите статьи из базы знаний. |
| **Сотрудники** | Пригласите команду по почте, распределите роли и группы. |
На главном экране есть чек-лист запуска: создать агента, подключить точку входа, пригласить сотрудников.
### Виджет на сайте
После создания веб-виджета вставьте на сайт один тег:
```html
<script src="https://<ваш домен>/chat-widget.js" data-widget-key="<ключ виджета>" async></script>
```
Чат откроется в изолированном окне поверх сайта.
Данные посетителя передаются через `Chatballs.setFields()`. Чтобы вызвать его до загрузки асинхронного скрипта, объявите очередь перед тегом подключения:
```html
<script>
window.Chatballs = window.Chatballs || { q: [], setFields: function (fields) { this.q.push(fields); } };
Chatballs.setFields({ name: "Иван", email: "ivan@example.com" });
</script>
```
Каждый вызов обновляет только переданные ключи; `null` очищает значение. Свои поля сначала добавьте в настройках веб-подключения. Виджет объединяет обновления и отправляет их не чаще раза в 500 мс. Значения не используются для авторизации клиента.
### Звонки
Звонки работают сразу после установки. Между браузерами разговор идёт напрямую, а если одна из сторон за строгим NAT или в VPN — через relay, который поднимается вместе со стеком на том же адресе. Настраивать нечего: адреса relay появляются в **Настройки → TURN для звонков** сами, от адреса установки, и меняются только если вы ставите свой сервер.
На файрволе нужно открыть:
- 3478/udp и 3478/tcp — сам relay;
- 49160–49999/udp — порты разговоров (по два на звонок).
Сети, где наружу разрешён только порт 443, relay на 3478 не пройдут. Для них нужен TURN-over-TLS на 443, а это отдельный публичный адрес (443 на основном занят веб-шлюзом) либо внешний TURN-сервис — его адреса вписываются в те же настройки.
### Внешнее хранилище файлов (опционально)
По умолчанию файлы хранятся в томе Docker. В **Настройки → Хранилище** можно переключить установку на любое S3-совместимое хранилище. Уже загруженные файлы переносятся автоматически.
### Обновление
Когда выходит новый релиз, администратор установки видит баннер в интерфейсе и обновляется одной кнопкой; то же есть в **Настройки → Платформа → Обновления**. Установка идёт на сервере сама: скачивается `compose.yaml` релиза, загружаются образы, сервисы перезапускаются, приложение недоступно около минуты.
Вручную, из консоли сервера: скачайте `compose.yaml` нового релиза поверх старого и повторите запуск:
```bash
docker compose pull && docker compose up -d --wait
```
Миграции выполняются автоматически. Секреты и данные остаются в томах.
---
## Функции
### ИИ-агент отвечает клиентам сам
Настраивается за минуты: кто он, как говорит, по каким правилам работает. Отвечает только по вашим знаниям и не выдумывает. Если данных нет, честно говорит об этом и предлагает позвать сотрудника.
### Умная передача человеку
Когда агент не находит ответа или клиент просит живого сотрудника, диалог сразу уходит операторам с уведомлением. У каждого диалога три режима: отвечает ИИ, отвечает сотрудник, пауза.
### Все каналы в одном окне
Telegram, MAX, ВКонтакте, электронная почта и чат на сайте попадают в единый список диалогов. Сотрудник видит, откуда пришёл клиент, и отвечает в том же канале.
### База знаний с семантическим поиском
Статьи, категории, импорт из файлов, вложения. Агент находит нужное по смыслу, а не только по совпадению слов. Если провайдер не даёт эмбеддинги, поиск работает по тексту без потери функциональности.
### Публичный центр помощи
Портал с вашими статьями на своём домене и в своём оформлении. Категории, ревизии статей, оценка полезности от читателей. Агент отвечает по тем же статьям: правка статьи сразу меняет ответы бота.
### Чат на сайте одним тегом
Виджет ставится одной строкой кода и работает в изолированном окне. Голосовые сообщения, файлы, звонки. Ограничение по доменам и защита от злоупотреблений настраиваются в интерфейсе.
### Аудио- и видеозвонки из чата
Клиент и сотрудник созваниваются прямо из диалога без сторонних сервисов. Работает в веб-виджете, Telegram, MAX и ВКонтакте. Для сложных сетей есть relay.
### Рабочее место оператора
Приоритеты, цветные метки, заметки к диалогу, назначение на сотрудника, шаблоны ответов. Голосовые сообщения с расшифровкой по кнопке. Файлы и картинки. Уведомление звуком о новом сообщении.
### Единая карточка клиента
Один человек из разных каналов собирается в один профиль. Дубли сливаются вручную с указанием причины и возможностью отката. Список клиентов выгружается в CSV.
### Команда и доступы
Роли владельца, администратора и сотрудника. Приглашения по почте. Группы видимости: сотрудник видит диалоги своих групп и те, где он ответственный. Двухфакторная защита по TOTP. Полный журнал действий с фильтрами.
### Уведомления сотрудникам в мессенджер
Ждущие диалоги и новые сообщения приходят сотруднику в Telegram или MAX. Привязка делается из профиля одноразовым кодом.
### Свой сервер и своя ИИ-модель
Ставится одной командой, данные остаются у вас. Подключаете любого провайдера ИИ-моделей по своему ключу: OpenRouter, OpenAI-совместимый сервис, локальная модель.
### Защита данных клиентов
Телефоны, адреса почты и длинные числовые идентификаторы вырезаются из текста перед отправкой в ИИ-модель. Токены интеграций, пароли SMTP, ключи S3 и секреты TOTP хранятся в базе в зашифрованном виде.
---
## Решение проблем
<details>
<summary><strong>Стек не поднимается: порт 80 или 443 занят</strong></summary>
Шлюз публикует порты 80 и 443. Освободите их, привяжите шлюз к конкретному IP через переменную `CHATBALLS_WEB_LISTENING_IP` или используйте [Compose override за существующим nginx](docs/deployment-overrides.ru.md).
</details>
<details>
<summary><strong>Установка открывается по IP, но не по HTTPS</strong></summary>
Это нормально до того, как задан домен. Укажите домен в **Настройки → Платформа**. Убедитесь, что DNS-запись домена ведёт на сервер, а порты 80 и 443 доступны снаружи: без этого сертификат не выпустится.
</details>
<details>
<summary><strong>После смены домена сертификат не выписывается</strong></summary>
Сертификаты выпускаются по требованию, при первом обращении к домену. Откройте домен в браузере и подождите несколько секунд. Если не помогло, посмотрите журнал шлюза:
```bash
docker compose logs gateway
```
</details>
<details>
<summary><strong>Мастер первого запуска говорит «Первый запуск уже выполнен»</strong></summary>
Организация уже создана. Войдите по адресу установки под учётной записью владельца. Если пароль утерян, воспользуйтесь восстановлением по почте: для этого должна быть настроена исходящая почта.
</details>
<details>
<summary><strong>Приглашения и письма не уходят</strong></summary>
Проверьте SMTP в **Настройки → Платформа**. Там есть кнопка отправки тестового письма. Типичные причины: не тот порт, выключенный TLS, пароль приложения вместо пароля учётной записи.
</details>
<details>
<summary><strong>Агент не отвечает клиентам</strong></summary>
Проверьте по порядку:
1. Агент в статусе **Активен**, а не **Черновик**.
2. У агента выбран провайдер ИИ-моделей. Без него ответ невозможен.
3. Провайдер в **Интеграциях** имеет статус **Подключено**. Нажмите проверку, чтобы обновить статус.
4. Диалог не переведён в режим **Оператор** или **Пауза**.
</details>
<details>
<summary><strong>Интеграция в статусе «Ошибка»</strong></summary>
Откройте интеграцию и нажмите проверку. Для ботов частая причина: неверный токен или недоступный прокси. Для почты: неверные параметры IMAP или SMTP. Ошибки интеграций также приходят уведомлением.
</details>
<details>
<summary><strong>Сообщения из Telegram, MAX или ВКонтакте не приходят</strong></summary>
Фоновый воркер опрашивает ботов. Проверьте, что он запущен:
```bash
docker compose ps worker
```
```bash
docker compose logs worker
```
</details>
<details>
<summary><strong>Звонки не соединяются</strong></summary>
Между браузерами звонок идёт напрямую, за строгим NAT и в VPN — через relay. Проверьте, что контейнер `coturn` работает (`docker compose ps coturn`), а на файрволе открыты 3478/udp, 3478/tcp и диапазон 49160–49999/udp. В **Настройки → TURN для звонков** адреса должны быть непустыми: они строятся от адреса установки, поэтому сначала должен быть задан сам адрес.
</details>
<details>
<summary><strong>Миграции падают с ошибкой «must be owner of table»</strong></summary>
Права на объекты схемы принадлежат другой роли. Нормализуйте владение и повторите миграции:
```bash
docker compose exec -T postgres psql -v ON_ERROR_STOP=1 -U chatballs_bootstrap -d chatballs -f /chatballs-reassign-ownership.sql
```
```bash
docker compose run --rm init
```
</details>
<details>
<summary><strong>Файлы не загружаются или не открываются</strong></summary>
При локальном хранении файлы лежат в томе `chatballs-media`. Проверьте свободное место на диске. При S3 откройте **Настройки → Хранилище**: там отображается последняя ошибка подключения и статус переноса.
</details>
<details>
<summary><strong>Виджет не появляется на сайте</strong></summary>
Проверьте, что виджет в статусе **Опубликован**, а домен сайта добавлен в список разрешённых. Ключ в атрибуте `data-widget-key` должен совпадать с ключом из настроек виджета.
</details>
<details>
<summary><strong>Как проверить, что всё работает</strong></summary>
```bash
docker compose ps
```
Все сервисы должны быть в состоянии `healthy` или `running`. Готовность приложения проверяется по адресу `/api/v1/health/ready/`.
</details>
<details>
<summary><strong>Не удаляйте том с секретами</strong></summary>
В томе `chatballs-secrets` лежит ключ шифрования. Без него станут нечитаемы токены интеграций, пароли SMTP, ключи S3 и секреты двухфакторной защиты. В томах `chatballs-secrets-platform` и `chatballs-secrets-schema` лежат пароли ролей базы: без них стек не подключится к собственной базе. Включайте все три тома в резервные копии вместе с базой и файлами.
</details>
<details>
<summary><strong>Резервная копия</strong></summary>
Копируйте тома `chatballs-postgres`, `chatballs-media`, `chatballs-secrets`, `chatballs-secrets-platform` и `chatballs-secrets-schema`. Для базы можно снять дамп:
```bash
docker compose exec -T postgres pg_dump -U chatballs_bootstrap chatballs > backup.sql
```
</details>
---
## Лицензия
Chatballs распространяется по лицензии [GNU Affero General Public License v3.0](LICENSE). Продукт можно свободно использовать, менять и ставить у себя. Если вы меняете его и предоставляете другим как сервис, изменения нужно опубликовать под той же лицензией.