从公开广告库里抓出 300 条竞品标题后,谁都想尽快弄清对手到底在主打什么。最省事的做法,是把这些标题全部粘进对话框,问模型:“总结这些广告的卖点。”模型很快就会给出答案:强调高性价比、重视用户体验、营造紧迫感、整体情绪积极向上。问题在于,这四句话甚至不用看广告,你自己也能写出来。
数据本身没有问题。各平台的广告资料库和创意中心都是公开可浏览的,用自己的账号正常查看即可,没有绕过任何限制。真正的问题出在提问方式:你向模型抛出了一个汇总问题,它自然只能还给你一个汇总答案。300 条广告被压缩成四个形容词,压缩率高到几乎丢失了所有信息,最后只剩下一些正确但毫无用处的话。
想从批量文案分析中拿到能直接使用的结论,先得定义什么叫“能用”。“主打性价比”不能指导行动;“节省承诺 + 数字证明 + 时间限制这一组合,占本批样本的 40%,面向价格敏感型人群”才可以,因为它直接告诉你下一条素材该如何设置变量。要得到后者,不能一步到位,必须拆成两步。
为什么“一句话总结卖点”必然变成废话
单次调用失败,不是因为提示词写得不够好,而是任务结构本身就有问题。
你实际上要求模型同时完成两类性质完全不同的工作:先从每条广告里提取信息,再对提取出的信息分类。提取是相对确定的:广告承诺了什么、有没有提供证据,答案通常比较唯一。分类则需要判断:哪些承诺应归为同一类别、类别边界划在哪里,都需要推理。把两件事塞进一次调用,模型最容易走捷径:跳过逐条提取,凭整段文本留下的印象做概括,最后给你一堆它以为你想听到的正向形容词。
单次调用还有一个问题:没有中间产物。你拿到“主打性价比”这个结论,却无法追溯它来自哪些广告、占比多少、是否存在反例。换一批数据再跑一次,结论可能就变了。没有中间产物的分析,既无法审核,也无法迭代。
把一步拆成两步:先提字段,再做聚类
更可靠的流程是两步走,中间加一层结构化字段。
第一步,逐条提取文案字段,写入固定 schema。至少应覆盖四个维度:核心承诺、证据类型、紧迫感手段,以及隐含受众。这个阶段一次只看一条广告,输出严格 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":"..."}
提取完 300 条广告后,你手里不再是 300 段文本,而是 300 条结构化记录。此时,“总结卖点”已经从模糊的语义任务,变成可以统计、分组和绘制分布的数据任务。
第二步才是聚类,但聚的是字段,不是原始文案。直接聚类原文,本质上又回到了语义相似度的迷雾里;对字段聚类,则是在少量离散维度上分组,边界清楚得多。
聚类时,必须要求模型找反例
聚类提示词最关键的部分,不是“把这些内容分组”,而是强制模型拿出反例。
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 |
|
成本能拉开一个数量级,靠的正是这套分工。字段提取是唯一随数据量线性增长的步骤:300 条广告就是 300 次调用,1,000 条就是 1,000 次。聚类则是一批数据只运行一次。把最贵的推理档位留给每批只跑一两次的聚类,把最便宜的档位用在数百次的提取上,总账单可以相差十倍。反过来做,把昂贵模型放在提取、便宜模型放在聚类,是我见过最常见的浪费:提取并不需要那么强的推理,而聚类恰好会在低价档最薄弱的地方失效。
降档到底能省多少,不必听我说,自己跑一轮就知道:
从已经抓取的广告中选 20 到 30 条。
字段提取:让
claude-sonnet-5与claude-opus-5跑同一批数据,逐条比对四个字段的一致性。字段聚类:使用同一批提取结果,让两个档位分别聚类,重点看两件事:反例检查是否真的在挑刺,还是只是在复述候选项;缺口分析是否能指向下一步可执行的动作。
结论很直接:如果字段提取的一致性很高,就把这一环降到低价档省钱;如果低价档在聚类时给不出有价值的反例,这一环就保留在推理档。
陷阱一:让模型自己定义分类
最容易踩的坑,是提取时不给 enum,任由模型自己发明类别。
只看一批数据时似乎没问题。模型给出的类别听起来都合情合理,但问题会在第二批出现:同类文案换了一套类别名称,粒度变了,边界也挪了。等你把两批数据并排,想看趋势时,就会发现根本无法对齐。第一批里的“discount”和第二批里的“save money”到底算不算同一件事?没人说得清。类别随批次漂移,跨批比较就全是假象。
解决方法是把“定义类别”和“使用类别”分开。先让长上下文档位一次读完大批量样本——每次几百条,正是长上下文该做的事——归纳出覆盖完整、粒度一致的一套 enum;然后人工审核并冻结。之后,所有提取都只能从这套固定 enum 中选择,unknown 作为兜底项,绝不允许临时创造新类别。提取提示词中的“pick only from the given enum, do not invent”,就是把这条约束落实到执行层。
一句话概括:类别由你来定,模型只负责填格子。
陷阱二:把出现频率当成有效性
完成提取和聚类后,很多人会本能地按记录数排序,并把出现最频繁的卖点视作“最有效的卖点”。这一步错得很隐蔽。
高频只能说明“大家都这么写”,并不能说明“这么写有效”。广告领域真实存在跟风链条:一条广告跑出成绩后,整个行业可能在一周内一拥而上,创意中心隔夜就多出几十条相似标题。你的频率统计把这些跟风素材一起算进去,得出“这是最流行的卖点”;但它们可能正在集体失效,只是还没人先停下来。频率衡量的是一致性,不是效果。
要把频率和效果分开,必须为每条记录附上效果数据。公开广告库中的素材通常带有播放量、点赞、CTR 等字段。真正应该排序的,不是原始记录数,而是“某个卖点组合进入高表现分位区间的占比”。如何把逐秒留存和 CTR 分位数转化为有效信号,另一篇文章会详细展开。这里重点强调一点:频率表和效果表必须是两张独立的表,一旦把它们揉成一张,结论就毁了。
在这个阶段,模型的职责是归因,不是排序。把某个高频组合及其效果分布一并交给中等推理档,问它:“这个组合频率高,是因为确实有效,还是因为大家在互相复制?”让它依据数字判断即可。即便归因判断错了,成本也不高,因为最终仍会用真实效果数据验证。
陷阱三:只分析赢家
第三个坑藏在数据来源里,而且很容易被忽略:广告资料库和创意中心默认展示的,往往是跑得比较好的素材。像“热门广告”或“Top Ads”这样的入口,本质上就是平台已经按效果筛过的一批幸存者。
你对一堆赢家聚类,找出“成功广告的共同特征”,然后照着抄,这就是典型的幸存者偏差。因为那些失败的广告,很可能同样具备这些特征。假设 90% 的赢家使用了“时间限制”,于是你得出“时间限制有效”;但如果 90% 的失败广告也用了时间限制,这个特征就毫无区分度。它只是行业默认做法,与成功或失败未必有关。
解决办法,是给赢家补上对照组。公开广告库通常可以按行业、营销目标和时间范围筛选。用同样的筛选条件,找到有曝光但互动明显偏低的素材,也对它们进行提取和聚类,再与赢家组并排比较。真正有价值的不是“赢家有什么”,而是差异集合: “赢家有、输家没有什么”。只有出现在这个差异集合里的特征,才值得写进你的下一条素材。
你拿不到完整的失败样本,这没关系。哪怕只有一个小规模的低表现对照组,也远比只根据 Top Ads 得出的结论可信。
最终产物不是总结,而是一张变量表
走完两步、避开三个陷阱后,最终交付物不应该是一段“本批竞品都在主打 XX”的总结。那只会重新回到空话。你需要的是一张变量表:
各维度(承诺、证据、紧迫感、受众)分别有哪些取值。
哪些组合已经验证有效(出现在差异集合中,且效果分位表现较高)。
哪些组合还没有人尝试过(从缺口分析中挖出)。
这张表可以直接作为生成任务的输入。已验证有效的组合,用来批量产出变体;尚未覆盖的组合,则作为低成本试探。文案维度的变量交给文本模型写脚本,视觉与情绪变量交给图像和视频模型生成素材,从竞品文案到自己的成片,这条链路就闭合了。这张变量表,正是创意生产流程中 brief 阶段要读取的输入。
聚类的目的不是生成一张好看的分类图,而是产出一张能驱动下一批生产的变量表。
一个 Key,串起四档模型
上述流程需要四种档位:用于提取的低成本高并发档、用于定义类别的长上下文档、用于聚类的推理档,以及用于归因的中等推理档。它们来自不同供应商,对应不同 SDK、认证方式和错误格式。为了在不同步骤切模型而维护多套客户端接口,并不划算。这也正是很多人最终用一个模型包打天下的真正原因,然后又回到前面说的浪费:要么昂贵档位在提取环节烧钱,要么低价档位在聚类时给不出反例。
AIReiter把这一层抹平了:一个 Key,一个兼容 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 时,则以同一个 Key 请求 POST /api/v1/messages。
价格方面,Claude 模型按官方定价七折,GPT 模型半价,而折扣正好覆盖这套流程最主要的成本。字段提取是唯一随数据量线性增长的环节:300 条广告就是 300 次调用,1,000 条就是 1,000 次。它运行在最便宜的 Sonnet 档上,并额外享受七折优惠,因此构成主要节省来源。聚类和归因每批只运行几次,使用推理档不会造成太大负担;类别定义则通过同一个 Key 调用长上下文 Kimi K3,每批只需一次。
免注册试用:先手动跑几条广告,对比低价档与推理档在字段提取一致性和聚类反例上的表现,确认流程稳定后再脚本化。
结语
批量广告文案分析之所以总会产出一堆空话,不是模型能力不够,而是你把提取和分类硬塞进了一次调用。
把它拆成两步:先依据冻结的 enum 逐条提取结构化字段,在低价档上运行数百次;再对字段聚类,强制模型给出反例,在推理档上运行一次。过程中盯紧三个陷阱:不要让模型临场发明类别,不要把频率误读为有效性,也要为赢家补上对照组。最后得到的应是一张驱动下一批生产的变量表,而不是一句“主打性价比”。
在这套流程里,模型其实是两种不同的工具:一个低成本提取器,和一个愿意挑自己毛病的分类器。把它们分开,用在匹配的档位上,几百条广告才能变成可执行的洞察;把它们混进一个模型里,最后得到的仍然只有形容词。