Telegram-бот для подготовки к собеседованию по DevOps. Отвечаешь на вопросы своими словами, а ИИ проверяет ответ по эталонным тезисам и показывает, что раскрыто, что упущено, а где сказана неправда.
Пет-проект: Python, PostgreSQL, Docker Compose, LLM (GigaChat).
Вопросы взяты из репозитория Swfuse/devops-interview — сборника вопросов и ответов для собеседований на должность системного администратора и DevOps-инженера. Спасибо автору.
- Меню: выбрать тему (случайный вопрос или список по порядку), случайный режим, повторение уже пройденного.
- Проверка свободного ответа: разбор по каждому тезису с цитатой из твоего ответа.
- Интервальное повторение: срок следующего повтора зависит от оценки.
- Геймификация: XP, серия дней (streak), дневная цель и плашка «сегодня N из M вопросов».
- Напоминания: раз в день в выбранное время, если цель дня ещё не выполнена.
- Для каждого вопроса хранятся 3-5 коротких эталонных тезисов. Их один раз генерирует модель и сохраняет в базу.
- Ты пишешь ответ в свободной форме.
- Модель для каждого тезиса возвращает цитату из ответа и статус:
| Статус | Баллы | Значение |
|---|---|---|
covered |
+1 | тезис раскрыт |
partial |
+0,5 | раскрыт частично или расплывчато |
missing |
0 | в ответе об этом нет |
contradicted |
-1 | сказано обратное, неправда весит больше пропуска |
- Оценку 0-10 считает код, а не модель: сумма баллов делится на число тезисов.
- По оценке выставляется уверенность 1-5, от неё зависит срок повтора: 1-2 завтра, 3 через 3 дня, 4 через 7, 5 через 14.
Если цитата не найдена в тексте ответа, статус тезиса сохраняется, но цитата не показывается, а под тезисом появляется пометка. Модель могла правильно понять смысл и неточно скопировать слова, поэтому оценка из-за этого не падает.
app/
.github/workflows/ci.yml CI: ruff, pytest, сборка образа
certs/ корневой сертификат Минцифры для GigaChat
main.py меню, обработчики Telegram, напоминания
llm.py клиент GigaChat, промпты, разбор ответа модели, подсчёт оценки
db.py запросы к PostgreSQL и мини-миграции
scripts/
import_questions.py импорт вопросов из CSV
generate_all_keypoints.py генерация тезисов для всех вопросов
tests/
test_llm.py тесты разбора ответа модели
data/ CSV с вопросами (свои файлы не коммитятся, пример: questions.example.csv)
init.sql схема базы
docker-compose.yml, Dockerfile, requirements.txt
| Таблица | Назначение |
|---|---|
topics |
темы |
questions |
текст, приоритет, эталонные тезисы |
users |
XP, серия дней, дневная цель, время напоминания |
user_progress |
уверенность, интервал, next_review_at |
attempts |
история ответов, разбор ИИ, оценка |
cp .env.example .env
# заполнить BOT_TOKEN, POSTGRES_PASSWORD (тот же пароль в DATABASE_URL), GIGACHAT_AUTH_KEY
# положить вопросы в data/questions.csv (формат ниже), затем:
docker compose up -d db
docker compose run --rm bot python -m scripts.import_questions /data/questions.csv
docker compose up -d --build bot
docker compose logs -f botПовторный импорт безопасен: вопрос с той же темой и текстом не дублируется. Порядок «по порядку» в боте определяется порядком импорта.
Если Telegram недоступен с сервера напрямую, бот можно пустить через прокси, настройки см. в .env.example.
Колонки Тема и Вопрос обязательны, приоритет берётся из текста вида Приоритет 1 — ... в любой колонке (по умолчанию 2). Пример: data/questions.example.csv.
| Переменная | Назначение |
|---|---|
BOT_TOKEN |
токен от @BotFather |
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB |
база |
DATABASE_URL |
строка подключения (хост db) |
GIGACHAT_AUTH_KEY |
ключ авторизации GigaChat |
GIGACHAT_MODEL |
модель, по умолчанию GigaChat-2 |
BOT_TZ |
часовой пояс, по умолчанию Europe/Moscow |
GIGACHAT_VERIFY_SSL |
проверка сертификата, по умолчанию true; false отключает |
TELEGRAM_PROXY |
прокси для Telegram, например http://172.18.0.1:10809 (необязательно) |
Бот работает на виртуальной машине cloud.ru (Ubuntu), БД и бот в Docker Compose. Сервер не достаёт до Telegram напрямую, поэтому запросы к нему идут через прокси. GigaChat прокси не использует.
Схема:
bot (контейнер) ──► socat на docker-шлюзе :10809 ──► proxray на 127.0.0.1:10809
│
VPN-подписка HAPP ──► Telegram
-
proxray (терминальный клиент HAPP-подписок) запущен как systemd-сервис:
[Service] User=<пользователь> ExecStart=/usr/local/bin/proxray connect 1 --bypass off Restart=always RestartSec=5
Сервер №1 в подписке — «АВТО» с автопереключением между узлами.
-
socat (два сервиса, порты 10808 и 10809) пробрасывает порты прокси из localhost хоста на адрес docker-шлюза, потому что proxray слушает только
127.0.0.1, а контейнер до него не дотянется. -
В
.envна сервере:TELEGRAM_PROXY=http://172.18.0.1:10809.
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > backup_$(date +%F).sql- Схема БД, импорт вопросов из CSV
- Меню: тема, случайный режим, повторение
- Проверка ответов через GigaChat, оценка в коде
- XP, серия дней, дневная цель, напоминания
- Деплой на сервер через Docker Compose
- GitHub Actions CI (ruff, pytest, сборка образа)
- Проверка SSL с корневым сертификатом вместо отключённой
- Абстракция над LLM-провайдером
- Режим «собеседование» (10 случайных вопросов подряд)
- Alembic вместо init.sql
- Метрики (Prometheus + Grafana)