
Привет! У многих разработчиков бывают периоды, когда хочется сделать гениальный пет‑проект на 300кк в наносекунду. Весеннее обострение не обошло меня стороной — захотелось сделать свой Palantir. На старте я ещё не до конца понимал, что именно хочу построить, но было видение и вдохновение — большего, обычно, не нужно, свободное отобранное время находится само собой.
Вернёмся к делу: что мы делаем и, естественно, второстепенный вопрос — зачем? Вдохновившись видео про завайбкоженный палантир, я сформулировал первый тезис: «Хочу получить полную картину об интересующем событии». Это уже даёт некие очертания — какой‑то сервис, который соберёт за меня релевантную информацию и выдаст удобный отчёт.
Итак, что мы имеем:
Нужно собирать информацию
Нужно её очищать и индексировать
Нужно уметь искать по этой прекрасной базе данных
Как не сделать из мухи слона
Начиная пет‑проект, очень легко начать переусложнять архитектуру и раздувать скоуп. Пока у нас отлично получается делать обратное — из «Palantir 2.0 russian edition» мы дошли до двух конкретных функций: сбор информации и её раздача. Осталось не построить космолёт.
Вот простой стек, который я выбрал для проекта:
NestJS — много опыта, легко поддерживать, агенты хорошо справляются с DI и модулями, документации навалом.
pgvector — дёшево и сердито. Будем хранить тексты и эмбеддинги прямо рядом с метой.

Теперь по пунктам: сбор информации. Тут я решил ещё немного сузить скоуп — информации в мире очень много, а треша в ней всё больше и больше. Решение простое: собираем только новости.
Лёгкий старт: многие новостные сайты предоставляют RSS‑ленты, плюс золотая кладезь — Telegram‑каналы. Оба источника зачастую легко поддаются программному скрейпингу и отдают цифровое золото в виде текста.
Для скрейпинга веб‑страниц я использую поэтапный подход — от самого дешёвого к самому дорогому:
Просто скачиваем HTML. Новостные сайты обычно хорошо SEO‑оптимизированы и рендерятся на сервере. Загружаем страницу, ищем нужный блок по XPath — профит.
Не профит: страница рендерится на клиенте или закрыта каким‑нибудь антибот‑решением. Подключаем тяжёлую артиллерию: Playwright + Chromium + puppeteer‑extra‑plugin‑stealth. 99% страниц нормально так открываются — дожидаемся появления элемента по XPath и забираем контент.
-
Много чего может пойти не так — поэтому на каждый шаг вешаем retry:
сайт не ответил;
нас заподозрили в ботоводстве (hell nah);
сеть моргнула или ответ слишком долго грузился.
Всё это дело нужно ретраить. Поэтому ingest данных состоит из трёх шагов:
Получаем список новых постов, которые мы ещё не проиндексировали, и заводим для каждого таску на обработку.
Каждая таска пытается получить полный текст и сохранить его в базу. В случае ошибки — linear backoff: 60 сек × retryCount.
Если за 5 попыток не получилось — горечь поражения, помечаем статью как failed.
Данные у нас, что дальше?
Отлично, мы умеем добавлять Telegram и RSS‑источники и собирать с них текст. Это уже неплохо, но всё ещё бесполезно. Нужен поиск.
Я выбрал RRF (Reciprocal Rank Fusion) — подход, при котором несколько способов найти нужную статью объединяются в одну итоговую выборку. У нас таких способов два:
BM25 (Best Match 25) — поиск по ключевым словам. Грубо говоря, смотрит на то, как часто ключевое слово встречается в статье и какой у него вес. Частые слова вроде «и» или «но» — почти шум, и в выборке они практически не влияют на результат.
Semantic Search — поиск по смыслу. Для каждого текста считаем эмбеддинги — векторное представление, в котором закодирован смысл. То же самое делаем для поисковой фразы: считаем вектор и ищем документы, максимально близкие к нему по дистанции.
Интуитивно: представьте градусник. Одна ось — температура. Кладём его на стол — появляется вторая ось: левее или правее. Теперь представьте, что таких осей 1536 — это и есть наши «смысловые координаты», они же эмбеддинги.
Для этого я использую text‑embedding-3-small от OpenAI с размерностью 1536 — дёшево и сердито, и в моих масштабах куда проще, чем поднимать локальную модель.
Прорезюмируем, как работает поиск:
Пользователь отправляет поисковую фразу, например: «санкции против России».
Считаем для неё эмбеддинги через text‑embedding-3-small.
-
Делаем два запроса в pgvector (postgres с поддержкой векторных полей):
найди статьи, которые содержат слова «санкц», «против», «росс» — это BM25;
найди статьи, которые по смыслу похожи на «санкции против России» — это Semantic Search.
Объединяем результаты через RRF. Для каждой статьи считаем score по формуле:
где rank — позиция статьи в выдаче отдельного поиска, k — константа (обычно 60, потом тюнится). Складываем score из обоих поисков. В лучшем случае в топ залетают статьи, которые совпадают и по смыслу, и по ключевым словам. Если совпадение только по ключевым словам, а по смыслу — мимо, статья окажется ниже в выдаче.
Как этим пользоваться и для чего?

Прототип собран! Добавили кучу источников, данные собираются, поиск работает... но как этим вообще пользоваться? Ответ пришёл сам собой — я попросил своего верного товарища Claude Code исправить баг в поиске и понял: пусть он сам ищет нужные новости, агрегирует и обобщает их. 2026 год на дворе, в конце концов!
Решение напрашивалось: реализовать MCP-сервер, с которым любой ИИшке будет легко взаимодействовать.
По сути, MCP-сервер — это обёртка над уже существующим API, поэтому в подробности вдаваться не буду. Сервер живёт по адресу: https://api.vestly.ru/mcp
Локально его подключить можно так:
{ "mcpServers": { "vestly": { "type": "http", "url": "https://api.vestly.ru/mcp" } }
Рабочий пример в claude
Используя vestly составь мне подробный таймлайн блокировки телеграм в России - со всеми несостыковками из разных источников и официальной повестки. Сделай вывод - каков шанс полной блокировки, какой сентимент у граждан РФ



Мне кажется, получилось очень интересно: подробный отчёт вкупе с наглядной визуализацией от Claude — и в тему можно вникнуть за считанные минуты.


Резюмируя: да, это самопиар — но, кажется, полезный. В нашей неспокойной реальности, где всё нужно перепроверять и сравнивать источники, такой инструмент явно не лишний.
Сервис бесплатный. Если будет спрос и из этого вырастет полноценный продукт — сделаю, но не обещаю, что скоро.
Пара оговорок: исторических данных пока немного — индексация идёт примерно с 25 марта. Если руки дойдут и спрос будет, реализую исторический сбор тоже. На сейчас проиндексировано ~70 000 постов из 260 источников.
И бонусом — небольшой Telegram‑бот: можно подписаться на интересующий топик и получать новости из разных источников.

Все ссылки:
https://t.me/vestly_alert_bot - телеграм бот для подписки на новости
https://api.vestly.ru/docs swagger
https://api.vestly.ru/mcp mcp server
http://t.me/vestlyapi_bot - бот для получения апи ключа для использования mcp и api
С удовольствием отвечу на ваши вопросы в комментариях и обработаю запросы на новые фичи или обратную связь.
alexhu
Сделать такое можно, показать никому нельзя. Я делал примерно такое же https://moscowi.ru/ и технологии похожие. Проблема в другом - покажешь новость не из аккредитованного источника - статья УК, покажешь что то иностранное - статья УК, покажешь противоречивое - статья УК. Может быть сначала штраф, а уж потом статья ук.
Был у меня довольно умный и продвинутый поиск по архиву - пришлось убрать. Были разные источники по многим странам - пришлось убрать. Добавил цензуру, что бы ненароком чего не по повестке показало. Была сводная аналитика - пошла той же дорогой, куда и предыдущие. Были прогнозы - туда же. Аналитика работал великолепно, конечно на тех масштабах что я мог позволить по ресурсам.
Были нередкие случаи, когда новость проходила по многим средствам массовой информации, а через часы или сутки объявлялась дискредитирующей и ложной. СМИ новость убирали, а у меня она уже закешировалась - что бы меньше сервер дёргать. Добавил ещё фильтров на такие случаи.
Со статьями вообще сложно - авторские нельзя брать по разным причинам, не центральные - нельзя брать, региональные - нельзя брать. И их тоже нужно фильтровать по смыслу - а кого и когда из авторов и источников запишут в нежелательные не угадаешь.
В результате - довольно средненькие результаты.
enchantinggg Автор
Знал бы прикуп… Коли так, то судьба одна - закрытый приватный ресурс для личного пользования. Посмотрим, что выйдет. На другом проекте уже приходила от РКН “просьба” убрать страницу на сайте, срок давали 30 дней. Поживем увидим, кнопку выкл всегда нажать можно
Dahock
подскажите, пожалуйста, почему нельзя брать?
alexhu
Причины есть, их много, есть как смысловые, так и законодательные. И уж слишком часто они публикуют то, что потом объявляется ложным или нарушающим УК.
Были у меня случаи, когда действительно правдивая новость выходила в топ, а потом многие издания убирали их из потока, только потому, что как-то безнадёжно уныло выглядит действительность.
Даже была новость, которая судом была признана правдивой, а журналиста и издание оштрафовали - дискредитация. И это решение вынес один и тот же суд и судья, в рамках одного процесса. Законодательство подправили так наспех / коряво, что оно противоречит самому себе в разных местах.