ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

ChatGPT角色扮演提示词:四槽位骨架与工程化落地

ChatGPT角色扮演提示词:四槽位骨架与工程化落地

简介:《ChatGPT-角色扮演指南》PDF面向希望借助对话模型提升写作与办公效率的初、中级用户,系统梳理ChatGPT在学术论文、创意写作、商业文案、编辑校对、翻译、数据分析、技术文档、教育培训、网站内容、研究咨询、演讲稿、简历、广告文案、社交媒体、新闻稿、电商与医疗文案、儿童读物及小说创作等场景中的角色设定与提示词写法。包内仅含1个PDF文件,约797KB,篇幅紧凑,便于短时集中阅读和按目录跳读。资源已有286人学习下载,可作为内容生产与日常写作的速查手册。读者能获得不同任务的提问框架、角色设定示例和可改造的提示词模板,并参考Linux终端模拟、面试官、文字冒险游戏等案例,理解如何明确身份、目标与输出格式,让模型稳定产出专业结果。

1. 两百多条角色提示词:值钱的不是角色名,是后半段那几句约束

上周有同事直接把「你是一个资深后端架构师」这一句丢给模型,让它出一套接口设计方案。结果第一段写得挺像样,第三段开始给自己加戏,末尾还附了一句「希望对你有帮助」。真正的问题不在模型,而在于那条提示只写了角色,没写输出契约。

这份《ChatGPT-角色扮演指南.pdf》做的就是把这件事拆开。前半段按学术论文、创意写作、内容创作、商业文案、编辑校对、翻译、数据分析、技术文档、教育培训、网站内容、研究咨询、演讲稿、简历求职信、广告文案、SEO 优化、社交媒体、新闻稿、电商、旅游、医疗、儿童读物、小说这些类别,整理了一批可以直接套用的写作提示;后半段给了一大票角色扮演模板——终端模拟、面试官、表格生成器、文字冒险、SQL 终端、棋局对手、代码审查、正则表达式生成器、产品经理、私人教练都在里面。

真正能落到工程里的部分,不是「扮演谁」那一行,而是每条提示夹在中间的几句约束:只在一个代码块内回复、不要写解释、以 markdown 表格形式回复、等我回答后再问下一个。下面按怎么读、怎么改、怎么配参数、哪里会翻车四件事拆一遍。

2. 四槽位骨架:从「充当 Linux 终端」反推一条提示该怎么写

那份 PDF 里最短也最见功力的一条,是终端模拟。它全文没几个字,但把一条提示该有的东西全占了。把这条拆开,就能得到一套可以套用到任何角色上的骨架,而不是靠感觉写。

2.1 角色、边界、输出契约、首句:四个槽位缺一不可

我一般把一条角色提示切成四块:角色设定(你是谁、懂什么)、行为边界(不许做什么、什么时候停)、输出契约(用什么格式回、回多少)、首句启动(第一句话给什么,把上下文跑起来)。PDF 里终端那条的四个槽位是这样的:

  • 角色:你现在是一个 Linux 终端;
  • 边界:不要写解释、除非我下指令否则不要主动敲命令、需要我用英文说明时我会放在中括号里;
  • 输出契约:只在一个唯一的代码块里回复终端应显示的内容;
  • 首句:pwd。

对照着看表格生成器那条,结构一模一样:角色是表格生成器,边界是「不要附带任何额外解释」,输出契约是「只回复一个 markdown 表格、10 行」,首句是「十二生肖表」。这类提示之所以稳,不是因为角色选得好,而是四个槽位都填满了。

反过来,多数人写废的提示只填了第一个槽位。模型不知道什么时候该停,只好一直往外倒;不知道格式,只好按它自己的写作习惯来,于是就有了「好的,下面我来为您…」这种前缀。骨架写法可以直接抄:

# 角色 你是一名 {ROLE},熟悉 {DOMAIN},习惯用 {STYLE} 的方式表达。 # 边界 - 不解释你的推理过程,不输出与结果无关的客套话。 - 信息不足时先问一个最关键的问题,不要自行假设。 - {STOP_RULE} # 输出契约 - 只输出 {FORMAT},不要包裹在解释性段落里。 - {LENGTH_RULE} # 首句 {SEED}

{ROLE}和{DOMAIN}决定知识面,{FORMAT}决定你后面能不能用脚本处理输出,{SEED}决定会话从哪个状态起步。{STOP_RULE}是最容易被漏掉的一格——面试官那条写的是「不要一次写出所有的问题,等我回答」,文字冒险那条写的是「我输入命令,你回复行动结果」,本质都是给会话定一个回合制的节拍。没有这一格,交互型角色第一轮就会把整局游戏讲完。

2.2 输出契约怎么写才不被解释性文字污染

输出契约是四格里最需要抠字眼的。同一件事,写成「以表格形式回复」和写成「你只会回复一个包含 10 行的 markdown 表格,不要附带任何额外的解释」,实际命中率差得很远。前者模型有得商量,后者没有。

我在自己的模板库里做过一轮对照,只改输出契约那一句,跑二十次看格式违约率,粗略的结论是:

契约写法常见违约形态备注
「请用表格回答」表格前后各带一段说明几乎必违约
「以 markdown 表格形式回复结果」偶尔多一段开场白时好时坏
「只回复 markdown 表格,不要任何解释,不要代码块包裹」少数情况下仍会加标题行最稳的一档
上面再加一条首句示范基本不违约需要多花点 token

首句示范是最便宜的一招。表格生成器那条之所以好用,是因为你第一句就给了「十二生肖表」,模型从第一轮就进入「我在产表格」的状态,后面很难切回闲聊模式。终端那条同理,pwd一出手,格式就被钉死了。

还有一个细节值得抄:终端那条特意限定「只在一个唯一的代码块内回复」。如果不写「唯一」,模型有时会把命令和输出分成两个代码块,你后面用脚本解析就得多写一层判断。SQL 终端那条也踩过同样的坑,PDF 里的写法是「在单个代码块中使用查询结果表进行回复,仅此而已」。

提示:凡是打算用脚本二次处理输出的提示,输出契约里必须把「唯一代码块」「不要包裹」「不要解释」三件事写全,少一件就要在解析端补三层正则。

2.3 把两百多条提示收进可检索的表格

PDF 直接当文档翻很痛苦,两百多条提示没有索引,找一条「适合做代码审查的」得从头滑到尾。我的做法是先把它拆成一个带字段的表,字段定死之后,选哪条提示就是个筛选问题,不是记忆问题。

字段我一般用这几个:编号、类别、角色名、适用场景、输入形态(我给一句话 / 我给一段代码 / 我给一份表结构)、输出形态(纯文本 / 表格 / 代码块 / 多轮问答)、是否有状态(一次问完 vs 要做回合制)、风险等级(会不会碰到专业诊断、法律意见这类不能替代人工的领域)。风险等级那一列别省,它决定了这条提示能不能直接给业务方用。

从纯文本里抽提示块,写个二十行的脚本就够了:

import csv import re # 以「充当 / 担任 / 扮演 / 作为」开头的段落视为一条提示的起点 HEAD = re.compile(r'^(充当|担任|扮演|作为|我要你|我想让你)') rows = [] with open('chatgpt_role_prompts.txt', encoding='utf-8') as f: blocks = f.read().split('\n\n') # 空行分段,PDF 复制出来基本是这个形态 for i, block in enumerate(blocks): block = block.strip() if not HEAD.match(block): continue rows.append({ 'id': f'P{i:03d}', 'role': block.split('。')[0][:40], # 取第一句当前缀,够筛选用 'body': block, 'has_state': '等我' in block or '每次行动后' in block, 'has_format': '代码块' in block or '表格' in block, }) with open('prompts.csv', 'w', newline='', encoding='utf-8-sig') as f: w = csv.DictWriter(f, fieldnames=['id', 'role', 'body', 'has_state', 'has_format']) w.writeheader() w.writerows(rows) print(f'抽出 {len(rows)} 条,其中有状态约束 {sum(r["has_state"] for r in rows)} 条')

这里几个判断条件是经验值:等我这个关键词能捞出绝大部分回合制提示(面试官、棋局、辩论教练都会用到),代码块和表格能捞出输出契约比较硬的那批。抽完之后按has_format=True排序,剩下的就是可以直接接到自动化流程里的提示,其余的先当人工对话素材用。utf-8-sig那个参数别改,否则用表格软件打开会乱码。

3. 三类高频场景落地:写作、分析、状态型交互分别怎么写

PDF 里的条目按用途其实能归成三类,三类的写法差别很大:写作类是一次性产出,分析类要喂结构,状态型交互要管会话。三类混着用同一套提示,翻车是必然的。

3.1 写作类:从论文提纲到小说场景卡

写作类在 PDF 里占的篇幅最大——学术论文、文学创作、内容创作、商业计划书、简历求职信、演讲稿、新闻稿、儿童读物、小说都算。这类提示最常见的误用是「一句话要成品」:直接说「写一篇关于某某的论文」,拿回来的东西结构松散、论点空转。

我一般拆成三段投喂:先要结构,再要单节,最后才润色。第一段只让模型出大纲,明确约束「只要三级标题,不要正文」;第二段挑一节扩写,把字数、引用风格、目标读者说清楚;第三段才做语言层面的打磨。这条链路里,PDF 里那些现成的提示词可以直接当第一段的模板用,比如论文那条强调「进行研究、分析、组织思路」——落到提示上就是先让它列研究问题和论证路径,而不是直接出正文。

小说创作那条给了几个不错的切入角度:出人意料的结局、读者参与的交互小说、面向儿童的励志故事、未来世界设定、沉浸式幻想故事。这几个角度本质是在约束冲突类型和目标读者,比「写个好看的小说」有用得多。真要落到可复用的程度,我建议把人物和场景先抠成结构化数据,再让模型据此写正文:

你是一名擅长 {GENRE} 的小说作者。 第一步:只输出一个 JSON,字段为 {"protagonist": {"want": "", "flaw": ""}, "obstacle": "", "turning_point": "", "ending_type": ""} 不要写任何正文。 第二步:等我确认 JSON 后,按下面约束写 {WORDS} 字的开篇: - 第三人称限知视角; - 前 200 字内出现具体的时间与地点; - 不出现「他知道」「他明白」这类直接交代心理的句子。 现在执行第一步,题材是:{PREMISE}

第二步那几个约束是关键。「不出现直接交代心理的句子」这条比「写得生动一点」有用一百倍,因为它是可检查的——写完你自己数一遍就知道有没有违规。{GENRE}、{WORDS}、{PREMISE}三个变量分别控制风格、篇幅和题材,同一个骨架换变量就能覆盖 PDF 里的言情、悬疑、科幻几条线。

商业文案那一类也是同样的思路。PDF 里广告文案那几条强调「选择目标受众、制定关键信息、选择传播渠道」,落到操作上就是让模型先把受众和卖点写成两行,再写正文。少了这一步,出来的文案会往「高端大气」那个方向滑,谁看了都不知道在卖什么。

3.2 分析类:把表结构、字段含义喂进去再让它写 SQL

分析类包括数据分析、SQL 查询、技术文档、代码审查这几块。这类提示的成败几乎全在输入端:你给的信息结构化程度越高,输出越靠谱。

PDF 里的 SQL 终端那条是个典型的好模板,它明确了四张表的名字和「只回复查询结果表」的契约。但它只给了表名,没给字段,实际用起来模型会猜字段名。我的做法是把 DDL 直接塞进提示里:

-- 先建好最小可用结构,再让模型在这上面写查询 CREATE TABLE `user` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '昵称', `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '所在城市', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; CREATE TABLE `order` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL, `amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00, `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0待付 1已付 2退款', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_time` (`user_id`, `created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

把这两段 DDL 连同「按昵称查用户 id」这种需求一起发过去,再要求它「指出你用到哪个索引、为什么不用另一个」,输出质量会明显不一样。字段注释是这个环节里最值钱的东西——模型读status的注释比读字段名准得多,0待付 1已付 2退款这种枚举值写进注释,能挡掉一大半「用 status = 'paid' 去比数字字段」的低级错误。

技术文档那一类反过来,是输出端要约束。PDF 里技术文档那条强调「清晰、准确、易懂」,实际操作时我会加两条硬约束:每个接口必须给请求方法、路径、参数表、返回示例四段;参数表必须是 markdown 表格且含类型和是否必填两列。有了这两条,输出能直接贴进仓库的文档目录,不用再手工排版。

3.3 状态型交互:面试官、文字冒险和棋局的会话管理

状态型交互是 PDF 后半段最有意思的部分——面试官、文字冒险、五子棋、下棋、辩论教练都属于这类。它们的共同点是:模型的每一轮输出都依赖上一轮的状态,而模型自己维护状态并不可靠。

五子棋那条写得很克制:「请记住,我们是竞争对手,所以请不要解释你的举动。在你采取行动之前,请确保你在脑海中更新了棋盘状态。以 markdown 表格形式回复最新的棋盘。」问题就在「在脑海中更新」这几个字上——它没有真正的棋盘,几轮之后棋子会飘,甚至一个位置出现两枚子。

我一般的解法是让状态外置:要求模型每次回复末尾附一份棋盘快照,本地做一次合法性校验,不合法就把快照塞回去让它重下。

BOARD = 15 # 15 路棋盘 def parse_board(md_table: str) -> list[list[str]]: """从模型返回的 markdown 表格里还原棋盘,'.' 表示空点""" rows = [] for line in md_table.strip().splitlines(): if not line.startswith('|'): continue cells = [c.strip() for c in line.strip('|').split('|')] if len(cells) != BOARD or set(cells[0]) <= set('-: '): continue # 跳过表头和分隔行 rows.append(cells) return rows def check(board: list[list[str]], last_move: tuple[int, int]) -> str | None: """返回 None 表示通过,否则返回错误原因,直接回喂给模型""" if len(board) != BOARD or any(len(r) != BOARD for r in board): return '棋盘尺寸不对,应为 15x15' if board[last_move[0]][last_move[1]] == '.': return f'第 {last_move} 手位置为空,请确认你落子的坐标' stones = sum(c in ('X', 'O') for row in board for c in row) if stones % 2 == 0: return '棋子总数应为奇数(黑先手),请检查是否漏记或多记' return None

BOARD这个常量按实际棋盘改,五子棋 15、围棋 19。check里那条奇偶校验是最省事的一致性检查——棋子总数对不上,说明前面某一轮丢子了,与其在错误状态上继续下,不如让它从快照重新走一遍。文字冒险那条也是同理,让模型在每次回复里带一个「当前场景 / 持有物 / 已触发事件」的小结构,比让它自由发挥稳定得多。

面试官那条相对简单,PDF 里已经写清楚了「不要一次写出所有的问题,只对我进行采访,问我问题,等待我的回答」。这里唯一要补的是终止条件:面到第几题收尾、什么时候给评价。我的习惯是在首句里就写明「一共 8 个问题,第 8 个回答完后输出一份评分表」,否则它会一直问下去。

4. 参数与上下文调优:温度、停止序列和记忆锚点怎么配

提示词写对了,参数配错一样白搭。角色扮演这个场景对参数其实挺敏感——同一个模板,温度从 0.2 拉到 1.0,模拟终端会开始写诗,诗人会开始列条陈。

4.1 温度、最大长度、停止序列的搭配

我按角色类型大致归了几档,跑下来比较稳:

角色类型temperaturetop_pmax_tokens必设停止序列
终端 / SQL 终端 / 表格生成0~0.21.0512代码块闭合符
数据整理、结构化抽取0.2~0.41.01024空行
技术文档、代码审查0.3~0.50.92048无
小说、剧本、广告文案0.8~1.01.02048无
多轮问答(面试官、教练)0.6~0.81.0512问号后半句交给客户端截断

表格生成那一档温度必须压到接近 0。它要的是「十行、固定列、不加解释」,温度一高就开始自由发挥,第十一行会冒出「以上是十二生肖表」。模拟终端那档更极端,我在 0.2 以上试过几次,它会在代码块外面补一句「该命令会输出当前工作目录」——正好违反「不要写解释」。

max_tokens太小有个隐蔽的坑:输出被硬截断,代码块没有闭合符,你按 ``` 切分的时候会把下一轮的文本一起吞进去。终端和表格这类输出短的,给 512 够;文档类给 2048,宁可多给。

停止序列在终端和表格这两个场景是必需品。设成代码块闭合符之后,模型一收笔就被掐掉,很难再补客套话。下面是带参数的调用骨架:

import os from openai import OpenAI client = OpenAI(api_key=os.environ["API_KEY"]) resp = client.chat.completions.create( model="your-model-name", # 按你实际可用的模型填 temperature=0.1, # 终端/表格类压到 0.1 top_p=1.0, max_tokens=512, stop=["```\n"], # 代码块一闭合就停,挡掉后续解释 messages=[ {"role": "system", "content": TERMINAL_PROMPT}, # 四槽位骨架填好的提示 {"role": "user", "content": "pwd"}, ], ) print(repr(resp.choices[0].message.content))

stop里的字符串要给足上下文。只写三个反引号,模型输出里正文中的行内代码也会命中,输出会莫名其妙地被截在半句;写成带换行的闭合符,命中率就正常了。model那一栏按自己手头能调的模型填,别照抄。

4.2 记忆锚点与上下文裁剪

多轮会话跑到十几轮之后,角色漂移几乎是必然的。PDF 里那些「不要破坏性格」「不要写解释」的约束,到第 15 轮基本就失效了。我的做法是每 5 轮重贴一次约束,也就是在用户消息末尾追加一句极短的提醒:

[提醒] 仍然只用代码块回复,不要写任何解释。

这句话放在用户消息里,效果比塞进 system 更好,因为它离当前轮次最近。别嫌土,实测比反复强调更有用。

上下文裁剪也得处理。全量历史塞进去,一是贵,二是旧内容会稀释当前的约束。我一般保留三样东西:首条 system 提示、最近 k 轮对话、以及一份状态快照。快照是给状态型角色用的纯文本摘要,比如「已问 3 题 / 候选人回答了 3 次 / 下一题方向:并发」,它比翻十轮原文更省 token 也更准。

def trim(messages, keep_rounds=6, snapshot=""): """保留 system + 最近若干轮 + 状态快照,其余丢弃""" system = [m for m in messages if m["role"] == "system"] rest = [m for m in messages if m["role"] != "system"] tail = rest[-keep_rounds * 2:] # 一轮含 user 和 assistant 两条 if snapshot: tail = [{"role": "system", "content": f"当前进度:{snapshot}"}] + tail return system + tail

keep_rounds我按角色调整:面试官这类节奏慢的给 6 够用,文字冒险因为依赖道具和场景,给 8 到 10。snapshot千万别省,它是唯一能在裁剪后保住状态的东西。

4.3 模板变量化与批量复用

PDF 里那些提示词,真正高频复用的其实就十来条。剩下的偶尔用一次,翻 PDF 就行。高频的那批,值得抽成模板文件,变量用花括号占位,跑批的时候一次填。

prompts/ ├── _skeleton.md # 四槽位骨架 ├── terminal.md # 终端模拟 ├── table_gen.md # 表格生成 ├── interviewer.md # 面试官 ├── paper_outline.md # 论文提纲 └── novel_card.md # 小说场景卡

每个文件保持纯文本,变量写成{TOPIC}、{AUDIENCE}、{WORDS}这种大写形式,方便写脚本时用正则统一扫一遍,检查有没有漏填的占位符。发布前跑一次空变量检测,能挡掉一大类「把{TOPIC}原样发给模型」的低级事故。

注意:模板文件里不要留任何真实项目名、内部系统名或者人名,哪怕是注释。模板是要在团队里流转的,粘来粘去最后一定会出现在不该出现的地方。

5. 避坑与排查:五个真实翻车现场,现象、原因和补救

下面这五条都是我在把 PDF 里的提示词往实际流程里搬的时候踩过的,按现象、原因、解决三段写,遇到同样的现象可以对着查。

5.1 角色类翻车:漂移和失忆

第一条:跑到第八轮,律师开始写诗。

现象:用「法律顾问」这类角色做多轮咨询,前几轮一本正经,第八轮之后开始用「让我们一起探索」这种语气,甚至给出情绪安慰。原因:角色约束只写在首条 system 里,随着上下文变长,它的权重被稀释,模型退回到默认的助手人格。解决:每 4 到 5 轮在用户消息尾部追加一句极短的复述,比如「仍然是法律顾问,只给建议,不谈情绪」,同时把keep_rounds压到 6 以内,让旧内容不再占位。

第二条:下到第十二手,棋盘上出现了三枚白子连在一起。

现象:棋局类角色自己维护棋盘,越往后错得越多,同一格反复落子。原因:「在脑海中更新棋盘状态」对模型来说并不成立,它每一轮都在重新生成一个看起来合理的棋盘,而不是真的在更新。解决:要求每轮输出末尾附完整棋盘快照,本地做奇偶校验和占位校验,不通过就把错误原因连同上一份快照回喂,让它重下这一手。校验跑不通就重开一局,别在错的状态上继续。

5.2 格式类翻车:输出被解释性文字污染

第三条:说好只回代码块,它非要加一句「以下是输出」。

现象:终端模拟的输出前面多了一行中文说明,或者代码块外面套了一层「好的,我来执行」。原因:输出契约里只写了「用代码块回复」,没写「唯一」和「不要解释」,模型有解释空间。解决:把契约改死——「只在一个唯一的代码块内回复,不要写任何解释性文字,不要在代码块外输出任何内容」。再加一个stop序列,代码块一闭合就掐断。这一条在 PDF 原文里其实是写全了的,多数人抄的时候只抄了前半句。

第四条:表格生成出来是 12 行,还带了个标题。

现象:要求 10 行表格,回来 12 行,或者第一行是个「十二生肖表」的标题。原因:把标题当成了表格的一部分,行数约束没有明确「不含表头」。解决:契约里写明「表格共 11 行:1 行表头 + 10 行数据,不要标题,不要前后说明」,然后解析端加一条断言,行数不对直接判失败重跑,不要靠肉眼挑。

5.3 边界类翻车:谐音注音和专业领域

第五条:英语发音助手的汉语谐音,声调全错。

现象:让模型用汉语谐音给英语句子注音,辅音基本对,重音和连读全丢,拿去教人会被带偏。原因:汉语音节结构和英语音素不是一一对应,这个任务本身有失真上限。解决:把它定位成「提示工具」而不是「标准答案」——提示里要求它只给音节级近似,同时输出一份 IPA 音标,两个版本对照着看。真要练发音,最后还得回到音频材料上。

同类的还有医疗、法律那几个角色。PDF 里给的是「提供诊断思路」「就如何处理提供建议」,这些当信息整理用没问题,但一定不能当成结论直接转给用户。我的习惯是在这类提示的输出契约里硬加一行:结尾必须注明「以上为信息整理,不构成专业意见,请以持证人员判断为准」,并且这一行不允许省略、不允许改写。

6. 进阶:给提示词库配一套能跑的自测集

提示词库最大的问题是「改一个字,你不知道是变好还是变坏」。PDF 里的模板拿来直接用,头两周感觉良好,等到换了模型版本,格式违约率悄悄涨上去,你是察觉不到的。所以最后一件事,是给它配一套小规模的自测集。

做法很土:挑 20 条高频提示,每条准备 3 个输入,固定 8 个检查项,跑一遍把结果落成表。检查项就这些——是否有解释性前缀、是否只有一个代码块、表格行数是否等于预期、是否包含占位符残留、是否出现了禁止词(比如模型自称、「希望对你有帮助」)、是否在应该反问的时候直接给了答案、状态型角色是否输出了快照、专业类角色是否带了免责那一行。

检查项判定方式失败后的第一动作
解释性前缀首个非空行是否以代码块或表格符号开头收紧输出契约
代码块唯一性统计 ``` 出现次数加stop序列
表格行数解析后行数比对预期契约里写死表头+数据行数
占位符残留正则扫\{[A-Z_]+\}检查模板填充脚本
自称与客套关键词表命中边界里加禁止项
该反问却直答人工抽查边界里加「信息不足先问」
状态快照缺失末尾是否含预期结构输出契约追加快照要求
免责声明缺失关键词命中契约里设为不可省略

前五项能全自动跑,后三项得人工抽查,二十条也就十分钟的事。关键是把它做成一个能重复执行的脚本,而不是一次性的人工验收。下面这段是最小实现,只覆盖前五项:

import re PLACEHOLDER = re.compile(r'\{[A-Z_]+\}') BANNED = ['希望对你有帮助', '作为一个AI', '以下是'] def check_output(text: str, expect_rows: int | None = None) -> list[str]: errs = [] first = next((l for l in text.splitlines() if l.strip()), '') if not (first.startswith('```') or first.startswith('|')): errs.append('解释性前缀') if text.count('```') not in (0, 2): errs.append('代码块数量异常') if PLACEHOLDER.search(text): errs.append('占位符残留') if any(b in text for b in BANNED): errs.append('客套/自称命中') if expect_rows is not None: rows = [l for l in text.splitlines() if l.startswith('|')] if len(rows) - 2 != expect_rows: # 扣掉表头和分隔行 errs.append(f'表格行数 {len(rows) - 2} != {expect_rows}') return errs

expect_rows传None表示这条提示不产表格。BANNED那张表按自己遇到的实际情况加,我这三个是从失败样本里捞出来的,不算全。跑完把errs汇总成一份按提示编号分组的报告,哪条提示的违约率超过两成,就回去改契约,别改模型参数——参数只能压住表现,压不住根本原因。

血泪经验是:这套自测集建起来花不了两个小时,但它救过我两次。一次是换了模型版本之后,终端模拟那条突然开始在代码块外加中文注释,违约率从 0 跳到 60%,报告一眼就看出来了;另一次是模板变量改名字,漏了一个文件,占位符残留直接被扫出来,不然那一整批输出全是废的。

从那以后我每次往库里加新提示,都强制先跑一遍这 20 条回归,哪怕只是改了个标点。这套东西本身不值钱,值钱的是它让你在改模板的时候敢下手。这份 PDF 里的两百多条提示,挑十来条高频的照着上面这条路走一遍,剩下的当素材库翻,基本就够用了。希望帮到你。

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

RELATED READING

延伸阅读

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