Выгрузили из публичной рекламной библиотеки триста заголовков конкурентов — и хотите понять, на чём они строят продажи. Самое очевидное решение: вставить всё в чат и попросить «суммировать продающие аргументы этих объявлений». Ответ приходит мгновенно: выгодная цена, акцент на пользовательском опыте, создание срочности, позитивный эмоциональный тон. Четыре строки, которые можно было написать, даже не открывая ни одного объявления.
С данными всё в порядке. Рекламные библиотеки и creative center платформ открыты: их можно просматривать со своего аккаунта, ничего обходить не нужно. Проблема в самом вопросе. Вы дали модели агрегированную задачу — и получили агрегированный ответ. Когда триста реклам сжимаются до четырёх прилагательных, степень сжатия слишком велика: полезная информация исчезает, остаются лишь формально верные, но совершенно бесполезные выводы.
Чтобы массовый анализ рекламных текстов дал практический результат, сначала нужно определить, что именно считать практическим результатом. Формулировка «делают упор на выгоду» не помогает ничего сделать. А вот «сочетание обещания экономии, численного доказательства и ограничения по времени встречается в 40% выборки и нацелено на чувствительную к цене аудиторию» — уже рабочий вывод: он прямо подсказывает, какие переменные задать в следующем креативе. Получить такой результат за один запрос нельзя. Один шаг придётся разделить на два.
Почему запрос «суммируй продающие аргументы» даёт кашу
Проблема одношагового подхода не в неудачном промпте, а в самой структуре задачи.
От модели одновременно требуют два принципиально разных действия: извлечь информацию из каждого объявления и классифицировать извлечённое. Извлечение почти детерминировано: какое обещание даёт реклама, есть ли в ней доказательство — на такие вопросы обычно существует один ответ. Классификация требует суждения: нужно решить, какие обещания отнести к одной категории и где провести границу между ними. Если объединить оба действия в одном вызове, модель выбирает короткий путь: не разбирает рекламу поштучно, а считывает общее впечатление от стены текста и выдаёт набор позитивных прилагательных, которые, как ей кажется, вы хотите услышать.
У одношагового анализа нет и промежуточного результата. Вы получаете вывод «делают упор на выгоду», но не можете проверить, из каких именно реклам он сложился, какую долю выборки они занимают и есть ли контрпримеры. Повторите запуск на другой партии данных — вывод изменится. Анализ, который нельзя проверить и доработать, не слишком полезен.
Два этапа вместо одного: сначала поля, потом кластеры
Рабочая схема строится в два этапа, а между ними появляется слой структурированных полей.
На первом этапе из каждого рекламного текста отдельно извлекаются данные по фиксированной схеме. Минимум в четырёх измерениях: главное обещание, тип доказательства, приём срочности и предполагаемая аудитория. Здесь модель смотрит на одно объявление за раз и возвращает строгий JSON без пояснений.
You will receive one ad headline. Break it apart along the fixed fields below.
Output JSON only, no explanation.
<copy>
{{one piece of copy}}
</copy>
Fields and allowed values (pick only from the given enum; when unsure pick
unknown; do not invent values):
- promise: [save money, save time, look better, get healthier, make money,
learn a skill, belong, identity, unknown]
- evidence: [testimonial, data/numbers, authority, before/after, demo,
none, unknown]
- urgency: [time limit, scarcity, price-rise warning, fear of missing out,
none, unknown]
- audience: a short phrase, inferred from the wording, for who it's talking to
(e.g. "night owls", "moms with kids", "junior designers")
Output:
{"promise":"...","evidence":"...","urgency":"...","audience":"..."}
После обработки трёхсот объявлений у вас будут не триста текстовых блоков, а триста структурированных записей. Задача «суммировать продающие аргументы» перестаёт быть расплывчатой семантической задачей: это уже данные, которые можно считать, группировать и раскладывать по распределениям.
Второй этап — кластеризация, но кластеризовать нужно поля, а не исходные тексты. Кластеризация сырого текста возвращает вас к той же туманной семантической похожести. Поля же группируются по нескольким дискретным измерениям с понятными границами.
Как кластеризовать и зачем требовать контрпример
Главное в промпте для кластеризации — не просьба «сгруппируй это». Важно обязать модель привести контрпример.
Below are N ad headlines already extracted into structured records.
The categories are frozen. Do not add categories.
<records>
{{JSON array, each with promise/evidence/urgency/audience}}
</records>
Output three things in order:
1. Combination clustering
Group by (promise x evidence x urgency), and give each group's record
count and one representative sample.
2. Counterexample check
For the top 3 groups by record count, pick one record per group whose
audience clearly departs from the group's mainstream, and explain why it
got grouped there. Is it really the same selling point, or did step one
extract a field wrong?
3. Gaps
Which combinations that should be common don't appear even once in this
batch? Are those gaps "nobody's doing it" or "my sample didn't cover it"?
Именно второй блок делает промпт полезным. Модель по умолчанию стремится быть полезной и соглашаться с вами; если её не подталкивать, каждый найденный кластер будет выглядеть подозрительно цельным. Требование вытащить из только что созданной группы запись, которая в неё не вполне вписывается, заставляет модель продолжить проверку и после того, как ей уже кажется, что задача решена. В результате либо проявляется слишком грубая граница классификации, либо выясняется, что поле на первом этапе извлекли неверно.
Приём, при котором модель заставляют критиковать собственную работу, полезен не только для анализа рекламы. В реверс-инжиниринге кода это называют разделом с контрдоказательствами: распознав семейство алгоритма, нельзя просто поверить выводу — нужно спросить, «чем эта реализация отличается от стандартной». Принцип тот же: он сдерживает склонность модели соглашаться с пользователем при работе с обфусцированным кодом и идентификации алгоритмов по отпечаткам. В кластеризации рекламных текстов проверка контрпримеров и есть такой раздел с контрдоказательствами.
Какую модель поставить на каждый этап
Эти два этапа требуют от модели противоположных качеств, поэтому использовать одну модель для всего — прямой перерасход:
Этап | Необходимые качества | Выбор | model id |
|---|---|---|---|
Извлечение полей из каждого объявления (сотни или тысячи, по одному вызову) | Низкая цена, высокая параллельность, стабильный структурированный вывод | Claude Sonnet 5 |
|
Формирование категорий (один раз прочитать всю выборку и вывести enum) | Длинный контекст | Kimi K3 |
|
Кластеризация полей, контрпримеры, пробелы | Сильное рассуждение и готовность критиковать собственный вывод | Claude Opus 5 |
|
Атрибуция частотности: высокий счётчик означает результативность или цепочку копирования? | Средний уровень рассуждений, объяснение на основе данных | GPT-5.6 Sol |
|
Именно это разделение даёт разницу в затратах на порядок. Извлечение полей — единственный этап, который линейно масштабируется с объёмом: триста реклам означают триста вызовов, тысяча — тысячу. Кластеризация выполняется один раз на пакет данных. Поставьте дорогой уровень рассуждений на кластеризацию, которая запускается один-два раза, а самый дешёвый — на извлечение, которое выполняется сотни раз, и итоговый счёт сократится в десять раз. Сделайте наоборот — дорогую модель на извлечение, дешёвую на кластеризацию — и получите самый частый вид перерасхода: извлечению не нужен настолько глубокий анализ, а кластеризация провалится ровно там, где дешёвая модель слабее всего.
Насколько оправдано понижение модели, не принимайте на веру — проверьте за один прогон:
Возьмите 20–30 объявлений из уже собранных данных.
Извлеките поля: пропустите один и тот же пакет через
claude-sonnet-5иclaude-opus-5, затем сравните совпадение всех четырёх полей запись за записью.Кластеризуйте: возьмите те же извлечённые записи, обработайте их обоими уровнями и проверьте две вещи. Действительно ли проверка контрпримеров разбирает группы, а не пересказывает кандидата, и указывают ли найденные пробелы на практический следующий шаг.
Вывод считывается прямо из результата: если совпадение на извлечении высокое, переводите этот этап на дешёвый уровень и экономьте; если дешёвый уровень не способен дать полезный контрпример при кластеризации, этот этап остаётся на модели для рассуждений.
Ловушка №1: позволить модели самой придумывать категории
Самая простая ловушка — не задать enum при извлечении и разрешить модели изобретать категории на ходу.
На одном пакете всё выглядит нормально: модель выдаёт набор разумно звучащих категорий. Проблема обнаруживается на втором. Тексты того же типа, но названия категорий уже другие, детализация изменилась, границы сдвинулись. Вы пытаетесь сопоставить две выборки, чтобы увидеть тренд, — и они не стыкуются. «Скидка» в первой партии — то же самое, что «экономия» во второй, или нет? Никто не знает. Когда категории дрейфуют от пакета к пакету, любые межпакетные сравнения становятся фикцией.
Решение — отделить создание категорий от их применения. Сначала дайте модели с длинным контекстом прочитать большую выборку за один проход — сотни примеров за раз, именно для этого и нужен длинный контекст — и вывести полный enum с одинаковой детализацией. Затем проверьте его вручную и зафиксируйте. После этого при извлечении разрешено выбирать только из зафиксированного enum, а роль универсальной категории играет unknown; новые категории на месте не создаются. Строка в промпте извлечения «pick only from the given enum, do not invent» как раз формализует это ограничение.
Если кратко: категории задаёте вы, модель лишь заполняет ячейки.
Ловушка №2: путать частотность с эффективностью
После извлечения и кластеризации возникает естественное желание отсортировать результаты по числу записей и назвать самый частый продающий аргумент «самым эффективным». Это ошибочный шаг, и его легко не заметить.
Высокая частотность говорит только одно: «все пишут именно так». Она не говорит, что такой подход работает. В рекламе существует реальная цепочка копирования: один креатив выстреливает, через неделю вся ниша бросается повторять его, и в creative center за ночь появляются десятки почти одинаковых заголовков. Счётчик частотности включает всех этих подражателей и сообщает, что аргумент «самый популярный», хотя вся группа может показывать плохие результаты, просто никто ещё не остановился. Частотность измеряет конформность, а не эффект.
Чтобы отделить частоту от эффективности, к каждой записи нужно прикрепить данные о результате. У каждого креатива в публичной рекламной библиотеке есть поля вроде числа просмотров, лайков, CTR и другие подобные метрики. Сортировать нужно не по количеству записей, а по «доле конкретного сочетания продающих аргументов, попадающей в высокий перцентиль эффективности». О том, как превратить посекундное удержание и перцентили CTR в осмысленный сигнал, рассказано в отдельном материале. Здесь важно другое: таблица частотности и таблица эффекта должны быть разными таблицами. Как только вы склеиваете их в одну, вывод становится неверным.
На этом этапе модель должна заниматься не сортировкой, а атрибуцией. Передайте модели среднего уровня рассуждений частое сочетание вместе с распределением его показателей и спросите: «эта частотность высока потому, что подход работает, или потому, что все копируют друг друга?» Пусть она опирается на цифры. Ошибка в атрибуции обходится недорого: финальную проверку вы всё равно делаете по реальным данным об эффективности.
Ловушка №3: анализировать только победителей
Третья ловушка спрятана в самом источнике данных, поэтому её легко вовсе не заметить: рекламная библиотека и creative center по умолчанию показывают объявления, которые хорошо откручивались. Разделы вроде «hot ads» или «Top Ads» — по сути, уже отфильтрованные платформой по эффективности выжившие.
Вы кластеризуете подборку победителей, находите «общие признаки успешной рекламы» и копируете их. Это классическая ошибка выжившего: у провалившихся реклам вполне могут быть ровно те же признаки. Допустим, «ограничение по времени» использовали 90% победителей — и вы заключаете, что этот приём работает. Но если те же 90% неудачных объявлений тоже использовали ограничение по времени, признак вообще ничего не различает. Это отраслевой стандарт, не связанный ни с успехом, ни с провалом.
Решение — добавить к победителям контрольную группу. В публичной рекламной библиотеке обычно доступны фильтры по индустрии, маркетинговой цели и временному окну. Примените те же фильтры к креативам, которые получили показы, но показали явно низкую вовлечённость, также извлеките из них поля и кластеризуйте, затем поставьте рядом с группой победителей. Ценность представляет не набор «того, что есть у победителей», а разностное множество: «что есть у победителей, но отсутствует у проигравших». Только признак из этого множества стоит переносить в следующий креатив.
Полную выборку неудачников вы не получите — и это нормально. Даже небольшая контрольная группа с низкой эффективностью значительно надёжнее выводов, сделанных только по Top Ads.
На выходе нужна таблица переменных, а не сводка
Если пройти два этапа и избежать трёх ловушек, итогом не должен стать абзац в духе «конкуренты в этой выборке делают упор на XX». Это снова возвращает нас к бессодержательной сводке. Нужна таблица переменных:
Какие значения принимает каждое измерение: обещание, доказательство, срочность, аудитория.
Какие сочетания уже подтверждены как эффективные: попадают в разностное множество и показывают высокий перцентиль эффективности.
Какие сочетания ещё никто не тестировал: их можно найти в разделе с пробелами.
Эту таблицу можно сразу подавать на вход генеративной задаче. Для подтверждённо эффективных сочетаний массово создаются вариации, пустые сочетания отправляются в недорогие тестовые пробы. Переменные рекламного текста передаются текстовой модели для написания сценариев, визуальные переменные и параметры тона — моделям изображений и видео для создания креативов. Так замыкается цепочка от текста конкурента до вашего готового ролика. Именно такую таблицу переменных использует этап брифа в креативном пайплайне.
Кластеризация нужна не для красивой схемы классификации. Её задача — создать таблицу, которая управляет следующей партией производства.
Один ключ для всех четырёх уровней моделей
Описанному процессу нужны четыре уровня: дешёвый высокопараллельный — для извлечения, модель с длинным контекстом — для задания категорий, модель для рассуждений — для кластеризации и средний уровень рассуждений — для атрибуции. Это несколько поставщиков, несколько SDK, схем авторизации и форматов ошибок. Подключать клиент к нескольким интерфейсам лишь ради переключения моделей между этапами не стоит усилий. Именно поэтому большинство в итоге использует одну модель для всего и сталкивается с описанным перерасходом: либо дорогой уровень сжигает бюджет на извлечении, либо дешёвый не может подобрать контрпример при кластеризации.
AIReiter убирает этот слой сложности: один ключ, один OpenAI-совместимый интерфейс, все четыре уровня за ним; чтобы переключить модель, достаточно изменить поле model в теле запроса.
# Extract fields: the cheap high-concurrency tier
curl https://aireiter.com/api/v1/chat/completions \
-H "Authorization: Bearer $AIREITER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "<extraction prompt + one piece of copy>"}]
}'
# Cluster: switch to the reasoning tier, leave the rest
# "model": "claude-opus-5"
# Frequency attribution:
# "model": "gpt-5.6-sol"
Если вы уже используете OpenAI SDK, укажите для base_url адрес https://aireiter.com/api/v1 — больше ничего менять не нужно. В Anthropic SDK используйте POST /api/v1/messages с тем же ключом.
По цене модели Claude доступны со скидкой 30% от прайса, а GPT — за половину стоимости. Скидка приходится именно на главный источник затрат в этой схеме. Извлечение полей — единственный этап, который линейно растёт вместе с объёмом: триста реклам — это триста вызовов, тысяча — тысяча. Он работает на самом дешёвом уровне Sonnet, поверх которого действует скидка 30%, и именно здесь образуется основная экономия. Кластеризация и атрибуция запускаются несколько раз на пакет, поэтому уровень для рассуждений не создаёт заметных затрат. Категории задаются на Kimi K3 с длинным контекстом, доступной по тому же ключу, один раз на пакет.
Попробовать без регистрации: сначала вручную прогоните несколько реклам, сравните дешёвый уровень и уровень рассуждений по совпадению извлечения и контрпримерам в кластеризации, а автоматизируйте процесс, когда результат станет стабильным.
Итог
Массовый анализ рекламных текстов превращается в кашу не потому, что модель слабая, а потому, что извлечение и классификацию пытаются уместить в один вызов.
Разделите задачу на два этапа: извлекайте из каждого объявления структурированные поля по зафиксированному enum, запускайте эту операцию сотни раз на дешёвом уровне, затем кластеризуйте поля и требуйте от модели контрпример — это выполняется один раз на уровне для рассуждений. И следите за тремя ловушками: не позволяйте модели изобретать категории на месте, не принимайте частотность за эффективность и добавляйте к победителям контрольную группу. Завершайте работу таблицей переменных для следующей партии креативов, а не фразой «делают упор на выгоду».
В этой схеме модель выполняет две разные роли: дешёвого извлекателя и классификатора, который готов критиковать собственные выводы. Используйте их раздельно и на подходящих уровнях — и несколько сотен реклам дадут практический результат. Сведите всё к одной модели — получите только прилагательные.