«Я всё сломал за выходные»: как мы учим LLM писать в стиле конкретного СМИ. llm.. llm. mvp.. llm. mvp. nlp.. llm. mvp. nlp. rag.. llm. mvp. nlp. rag. Алгоритмы.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект. Контент и копирайтинг.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект. Контент и копирайтинг. Машинное обучение.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект. Контент и копирайтинг. Машинное обучение. промпт-инжиниринг.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект. Контент и копирайтинг. Машинное обучение. промпт-инжиниринг. рерайт.. llm. mvp. nlp. rag. Алгоритмы. декомпозиция. искусственный интеллект. Контент и копирайтинг. Машинное обучение. промпт-инжиниринг. рерайт. сми.

Привет, я Лена, это мой первый пост здесь, и он про техническую задачу, с которой мы столкнулись: как заставить LLM писать текст так, чтобы его нельзя было отличить от написанного конкретной редакцией. Не «хороший текст», не «грамотный текст», а такой, который звучит как этот конкретный городской портал или этот Telegram-канал.

Мы строим AI-систему для автоматизации рерайта новостей в региональных СМИ. Суть простая: система собирает новости из источников, проверяет факты и пишет рерайт в стиле конкретного издания. Тем временем журналисты занимаются своей нормальной работой, а не переписыванием чужих текстов. Звучит понятно. А потом начинаешь делать «в стиле конкретного издания» — и всё ломается.

Расскажу, как мы спорили, передумывали и к чему пришли.

Почему «просто хороший промпт» не работает

Первое, что пробуешь — написать детальный системный промпт. Что-то вроде: «Пиши коротко. Используй разговорный тон. Не ставь точку в заголовке (или ставь?). Начинай с факта, не с контекста».

Я прошла достаточно серьёзное обучение по промпт-инжинирингу и думала, что хороший промпт решит проблему. Мои эксперименты показали: нет.

Проблема 1: стиль — это не набор правил. Ты можешь описать 20 правил, и текст всё равно будет «не тот». Потому что стиль — это паттерн, который проще показать, чем сформулировать. У «Фонтанки» один ритм предложений, у «66.ru» — другой. Это не описывается инструкцией «предложения 10–15 слов».

Проблема 2: длинный промпт = дорогой промпт. Если начать добавлять в инструкцию примеры — а без них никак — промпт разрастается. На Claude это терпимо. На YandexGPT уже ощущается по токенам. А нам нужно генерировать десятки текстов в день для каждого клиента.

Проблема 3: промпт не масштабируется. У каждого издания или тг-канала свой стиль. Писать и поддерживать отдельные промпты для каждого клиента — это ручная работа, которая убьёт продукт.

Спор 1: RAG и векторная база — нужны или нет?

Классическое решение в таких случаях — RAG (Retrieval-Augmented Generation). Загружаешь статьи издания в векторную базу, при г��нерации ищешь семантически похожие тексты и подаёшь их модели как примеры стиля.

Я была за этот подход. Логика казалась простой: у нас есть 500–700 статей издания, эмбеддинги найдут ближайших «соседей» по смыслу к входящей новости, модель увидит, как именно это издание пишет про похожие темы.

Наш разработчик был против. Цитирую (с сохранением стиля чата в 9 вечера воскресенья):

«Подождите, ну а почему вы говорите “векторизация”, как это какое-то решение? Я помощи в векторе сейчас вообще никак не вижу.»

Его аргументы:

Чанки не работают для стиля. Векторная база режет тексты на куски. Нельзя дать модели вырезанный ниоткуда блок текста и сказать «пиши как тут» — даже если таких блоков будет 5–10. Стиль живёт в целом тексте, а не в абзаце.

Семантическая близость ≠ стилистическая близость. Если издание написало статью про ремонт дороги и мы ищем семантических соседей для новости про ремонт моста — мы найдём тематически похожие тексты. Но стиль одинаковый во всех текстах издания, не только в тематически близких.

Теги проще и дешевле. Вместо векторного поиска можно просто прогнать статьи через LLM, попросить расставить теги, и искать примеры по тегам. Дешевле по вычислениям, проще в реализации, понятнее в отладке.

Третий участник нашей команды подытожил:

«Сначала всегда кажется всё просто, но если достаточной экспертизы нет, всплывают нюансы, которые тормозят MVP. Я бы сделал без [RAG] сначала — и если будет понимание, что недостаточно, добавил.»

Я согласилась. Не потому что RAG бесполезен — он может понадобиться позже. А потому что для MVP нам важнее скорость и качество базового подхода.

Спор 2: один промпт или декомпозиция?

Окей, без RAG. Но промпт-only тоже не работает. Что тогда?

Вот тут наш разработчик предложил штуку, которая изменила первичную архитектуру: декомпозиция стиля на аспекты.

Вместо того чтобы одним запросом просить модель «определи стиль этого издания», мы разбиваем стиль на компоненты:

  • Структура — как строится статья: лид, абзацы, длина, подзаголовки.

  • Тон — формальный, разговорный, ироничный, нейтральный.

  • Лексика — характерные слова, клише, профессионализмы.

  • Заголовки — длина, формат, используют ли вопросы, числа, кликбейт.

  • Эмоциональность — сухо-информационный стиль или с позицией автора.

Каждый аспект — отдельный промпт, который анализирует образцы и выдаёт краткое описание. Потом аспекты собираются в профиль стиля — компактный документ, который хранится и переиспользуется.

┌─────────────────-┐
│ 70–100 образцов  │    Загружает клиент при подключении
│  статей издания  │
└────────┬──────-──┘
         │
         ▼
┌─────────────────┐
│  Аспект:        │    Отдельный промпт для каждого аспекта
│  «Структура»    │──► «Статьи начинаются с факта. Лид — 1–2
│                 │     предложения. Абзацы 3–5 строк...»
├─────────────────┤
│  Аспект:        │──► «Тон нейтрально-информационный с
│  «Тон»          │     элементами разговорности...»
├─────────────────┤
│  Аспект:        │──► «Частотные слова: "отметим", "напомним".
│  «Лексика»      │     Избегают: канцелярит, англицизмы...»
├─────────────────┤
│  Аспект:        │──► «Заголовки 5–8 слов. Формат:
│  «Заголовки»    │     Факт + локация. Без вопросов...»
├─────────────────┤
│  Аспект:        │──► «Сухой стиль. Мнение автора —
│«Эмоциональность»│  только в колонках...»
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  ПРОФИЛЬ СТИЛЯ  │    Агрегация всех аспектов.
│  (хранится)     │    Создаётся один раз, переиспользуется
└─────────────────┘
«Я всё сломал за выходные»: как мы учим LLM писать в стиле конкретного СМИ - 1

Почему это лучше, чем один промпт:

Контролируемость. Если тексты получаются хорошие по структуре, но не те по тону — меняешь один аспект, а не переписываешь всё.

Экономичность. Профиль создаётся один раз при подключении клиента. При генерации каждого текста используется только компактный результат, а не 100 примеров.

Гибкость для клиента. Издание может задать свои аспекты. Кому-то важны правила заголовков. Кому-то — длина предложений. Кому-то — список запрещённых слов. Универсальный набор аспектов + возможность добавить свои.

Спор 3: автоматический анализ или ручные правила?

Следующий вопрос, который возник в процессе: аспекты должны извлекаться автоматически из образцов или задаваться вручную?

Мой вопрос разработчику: «А если клиент — Telegram-канал, у которого тегов отродясь не было и он сам не знает свои правила?»

Его ответ: «Дать инструмент. Как каждый решит его использовать — их дело.»

В итоге мы пришли к гибридному подходу:

Автоматические аспекты. Система анализирует образцы и сама определяет структуру, тон, лексику. Для этого не нужна экспертиза клиента — загрузил статьи, получил профиль.

Ручные правила. Клиент может добавить свои ограничения: «никогда не используй слово “данный”», «заголовок всегда с глаголом», «максимум 3 абзаца». Некоторые редакции знают свои правила наизусть — зачем заставлять LLM угадывать то, что можно просто указать?

Разделение на «что LLM извлекает из образцов» и «что клиент задаёт сам» оказалось ключевым архитектурным решением. Мы назвали вторую категорию «rules» — правила, которые система соблюдает безусловно, независимо от того, что она увидела в образцах.

Как работает генерация текста

Когда профиль стиля собран, процесс генерации выглядит так:

┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│ Входящая новость │    │  Профиль стиля   │    │ 2–3 примера      │
│ (источник)       │    │  (аспекты +      │    │ статей издания   │
│                  │    │   правила)       │    │ (по тегам)       │
└────────┬─────────┘    └────────┬─────────┘    └────────┬─────────┘
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
                                 ▼
                    ┌────────────────────────┐
                    │  Промпт-шаблон         │
                    │  (Handlebars)          │
                    │                        │
                    │  «Вот новость: {{src}} │
                    │   Стиль: {{style}}     │
                    │   Примеры: {{samples}} │
                    │   Правила: {{rules}}»  │
                    └────────────┬───────────┘
                                 │
                                 ▼
                    ┌────────────────────────┐
                    │       LLM              │
                    │  (Claude / YandexGPT)  │
                    └────────────┬───────────┘
                                 │
                                 ▼
                    ┌────────────────────────┐
                    │   Рерайт в стиле       │
                    │   издания              │
                    └────────────────────────┘
«Я всё сломал за выходные»: как мы учим LLM писать в стиле конкретного СМИ - 2

Промпт собирается через шаблонизатор (Handlebars). Клиент может редактировать шаблон в личном кабинете — подставлять переменные из профиля, менять структуру запроса, экспериментировать. Для тех, кто не хочет лезть в шаблоны — работает дефолтный.

Примеры статей пока подбираются просто: по тегам или случайно 2–3 штуки из загруженных образцов. Это MVP-решение. Дальше можно усложнять — добавить семантический поиск, ранжирование по релевантности. Но для старта хватает.

Что не вошло в MVP (и почему)

Векторная база. Отложили. Если качество подбора примеров по тегам окажется недостаточным — добавим. Но усложнять стек на старте без доказанной необходимости мы отказались.

Автоматическая генерация тегов для всех источников. Пока теги ставятся при загрузке образцов. Автоматическая простановка через LLM — следующий шаг.

A/B-тестирование стилей. Архитектура это позволяет — можно создать несколько профилей и сравнивать. Но в MVP фокус на одном рабочем профиле.

Мультиплатформенность. Одно издание часто пишет по-разному для сайта, Telegram и Дзена. Это значит несколько стилевых профилей на клиента. Архитектурно заложено, но реализация — после валидации базового сценария.

Что мы поняли в процессе

1. Споры в команде — это норм.

За один вечер в чате мы прошли путь от «нам нужна векторизация» до «нам не нужна векторизация» и от «промпт решит всё» до «промпт не решит ничего без декомпозиции». Если бы каждый молча делал своё — пришли бы к рабочему решению на месяц позже.

2. MVP ≠ плохо. MVP = осознанно просто.

Каждое «а давайте ещё добавим» на старте — это неделя разработки и неизвестно сколько новых багов. Мы сознательно выбрали простые решения там, где можно усложнить потом: теги вместо эмбеддингов, случайные примеры вместо семантического поиска, фиксированный набор аспектов вместо динамического.

3. Стиль текста — задача декомпозиции, а не задача «найти лучшую модель».

Мы пробовали разные модели. Claude, YandexGPT, OpenAI. Качество зависит от модели, да. Но гораздо больше оно зависит от того, как ты подаёшь задачу. Декомпозиция на аспекты дала больший прирост качества, чем переход на более дорогую модель.

Текущий статус и следующие шаги

Сейчас у нас работает базовый пайплайн: загрузка образцов → создание аспектов → генерация профиля стиля → рерайт с подстановкой стиля и примеров.

Что дальше:

Фактчекинг — кросс-проверка сгенерированного текста с источником. Цифры, имена, должности, цитаты. Это отдельная большая задача, про которую будет отдельная статья.

Умный подбор примеров — от случайных к тематически релевантным. Возможно, тут векторная база всё-таки вернётся.

Пользовательское тестирование — дать реальным редакциям пощупать систему и собрать фидбэк по качеству стиля.

На связи!

Автор: vaganovelena

Источник

Rambler's Top100