Проверка настроек: что означает каждый отказ

Кнопка «Проверить настройки» в разделе «Настройки бота» → вкладка «Для разработчиков» проходит по вашему серверу сверху вниз и на каждом шаге говорит, что именно случилось. Здесь - полный разбор исходов с командами, которые нужно выполнить на вашем сервере.

Проверки идут от «есть ли куда стучаться» к «правильно ли отвечает». Первая же неудача объясняет все последующие, поэтому чините сверху вниз: нижние отказы часто исчезают сами.

Протокол

«указан http» или «без схемы» - мы ходим только по https. Выпустите бесплатный сертификат и укажите адрес со схемой:

certbot --nginx -d kb.вашдомен.ru

Домен разрешается

Имя не превращается в адрес. Три причины по частоте: нет A-записи, опечатка в адресе, домен не делегирован на ваши серверы имён. Проверьте с любой машины:

dig +short kb.вашдомен.ru          # ожидаем адрес вашего сервера
nslookup kb.вашдомен.ru

Пусто - записи нет или она ещё не разошлась. Новая A-запись расходится до нескольких часов.

Порт доступен с нашего адреса

Это не то же самое, что «у меня открывается»: у вас может стоять фильтр по адресам, и с вашего рабочего места всё работает, а с нашего - нет. Причины: не запущен nginx, закрыт порт в брандмауэре, наш адрес не в белом списке, сервер за NAT без проброса.

systemctl status nginx
ss -ltnp | grep :443            # кто слушает 443
ufw status                      # что разрешено
ufw allow from 157.228.138.231 to any port 443 proto tcp

Запросы к вам приходят с адреса 157.228.138.231.

Сертификат

Отказ бывает четырёх видов, и лечатся они по-разному:

  • самоподписанный - выпустите бесплатный через certbot;
  • истёк - certbot renew, и проверьте таймер: systemctl status certbot.timer;
  • выдан на другое имя - в сертификате не то доменное имя, которое вы вписали в кабинете. Частый случай: сертификат на вашдомен.ru, а адрес kb.вашдомен.ru;
  • нет цепочки - сервер отдаёт только свой сертификат, без промежуточного. В браузере такое иногда работает, у нас нет.
echo | openssl s_client -connect kb.вашдомен.ru:443 -servername kb.вашдомен.ru 2>/dev/null \
  | openssl x509 -noout -subject -dates -issuer

Мы предупреждаем заранее: если до конца срока меньше двух недель, проверка попросит обновить сертификат, хотя он ещё годен.

Поиск отвечает: 401 или 403

Ваш сервер отверг нашу подпись. Причины по частоте:

  • секрет в кабинете и в kb.service разошлись;
  • в переменной окружения остался пробел или перевод строки - глазами не видно;
  • службу не перезапустили после правки, и она работает со старым секретом.
systemctl show kb -p Environment   # что реально видит служба
systemctl restart kb

Сверяйте посимвольно. Если правили секрет и там, и там - меняйте сначала в кабинете, потом на сервере: в обратном порядке несколько минут ответы будут отказами.

Поиск отвечает: 404

Адреса нет на вашем сервере. Обычно в кабинете указан корень вместо полного пути - должно быть .../knowledge/search, а не .../.

curl -i -X POST https://kb.вашдомен.ru/knowledge/search

Ожидаем 401 - это значит, что адрес есть и подпись проверяется. Настоящий 404 - адреса нет.

Поиск отвечает: 405

Адрес есть, но метод не разрешён. Эндпоинт должен принимать POST. Частая причина - в nginx стоит правило, пропускающее только GET.

Поиск отвечает: 500, 502, 503

Упало внутри вашего сервиса. Смотрите журнал - там будет настоящая причина:

journalctl -u kb -n 50 --no-pager

Что встречается:

  • relation "kb_chunks" does not exist - не создана таблица;
  • type "vector" does not exist - не создано расширение: CREATE EXTENSION vector;;
  • ModuleNotFoundError - не установлен пакет в виртуальном окружении;
  • connection refused к базе - не поднят PostgreSQL;
  • 502 от nginx - служба не отвечает вовсе: systemctl status kb.

Поиск отвечает: таймаут

Сервер не ответил за отведённое время. Первый запрос после простоя долгий - модель грузится в память, это 15-30 секунд. Дальше должно быть 50-150 мс.

  • держите службу тёплой: запрос к /knowledge/health раз в минуту из своего мониторинга;
  • или поднимите таймаут до 5000 мс в кабинете;
  • если медленно всегда - проверьте, что создан индекс: без него поиск идёт перебором и на большой базе занимает секунды.
sudo -u postgres psql -d kb -c "\di kb_*"
sudo -u postgres psql -d kb -c "EXPLAIN ANALYZE SELECT id FROM kb_chunks ORDER BY embedding <=> (SELECT embedding FROM kb_chunks LIMIT 1) LIMIT 6"

В плане должно стоять Index Scan using kb_vec_idx, а не Seq Scan.

Поиск отвечает: пустой ответ

Связь есть, подпись принята, но фрагментов ноль. Проверка это не считает отказом - но бот в таком состоянии будет отвечать «не знаю» на всё.

sudo -u postgres psql -d kb -c "SELECT count(*) AS кусков, count(embedding) AS с_векторами FROM kb_chunks;"
  • оба нуля - материалы не загружены, запустите индексатор;
  • кусков много, векторов ноль - индексатор отработал без модели, векторы NULL. При векторном режиме поиск не найдёт ничего;
  • всё на месте, а пусто - спросили словами не из материалов. Проверьте вопросом, который точно есть в тексте.

Поиск отвечает: ответ не в том формате

Ждём объект с полем chunks - списком из id, content и score. Массив верхним уровнем ([ ... ] вместо {"chunks": [ ... ]}) или другое имя поля не подойдут. Точный вид - в статье Материалы на своём сервере.

Запас по времени

Ответ пришёл, но занял больше семидесяти процентов таймаута. Это не отказ сегодня, а отказ завтра: под нагрузкой ответ станет медленнее, и бот начнёт отвечать «не знаю» покупателям. Ускорьте поиск или поднимите таймаут.

Закрыт без подписи

Мы отправляем запрос без заголовка X-CyberAI-Signature и смотрим, что будет. Ждём 401 или 403.

Если сервер ответил 200 - эндпоинт открыт, и ваши материалы может выкачать кто угодно. При том что режим вы выбрали ровно ради их сохранности. Добавьте проверку подписи - готовый пример в инструкции для администратора, функция checked.

Сравнивать подписи надо постоянным по времени сравнением (hmac.compare_digest), а не обычным ==.

Приём правок ответов

Проверка отправляет настоящую правку с пометкой «Проверка связи CyberAI». Если её не приняли - не поднят второй адрес, /knowledge/correction. Без него правки, которые вы делаете в «Диалогах», сохранять будет негде.

После успешной проверки тестовая правка остаётся в вашей базе - мы об этом говорим в отчёте. Удалите её, если мешает:

sudo -u postgres psql -d kb -c "DELETE FROM kb_chunks WHERE content LIKE '%Проверка связи CyberAI%';"

Если ничего не помогло

Соберите три вещи и напишите нам: отчёт проверки целиком, вывод journalctl -u kb -n 50 и ответ curl -s https://kb.вашдомен.ru/knowledge/health. По ним видно почти всё.