Розробка AI-системи для автоматизованої журналістики
Автоматизована журналістика — генерація новинних текстів зі структурованих даних: фінансових звітів, спортивної статистики, даних про вибори, метеозводок. Технологія працює там, де є дані та чіткий шаблон нарату. AP та Reuters публікують десятки тисяч таких матеріалів щорічно.
Де автоматизація виправдана
Фінансова звітність: квартальні результати компаній — дані з бірж → текст з ключовими показниками, динамікою, порівнянням з прогнозами. Один шаблон охоплює тисячи компаній.
Спортивна статистика: результати матчів, ігрова статистика — стандартний наратив з варіацією на ключові моменти.
Зводи з реєстрів: дані про угоди, дані про ДТП, реєстри банкрутств — автоматичні зводи з аномаліями.
Метеозводки та попередження: прогноз погоди в читаємий текст з акцентом на небезпечні явища.
Архітектура 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"),
]
Варіативність та antishablonnist
Одна з проблем автоматичної журналістики — однопорідність текстів. Кілька методик:
- 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 та вимога медійної етики.
Продуктивність
Одна інстанція системи на GPU A100: ~500 матеріалів на час при середньому обсязі 300 слів. Для новинної агенції це означає повне покриття фінансової звітності всіх компаній в день публікації результатів.







