Сравнение каналов #

Rich PresenceWebhook
Что показываетСтатус в профиле DiscordКарточки в канале
Нужен локальный клиентДаНет
Работает по SSH / headlessНетДа
Сообщений на ран1 (редактируется на месте)
Rate limit1 обновление / 15 с30 запросов / 60 с

Rich Presence #

Rich Presence показывает прогресс обучения прямо в статусе Discord-клиента. Другие пользователи видят что-то вроде:

пример статуса Discord
Играет в Кузню
spiral-classifier · adamw lr=0.003
эпоха 23/40 · val_acc 0.876

Статус обновляется не чаще 1 раза в 15 секунд — это ограничение Discord. Кузня применяет коалесценцию: хранит последнее pending-обновление и отправляет его, когда окно открывается.

Настройка Rich Presence — шаги #

  1. 1

    Создайте приложение Discord

    1. Откройте discord.com/developers/applications.
    2. Нажмите New Application.
    3. Введите имя, например Кузня.
    4. Скопируйте APPLICATION ID (18–19 цифр) со страницы General Information.
  2. 2

    Загрузите арт-ассеты (опционально)

    1. В левом меню выберите Rich Presence → Art Assets.
    2. Нажмите Add Image(s) и загрузите файл.
    3. Дайте ключ, например kuznya (только строчные латинские буквы, цифры, дефисы).
    4. Этот ключ указывается в discord.presence.large_image.
    Зачем это нужно
    Без загруженного арт-ассета presence не будет отображаться для других пользователей. Достаточно загрузить любое изображение с ключом kuznya.
  3. 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. 4

    Запустите с открытым Discord

    Десктопный Discord-клиент должен быть запущен на той же машине. Кузня ищет IPC-сокет в следующем порядке:

    • Linux/macOS: $XDG_RUNTIME_DIR/discord-ipc-{n}, затем snap/flatpak-пути, затем /tmp.
    • Windows: именованный pipe \\.\pipe\discord-ipc-{n}.

    Если IPC-сокет не найден — Кузня продолжит работу без presence (предупреждение в логе, обучение не прерывается).

Webhook #

Webhook публикует карточки в Discord-канал. Работает headless — без локального клиента, в том числе по SSH.

В канале появляется одна карточка в начале обучения. По мере прогресса та же карточка редактируется (PATCH). По завершении — обновляется итогами и получает прикреплённый PNG с графиком потерь.

Это значит: 1 POST + N PATCH на ран — никакого спама в канале.

Настройка Webhook — шаги #

  1. 1

    Создайте вебхук в канале

    1. Откройте настройки канала (иконка шестерёнки рядом с именем).
    2. Перейдите в Integrations → Webhooks → New Webhook.
    3. Укажите имя и иконку (по желанию).
    4. Нажмите Copy Webhook URL.

    URL выглядит так:

    https://discord.com/api/webhooks/1234567890/ваш-токен-здесь
  2. 2

    Сохраните URL в переменной окружения

    bash
    export KUZNYA_WEBHOOK_URL="https://discord.com/api/webhooks/..."

    Для постоянного хранения добавьте строку в ~/.bashrc или ~/.zshrc.

  3. 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 напрямую в конфиг
Токен в webhook URL — это bearer-credential: любой, кто его увидит, сможет постить от вашего имени. Используйте url_env — Кузня прочитает URL из переменной окружения, и в конфиг-файл ничего секретного не попадёт.

Безопасно:

"webhook": {
  "enabled": true,
  "url_env": "KUZNYA_WEBHOOK_URL"
}

Небезопасно (не делайте так, особенно в git):

"webhook": {
  "enabled": true,
  "url": "https://discord.com/api/webhooks/..."
}

Паттерн: сервер + ноутбук #

Типичный сценарий: обучение идёт на GPU-сервере по SSH, а вы хотите видеть прогресс в Discord на ноутбуке.

text
Сервер (GPU, headless):              Ноутбук (Discord открыт):
┌─────────────────────────┐          ┌──────────────────────────┐
│ kuz train config.json   │          │  Discord клиент          │
│ + webhook enabled       │──POST──► │  #training-log канал     │
│   (карточки в канале)   │          │                          │
└─────────────────────────┘          │  Статус: Кузня           │
                                     │  "epoch 23/40 · acc 0.8" │
                           ◄─IPC──── │  (Rich Presence)         │
                                     └──────────────────────────┘

Конфиг для сервера — только webhook:

json — сервер
"discord": {
  "presence": { "enabled": false },
  "webhook": {
    "enabled": true,
    "url_env": "KUZNYA_WEBHOOK_URL",
    "live_panel": true
  }
}

Конфиг для ноутбука — только presence:

json — ноутбук
"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 limit30 запросов / 60 секунд на токен
Embeds в сообщениимаксимум 10
Суммарный бюджет символов (все embeds)6000 символов
embed.title256 символов
embed.description4096 символов
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 только с локальным клиентом