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

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

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

Часті запитання

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

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

Ми зіткнулися із завданням автоматизації випуску новин для одного з великих видавництв: щоквартально потрібно було обробляти звіти 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 матеріалів. За результатами оцініть точність і швидкість. Отримайте безкоштовну консультацію щодо впровадження у вашу редакцію — пишіть, розповімо, як система впишеться у вашу редакційну ланцюжок.