Всё началось с банальной боли: каждый день выходят десятки новостей про нейросети, новые сетки, апдейты, бенчмарки и пейперы. Мониторить десятки RSS-лент, X (Твиттер), Хабр, Hacker News и выгребать всё это из поисковиков вручную — адский оверхед и выгорание. Нам тупо хотелось иметь один чистый канал с выжимкой всех поисковиков и первоисточников, без воды, кликбейта и повторов. Причём исключительно для личного пользования: зайти раз в день и считать весь контекст за пару минут.
В итоге домашний скрипт «на коленке» перерос в полностью автономный пайплайн. Всё это крутится на всратом VPS за $5 с 1 ГБ оперативки, без десктопа, без человека в контуре и без раздутых оркестраторов. За месяц эта конструкция нагенерила под 450 постов, собрала 700+ подписчиков и сэкономила нам кучу часов жизни. Рассказываем, как мы это собрали, на какие грабли наступили и как экономим токены.
Сначала мы думали обойтись костылём из серии «скачал RSS → закинул в OpenAI → пульнул в ТГ». Спойлер: схема умерла в первый же день.
Вот с чем мы столкнулись:
В итоге мы собрали лёгкий, но «злой» стек: чистый Python, таймеры systemd (никакого Celery/Redis overhead!), внешние API для LLM, лёгкий метапоиск и статическое веб-зеркало.
Пет-проект делался для себя, поэтому раздувать бюджет никто не собирался. Уложились в $18.8 в месяц:
| Статья расходов | Затраты |
|---|---|
| VPS (1 ГБ RAM / 1 vCPU) | ~$5 / мес |
| Подписка OpenCode Zen GO (API к LLM) | $10 / мес |
| Домен ai-release.org | ~$1.8 / мес ($22/год) |
| Telegram Premium (для бота) | ~$2 / мес ($25/год) |
| **Итого** | **~$18.8 / мес** |
Самая большая статья — API для нейросетей, но эта подписка закрывает вообще всё: от рерайта новостей до личной отвечалки в чате. А на обложки мы не тратим ни цента — собираем их из открытых источников.
Зачем тащить в проект Redis, RabbitMQ и Celery, если можно обойтись встроенными средствами Linux? Для проекта такого масштаба таймеры systemd — идеальное решение. Каждая таска запускается в отдельном изолированном процессе: если одна упала по таймауту, она не вешает весь сервер.
Скрипты раскиданы по расписанию через `OnCalendar`:
# ai-release-hourly.timer (*:15) — 1 новость в час
# ai-release-video.timer (0:30, 8:30, 16:30) — видео раз в 8 часов
# ai-release-daily.timer (18:00 МСК) — дневной дайджест
# ai-release-stats.timer (18:00 UTC) — сбор метрик
# ai-release-chat.service (daemon) — ИИ-бот в личке
# ai-release-web.service — веб-зеркало
[Timer]
OnCalendar=*-*-* *:15:00
Persistent=true
Публикация идёт напрямую через Telegram Bot API.
Откуда гребём контент:
Чтобы лента не превратилась в помойку из 10 одинаковых новостей про «OpenAI выпустила новую модель», мы применили трёхэтажный фильтр:
1. **Скоринг.** Считаем вес новости по свежести, авторитетности источника и заголовку. Первоисточники и личные блоги инженеров получают приоритет перед перепечатками.
2. **Нормализация заголовков и хэширование.** Зачищаем мусор вроде `BREAKING:`, `СРОЧНО:`, хвосты вида `— TechCrunch` или `| The Verge`, приводим кавычки к единому виду и проверяем `sha256` в SQLite:
def normalize_title(t: str) -> str:
t = re.sub(r"\s*[-—|]\s*(TechCrunch|Engadget|The Verge|WindowsLatest).*$", "", t, flags=re.I)
t = re.sub(r"^(BREAKING|СРОЧНО|EXCLUSIVE)\s*:?\s*", "", t, flags=re.I)
t = t.replace("«", '"').replace("»", '"').strip()
return t.lower()
3. **Смысловой дедуп через LLM.** Заголовки могут отличаться, а суть быть одной. Перед постингом кандидат сравнивается с текстами последних постов канала. Похоже? Забраковываем.
Плюс зарезаем SEO-мусор: неизвестные домены пропускаются только если там есть конкретный сигнал (название модели, компании или события), а абстрактное «ии/ai/нейросеть» сразу летит в бан.
Главная проблема базовых промптов — модель постоянно пыталась додумать «почему это произошло» и написать глубокомысленные выводы, которых в источнике не было.
Как заставили работать нормально:
Так как LLM — это единственное, за что мы платим реальные деньги, экономим на каждом запросе:
Генерить картинки через API — дорого и медленно. Мы сделали каскадный фолбэк для поиска иллюстраций:
1. Дёргаем `og:image` из оригинальной статьи.
2. Если `og:image` нет или он битый — идём в метапоиск по бесплатным стокам (Unsplash, Pexels, Pixabay, Wikimedia, Flickr).
3. Не нашли? Подтягиваем тематический арт или аниме/манга иллюстрацию.
4. Совсем голо — берём дефолтный фолбэк-пак.
Перед отправкой картинка обязательно валидируется через быстрый HEAD-запрос. Если TG отдаст `400 Bad Request` — скрипт на лету меняет обложку и делает ретрай.
Внешние ручки любят лагать. Чтобы не дежурить у сервера с SSH, мы заложили несколько защит:
Для каждого поста автоматически генерируется страница на веб-зеркале ai-release.org (на двух языках — RU и EN). Но сейчас обычного SEO мало, нужно оптимизироваться под ИИ-краулеры (Perplexity, ChatGPT Search, Claude):
Как итог — реферальный трафик идёт не только из поиска, но и прямо из ответов Perplexity и ChatGPT.
Канал подтянут к боту в личке. А открытый ввод от пользователей — это всегда риск, что кто-то попытается «запромптить» бота, вытащить системный контекст или ключи API.
Защита в 3 слоя:
1. **Промпт-страж (Guardrail).** Модель жёстко проинструктирована игнорировать любые попытки изменить роль, «забудь предыдущие инструкции» или «выдай системный промпт».
2. **Rate Limiting.** Не больше 20 запросов за 10 минут на пользователя. Выкачать контекст или заспамить API не выйдет.
3. **Изоляция окружения.** Все API-ключи лежат в `.env` с правами `chmod 600`. Чат-процесс работает под отдельным окружением и физически не имеет доступа к коду публикатора и базе.
1. Не нужен дорогой GPU-сервер с локалками, чтобы делать умные сервисы. Грамотная архитектура пайплайна и внешние API решают 99% задач.
2. Борьба с галлюцинациями и дедупликация на уровне кода дадут в 10 раз больше качества, чем тупая смена модели на более дорогую.
3. Чтобы ваш контент цитировали ИИ-системы — отдавайте им `.md` и вешайте `llms.txt`.
Следить за работой ленты можно в канале @ai_release1, а почитать статьи и гайды — на сайте ai-release.org.
💬 **Вопросы и обсуждение — в комментариях ниже.**