ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

拆解150条提示词模板:三段式结构、本地检索与回归验收

拆解150条提示词模板:三段式结构、本地检索与回归验收

简介:这份PDF面向自然语言处理爱好者、机器学习从业者与语言模型研究者,也适合希望提升日常对话与内容生产效率的普通用户。它以150个中英文提示词模板为核心,把角色设定、任务约束与输出格式写成可复用句式,覆盖终端命令模拟、英语翻译与润色、岗位面试、JavaScript控制台、Excel表格、发音辅助、旅游指南、抄袭检查及角色扮演等场景,帮助读者快速搭建符合需求的对话流程,减少反复试错。压缩包仅含1个PDF文件,大小约5.18MB,便于在电脑与移动设备上查阅和检索。目前已有1274人学习,说明其在提示词学习与实操参考方面具有一定关注度。读者可从中获得可直接改写的中英文模板、面向具体任务的表达思路,以及将模板迁移到写作、编程、办公和出行咨询等场景的方法;需具备一定自然语言处理与机器学习基础,并结合实际需求调整,才能更好发挥模板价值。

1. 150 条提示词不是拿来抄的:先摸清这套模板的共用骨架

最容易翻车的,往往正是被复制最多的那几条。直接粘贴「充当 Linux 终端」,十次里有六七次模型先来一句「好的,以下是执行结果」,把你指望的纯代码块冲掉;「担任岗位面试官」不补一句「一次只问一个问题」,它会一口气把整轮面试题全列出来。这套 150 条中英文提示词模板真正值得拆的,不是数量,而是每条都重复同一种写法:先声明角色,再限定输出,最后给一个启动输入。

只会用 Ctrl+F 搜场景的人,拿到的只是 150 个一次性玩具。能把骨架拆开,你才改得动它,也才敢往自己的业务里塞。下面的路线是:拆三段式结构、把模板落成本地可检索资产、判断中英版本怎么选、排查五类高频失败现场、最后用一条回归线验收。

2. 拆开三段式:角色声明、输出约束、启动语各管什么

2.1 角色声明是给语言模型划语域,不是许愿

把「充当英语翻译和改进者」换成「你是一个很厉害的翻译」,输出质量立刻散掉。差别不在措辞礼貌,而在于前者给的是三个可检索的语域标签:职业(翻译)、动作(翻译 + 拼写纠正 + 改进)、目标读者(正式书面)。语言模型生成时是在给定上文下预测下一个词的条件分布,标签越具体,候选词收得越窄,输出越稳。这在自然语言处理里不算新结论,但落到写模板上,很多人第一句还是「你是一位资深专家」——这句话没有任何信息量,等于没写。

我一般把角色声明压成「身份 + 介质 + 受众」三段,再把边界一并写进去。比如翻译类模板我改成「英语翻译,只做笔头输出,面向正式书面读者,不做扩写、不做内容补充」。最后半句看着多余,实际决定了模型会不会顺手给你加一段「以下是润色后的版本,主要改动有……」。

弱声明问题强声明写法
你是一个很厉害的翻译无语域标签,输出风格随机英语翻译,笔头输出,面向正式书面读者
你是一个专家领域未限定,知识面铺得过宽前端方向的代码审查者,只看可维护性与边界条件
请扮演面试官未限定节奏,容易一次问完面试官,一次只问一个问题,等我回答后再问下一题

三类角色里,「终端仿真」和「表格仿真」最依赖角色声明的精度。模板里那句「我会输入命令,你会回复终端应该显示的内容」,把输入输出的介质说死了,模型才不会把pwd解释成一段说明文。反过来,创意类模板(讲故事、写诗、编剧本)角色声明可以松,因为你要的就是发散,约束收紧反而坏事。

2.2 输出约束条款才是模板的真实价值

一条 200 字的模板,约束句往往占到 140 字。「只回复一个唯一的代码块」「不要写解释」「除非我指示你这样做,否则不要输入命令」「当我需要用英语告诉你一些内容时,我会用花括号 {像这样}」——这些不是客套,是给下游解析器写的接口契约。做工程的人真正该关心的,是输出能不能被稳定 parse,而不是答得漂不漂亮。

我把这类约束归成四类,写模板时按需取用:

约束类型模板原句示例解决的问题
格式约束只回复一个唯一的代码块输出可直接落盘或执行
范围约束不要写解释去掉开场白和收尾总结
节奏约束一次只问一个问题,等我回答控制多轮交互的推进速度
边界约束除非我指示,否则不要输入命令防止模型替你做下一步

有个位置上的讲究:约束要放在用户指令的近端。同一句话写在模板开头和写在末尾,遵守率不一样,越靠近你本次实际输入的位置,权重越高。我改模板时习惯把最硬的那条(通常是「不要写解释」)在末尾原样重复一次,代价是十几个字,收益是省掉一轮返工。

还有一条容易被忽略:约束要可判定。写「请简洁一点」,模型没法验证自己是否符合;写「不超过三句话」,它能数。写「用专业术语」,不如写「术语保留英文原词,不翻译」。可判定的约束才能被稳定执行。

2.3 启动语解决的是空转问题

「我的第一个命令是 pwd」「我的第一句话是……」「First, reply me the empty sheet」——这类句子在模板里看着最像凑数,实际上是最不该删的部分。不给启动语,模型会自己补一个开场,通常是一段确认:「好的,我已准备好充当 Linux 终端,请发送你的第一个命令。」这段确认会污染后续所有输出的格式。

「充当 Excel 工作表」那条最能说明问题。模板明确要求先回一个 10 行、A 到 L 列的空表,首列表头留空用于行号。你不给启动语,模型很可能直接开始演示填数据;给了「先回空表」,它才老老实实把骨架搭出来,后面你往里填公式才有稳定的参照系。

把三段拆出来存成结构化字段,是后面所有工作的基础。下面这段脚本处理单条模板,拆出角色句、约束句和启动语:

import re RAW = """我希望你充当 Linux 终端。我会输入命令,你会回复终端应该显示的内容。 我希望你只回复一个唯一的代码块,不要写解释。除非我指示你这样做,否则不要输入命令。 当我需要用英语告诉你一些内容时,我会用花括号 {像这样}。 我的第一个命令是 pwd。""" # 约束句识别:以「我希望你只」「不要」「除非」「当…时」开头 CONSTRAINT_RE = re.compile(r"^(我希望你只|不要|除非|当[^\n]{0,30}时)") # 启动语识别:末尾「我的第一个…是…」,注意结尾可能带句号 STARTER_RE = re.compile(r"(我的第[一二三四五六七八九十0-9][^\n]*?是[^\n。]*。?)\s*$") def split_prompt(text: str) -> dict: text = text.strip() m = STARTER_RE.search(text) starter = m.group(1).strip() if m else "" body = text[: m.start()].strip() if m else text sents = [s.strip() for s in re.split(r"(?<=[。!?])", body) if s.strip()] role = sents[0] if sents else "" cons = [s for s in sents[1:] if CONSTRAINT_RE.match(s)] rest = [s for s in sents[1:] if s not in cons] # 通常是占位符约定,别丢 return {"role": role, "constraints": cons, "starter": starter, "rest": rest} if __name__ == "__main__": print(split_prompt(RAW))

几个参数要按你的语料调。CONSTRAINT_RE里的前缀词表是硬编码的,中文模板里还有「请勿」「只输出」「严禁」这类变体,跑完一轮要把漏掉的补进去。STARTER_RE依赖「我的第一个……是」这个句式,英文版对应my first ... is,得单独写一条正则,中英混着跑会漏。rest字段不要当垃圾扔掉,里面装的往往是花括号占位符的使用约定,改写模板时要用它对齐变量风格。

跑通这一步,150 条模板就从一堆散文变成了 150 条带字段的记录,后面才好做检索、比对和批量改写。

3. 把 150 条落成本地可检索资产:目录分层与批量抽取

3.1 按任务域分层,别按标题首字母排

原始 PDF 的顺序是编辑顺序,不是使用顺序。按标题首字母或笔画排更糟,充当、担任、扮演三种前缀混在一起,你根本不知道该翻哪一页。我按任务域分六层,每层对应一类输出形态:

任务域典型模板主要输出形态复用频率
终端与代码仿真Linux 终端、JavaScript 控制台、Excel 工作表纯代码块、纯表格文本高,适合做自动化前置
文本改写与校对英语翻译和改进者、抄袭检查员、AI 写作导师定稿文本、差异列表高,几乎每天用
职业与面试岗位面试官、招聘人员、职业顾问多轮问答中,节奏约束是关键
创意生成讲故事的人、诗人、编剧、小说家、说唱歌手长文本、多版本中,需要给素材槽
教学与解释数学老师、哲学老师、词源学家分层解释、举例中,受众标签要写死
咨询与建议人生教练、关系教练、励志教练建议清单、追问低,但对话轮次最多

生活娱乐和餐饮旅游类的模板(旅游指南这类)单独放一层更合适,因为它们的输入是「我在哪、想看什么类型」,属于典型的槽位填充型,跟咨询类那批自由文本差别很大。

分层之后给每条模板加三个字段:domain(上面六个值之一)、slots(需要用户填的变量列表)、starter_required(是否必须带启动语)。这三个字段决定了你在检索时能不能一次筛准。

3.2 从纯文本里批量切模板

PDF 转出来的纯文本有两个坑:标题行和正文之间可能夹空行,正文里可能有分页残留。切分逻辑要按「标题行识别 + 累积到下一个标题」的方式做,不要指望固定行号。下面这段是能直接跑的版本:

import json import re from pathlib import Path SRC = Path("prompts_raw.txt") # PDF 转出的纯文本,UTF-8 编码 OUT = Path("prompts.jsonl") # 标题行:中文「充当/担任/扮演 XXX」,英文「Act as XXX」 TITLE_RE = re.compile(r"^\s*(?:(充当|担任|扮演)\s*(.+)|Act as\s+(.+))\s*$", re.I) # 启动语:模板末尾交给模型的第一个输入 STARTER_RE = re.compile( r"(我的第[一二三四五六七八九十0-9][^\n]{0,60}?是[^\n]*" r"|my first[^\n]{0,80}?is[^\n]*)", re.I, ) def parse_blocks(text: str): rows, cur = [], None for line in text.splitlines(): m = TITLE_RE.match(line) if m: if cur: rows.append(cur) cur = {"title": (m.group(2) or m.group(3)).strip(), "body": []} elif cur is not None: cur["body"].append(line) if cur: rows.append(cur) return [{"title": r["title"], "body": "\n".join(r["body"]).strip()} for r in rows] def classify_lang(prompt: str) -> str: head = prompt[:60] return "zh" if len(re.findall(r"[\u4e00-\u9fff]", head)) >= 5 else "en" def enrich(row: dict) -> dict: body = row["body"] m = STARTER_RE.search(body) starter = m.group(1).strip() if m else "" prompt = body[: m.start()].strip() if m else body return { "title": row["title"], "lang": classify_lang(prompt), "prompt": prompt, "starter": starter, "chars": len(prompt), } if __name__ == "__main__": blocks = parse_blocks(SRC.read_text(encoding="utf-8")) out = [enrich(b) for b in blocks] with OUT.open("w", encoding="utf-8") as f: for i, r in enumerate(out, 1): f.write(json.dumps({"id": i, **r}, ensure_ascii=False) + "\n") print(f"{len(out)} 条 -> {OUT}")

参数说明集中在三处。TITLE_RE里的前缀词表要按你的 PDF 实际用词补,有些版本还会出现「我希望你扮演」这种四字前缀,漏了就会把整段正文吞进上一条模板。STARTER_RE的{0,60}和{0,80}是长度容忍度,设太小会截断长启动语,设太大会误伤正文里的「第一句话」这类描述。classify_lang只看前 60 个字符,因为中英版模板正文往往是同一种语言,但角色声明必然用各自语言写,看开头最稳。

跑完之后先看行数。150 条模板正常切出来应该在 145 到 155 之间,少了说明有标题没被识别,多了说明正文里某句话被误判成标题——通常是正文里出现了「扮演 X 角色」这种描述句。

3.3 占位符统一改写,别让语种惯性带偏

原始模板里占位符有两种写法:花括号{like this},和直接写示例值(某座城市名、某支球队名、某部片名)。前者是显式约定,后者是隐式示例,问题都出在隐式示例上——模型会把你给的示例值当成语境信号,顺着它的语种和地域往下编。

常见做法是把所有示例值换成中性占位符,并在模板末尾补一行约定:「花括号内的内容由我替换,你不要自行填充。」改法对照:

原始写法问题改后
我的第一句话是「我很喜欢某座城市」示例值带地域语境我的第一句话是 {待翻译句子}
我想看 A 队对 B 队的比赛队名激发模型对联赛的联想我想看 {主队} 对 {客队} 的比赛
给一部 {片名} 写影评片名会诱导模型复述剧情给 {片名} 写影评,不剧透

多槽位模板(角色扮演类里的{character}和{series})要额外加一条:「角色的全部知识限于原作已公开内容,不得虚构未出现的设定。」不加这条,模型会给你补出原作里根本没有的情节,而且写得像真的。

4. 中英双版本怎么选:输出语种、约束强度和术语密度

4.1 模板语种不等于输出语种

最常见的误判是以为中文模板出中文、英文模板出英文。实际影响更大的是约束句的语种。英文模板里do not write explanations这种短句祈使结构,模型执行得更干脆;中文模板里的「不要写解释」有时候会被当成软建议,模型回你一段「好的,我不会写解释,以下是结果」。这不是玄学,是指令-遵守配对在训练语料里的密度差异。

我的用法是混搭:中文场景用中文模板保证术语和表达地道,但把三条硬约束用英文原句附在末尾。实测下来格式遵守率会明显好一些,代价只是多两行。反过来,创意生成类模板我全用中文,因为英文模板写出来的中文故事有明显的翻译腔。

还有一类要单独说:教学解释类模板(数学老师、哲学老师、词源学家)对受众标签极其敏感。模板里如果不写「面向零基础」,模型会默认按本科水平讲,一堆术语砸下来。加上受众标签之后,同一个模板的输出能差出一个量级。

4.2 双版本对齐:先按结构字段配,再人工补

150 条里中英各一份,但标题翻译并不统一。「充当英语翻译和改进者」对应的英文标题是English Translator and Improver,字面对不上。指望自动配对全对不现实,做法是先按starter句式 + 正文长度 + 关键词做粗配,配不上的手工补一张别名字典。

粗配之后跑一轮体检,比一条条肉眼过要快得多:

import json import re from pathlib import Path rows = [json.loads(l) for l in Path("prompts.jsonl").read_text(encoding="utf-8").splitlines()] CJK = re.compile(r"[\u4e00-\u9fff]") def audit(r: dict): issues = [] if not r["starter"]: issues.append("缺启动语") if r["chars"] < 80: issues.append("正文过短,疑似切分失败") if r["lang"] == "zh" and len(CJK.findall(r["prompt"])) < 30: issues.append("中文模板汉字过少") if r["lang"] == "en" and CJK.search(r["prompt"]): issues.append("英文模板夹中文") return issues bad = 0 for r in rows: iss = audit(r) if iss: bad += 1 print(r["id"], r["title"], "->", ";".join(iss)) print(f"共 {len(rows)} 条,异常 {bad} 条") lens = sorted(r["chars"] for r in rows) print("长度 P10/P50/P90 =", lens[len(lens) // 10], lens[len(lens) // 2], lens[len(lens) * 9 // 10])

判断阈值要按语料定。chars < 80这条是用来抓切分失败的,正常模板很少短于这个数;< 30个汉字抓的是「中文标题配了英文正文」这种错位;英文模板夹中文则基本只有一个原因——PDF 转换时把中文页眉混进了正文。长度分位数是最后一道保险,P90 突然拉高说明有两条模板被合并了,P10 拉低说明有模板被截断。

4.3 用指标而不是感觉来判断版本质量

体检完之后,中英两个版本各算一组指标,横向比一比再决定用哪版:

指标健康区间异常含义
有启动语的比例85% 以上低于这个数说明模板不完整
正文长度 P50150 到 350 字符过短是截断,过长是合并
约束句条数均值2 到 4 条少于 2 条基本控不住格式
中文模板夹英文句比例15% 以下高了会让输出语种漂移

约束句条数这个指标我在第 2 章提过怎么抽,这里直接复用。均值明显偏低的那批模板,就是后面最容易翻车的,优先重写。

5. 避坑与排查:模板跑不出预期输出的五类现场

5.1 现象:要纯代码块,模型先来一句「好的,以下是执行结果」

原因有两层。表层是约束句写在了模板中段,离用户本轮输入太远;深层是模板里没有说清「一个唯一的代码块」到底是什么意思——模型默认代码块可以有前置说明。

解决分两步。第一步把格式约束提到角色声明之后的第一句,第二步把「唯一的」量化成可判定的描述:「你的回复以三个反引号开头,以三个反引号结尾,反引号之外不出现任何字符。」改完之后我还会在启动语前面加一行「重复一遍这条格式要求,然后直接输出」。这行看着啰嗦,但它把约束重新拉回了近端,实测遵守率差距很明显。

5.2 现象:角色扮演模板一次性把整段剧情写完

原因不是模型不听话,是模板只写了「像角色那样回答」,没写「一次说多少」。这类模板的正确约束是节奏而不是格式:一次只输出一句台词,等我回一句再继续。缺了这句,模型会把「扮演」理解成「创作一段扮演的文本」。

修法是在模板末尾补两条:「每次回复不超过两句角色台词,不加旁白说明」「如果我的输入不足以推进,就反问一句,不要自行续写」。第二条尤其关键,它给了模型一个合规的「不输出」选项,否则模型只能靠编。

5.3 现象:中文模板跑出来中英混杂,术语一半不翻译

原因在模板里的示例值。原始模板的示例句子、示例城市、示例句子里的英文词,都会成为语种信号。中文模板里夹着好几个英文词,模型会判断这个语境允许中英混排,于是术语就随机翻一半。

处理办法是清场:把模板正文里非必要的英文全部换成中文占位符,术语单独列一行「保留英文原词不翻译:X、Y、Z」。这行的作用是把「允许保留英文」限定成一个白名单,而不是全局许可。改完之后你会发现输出稳定很多,连标点风格都不乱跳了。

5.4 现象:聊到第五六轮,约束彻底失效,又开始写解释

原因很直接:早期轮次里的约束句,在多轮对话里被后续输入稀释了。每多一轮,约束在上下文里的相对权重就低一点,到五六轮基本压不住。

解决办法有两个,看你的接入方式。如果能控制消息结构,把约束句放进系统侧的位置,每轮都带上,这是最干净的。如果只能整段对话喂进去,就在每轮用户输入末尾固定追加一行「保持第 1 条格式要求」,用一句话的代价换取遵守率。我一般还会在第四轮左右主动重述一次全部约束,相当于给对话做一次校准。

5.5 现象:套上自己的业务素材后,150 条跑出来长得都差不多

原因是模板只给了角色和格式,没给事实槽。你让它「充当广告商」,它只能拿通用知识硬编,编出来的东西自然高度同质,换十个模板都是一个味儿。

修法是在启动语之前加一个素材区,先喂 3 到 5 条真实素材(产品参数、用户原话、竞品描述),再让模型基于素材做。模板改成两段:第一段是角色和约束,第二段是「以下是我的素材,你先复述关键事实,等我确认后再创作」。多出来的这一步复述,能挡掉大部分凭空发挥。这类改写对餐饮旅游、生活娱乐方向的模板收益最大,因为那些场景最依赖具体细节,模型编不出来。

6. 建一条回归线:把模板当代码一样验收

改完 150 条模板,别靠手感判断好了没有。我把模型输出存成 jsonl,跑一个规则打分脚本,二十分钟能看到全量结果:

import json import re from pathlib import Path # 每行 {"id": 1, "output": "...", "expect_block": true, "expect_cjk": true} rows = [json.loads(l) for l in Path("model_out.jsonl").read_text(encoding="utf-8").splitlines()] OPENERS = re.compile(r"^(好的|当然|以下是|Sure|Certainly|Here)", re.I) def check(r: dict): out = r["output"].strip() flags = [] if OPENERS.match(out): flags.append("开场白未去掉") if out.count("```") % 2: flags.append("代码块未闭合") if r.get("expect_block") and not out.startswith("```"): flags.append("首行不是代码块") if r.get("expect_cjk") and not re.search(r"[\u4e00-\u9fff]", out): flags.append("输出无中文") return flags fail = [(r["id"], f) for r in rows if (f := check(r))] print(f"通过 {len(rows) - len(fail)}/{len(rows)}") for i, f in fail[:10]: print(i, f)

验收清单我固定看四项:格式项(首行是不是代码块、代码块是否闭合)、开场白项(有没有「好的」这类垫话)、语种项(该出中文的有没有出)、槽位项(占位符有没有被原样吐回来)。前两项是工程可用性,后两项是内容可用性,四项全过才进正式使用。

这套东西我踩过一次印象很深的坑:一批模板改完直接上了线,前三天看着都正常,第四天开始有人反馈输出格式乱了。回头查,是我在批量改写时把「不要写解释」那句的句号删了,结果约束句和下一句粘成了一句,被模型当成了描述而不是指令。一行标点,排查了两个小时。

从那以后我每次改模板都强制走一遍「抽取 → 体检 → 小批量回放」,三条命令跑完再动正式库。这套流程笨,但它把玄学问题变成了能复现的问题。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进