
Привет! У многих разработчиков бывают периоды, когда хочется сделать гениальный пет‑проект на 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
С удовольствием отвечу на ваши вопросы в комментариях и обработаю запросы на новые фичи или обратную связь.
