Разработка AI-системы автоматизированной журналистики
Автоматизированная журналистика — генерация новостных текстов из структурированных данных: финансовых отчётов, спортивной статистики, данных о выборах, погодных сводок. Технология работает там, где есть данные и чёткий шаблон нарратива. AP и Reuters публикуют десятки тысяч таких материалов ежегодно.
Где автоматизация оправдана
Финансовая отчётность: квартальные результаты компаний — данные из EDGAR/Мосбиржи → текст с ключевыми показателями, динамикой, сравнением с прогнозами. Один шаблон покрывает тысячи компаний.
Спортивная статистика: результаты матчей, игровая статистика — стандартный нарратив с вариацией по ключевым моментам.
Сводки из реестров: данные Росреестра о сделках, данные ГИБДД о ДТП, реестры банкротств — автоматические сводки с аномалиями.
Метеосводки и предупреждения: прогноз погоды в читаемый текст с акцентом на опасные явления.
Архитектура data-to-text системы
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)
Нарративные шаблоны
Шаблон определяет логику нарратива, а не конкретный текст. Для финансовой отчётности:
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"),
]
Вариативность и антишаблонность
Одна из проблем автоматической журналистики — однообразие текстов. Несколько техник:
- Synonym variation: несколько вариантов каждого ключевого выражения, случайный выбор
- Sentence structure variation: перестановка порядка фактов в зависимости от «угла»
- Contextual enrichment: добавление контекста (отраслевые тренды, история компании) из базы знаний
- LLM rewriting: финальный проход через LLM для разнообразия стиля при сохранении всех фактов
Верификация фактов
Критично: каждое числовое утверждение в тексте должно быть 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 Automation и требование медийной этики.
Производительность
Одна инстанция системы на GPU A100: ~500 материалов в час при среднем объёме 300 слов. Для новостного агентства это означает полное покрытие финансовой отчётности всех компаний Мосбиржи в день публикации результатов.







