Discord
Кузня поддерживает два независимых Discord-канала. Оба опциональны — каждый работает без другого.
Сравнение каналов #
| Rich Presence | Webhook | |
|---|---|---|
| Что показывает | Статус в профиле Discord | Карточки в канале |
| Нужен локальный клиент | Да | Нет |
| Работает по SSH / headless | Нет | Да |
| Сообщений на ран | — | 1 (редактируется на месте) |
| Rate limit | 1 обновление / 15 с | 30 запросов / 60 с |
Rich Presence #
Rich Presence показывает прогресс обучения прямо в статусе Discord-клиента. Другие пользователи видят что-то вроде:
Играет в Кузню
spiral-classifier · adamw lr=0.003
эпоха 23/40 · val_acc 0.876
Статус обновляется не чаще 1 раза в 15 секунд — это ограничение Discord. Кузня применяет коалесценцию: хранит последнее pending-обновление и отправляет его, когда окно открывается.
Настройка Rich Presence — шаги #
-
1
Создайте приложение Discord
- Откройте discord.com/developers/applications.
- Нажмите New Application.
- Введите имя, например
Кузня. - Скопируйте APPLICATION ID (18–19 цифр) со страницы General Information.
-
2
Загрузите арт-ассеты (опционально)
- В левом меню выберите Rich Presence → Art Assets.
- Нажмите Add Image(s) и загрузите файл.
- Дайте ключ, например
kuznya(только строчные латинские буквы, цифры, дефисы). - Этот ключ указывается в
discord.presence.large_image.
Зачем это нужноБез загруженного арт-ассета presence не будет отображаться для других пользователей. Достаточно загрузить любое изображение с ключомkuznya. -
3
Настройте конфиг
json"discord": { "presence": { "enabled": true, "client_id": "1234567890123456789", "large_image": "kuznya", "small_image": "", "show_metrics": true, "buttons": [ {"label": "Репозиторий", "url": "https://example.com/your-repo"} ] } } -
4
Запустите с открытым Discord
Десктопный Discord-клиент должен быть запущен на той же машине. Кузня ищет IPC-сокет в следующем порядке:
- Linux/macOS:
$XDG_RUNTIME_DIR/discord-ipc-{n}, затем snap/flatpak-пути, затем/tmp. - Windows: именованный pipe
\\.\pipe\discord-ipc-{n}.
Если IPC-сокет не найден — Кузня продолжит работу без presence (предупреждение в логе, обучение не прерывается).
- Linux/macOS:
Webhook #
Webhook публикует карточки в Discord-канал. Работает headless — без локального клиента, в том числе по SSH.
В канале появляется одна карточка в начале обучения. По мере прогресса та же карточка редактируется (PATCH). По завершении — обновляется итогами и получает прикреплённый PNG с графиком потерь.
Это значит: 1 POST + N PATCH на ран — никакого спама в канале.
Настройка Webhook — шаги #
-
1
Создайте вебхук в канале
- Откройте настройки канала (иконка шестерёнки рядом с именем).
- Перейдите в Integrations → Webhooks → New Webhook.
- Укажите имя и иконку (по желанию).
- Нажмите Copy Webhook URL.
URL выглядит так:
https://discord.com/api/webhooks/1234567890/ваш-токен-здесь -
2
Сохраните URL в переменной окружения
bashexport KUZNYA_WEBHOOK_URL="https://discord.com/api/webhooks/..."Для постоянного хранения добавьте строку в
~/.bashrcили~/.zshrc. -
3
Настройте конфиг
json"discord": { "webhook": { "enabled": true, "url_env": "KUZNYA_WEBHOOK_URL", "live_panel": true, "attach_curves": true, "notify": ["run_start", "run_end", "best", "crash"] } }Поле
url_envсодержит имя переменной окружения, а не сам URL. Кузня прочитает переменную при запуске.
Безопасность URL #
url_env — Кузня прочитает URL из переменной окружения,
и в конфиг-файл ничего секретного не попадёт.
Безопасно:
"webhook": {
"enabled": true,
"url_env": "KUZNYA_WEBHOOK_URL"
}
Небезопасно (не делайте так, особенно в git):
"webhook": {
"enabled": true,
"url": "https://discord.com/api/webhooks/..."
}
Паттерн: сервер + ноутбук #
Типичный сценарий: обучение идёт на GPU-сервере по SSH, а вы хотите видеть прогресс в Discord на ноутбуке.
Сервер (GPU, headless): Ноутбук (Discord открыт):
┌─────────────────────────┐ ┌──────────────────────────┐
│ kuz train config.json │ │ Discord клиент │
│ + webhook enabled │──POST──► │ #training-log канал │
│ (карточки в канале) │ │ │
└─────────────────────────┘ │ Статус: Кузня │
│ "epoch 23/40 · acc 0.8" │
◄─IPC──── │ (Rich Presence) │
└──────────────────────────┘
Конфиг для сервера — только webhook:
"discord": {
"presence": { "enabled": false },
"webhook": {
"enabled": true,
"url_env": "KUZNYA_WEBHOOK_URL",
"live_panel": true
}
}
Конфиг для ноутбука — только presence:
"discord": {
"presence": {
"enabled": true,
"client_id": "1234567890123456789"
},
"webhook": { "enabled": false }
}
Лимиты API #
Rich Presence
| Параметр | Значение |
|---|---|
| Минимальный интервал обновлений | 15 секунд |
| Как применяется | Коалесценция: хранится только последнее pending-обновление |
details / state | максимум 128 байт UTF-8 |
large_image / small_image (ключ) | максимум 32 байта |
button.label | максимум 31 байт (32 делает кнопку невидимой для других) |
button.url | максимум 512 символов |
| Максимум кнопок | 2 |
Webhook
| Параметр | Значение |
|---|---|
| Rate limit | 30 запросов / 60 секунд на токен |
| Embeds в сообщении | максимум 10 |
| Суммарный бюджет символов (все embeds) | 6000 символов |
embed.title | 256 символов |
embed.description | 4096 символов |
embed.field | максимум 25, каждое значение ≤ 1024 символов |
| Размер вложения | 10 МБ |
Кузня автоматически обрезает контент до лимитов перед отправкой (с маркером «…»). На HTTP 429 — ждёт и повторяет с экспоненциальным бэкоффом.
Поиск неисправностей #
| Симптом | Причина | Решение |
|---|---|---|
| «Discord не найден — запусти десктопный клиент» | Discord не запущен или IPC-сокет не найден | Откройте десктопный Discord-клиент |
| Presence не отображается у других пользователей | Нет арт-ассета large_image |
Загрузите хотя бы один арт-ассет с ключом kuznya в портале разработчика |
| Presence не работает (Snap/Flatpak Discord) | Сокет в нестандартном месте | Кузня проверяет $XDG_RUNTIME_DIR/snap.discord и …/app/com.discordapp.Discord автоматически |
| «webhook включён, но URL не найден» | Переменная окружения не установлена | export KUZNYA_WEBHOOK_URL="https://..." |
| Карточка в Discord не обновляется | Вебхук 429 (rate limit) | Уменьшите частоту логирования: train.log_every: 5 |
404 на PATCH вебхука |
Сообщение было удалено вручную | Кузня автоматически создаёт новое — это ожидаемое поведение |
| Webhook перестал работать через некоторое время | Токен был revoked | Создайте новый вебхук в настройках канала и обновите переменную окружения |
| На headless-сервере presence молча не работает | IPC-сокет недоступен без GUI | Используйте только webhook на сервере; presence только с локальным клиентом |