简介:这是一份面向小红书内容创作者与新媒体运营者的AI写作指令文档,聚焦爆款文案的标题、正文与标签三要素,帮助缺乏选题与表达经验的人借助提示词快速产出符合平台调性的笔记。文档以角色设定、背景与目标为起点,依次拆解标题的二极管法与爆款关键词用法、正文的口语化结构与表情符号节奏、SEO标签的核心词与长尾词布局,并给出从用户调研、主题选定到成稿发布的流程步骤,可直接作为提示词模板套用。压缩包内共1个docx文件,约19KB,篇幅紧凑却覆盖完整指令框架与示例化要求,便于复制、修改和归档。已有649人学习,适合希望提升账号影响力与个人IP塑造的运营者结合自身案例反复演练,在保持内容质量的同时提高选题效率与文案吸引力。
1. 指令合集不是文案模板库:把「爆款」拆成可复现的生成约束
很多做小红书爆款文案的人对「AI 指令合集」这件事的理解,停留在几十条写死的模板:换个产品名、换个地名就丢出去,结果十条里九条是同一种腔调,读三行就能闻出机器味。真正稀缺的素材不是模板条数,而是把「爆款」这个模糊判断拆成模型能执行的约束:标题允许多长、首句必须落在哪个冲突点、正文几段、每段承担什么信息、标签用几层词、哪些词一出现就必须重写。这篇内容围绕一个可落地的指令合集工程方案展开,讲清它的分层结构、槽位校验、批量流水线和去重与回归,适合已经在用大模型产出内容、但被同质化和低可用率卡住的从业者。读完你手上应该有一套能持续迭代、而不是一次性拷走的指令资产。
2. 四层骨架拆解:小红书笔记里哪些位置真正决定点击与完读
写指令之前,先要知道一篇笔记的结构里哪些位置有固定规律、哪些位置必须留空给模型发挥。把整篇笔记当成一个整体去描述,模型只会输出一段四平八稳的说明文;把它拆成标题、首句、正文、标签四个独立单元,每个单元单独给约束,产出质量的方差会立刻收窄。
2.1 标题的三种可计算句式与字数区间
标题是唯一一个「不点开就没有后面一切」的位置,所以它的约束要最硬。行业里比较通用的做法是把标题限制在 12 到 20 个汉字,原因很实在:这个平台上标题超过一定长度会被折叠成一行,后半截直接被截掉,用户看到的是半句话,点击率会掉得很难看。指令里我一般会直接写死「标题 14 到 18 字,不得超过 20 字,不得使用省略号结尾」,而不是含糊地说「标题要简短」。
句式层面,能稳定复现的主要是三类,做得久了你会发现大部分高互动标题都能归到这三类里,剩下的所谓玄学其实是运气。
| 句式 | 结构骨架 | 字数区间 | 适配内容 | 常见错误 |
|---|---|---|---|---|
| 数字清单 | 数字 + 人群限定 + 结果 | 14-18 | 工具合集、教程、避坑 | 标题写 5 条,正文只有 3 条 |
| 反差否定 | 别再 X 了 / 我劝你先别 | 12-16 | 观点、避雷、经验纠偏 | 只否定不给替代方案 |
| 结果前置 | 结果 + 时间或代价 | 12-18 | 过程记录、效果展示 | 结果无法在正文里被验证 |
数字清单型最容易写、也最容易出错。模型天生喜欢凑整数,你说「写几条建议」,它给你五条,但正文里可能只有三条是实的,另外两条是「保持良好心态」这种废话。所以指令里必须补一句「标题中的数字必须等于正文中可被独立编号的信息点数量」,并且在后处理阶段做一次数字一致性校验——这条后面第 5 章会详细说。
反差否定型的风险在另一个方向。模型很擅长写「别再盲目买了」这种半句话,但它不知道替代方案是什么,于是正文绕一圈又回到原点。指令里要强制要求「否定句之后 200 字内必须给出一个具体可执行的替代动作」,否则这条产出直接判不合格。
结果前置型最考验真实性。「三个月从零到稳定出单」这种标题,如果没有可验证的过程细节撑着,正文会立刻露怯。常见做法是要求模型在正文第二段必须给出一个具体时间点、一个具体动作、一个具体数字,三者缺一不可。
提示:标题句式不要每次都随机挑。合集里应该给每条选题预设一个句式字段,让句式分布可控,否则批量生成 100 条会出现 70 条同句式的情况,一眼假。
2.2 首句钩子:把「我买了」改成「我后悔买晚了」
正文第一句的作用不是介绍背景,是在用户下滑的手指上踩一脚刹车。这个位置我给模型的约束比标题还细:首句 25 到 40 字,前 15 字内必须出现冲突、结果或代价中的至少一个,禁止以「今天」「最近」「大家好」开头。
为什么是 25 到 40 字?太短撑不住信息量,用户觉得你在喊口号;太长在移动端会占三行以上,视觉上像一段说明文,直接劝退。25 到 40 字大概是两行出头,正好是一个「读完就大概知道值不值得往下看」的体量。
三种可复现的钩子写法:
结果前置,比如「用了两周把这个桌面收干净之后,我加班时间少了一个小时」。特点是把结论砸在第一句,代价是必须真的有一个能站住的结果,不能编。
代价前置,比如「为了省下每个月两百块的订阅费,我折腾了三个晚上,最后发现只用改一个设置」。这类钩子靠「付出感」换信任,适合经验分享类内容。
反常识前置,比如「这类产品越贵越好用这句话,在我身上完全不成立」。这类开头点击不差,但正文必须有对比样本,否则就是纯粹的标题党,评论区会翻车。
指令里怎么写?不要写「写一个吸引人的开头」,要写成模板化的槽位填充:
首句必须满足以下三条中的一条,并在句首 15 字内完成: A. 结果前置:{时间跨度} + {具体结果} + {与常识相反的部分} B. 代价前置:{付出的代价} + {最后的转折} C. 反常识:{被普遍相信的说法} + {否定的判断} 禁止使用:今天、最近、大家好、姐妹们、家人们这种写法让模型没有退路,它必须选一个模板去套,而不是自由发挥。代价是句子会有点公式化,所以风格样本(第 3 章会讲)要把这部分「人味」补回来。
2.3 正文段落配比与标签组合
正文我一般要求 3 到 5 段,每段 40 到 80 字,段与段之间空行,每段只承担一个信息点。这个配比不是拍脑袋定的:段落在移动端超过 80 字就会变成密集文字块,完读率明显下降;低于 40 字又容易变成流水账,用户会觉得你什么也没说。
段落职能也要分开。第一段承接首句给结论,第二段给过程或者对比,第三段给「不适合谁」,第四段给一个可执行的小动作,第五段收标签前的最后一句话。指令里把段落职能写成显式清单,比让它自由发挥稳定得多。这里有个血泪经验:如果你只写「写一篇 300 字左右的笔记」,模型给你的结构永远是「总—分—总」,因为它训练数据里这种结构最多,而这种结构在小红书上恰恰是最没人看的。
标签是另一个容易被忽略的位置。我一般要求 6 到 9 个标签,分三层:一个大词(覆盖人群最广的品类词)、三到四个精准词(具体到场景或人群)、两个长尾词(更像是用户真的会在搜索框里敲的词)。指令里要明确「不得堆砌互不相关的热门词」,因为标签和正文内容对不上,平台的分发会把这篇推给完全不对的人,点击率反而更差。
把这套结构落成字段,才有后面工程化的可能:
| 字段 | 类型 | 必填 | 约束 |
|---|---|---|---|
| title | string | 是 | 14-18 字,含一个数字或一个否定词 |
| hook | string | 是 | 25-40 字,命中 A/B/C 之一 |
| body | array | 是 | 3-5 段,每段 40-80 字 |
| tags | array | 是 | 6-9 个,三层结构 |
| audience | string | 是 | 明确到「谁在什么场景下」 |
| risks | array | 是 | 模型自报的存疑表述 |
最后那个 risks 字段值得单独说一句。让模型在输出末尾自己列出「这条内容里我不确定的事实」,人工抽检效率能提高一倍——它列出来的东西,八成真的有问题。
3. 指令合集的三层分层:系统提示、任务指令、风格样本
把几十条指令平铺在一个文件夹里,用不了两周就会乱:改了标题规则,忘了同步到另外三十条;某条产出突然变差,翻半天不知道是哪次改动造成的。工程化的第一件事是分层,第二件事是给每条指令一个可追踪的身份。
3.1 目录结构与 YAML 字段定义
我习惯用 YAML 存指令,而不是 Markdown 或纯文本。原因很实际:YAML 天然支持嵌套和多行字符串,槽位、禁用词、样本可以放在同一个文件里,读的时候一次读完,不用跨文件拼装。目录按「场景/品类」两级分,文件名带语义化版本号。
# prompts/note/daily_goods_v3.yaml id: xhs-note-daily-goods # 全局唯一,程序里用它索引 version: 3.2.0 # 语义化版本,改动必升 updated: 2024-11-02 locale: zh-CN system: | 你是一名长期写生活类笔记的内容作者。 你的输出必须严格符合 JSON,不要输出任何解释性文字。 不要在正文中使用"首先""其次""最后"这类连接词。 task: | 根据 {audience}、{pain_point}、{product}、{scene} 四个变量, 生成一篇笔记,字段定义见下方 schema。 标题必须命中句式:{sentence_type} 首句必须命中钩子类型:{hook_type} slots: - name: audience required: true max_len: 30 desc: 谁在什么状态下会看这篇 - name: pain_point required: true max_len: 40 - name: product required: true max_len: 20 - name: scene required: false max_len: 30 - name: sentence_type required: true enum: [数字清单, 反差否定, 结果前置] - name: hook_type required: true enum: [A, B, C] guard: banned_words: ["最", "第一", "国家级", "绝对"] max_emoji: 3 max_tags: 9 few_shot: - in: {audience: "每天通勤一小时的上班族", pain_point: "包太乱找不到卡", product: "分隔内胆包", scene: "地铁进站口"} out: {title: "...", hook: "...", body: ["...", "..."], tags: ["..."]}这份文件里有几个字段值得解释。id和version分开,是因为你可能同时存在两套逻辑不同但品类相同的指令,用 id 区分用途、用 version 区分迭代。slots里带enum的字段是「受控变量」,这类变量不要交给模型去发挥,直接由选题表指定,能把产出方差压掉一大截。guard.banned_words里那几个词不是随便写的,是广告法里明确不能随便用的绝对化表述,凡是做带货类文案,这一层过滤必须有,靠模型自觉是靠不住的。
few_shot里的样本尽量从你自己的历史产出里挑,而不是从网上抄。抄来的样本带别人的语感,模型会连那种语感一起学走,最后你所有账号读起来像同一个人。
3.2 变量槽位:把「产品名、人群、痛点」变成必填校验
槽位不校验,等于没有槽位。我见过太多人写完模板直接str.format(**row),结果 CSV 里某一列是空的,模型收到一个「针对 的 人群」这种残缺输入,然后开始自己编——编出来的东西看着通顺,但和你的选题完全对不上,你会以为是模型能力不行。
# validate_slots.py from enum import Enum def validate(row: dict, slots: list) -> tuple[bool, list[str]]: """返回 (是否通过, 错误列表)。任何一条不通过都不应该发请求。""" errors = [] for slot in slots: name = slot["name"] val = (row.get(name) or "").strip() if slot.get("required") and not val: errors.append(f"{name}: 必填为空") continue if not val: continue # 非必填且为空,跳过后续校验,交给模型用默认值 if len(val) > slot.get("max_len", 999): errors.append(f"{name}: 长度 {len(val)} 超过 {slot['max_len']}") if "enum" in slot and val not in slot["enum"]: errors.append(f"{name}: {val} 不在枚举 {slot['enum']} 中") return (len(errors) == 0, errors)这段代码不长,但它是整条流水线里性价比最高的一段。required挡住的是「模型瞎编」,max_len挡住的是「用户把一整段需求说明塞进产品名槽位」,enum挡住的是「选题表里手填的句式名和指令里定义的对不上」。第三种情况最隐蔽:你以为是模型不听话,其实是结果前置被写成了结果型,枚举校验失败后如果你只是打日志不拦截,模型收到的就是一个不存在的句式,它只能自己猜。
实际跑的时候我会把校验失败的行单独写到一个rejected.csv,带上错误原因。运营同学第二天看一眼就知道选题表哪几列填得不规范,比事后返工便宜得多。
注意:
max_len不要设得太松。槽位超过 40 字,模型倾向于把整句话原样搬进标题,标题会立刻超长。
3.3 风格样本怎么放:few-shot 的数量与顺序效应
风格样本是决定「像不像人写的」的关键,但很多人放样本的方式是错的:塞十条进去,以为越多越好。实际测下来,2 到 3 条是最优区间。少于 2 条,模型抓不住语感;多于 4 条,它开始机械模仿样本的句式,十条产出里有八条开头一模一样。
顺序也有讲究。模型对靠近输出的内容更敏感,所以最像目标风格的那条样本要放在最后。我一般的排列是:一条「结构标准但语气平淡」的,一条「语气强但结构一般」的,最后一条是「结构和语气都接近目标」的。前两条负责划边界,最后一条负责定调。
样本长度也要和目标输出接近。如果你放一条 500 字的样本,模型会默认往 500 字写,即使你的 task 里写了「正文 3 到 5 段,每段 40 到 80 字」,它也会被样本的体量带跑。这个现象我在不同模型上都遇到过,属于那种不看数据想不到、看了数据觉得理所当然的坑。
还有一点:样本里不要出现真实品牌名和真实人名。一方面是合规,另一方面模型会把这些具体词当成必须出现的元素,生成一堆「XX 牌」的硬广句式。样本里的产品统一写成「某款保温杯」「某款折叠键盘」这种占位表述就够了。
3.4 版本号与灰度:指令改一个字,产出全变
指令合集最大的坑不是写不出来,是改坏了不知道。改一句「语气可以活泼一点」,可能让整个批次的标签全变成网络流行语。所以我给每条指令配一个固定的回归集:20 条覆盖不同品类、不同句式的选题,每次改动前跑一遍,改动后再跑一遍,人工对比两份产出的差异。
版本号用语义化三段:主版本变更代表结构变了(比如从三段正文改成五段),次版本代表约束变了(字数、枚举、禁用词),补丁号代表只改了措辞。改主版本必须重跑全量回归,改补丁号抽查 5 条就够。
灰度这块简单说就是「别一次全量」。新版本先跑 10 条投出去,看两天的数据再决定要不要铺开。指令的效果不比代码好验证,你看着漂亮的句子,实际点击率可能是最差的——这种反直觉的事在小红书上太常见了。
4. 批量流水线:从选题表到可发布文案的最小实现
到这一步,指令文件写好了、槽位校验也写了,剩下的是把它跑起来。我自己用的流水线不长,大概两百行代码,核心就三块:请求组装、输出解析、相似度去重。这三块任何一块偷懒,后面的返工量都会翻倍。
4.1 请求组装与并发退避
# generate.py import json, os, time, random, requests from concurrent.futures import ThreadPoolExecutor BASE_URL = os.environ["LLM_BASE_URL"].rstrip("/") # 兼容 chat/completions 协议的接口地址 API_KEY = os.environ["LLM_API_KEY"] MODEL = os.environ.get("LLM_MODEL", "chat-large") def call_llm(messages, temperature=0.8, max_tokens=900, retries=3): """带指数退避的调用。只对可重试错误重试,参数错误直接抛出。""" for attempt in range(retries): try: resp = requests.post( f"{BASE_URL}/chat/completions", headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}, json={"model": MODEL, "messages": messages, "temperature": temperature, "max_tokens": max_tokens}, timeout=60, ) if resp.status_code in (429, 500, 502, 503): raise RuntimeError(f"retryable {resp.status_code}") resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"] except Exception as e: if attempt == retries - 1: raise # 加抖动,避免多个线程同时重试打成脉冲 time.sleep((2 ** attempt) + random.uniform(0, 0.8))temperature是最需要调的参数。写标题和首句时我一般用 0.9,逼它给出不那么常见的表达;写正文用 0.7,保证信息点不跑偏;写标签用 0.5,标签要的是稳定命中而不是创意。同一条指令里给不同字段不同的温度做不到(一次请求一个温度),所以常见做法是把「标题+首句」和「正文+标签」拆成两次请求,虽然贵一点,但可控性高很多。
max_tokens不要设成 4096 这种大值。设大了模型会给你写小作文,正文直接冲到 800 字;设成 900 左右,配合指令里的段落约束,长度基本能卡在你要的区间。
并发数我一般压到 3 到 5。看着慢,但比因为触发限流导致整批失败重跑要快。retries给 3 次够了,三次还失败通常是参数或额度问题,重试解决不了。
4.2 输出解析:让它必须吐 JSON
模型输出的 JSON 有三类常见问题:包在 Markdown 代码块里、前后带一句「以下是生成的内容」、少一个右括号。解析器要能处理前两种,第三种只能靠重试加修错指令。
import json, re def parse_output(raw: str, required_keys=("title", "hook", "body", "tags")): """剥离代码块并解析;失败返回 None,由上层决定是否重试。""" text = raw.strip() # 去掉 ```json ... ``` 包裹 text = re.sub(r"^```(?:json)?\s*|\s*```$", "", text, flags=re.S).strip() # 截取第一个 { 到最后一个 },挡掉前后的解释性文字 start, end = text.find("{"), text.rfind("}") if start == -1 or end == -1: return None try: data = json.loads(text[start:end + 1]) except json.JSONDecodeError: return None if not all(k in data for k in required_keys): return None # 长度硬校验,超出直接判失败,别指望后面的人工去改 if not (12 <= len(data["title"]) <= 20): return None return data解析失败后的处理比解析本身重要。我的做法是带着原始输出再请求一次,指令是「下面这段输出不是合法 JSON,请只输出修正后的 JSON,不要解释」,通常一次就能修好。修两次还失败的,直接落盘到failed.jsonl人工看——这类样本往往能暴露指令里的结构矛盾,是改进的素材。
长度校验放在解析器里而不是校验脚本里,是因为标题超长是最常见的失败模式,早点拦掉能省一次人工返工。
4.3 相似度去重:3-gram Jaccard 与阈值
批量生成最大的浪费不是钱,是你看两百条几乎一样的东西。去重要在生成之后、人工看之前做。
def ngrams(text: str, n=3) -> set: text = "".join(text.split()) # 去掉空白,中文不需要按词切 return {text[i:i + n] for i in range(len(text) - n + 1)} def jaccard(a: str, b: str, n=3) -> float: ga, gb = ngrams(a, n), ngrams(b, n) if not ga or not gb: return 0.0 return len(ga & gb) / len(ga | gb) def dedup(items, threshold=0.55, key=lambda x: x["title"] + x["hook"]): """贪心去重:与已保留项相似度超过阈值的丢弃。""" kept = [] for it in items: k = key(it) if all(jaccard(k, key(x)) <= threshold for x in kept): kept.append(it) return keptn=3对中文短文本比较合适,2-gram 太敏感(「一个」「可以」这类高频二元组会把不相干的文本拉到 0.3 以上),4-gram 又太钝。阈值 0.55 是我在几千条产出上试出来的经验值,低于这个数基本还是不同内容,高于它就明显是换了个说法的同一篇文章。
去重只比标题和首句就够了,不用比全文。标题和首句重复,正文再怎么变也是同一篇。这一条能省掉大量计算,实测效果差别不大。
4.4 人工抽检表怎么设计
机器筛完还是要人看。抽检表不要做成「好/不好」两栏,太粗,看完你也不知道改哪里。我的表是四个 1 到 5 分的维度:钩子强度(首句是否让人想往下读)、信息密度(有没有具体数字和动作)、可执行性(读者看完能不能做一件事)、人味(有没有模板腔)。
四个维度里,「人味」低于 3 分的直接退回重写,其他三个维度只要有一个低于 3 也退回。剩下的按总分排序,前 30% 优先发布。这套规则不完美,但比凭感觉挑要稳定,也不会让运营同学每天纠结两小时。
5. 避坑与排查:AI 味重、同质化、产出可用率低的 5 个成因
5.1 十条里有八条开头是「姐妹们」
现象:整批产出的首句高度雷同,全是几个固定的口语化称呼轮着来。
原因:风格样本全是从同一类爆款笔记里抄的,语感单一,模型只能在这个语感里打转。另外「语气活泼」这种描述性指令,模型的默认理解就是加网络流行语。
解决:样本换成三种不同语气——一种克制叙述、一种带具体数字的干货、一种第一人称踩坑。指令里把「活泼」换成可执行的约束,比如「允许出现 1 个口语词,不得超过 3 个 Emoji,禁止使用称呼类词语开头」。约束越具体,模型越没有偷懒空间。
5.2 标题全部以「我」开头
现象:一百条标题,六十条是「我发现」「我用了」「我劝你」。
原因:槽位顺序固定。你的 task 里如果是「根据 {audience}、{pain_point}、{product} 生成」,模型会优先从第一人称视角切入,因为这是最省力的叙述方式。
解决:加一个sentence_type受控变量(第 2 章那张表),由选题表指定句式,不让模型自己选。同时把「以第一人称开头的标题不得超过本批次的 30%」写进批处理后的统计校验里,超了就重跑那部分。
5.3 正文变成「首先、其次、最后」的说明书
现象:明明是生活类笔记,读起来像产品说明书。
原因:指令里写了「分点说明」「逻辑清晰」这类词。这两个词在模型的语义空间里强关联议论文结构。
解决:把「逻辑清晰」删掉,改成「用三段场景叙述,每段开头是一个具体时间点或动作」。另外在system里显式禁用连接词列表,比在 task 里描述风格有效得多。
5.4 生成 200 条只有 30 条能用
现象:人工挑完,可用率不到 20%,投放成本摊不下来。
原因:温度开到 1.0 以上追求多样性,同时没有分段约束,模型在自由发挥和结构化之间来回横跳,产出大量半成品。
解决:温度降到 0.7 到 0.85,段落职能写死,输出加 JSON schema 校验,不合格的直接重试一次。可用率通常能从 20% 提到 50% 左右,剩下的差距靠样本质量补,不是靠调参。
5.5 标题里的数字和正文对不上
现象:标题写「5 个方法」,正文只有 3 条。
原因:模型的数字是生成的,不是数出来的。它在写标题时还没写正文,两边的数字天然不保证一致。
解决:后处理加一条规则,正则提取标题里的阿拉伯数字和中文数字,再数正文里的编号项或段落数,不一致就自动重写标题、把数字替换成实际条数。这条校验十几行代码,能挡掉一批看起来没问题、发出去被评论区指出的低级错误。
6. 用打分表做小样本回灌:让指令合集自己长
指令合集放到第二个月就会开始退化:你投的品类变了、平台的热门句式变了、用户对某种开头脱敏了,而文件夹里那几十条指令还是老样子。真正让这套东西活下来的,不是写得多全,是有没有一个能自转的闭环。
我的做法很土,但有效。每两周,把人工抽检里四个维度全部打 4 分以上的产出捞出来,按品类分组,每组挑 3 条替换掉few_shot里最旧的那 3 条。替换的时候不要挑最"漂亮"的,要挑最"像人"的——那种带一点不完美、有具体细节、句子长度参差的。太工整的样本教出来的还是工整的机器腔。
同时维护一个 20 条的固定回归集,覆盖不同句式、不同品类、不同人群。每次改指令,改前跑一次、改后跑一次,两份产出并排放着看。这个动作看着繁琐,但它是唯一能让你在改坏的时候立刻发现的办法。我有一次把「正文 3 到 5 段」改成「正文不超过 5 段」,本以为只是放宽,结果模型全按 5 段写,笔记长度肉眼可见地拉长,完读率掉了快两成——不改回归集根本发现不了。
再补一个习惯:给每条指令记「决策日志」,不写代码注释那种,就记一句话,比如「把首句的 25 字下限提到 30 字,因为 25 字的句子信息量不够,评论区老问『所以到底怎么样』」。半年后你回头看,这份日志比指令本身值钱,因为它记的是你为什么这么定,而不只是定了什么。
我做这块最大的教训是:一开始总想着把指令写到完美再跑量,结果憋了两周写出来的东西,实际跑一百条就发现结构有问题。后来改成先跑 20 条、看数据、再改,迭代速度快了不止一倍。指令合集从来不是一次性交付的文件,它更像一份需要持续喂养的资产,你喂它真实反馈,它才会慢慢长成你自己的语感。希望帮到你。
本文还有配套的精品资源,点击获取