AI-система генерации новостных сводок

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система генерации новостных сводок
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Разработка AI-системы генерации новостных дайджестов

Персонализированный новостной дайджест из сотен источников — задача, которую человек не решит вручную в приемлемые сроки. AI-система мониторит источники, кластеризует публикации по темам, удаляет дубли и генерирует связный дайджест под конкретного пользователя или сегмент аудитории.

Пайплайн сбора и обработки

class NewsDigestPipeline:
    def __init__(self, sources: list[NewsSource]):
        self.crawler = NewsCrawler(sources)
        self.deduplicator = SemanticDeduplicator(threshold=0.85)
        self.clusterer = NewsClusterer()
        self.summarizer = NewsSummarizer()
        self.ranker = PersonalizedRanker()

    async def generate_digest(
        self,
        user_profile: UserProfile,
        period_hours: int = 24
    ) -> Digest:
        # 1. Сбор новостей за период
        articles = await self.crawler.fetch_since(
            datetime.utcnow() - timedelta(hours=period_hours)
        )

        # 2. Удаление дублей (одна новость из 20 источников → 1 запись)
        unique_articles = self.deduplicator.deduplicate(articles)

        # 3. Кластеризация по событиям
        clusters = self.clusterer.cluster(unique_articles)

        # 4. Персонализированный ранжинг кластеров
        ranked_clusters = self.ranker.rank(clusters, user_profile)

        # 5. Генерация резюме по кластеру (multi-document summarization)
        summaries = [
            self.summarizer.summarize_cluster(cluster)
            for cluster in ranked_clusters[:user_profile.digest_size]
        ]

        return Digest(items=summaries, generated_at=datetime.utcnow())

Дедупликация новостей

Одно событие освещается десятками изданий. Near-duplicate detection:

class SemanticDeduplicator:
    def __init__(self, threshold: float = 0.85):
        self.encoder = SentenceTransformer("paraphrase-multilingual-mpnet-base-v2")
        self.threshold = threshold

    def deduplicate(self, articles: list[Article]) -> list[Article]:
        # Энкодирование заголовков + лида
        texts = [f"{a.title}. {a.lead}" for a in articles]
        embeddings = self.encoder.encode(texts, batch_size=256)

        # MinHash LSH для эффективного поиска похожих
        lsh = MinHashLSH(threshold=self.threshold, num_perm=128)
        groups = lsh.find_groups(embeddings)

        # Из каждой группы берём первоисточник (по времени публикации)
        result = []
        for group in groups:
            primary = min(group, key=lambda a: a.published_at)
            primary.alternative_sources = [a.url for a in group if a != primary]
            result.append(primary)

        return result

Multi-document summarization для кластера

Задача: из 5–20 статей об одном событии составить краткое резюме без потери ключевых деталей. Стратегия map-reduce:

def summarize_cluster(articles: list[Article]) -> ClusterSummary:
    # Ранжирование статей по авторитетности источника и полноте
    ranked = rank_articles_by_quality(articles)

    if len(articles) <= 3:
        # Небольшой кластер — прямая суммаризация
        combined = "\n\n".join(a.full_text for a in ranked[:3])
        summary = llm.generate(f"Кратко изложи ключевые факты:\n{combined}", max_tokens=200)
    else:
        # Большой кластер — map-reduce
        individual_summaries = [
            llm.generate(f"Выдели ключевые факты (2-3 предложения):\n{a.full_text}", max_tokens=100)
            for a in ranked[:10]
        ]
        # Объединяем уникальные факты
        summary = llm.generate(
            f"Составь связный абзац из этих фактов (без повторов):\n" +
            "\n".join(individual_summaries),
            max_tokens=200
        )

    return ClusterSummary(
        headline=ranked[0].title,
        summary=summary,
        key_sources=[a.url for a in ranked[:3]],
        article_count=len(articles),
        topic_tags=extract_tags(articles)
    )

Персонализация

Три уровня персонализации:

Тематические интересы: явные (пользователь выбрал рубрики) + неявные (клики, время чтения). Collaborative filtering для новых пользователей.

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

Формат доставки: email-дайджест, Telegram-бот, push-уведомления в приложении, RSS-лента. Частота: утром, вечером, раз в неделю — по выбору пользователя.

Метрики качества дайджестов

  • CTR по статьям: какой % материалов пользователь открывает — цель 15%+
  • Read-through rate: дочитываемость — цель 60%+
  • Diversity score: разнообразие тематик — не все статьи об одном
  • Freshness: среднее время от события до дайджеста — цель < 4 часа для важных новостей