AI-система генерації новинних зведень

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
AI-система генерації новинних зведень
Середній
від 1 дня до 3 днів
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Розробка 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 години для важливих новин