☰
ChatGPT提示词模板工程化:三段式骨架、YAML角色库与批量回归
2026/10/29 23:58:39 网站建设 项目流程

简介:这是一份面向自然语言处理爱好者、机器学习从业者及语言模型研究者的ChatGPT提示词模板合集,聚焦对话系统搭建与提示词工程入门,帮助读者在问候、聊天、娱乐、购物、旅游、科技等场景中快速组织高质量指令。压缩包仅含1个PDF文件,大小约5.18MB,便于跨设备查阅与检索。内容围绕150个中英文提示词模板展开,涉及充当Linux终端、英语翻译与润色、岗位面试官、JavaScript控制台、Excel工作表、旅游指南、抄袭检查员、广告商等角色设定,并强调限定输出格式、逐步提问和避免多余解释等实用技巧,便于理解提示词结构、输出约束与多轮对话控制。已有1274人学习,适合希望积累提示词范式、对照改造并用于自身对话系统或学习研究的读者参考。

1. 拆开这份 150 条提示词模板:它到底能省掉哪一步

拿到这份 PDF 的时候,我第一反应是又一个把「你是一个……」抄一百遍的合集。翻完之后我改观了:150 个 ChatGPT 提示词模板,中英文各一份,值钱的不是数量,而是每条都按「角色设定 + 行为约束 + 首句输入」三段硬编码,连「只回复一个代码块、不要写解释」这种格式约束都明确写了进去。新手缺的往往就是这第一句话该怎么说,熟手缺的是一套能直接抄进脚本的角色库,这份资源两头都能接着用。它适合要把语言模型塞进日常流程的人——写文案、做翻译校对、出教学材料、做面试演练;不适合指望它替代模型原理学习的人。下面按我自己的实施顺序拆:先看结构骨架,再讲怎么改成代码、怎么分类管理、怎么调参,最后是几个真踩过的坑。

2. 三段式骨架:为什么「充当 Linux 终端」这条模板能稳定复现

2.1 role / rule / seed 三段各管什么

先不急着抄,把「充当 Linux 终端」这条拆开看。第一条是角色锚定:我希望你充当 Linux 终端。这句话在模型侧起的作用是收窄输出分布——它把「回复风格」从通用闲聊切换到命令行的语法体系和语气里。第二段是行为约束,而且写得很密:只回复一个唯一的代码块、不要写解释、除非我指示否则不要输入命令、需要用英文补充时用花括号包起来。第三段是种子输入:我的第一个命令是 pwd。

三段里最容易被忽略的是第三段。很多人只写「你是 Linux 终端」,然后干等,模型就会自己编一段欢迎语、自己执行几条命令、再给你解释一遍。加上一句「我的第一个命令是 pwd」,等于把第一轮对话的输入也定死了,模型没有自由发挥的空间,只能进入「你输一条、它回一条」的循环。这是这类模板能稳定复现的真正原因,不是「你是 XX」有什么魔力。

对照原文里另一条「充当 JavaScript 控制台」,结构几乎是同构的:角色换成 JavaScript 控制台,约束还是那几个,种子输入换成console.log("Hello World")。两条模板摆在一起看,骨架就露出来了——角色名可以换,约束条款基本用一套,种子输入随场景变。再看「充当 Excel 工作表」这条,多了一层东西:列头定义(A 到 L、第一列留空当行号、只回 10 行)。这等于把「输出结构」也写进了约束段。所以严格说约束段里其实混着两类内容:行为禁令(不要解释)和结构规格(几列几行、格式是什么)。这两类东西的调参方式不一样,后面第 4 章会说。

提示:判断一条模板值不值得留下来复用,看它有没有把「结构规格」写死。只写角色不写结构的模板,复用价值通常只有一半。

原文里还有一批纯对话型的模板,比如岗位面试官、人生教练、职业顾问,它们的约束段写的是节奏而不是格式:「请你只与我进行面试」「一个一个地问我问题,像面试官一样等待我的回答」「不要一次性写下所有对话」。这类模板调参的抓手不在输出格式,而在多轮的间隔控制,第 4 章会单独讲。而创作类的模板,比如诗人、小说家、编剧、说唱歌手,约束段反而应该松——写太死,产出就变成填空。原文这几条写得相对克制,只给了主题和体裁,没给句式限制,这是对的。

2.2 把模板改成可复用的拼装器

手工拷贝粘贴到第五十条就会崩,因为你会发现同一个角色你想改一个约束、想在中文版和英文版之间切换、想批量跑一遍看哪条坏掉了。我一般的做法是先写一个三十行的拼装器,把三段拆成三个字段。

from dataclasses import dataclass @dataclass class Prompt: role: str # 角色锚定:一句话定身份,越短越好 rules: list[str] # 行为约束:每条一个祈使句,禁令和结构规格分开写 seed: str = "" # 种子输入:把第一轮的用户输入也写死 def render(self, lang: str = "zh", seed_override: str | None = None) -> str: head = {"zh": "我希望你充当", "en": "I want you to act as "}[lang] body = "\n".join(f"- {r}" for r in self.rules) tail = seed_override if seed_override is not None else self.seed return "\n".join(x for x in (f"{head}{self.role}", body, tail) if x) terminal = Prompt( role="Linux 终端", rules=[ "我只输入命令,你只回复终端应该显示的内容", "只回复一个唯一的代码块,不要写任何解释", "除非我明确指示,否则不要自行输入下一条命令", "我需要用英文补充说明时,会用花括号 {像这样} 包起来", ], seed="我的第一个命令是 pwd", ) print(terminal.render())

render()里的lang只切换角色那句的开头,seed_override是给「同一角色换一个开场命令」留的入口——比如把pwd换成ls -la,不用改整个对象。rules用列表而不是一段长字符串,是为了后面能按索引单独替换某一条:排查问题的时候经常只需要改第三条,把「不要自行输入下一条命令」改成「绝对不要自行输入下一条命令」,其他不动。

这个拼装器看起来简陋,但它把「模板」从一个文本文件变成了一个可以 diff、可以单测、可以版本管理的对象。后面做索引、做批量回归、做参数绑定,都建立在这个结构上。如果一开始就用字符串,走到第三步就得推倒重来,这是血泪经验。

2.3 中英文对照的真实用途:排错工具而不是备份

很多人以为中英双版是为了照顾不同阅读习惯,实际上它的最大价值在排错。同一个角色,你跑中文版发现模型老是附带解释,跑英文版发现它老老实实只吐代码块,那就说明问题不在模板结构,而在语言本身对格式约束的服从度。这时候的正确操作不是换成英文就完事,而是混写:约束段用英文,内容部分用中文。

terminal_mixed = Prompt( role="a Linux terminal", rules=[ "reply only with what the terminal should display, inside one single code block", "do not write explanations", "do not type the next command unless I instruct you to", ], seed="my first command is pwd", # 种子保持英文,因为命令本身就是英文 )

判断标准其实很朴素:模型输出的是代码、命令、JSON、表格这类对格式敏感的东西,约束就用英文写;输出的是成品中文文案,约束用中文写反而更自然,因为模型会顺着中文语境给出中文。翻译类模板尤其要注意这一点——原文里那条「充当英语翻译、拼写纠正和改进者」的示例句是英文,如果能换成你要处理的实际句子,效果会立刻不一样。

还有一条经验:不要把中英文两版混在同一个会话里来回切。混合语言会让模型在某个轮次突然切换输出语言,尤其是多轮跑到五六轮之后,前面的语言惯性会盖过系统提示。真要切,新开会话。

3. 从 150 条到一张索引表:把模板做成可管理的资产

3.1 按输出形态分类,而不是按行业分类

拿到 150 条,第一件事是分类。绝大多数人会按行业分:写作类、教育类、娱乐类、职场类。这个分法对找模板友好,对工程化极不友好,因为同一个「行业」下的模板,输出约束强度可能差一个数量级。我按输出形态分四类:

类别代表模板输出约束强度是否适合脚本化
确定性执行Linux 终端、JavaScript 控制台、Excel 工作表高,格式完全固定非常适合,可以断言
结构化评审影评人、写作导师、抄袭检查员、词源学家中,段落结构固定内容自由适合,能校验字段
多轮对话面试官、辩论教练、人生教练、职业顾问低,节奏靠约束维持适合,但要控轮次
开放式创作诗人、小说家、编剧、说唱歌手极低,只给体裁和主题不适合断言,只适合采样

这个表的用处是决定「要不要写测试」。确定性执行类的模板,输出格式是可以断言的——第一个字符是不是代码围栏、有没有出现解释性文字,机器一扫就知道。开放式创作类你去断言格式就是自找麻烦,它们只适合跑几遍看质量。中间两类可以做半自动校验,比如评审类检查有没有分段、有没有落到结论。

我踩过的一个坑是按行业分类之后,把「Excel 工作表」和「广告商」放在同一个「职场」文件夹里,结果批量跑测试的时候,前者因为格式断言挂了,后者因为根本没有格式断言被跳过,报告一片混乱。换成按输出形态分之后,测试策略自然就分层了。

3.2 用 YAML 建角色库,让模板脱离文本文件

分类完成之后,逐条把模板落成 YAML。用 YAML 而不是 JSON,因为规则是多行句子,YAML 的可读性明显更好,改起来不用纠结逗号和引号。

# prompts/terminal_linux.yaml id: terminal_linux category: deterministic # 对应 3.1 的四分类 role_zh: Linux 终端 role_en: a Linux terminal rules_zh: - 只回复终端应该显示的内容,并放在一个代码块里 - 不要写任何解释 - 未经指示不要自行输入下一条命令 rules_en: - reply only with terminal output inside one single code block - do not write explanations - do not type commands unless instructed seed_zh: 我的第一个命令是 pwd seed_en: my first command is pwd temperature: 0.0 # 确定性任务,温度必须压到 0 max_tokens: 300 # 够装一个命令的回显就行 tags: [命令行, 开发, 格式敏感]

装载很简单,一个 glob 加一个字典就够了:

import glob, yaml def load_library(pattern="prompts/*.yaml") -> dict: lib = {} for path in glob.glob(pattern): with open(path, encoding="utf-8") as f: item = yaml.safe_load(f) lib[item["id"]] = item return lib lib = load_library() print(f"{len(lib)} 条模板已装载") # 装载数量应该接近 150,缺了就是文件名或缩进有问题

temperature和max_tokens直接写在模板文件里,是这套做法最关键的一步。参数和模板绑在一起,才不会出现「模板对了但参数用错」这种排查一下午的情况。tags字段是给检索用的,第 6 章会用到。

落到这一步,150 个文本片段就变成了 150 条配置。配置的好处是可以被程序读、被 diff、被校验。比如你可以写一个三行的检查,扫出所有rules_en为空但category是 deterministic 的条目——这类模板基本一定会翻车,因为确定性任务靠中文约束往往压不住格式。

3.3 批量回归:给模板跑一遍冒烟测试

装好库之后,别急着上生产,先跑一遍冒烟。目标是筛出「结构上就跑不通」的模板,比如渲染出来是空的、参数没填、约束全是空字符串。

def call_llm(prompt: str, temperature: float, max_tokens: int) -> str: """替换成你手上的任意客户端;只要返回纯文本即可。""" raise NotImplementedError def smoke_test(lib: dict, seed_override: str = "echo hello") -> list[tuple]: report = [] for pid, t in lib.items(): if t["category"] != "deterministic": continue # 先只测最严格的一类 prompt = Prompt( role=t["role_zh"], rules=t["rules_zh"], seed=t.get("seed_zh", ""), ).render(seed_override=seed_override) try: out = call_llm(prompt, t["temperature"], t["max_tokens"]) has_fence = "```" in out # 确定性模板的硬指标:有没有代码围栏 no_talk = "解释" not in out[:40] # 开头四十字里不该出现解释性套话 report.append((pid, "pass" if has_fence and no_talk else "fail", len(out))) except Exception as e: report.append((pid, "error", str(e)[:80])) return report

seed_override这个参数是刻意留的:同一条终端模板,用pwd测和用ls -la测,模型的输出长度差很多,前者几十字符,后者可能几百。用固定种子测不出来长度问题,换一个种子就能看出max_tokens设得够不够。我第一次跑的时候max_tokens统一设了 200,结果所有列目录类的模板全部被截断,报告里一堆 fail,白排查了半天。

冒烟通过之后不要急着删测试代码。这类模板是会漂移的——同一个 prompt,模型侧更新一次、或者你自己改了某条约束的位置,输出形态就可能变。留着一个能在三十秒内跑完的脚本,比每次出问题再手工赌一把划算得多。

4. 输出格式与多轮控制:让模板按你要的形状吐内容

4.1 格式约束必须和温度一起调

原文那些模板里写「不要写解释」「只回复一个代码块」,很多人照抄之后发现还是偶尔会带解释。原因通常不是模板写得不够狠,而是温度没降。格式敏感的任务,温度压在 0 到 0.2,反复强调禁令都行;温度上到 0.7 以上,模型有采样自由度,再硬的禁令也可能被绕过一次。

模板类别代表temperaturemax_tokens判断标准
确定性执行Linux 终端、JavaScript 控制台、Excel 工作表0.0 – 0.2200 – 600输出里出现非格式内容即为失败
结构化评审影评人、写作导师、抄袭检查员0.3 – 0.5600 – 1200分段完整、有结论句
多轮对话面试官、辩论教练、职业顾问0.3 – 0.6300 – 500一次只问一个问题
开放式创作诗人、小说家、编剧0.8 – 1.0800 以上不设断言,只做人工抽样

这张表我一般直接写进代码,让它从配置里读,而不是靠人记:

PRESETS = { "deterministic": dict(temperature=0.0, max_tokens=400), "review": dict(temperature=0.4, max_tokens=900), "dialogue": dict(temperature=0.4, max_tokens=400), "creative": dict(temperature=0.9, max_tokens=1200), } def resolve_params(t: dict) -> dict: base = PRESETS[t["category"]].copy() # 模板文件里显式写的参数优先级更高,允许单条覆盖 for k in ("temperature", "max_tokens"): if k in t: base[k] = t[k] return base

覆盖顺序是「模板文件 > 类别预设」,因为总有个别模板需要例外。比如「充当 Excel 工作表」这条要输出 10 行 12 列的文本表,400 个 token 根本不够,必须在它自己的 YAML 里把max_tokens提到 800 以上,否则表格一定塌在中间几行。这种例外如果写进全局预设,会连带影响其他确定性模板,所以只能单条覆盖。

还有一个细节:max_tokens设得太小,模型会在句子中间硬停,看起来像是「模板坏了」,其实是预算不够。判断方法很简单,把同一 prompt 的max_tokens翻倍再跑一遍,如果内容突然完整了,那就是预算问题,不用去改模板。

4.2 多轮节奏:像面试官那样一次只问一个问题

原文的面试官模板里有一句很关键的约束:「请你只回答面试官的问题,不要一次性写下所有对话」「一个一个地问我问题,像面试官一样等待我的回答」。这类约束在多轮场景里的作用,比格式约束难维持得多,因为上下文越堆越长,最初那条规则的权重会被稀释。

我的做法是每四轮重放一次规则,而不是每轮都放——每轮都放会占用大量上下文,还容易让模型产生「你在催它」的错觉。

messages = [{"role": "system", "content": interviewer_prompt}] for turn in range(10): answer = input("你的回答:") messages.append({"role": "user", "content": answer}) # 每四轮补一次规则,压住格式漂移和一次性输出 if turn % 4 == 3: messages.append({ "role": "system", "content": "提醒:一次只问一个问题,等我回答后再问下一个,不要写解释。", }) reply = call_chat(messages, temperature=0.4, max_tokens=400) messages.append({"role": "assistant", "content": reply}) print(reply)

turn % 4 == 3这个间隔是试出来的。间隔太短(比如每两轮),模型会频繁回头确认规则,问出来的问题变得机械;间隔太长(比如每八轮),中期就开始出现一次抛出三个问题的情况。四轮在面试、教练、辩论这几类模板上都比较稳,但不是普适值,换成辩论教练这种需要长论证的场景,六轮更合适。

另一个边界是轮次上限。多轮对话跑到十五轮之后,早期信息基本被淹,模型开始编造前文没提过的细节。我的习惯是给每个多轮场景设一个硬上限,到点就总结并新开一轮,而不是硬撑着聊下去。这一点原文模板里没写,属于落地时自己得加的。

4.3 结构化输出的兜底:解析失败怎么办

就算温度压到 0,模型也可能偶尔不按代码围栏来。线上跑的时候不能假设格式永远正确,必须有一层解析兜底。

import re def extract_block(text: str) -> str | None: """优先取代码围栏内的内容;退化时取第一段非空文本。""" m = re.search(r"```(?:\w+)?\n(.*?)```", text, re.S) if m: return m.group(1).strip() lines = [ln for ln in text.splitlines() if ln.strip()] return lines[0].strip() if lines else None

正则里的(?:\w+)?是为了兼容带语言标注的围栏,re.S让.能跨行匹配,否则多行输出会被截断在第一行。兜底分支只取第一段非空文本,是保守做法——宁可返回一个可能有噪声的结果,也不要直接抛异常打断整个流程。

解析失败之后的选择有两条:重试一次,或者降级。重试要带上失败原因,比如「上次回复里带了说明文字,请只输出代码块」,直接原样重发一般还是同样的结果。降级就是把这条模板从确定性类别里摘出去,标记成需要人工看一眼,别让它在流水线里继续污染下游。

5. 避坑与排查:照抄模板后翻车的五个现场

5.1 终端模板自己连跑三条命令

现象:输入pwd之后,模型回了三行命令和对应的输出,甚至自己把ls、cd也演了一遍。原因:约束里只写了「不要写解释」,没写「不要连续执行」,而模型有强烈的补全倾向,看到pwd就顺手往下演。解决:把禁令写死成「只响应当前这一条命令,回复完立刻停止,不要预设我的下一条命令」,温度必须同步压到 0。补上这条之后我复测了十次,没有一次跑偏。

5.2 翻译模板把「改进」做成了「重写」

现象:原文那条翻译加纠错加改进的模板,用中文句子喂进去,返回的内容意思变了,甚至加了几段原文没有的论述。原因:一条模板里塞了三个任务——翻译、拼写纠正、文体提升,模型会自己决定优先级,结果把「提升」做成了主导。解决:拆成两步,第一步只做翻译和拼写纠正,第二步单独发一条「在不改变意思的前提下提升表达」的指令。合并任务看起来省事,实际排错成本高得多。

5.3 Excel 模板的表格塌在第七行

现象:要求输出 10 行,实际只给了 7 行,后面几行是半截。原因:不是模型不会算,是max_tokens不够,输出被硬截断。解决:把这条模板的max_tokens单独提到 800 以上,同时把列数从 A 到 L 收到实际用得上的范围。列越多、行越多,token 消耗是乘法的,12 列 10 行看着不多,实际很容易超预算。

5.4 角色扮演模板开始编知识

现象:拿角色扮演类模板去演一个虚构角色,问到设定之外的问题,模型不说不确定,直接编一段听起来很合理的背景。原因:原文这类模板里有一句「你必须知道该角色的全部知识」,这句话是幻觉催化剂,等于授权它补齐所有空白。解决:改成「只使用我提供的设定,超出设定范围时明确说这段设定里没有」,同时在系统提示里加一句「不确定就直说不确定」。这一条改动对评审类模板同样有效。

5.5 脚本化之后中英文语言漂移

现象:模板存成 YAML 之后,中文版偶尔会输出英文段落,尤其在多轮跑到第五六轮时。原因:约束段是中文、种子是英文命令,加上模型自身的语言惯性,跑到后面就切过去了。解决:在规则里显式加一条语言锁定——「无论输入是什么语言,回复一律使用中文」,并且这条要放在规则列表的最后一条,位置靠后权重更高。如果还是漂,就新开会话,别在同一段上下文里反复纠正。

注意:这五条里有四条不是模板写错,而是参数或上下文的问题。照抄模板之后先别怀疑内容,先检查温度和长度预算。

6. 进阶玩法:把 150 条模板压成一条命令能搜的本地库

把模板拆成 YAML 之后,最实用的一件事是把它变成一个能搜的本地库。150 条听着不多,真到要用的时候你根本记不住哪条叫什么名字,只记得「有个角色能帮我改简历」或者「有个能当终端用的」。这时候关键词检索比翻 PDF 快十倍。

最粗的版本一行就够,前提是文件都在同一个目录下:

# 按中文角色名或标签粗搜,-l 只列文件名,-i 忽略大小写 grep -ril "终端" prompts/ | head -5

这行的局限是只能匹配文件里出现过的字面词,搜「命令行」搜不到只写了「终端」的文件。所以我一般在 Python 里做一层标签匹配,把role_zh、role_en、tags拼成一个可搜的字符串:

def search(lib: dict, kw: str, limit: int = 8) -> list[tuple]: hits = [] kw_low = kw.lower() for pid, t in lib.items(): blob = " ".join([ str(t.get("role_zh", "")), str(t.get("role_en", "")), " ".join(t.get("tags", [])), ]).lower() if kw_low in blob: hits.append((pid, t.get("role_zh") or t.get("role_en"))) return hits[:limit] for pid, name in search(lib, "面试"): print(f"{pid:24s} {name}")

limit是必须的,不设上限的时候搜「写作」能命中二十条,输出刷屏反而找不到想要的那条。tags字段在这里兑现了价值——你可以给同一条模板挂多个别名标签,比如「终端」那条挂上「命令行、shell、开发、格式敏感」,搜哪个词都能命中。

再往上走一步,是把它接成命令行工具,一条命令直接渲染出可用的 prompt 并复制到剪贴板:

# 用法:pt terminal_linux → 渲染后直接进剪贴板 pt() { python -c " import sys, yaml from pathlib import Path t = yaml.safe_load(Path(f'prompts/{sys.argv[1]}.yaml').read_text(encoding='utf-8')) print('\n'.join([f\"我希望你充当{t['role_zh']}\"] + [f'- {r}' for r in t['rules_zh']] + [t.get('seed_zh','')])) " "$1" | pbcopy }

这个函数里pbcopy是某个桌面系统的剪贴板命令,换环境要改成对应的工具;sys.argv[1]直接对应 YAML 文件名,所以命名要统一用英文小写下划线,别用中文文件名,否则命令行里敲起来很痛苦。渲染逻辑和 2.2 节的render()是同一套,只是这里为了少依赖直接内联了——短期图快可以,长期还是应该 import 那个函数,避免两处逻辑不一致。

我现在的习惯是:新遇到一个场景,先搜库,搜不到再新写一条 YAML,写完挂三个标签。半年下来库从 150 条长到两百多条,但真正高频用的还是那二十来条——终端、翻译改进、写作导师、面试官、词源学家。剩下的一百多条更像是备选清单,需要的时候能翻到就行。

从那以后我每次拿到这类提示词合集,都不再整份往编辑器里贴,而是先花半小时拆成结构化配置、跑一遍冒烟、再挂上标签入库。这么做一次,后面每次用都省事。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询