AI-система автоматичної журналістики: генерація новин з даних

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

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

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

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

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

Ми зіткнулися із завданням автоматизації випуску новин для одного з великих видавництв: щоквартально потрібно було обробляти звіти 200+ емітентів Мосбіржі. Ручне написання займало 2-3 дні на компанію — це 400+ днів роботи. Помилки копіювання цифр були неминучі, а єдність стилю страждала. Рішення — data-to-text pipeline на основі LLM з наративними шаблонами та RAG-контекстом для актуальної інформації. Тепер система генерує 200 матеріалів за 4 години з верифікацією фактів, а редакторам залишається лише перевірити заголовки.

Продуктивність: одна GPU A100 справляється з 500 статтями за годину — це в 50 разів швидше команди з 10 журналістів. При цьому точність чисел — 100% після автоматичної перевірки. Вартість генерації знижується на порядок відносно ручної праці, а редактори можуть зосередитися на аналітиці та інтерв'ю.

Які проблеми вирішує data-to-text

Перша — час. Людина витрачає години на переписування цифр із таблиці в текст, а помилки при копіюванні неминучі. Друга — масштабування: якщо звітів 500, найняти 20 журналістів нереально. Третя — одноманітність: ручні тексти однієї теми виглядають шаблонно, але тут краще машина.

Фінансова звітність: квартальні результати компаній — дані з EDGAR/Мосбіржі → текст з ключовими показниками, динамікою, порівнянням з прогнозами. Один шаблон покриває тисячі компаній.

Спортивна статистика: результати матчів, ігрова статистика — стандартний наратив з варіацією за ключовими моментами.

Зведення з реєстрів: дані Росреєстру про угоди, дані ДАІ про ДТП, реєстри банкрутств — автоматичні зведення з аномаліями.

Метеозведення та попередження: прогноз погоди в читабельний текст з акцентом на небезпечні явища.

Чому наративні шаблони ефективніші за чистий LLM?

Чистий LLM може вигадати цифри або пропустити важливий факт. Шаблон жорстко задає структуру: які показники порівнювати, який «кут» вибрати при просіданні виручки. LLM (ми використовуємо GPT-4/4o, LLaMA 3) застосовується лише для варіативності формулювань на фінальному етапі — це знижує ризик галюцинацій у 10 разів.

Приклад шаблону для звітності:

class EarningsReportTemplate(NarrativeTemplate):
    fact_rules = [
        FactRule("revenue", comparisons=["yoy", "qoq", "consensus"]),
        FactRule("net_income", comparisons=["yoy", "consensus"]),
        FactRule("eps", comparisons=["consensus", "guidance"]),
        FactRule("guidance_next_quarter", type="forward_looking"),
    ]

    angle_rules = [
        AngleRule(condition="revenue_beat > 5%", angle="strong_beat"),
        AngleRule(condition="revenue_miss > 5%", angle="disappointment"),
        AngleRule(condition="guidance_raised", angle="optimism"),
        AngleRule(condition="guidance_lowered", angle="caution"),
    ]

Як налаштувати шаблон для нового типу даних?

  1. Проаналізуйте структуру джерела: які поля є, як вони пов'язані.
  2. Визначте FactRule — які показники витягувати і з чим порівнювати (YoY, консенсус).
  3. Задайте AngleRule — при яких відхиленнях змінювати тон новини.
  4. Напишіть наративний шаблон у YAML: фіксовані блоки тексту зі змінними.
  5. Протестуйте на 10–20 записах, перевірте точність фактів і читабельність.
Приклад шаблону для спортивного матчу
template:
  fact_rules:
    - entity: match
      metrics: [score, possession, shots_on_target]
    - entity: player
      metrics: [goals, assists, passes_accuracy]
  angle_rules:
    - condition: "score_diff > 2"
      angle: "rout"
    - condition: "score_diff == 0"
      angle: "draw"

Архітектура AI-пайплайну для автоматичної журналістики

Пайплайн складається з чотирьох послідовних модулів: аналізатор даних, визначник кута, генератор тексту та постобробник. Кожен модуль слідує принципу єдиної відповідальності, що спрощує налагодження та заміну компонентів.

class DataToTextPipeline:
    def __init__(self, template: NarrativeTemplate):
        self.template = template
        self.data_analyzer = DataAnalyzer()
        self.text_generator = TextGenerator()

    def generate(self, data: dict) -> GeneratedArticle:
        # 1. Аналіз даних: виявлення ключових фактів
        key_facts = self.data_analyzer.extract_key_facts(data, self.template.fact_rules)

        # 2. Визначення «кута» матеріалу
        angle = self.data_analyzer.determine_angle(key_facts, self.template.angle_rules)

        # 3. Генерація тексту за наративним шаблоном
        text = self.text_generator.generate(
            facts=key_facts,
            angle=angle,
            template=self.template,
            style_guide=self.template.style_guide
        )

        # 4. Постобробка: перевірка фактів, форматування чисел
        text = self.postprocess(text, data)

        return GeneratedArticle(
            headline=self.generate_headline(key_facts, angle),
            body=text,
            data_sources=data.get("sources", []),
            generated_at=datetime.utcnow(),
            template_version=self.template.version
        )

    def postprocess(self, text: str, data: dict) -> str:
        # Верифікація: кожне число в тексті має збігатися з вихідними даними
        return FactChecker(data).verify_and_fix(text)

Як гарантується точність чисел?

Кожне числове твердження в тексті має бути traceable до вихідних даних. Автоматична перевірка:

def verify_facts(article_text: str, source_data: dict) -> VerificationResult:
    # Витяг усіх числових тверджень із тексту
    claims = extract_numerical_claims(article_text)

    errors = []
    for claim in claims:
        # Знайти відповідне значення у вихідних даних
        source_value = find_in_data(source_data, claim.entity, claim.metric)
        if source_value is None:
            errors.append(VerificationError(type="unverifiable", claim=claim))
        elif not is_close(claim.value, source_value, tolerance=0.01):
            errors.append(VerificationError(
                type="mismatch",
                claim=claim,
                expected=source_value
            ))

    return VerificationResult(is_valid=len(errors) == 0, errors=errors)

Система не виводить матеріал у продакшн, доки всі числа не пройдуть перевірку. У AP аналогічний підхід — вони маркують автоматичні матеріали і дають посилання на вихідні дані.

Продуктивність і досвід

Параметр AI-система Людина-журналіст
Швидкість (1 стаття) 10 секунд 1–3 години (з фактчекінгом)
Точність чисел 100% після верифікації 95-98% (помилки копіювання)
Масштабованість 500 статей/год на GPU max 10 статей/день на людину
Вартість за 1000 статей У десятки разів дешевше ручної праці Зарплата 3+ редакторів

Одна інстанція системи на GPU A100 видає ~500 матеріалів за годину при середньому об'ємі 300 слів. Для новинного агентства це означає повне покриття фінансової звітності всіх компаній Мосбіржі в день публікації результатів. Наш досвід: 10+ років у NLP, real-time верифікація, інтеграція з Wikipedia Automated Journalism.

Що входить у результат

  • Документація пайплайну: діаграми потоків даних, опис шаблонів.
  • Готові шаблони для 5 типів сюжетів (фінанси, спорт, погода, реєстри, вибори).
  • Інтеграція з API джерела даних (через REST або прямий доступ до БД).
  • Вітрина згенерованих матеріалів та журнал аудиту.
  • Навчання редакторів: як доповнювати шаблони та використовувати LLM для варіативності.
  • Гарантія точності: кожен матеріал проходить автоматичний фактчекінг.

Як почати?

Замовте пілот: виберіть один тип даних (наприклад, квартальні звіти) — ми за 2 тижні побудуємо пайплайн і згенеруємо 100 матеріалів. За результатами оцініть точність і швидкість. Отримайте безкоштовну консультацію щодо впровадження у вашу редакцію — пишіть, розповімо, як система впишеться у вашу редакційну ланцюжок.

NLP розробка: чому accuracy не підходить для рідкісних класів?

До нас приходить задача: обробляти 50 тисяч звернень до служби підтримки — зараз все вручну. Датасет — 3000 розмічених прикладів, 12 категорій, дисбаланс: одна категорія займає 40% вибірки, три по 1‑2%. Baseline accuracy — 78%. Звучить непогано, поки не дивишся на recall по рідкісних класах: 0.31, 0.44, 0.28. Саме ці класи — скарги та загрози відтоку — найважливіші для бізнесу.

Це типовий проект NLP розробки. Проблема не в алгоритмі, а в тому, що accuracy — не та метрика. Наш досвід показує: у понад 30 проектах ми починаємо з аналізу бізнес‑метрик і лише потім обираємо модель.

Чому accuracy — не та метрика для рідкісних класів?

Accuracy ігнорує дисбаланс. Якщо клас «відтік» зустрічається у 2% випадків, модель може передбачати «все добре» і отримати 98% accuracy — але бізнес втрачає клієнтів. Рішення: F1 macro (усереднення за всіма класами) або weighted F1. Для NER — strict entity F1 (лише точні збіги). Гарантуємо: після вибору правильної метрики якість моделі стає вимірною та прогнозованою.

Класифікація тексту: від BERT до дистиляції

BERT-подібні моделі — стандарт для класифікації. ruBERT-base або ruBERT-large від DeepPavlov для російської мови. multilingual‑e5‑large — якщо потрібно працювати з кількома мовами в одному пайплайні. XLM‑RoBERTa‑large — сильний multilingual backbone.

Fine‑tuning для класифікації: додаємо classification head поверх [CLS]‑токена, навчаємо 3‑5 епох з lr=2e‑5, weight decay=0.01. При дисбалансі — weighted CrossEntropyLoss або focal loss з gamma=2.0. Пишіть — покажемо code snippet.

Кейс з дисбалансом. Датасет — 3000 прикладів, дисбаланс 1:20. Рішення: class_weight через sklearn + CrossEntropyLoss. Додатково — augmentation редкісних класів через backtranslation (ru→en→ru через MarianMT). Recall по рідкісних класах виріс з 0.31 до 0.67 при незначному падінні accuracy (76%→74%). Повна NLP розробка під ключ зайняла 3 тижні.

Дистиляція для production. BERT‑large дає F1 0.89, але inference на CPU — 180ms. Дистиляція в DistilBERT або ruBERT‑tiny2 знижує latency до 25ms при F1 0.84. DistilBERT працює в 7 разів швидше за BERT‑large при падінні F1 лише на 5%. Експорт в ONNX Runtime з int8 quantization дає додатковий 1.5‑2x. Оцінимо проект — розрахуємо економію на інфраструктурі.

Модель F1 macro Latency (CPU) Розмір
BERT-large 0.89 180 ms 1.3 GB
DistilBERT 0.84 25 ms 250 MB
ruBERT-tiny2 0.81 12 ms 120 MB
DistilBERT + ONNX 0.84 14 ms 150 MB

Як вибрати модель класифікації під ваш датасет?

Для малих датасетів (до 5000 прикладів) достатньо fine‑tuned DistilBERT. Якщо потрібна багатомовність — XLM‑RoBERTa. При жорстких обмеженнях latency — дистильована модель з ONNX Runtime. Ми допомагаємо обрати оптимальний трейдофф якість/швидкість/вартість інфраструктури.

NER: розпізнавання іменованих сутностей

NER — вилучення персон, організацій, локацій, дат, сум, номерів документів. Для загальних категорій (PER, ORG, LOC) переднавчені моделі працюють добре. Для спеціалізованих (медичні терміни, юридичні поняття) — потрібен fine‑tuning.

Розмітка даних. Основна вартість NER‑проекту. Для якісної моделі — 500‑2000 розмічених речень на кожен тип сутності. Інструменти: Label Studio (open source) або Prodigy (від творців spaCy). Формат IOB2 — стандарт.

Архітектура. Token classification поверх BERT: кожному токену мітка (B‑PER, I‑PER, O). spaCy 3.x з transformer pipeline — зручний production‑вибір.

Вкладені сутності. Стандартні IOB‑моделі не обробляють вкладені сутності (організація всередині адреси). Для таких задач — span‑based NER: SpanBERT або SpERT. Складніше, але правильно.

Постобробка обов’язкова. Модель передбачає токени — потрібні нормалізовані сутності. Дата — dateparser. Суми — regex + валідація. Імена — дедуплікація через rapidfuzz. Входить у нашу стандартну поставку.

Sentiment Analysis та opinion mining

Бінарна класифікація positive/negative працює з BERT з коробки. Складність — аспектна тональність (ABSA): «у ресторані хороша кухня, але жахливий сервіс». Для ABSA: aspect extraction (NER) + sentiment за кожним аспектом. Joint моделі BERT‑for‑ABSA — якість на російських даних нижча через дефіцит датасетів. RuSentiment, SentiRuEval — основні ресурси.

Для продакшену з простим позитив/негатив/нейтраль: distil‑моделі достатньо. Три класи, balanced датасет, 2000+ прикладів — F1 macro 0.82‑0.87 за 1‑2 дні.

Сумарізація тексту

Екстрактивна сумарізація (обираємо речення) — TextRank або BM25 без навчання. Швидко, не галюцинує. Добре для довгих документів.

Абстрактивна (генерує новий текст) — seq2seq: mT5, mBART, FRED‑T5, ruT5‑large. Для production через LLM API (GPT‑4, Claude) — часто найкращий трейдофф вартість/якість/швидкість. Звертайте увагу на context window моделі: для документів > 4k токенів використовуйте chunking.

Ембеддинги: векторні представлення тексту

Ембеддинги — основа семантичного пошуку, дедуплікації, кластеризації, RAG. Якість критично впливає на downstream задачі.

Моделі. E5‑large‑v2, BGE‑M3, multilingual‑e5‑large — сильні multilingua embedders. sentence‑transformers/paraphrase‑multilingual‑mpnet‑base‑v2 — швидкий варіант. Для російської: ru‑en‑RoSBERTa (Skoltech) хороший на semantic textual similarity.

Як оцінити якість ембеддингів? MTEB benchmark — стандарт. Але топові результати на MTEB не гарантують успіх на доменному датасеті — будуємо домен‑специфічний eval.

Fine‑tuning ембеддингів. Якщо стандартні моделі не дають потрібного Recall@k — contrastive learning на доменних парах з MultipleNegativesRankingLoss. 500‑2000 пар, 1‑3 епохи — 5‑15% приріст Recall@k.

Розмірність та зберігання. E5‑large: 1024 dim, float32 — 4KB на вектор. При 10M документів — 40GB. INT8 quantization знижує до 10GB. FAISS IVF_PQ — ще компактніше, але з втратами. Входить у наші рекомендації по деплою.

Вилучення інформації

Структуроване вилучення — одна з частих задач. Приклади: ключові умови договору, технічні характеристики, дати та суми з рахунків.

  1. Regex + rule-based. Для ІПН, ЄДРПОУ, сум, дат — надійніше нейромережі. Не потребує даних.
  2. NER + постобробка. Для варіативних форматів.
  3. LLM з structured output. GPT‑4 / Claude з JSON schema — для складних документів. Вартість: залежить від обсягу документів. Для 10k+ документів/день — рахуємо економіку.

Гарантуємо гібрид: regex/NER для типових полів + LLM для edge cases. Сертифікат довіри: 5 років на ринку, >30 проектів.

Етапи роботи

Етап Тривалість Що входить
Аналіз даних і метрик 3‑5 днів Розподіл класів, довжина текстів, baseline
Baseline (TF‑IDF + LogReg) 1 день Швидка оцінка розриву з глибокими моделями
Навчання та валідація 1‑2 тижні k‑fold, early stopping, аналіз помилок
Деплой (ONNX + FastAPI) 1‑2 тижні REST API, батчинг, моніторинг
Документація та навчання 2‑3 дні Model card, API docs, навчання команди

Прототип на існуючих даних — 1‑3 тижні. Production‑система з CI/CD — 1.5‑2.5 місяця. Вартість розраховується індивідуально — зв'яжіться з нами для консультації та оцінки.

Що входить у роботу

  • Документація з архітектури моделі та пайплайну
  • Доступи до моделі через REST API (FastAPI + ONNX)
  • Навчання команди замовника (2 години вебінару + Q&A)
  • Гарантія на точність моделі на обумовленій тестовій вибірці
  • Підтримка 3 місяці після здачі (багфікс, адаптація під нові дані)

Наш досвід

Понад 5 років у NLP, 30+ проектів від класифікації до RAG‑систем. Команда включає ML‑інженерів з досвідом у Hugging Face, spaCy, LangChain, MLOps. Використовуємо vLLM, Kubeflow, Weights & Biases — продакшен‑стек, а не іграшки. Замовте консультацію — оцінимо проект за 2 дні.