Личный Telegram-бот и CLI: присылаешь ссылку на статью — получаешь короткий конспект от LLM, решаешь, стоит ли читать, и складываешь статью в тематические «идеи». Всё хранится в SQLite и потом служит базой знаний для других AI-агентов.
- Парсинг статей с Хабра, GitHub и Инфостарта (ссылка извлекается из любого текста сообщения)
- Конспект через любой облачный API в формате OpenAI (по умолчанию) или через локальную Ollama
- Учёт комментариев к статьям Хабра и Инфостарта: если в обсуждении есть что-то полезное, конспект заканчивается абзацем «В комментариях:»
- Кэш статей в SQLite — повторная ссылка не парсится и не отправляется в LLM
- Идеи (тематические папки): привязка статей и генерация
.md-описания идеи - Лента Хабра по подпискам: подписка на хабы (каталог бот берёт с самого Хабра и обновляет раз в 7 дней),
/feed— новые статьи из своих хабов за последние сутки, без вызова LLM - Ежедневный дайджест Хабра в
DIGEST_TIME(по умолчанию 18:00 МСК) за вчерашний день, только статьи, без новостей. Две части: «Лучшее на Хабре» — топ-5 по всему сайту, «Твои хабы» — топ-5 из подписок. У топ-5 есть короткое описание «о чём и зачем читать» от LLM, кнопки «Саммари 1»…«Саммари 5» дают полный конспект, «Ещё 10 ▶» листает список дальше. Статьи, которые пользователь уже присылал или открывал, исключаются. Кнопки списков работают 30 дней, в том числе после перезапуска бота - Статьи Хабра узнаются по номеру: ссылки с utm-метками или из блога компании попадают в тот же кэш. Для присланных статей Хабра сохраняются хабы и теги
- Фоновый бэкфилл: при старте бот дозаполняет хабы и теги у статей Хабра, уже лежащих в базе. Запросы идут с паузами и не мешают боту отвечать на команды. Удалённые или скрытые в черновики статьи помечаются и больше не запрашиваются
| Источник | Что берётся |
|---|---|
| habr.com | Текст статьи + комментарии, хабы и теги; лента и дайджест по хабам |
| github.com | README и документация репозитория, звёзды, язык, лицензия, дата последнего push |
| infostart.ru | Текст статьи по 1С, автор, теги + комментарии |
Подробнее — docs/sources.md.
git clone https://github.com/FrowningMonk/study_agent.git
cd study_agent
python -m venv venv
venv\Scripts\activate # Windows; на Linux/macOS: source venv/bin/activate
pip install -r requirements.txtСкопируйте .env.example в .env и заполните значения (файл не попадает в git):
| Переменная | Обязательна | Назначение |
|---|---|---|
TELEGRAM_BOT_TOKEN |
да | Токен бота от BotFather |
OWNER_ID |
да | Ваш числовой Telegram ID (узнать — у @userinfobot). Без него бот не запустится |
POLZA_API_KEY |
да | Ключ облачного LLM-провайдера с OpenAI-совместимым API |
POLZA_BASE_URL |
нет | Адрес этого API (.../v1). Сменив его, можно подключить любой OpenAI-совместимый сервис |
GITHUB_TOKEN |
нет | Поднимает лимит GitHub API с 60 до 5000 запросов в час |
OLLAMA_HOST |
нет | Адрес локального Ollama, если используете его |
DIGEST_TIME |
нет | Время рассылки дайджеста Хабра, ЧЧ:ММ по МСК, по умолчанию 18:00. Неверный формат или время 23:59 и позже заменяются на 18:00 с предупреждением в логе |
Если дайджест не удалось собрать (Хабр недоступен или ответил не полностью), бот повторяет попытку каждые 15 минут. Если через 3 часа после DIGEST_TIME дайджест не ушёл, владельцу приходит предупреждение с причиной. Если не ушёл до 23:59 МСК, день пропускается, и владелец получает сообщение о пропуске. Если бот был выключен во время рассылки и поднялся в тот же день, он досылает дайджест тем, кому тот ещё не ушёл.
Ollama нужна только для локальных моделей: установите Ollama и скачайте модель, например ollama pull gemma3:12b.
Telegram-бот:
python bot.pyБот и сервер используют один токен: перед локальным запуском остановите бота на VPS, иначе Telegram вернёт 409 Conflict.
CLI — одна ссылка за запуск:
python pipeline.py <URL> [модель] [провайдер]
python pipeline.py https://habr.com/ru/articles/123456/
python pipeline.py https://github.com/owner/repo gemma3:12b ollamaПровайдер: polza — облачный OpenAI-совместимый API (по умолчанию) или ollama. Модель указывается так, как её называет выбранный сервис; значение по умолчанию задано в summarizer.py.
| Команда | Описание |
|---|---|
/start |
Приветствие и клавиатура |
/help |
Справка |
/model |
Выбор провайдера и модели для конспектов и для .md идей |
/new_idea |
Создать идею |
/ideas |
Список идей |
/articles |
Список статей |
/subscribe [хабы] |
Подписаться на хабы Хабра: алиасы или ссылки вида habr.com/ru/hubs/python/, можно несколько сразу. О несуществующих бот пишет «Не найдены: …». Без аргументов — кнопки топ-30 хабов по рейтингу |
/subscriptions |
Мои подписки; отписка — кнопкой ✖ (отдельной команды /unsubscribe нет) |
/feed |
Статьи из подписанных хабов за последние 24 часа, по 10 на страницу, с кнопками «Саммари» и «Ещё 10 ▶». На дайджест не влияет |
/digest on|off |
Включить или выключить ежедневный дайджест (по умолчанию включён). Без аргумента — текущее состояние |
/digest_now [final] |
Только владелец: собрать дайджест сейчас. Без final плановый дайджест придёт как обычно; с final запуск засчитывается как сегодняшний |
/users |
Только владелец: пользователи, заявки, одобрение и отзыв доступа |
/wipe |
Только владелец: удалить все статьи всех пользователей (с подтверждением). Идеи и пользователи остаются |
<ссылка> |
Получить конспект |
Бот приватный. Владелец (OWNER_ID) пользуется им всегда. Любой другой человек на первое сообщение видит объяснение и кнопку «Запросить доступ»; владельцу приходит заявка с кнопками «Одобрить» / «Отклонить». Пока заявка не одобрена, бот ничего не делает. Отклонённым бот не отвечает. Отозвать доступ — в /users. В группах бот не работает.
pip install -r requirements-dev.txt
pytestТесты проверяют парсеры (на сохранённых HTML/JSON из tests/fixtures/) и сборку промптов; в сеть и к LLM они не ходят.
Сервер — VPS с Docker. Push или merge в main запускает GitHub Actions, который обновляет код на сервере и пересобирает контейнер. Секреты сервера лежат в .env на VPS и в секретах GitHub Actions, в репозиторий не попадают.
study_agent/
├── bot.py # Telegram-бот
├── pipeline.py # CLI: ссылка → парсинг → конспект → БД
├── scraper.py # Парсеры источников
├── summarizer.py # Промпты и вызов LLM (OpenAI-совместимый API / Ollama)
├── database.py # SQLite
├── access.py # Доступ: владелец, заявки, одобрение
├── habr_api.py # Клиент публичного API Хабра: статьи, хабы, комментарии, номер статьи по ссылке
├── habr_store.py # Данные Хабра в SQLite: каталог хабов, подписки, хабы и теги статей, просмотры, списки, состояние дайджеста
├── hubs.py # Каталог хабов и подписки
├── feed.py # Выборка и ранжирование статей, страницы и кнопки списков (/feed и дайджест)
├── digest.py # Ежедневный дайджест: сборка, рассылка, расписание, /digest_now
├── habr_backfill.py # Фоновое дозаполнение хабов и тегов у статей в базе
├── tests/ # pytest + фикстуры страниц
├── Dockerfile, docker-compose.yml, scripts/deploy.sh
└── docs/ # Документация
- docs/sources.md — источники и что из них извлекается
- docs/add-new-source.md — как добавить источник
- docs/git-workflow.md — работа с ветками
- docs/ROADMAP.md — планы