1. 先弄清楚system_prompts_leaks 这类仓库到底在收什么1.1 系统提示词和你在输入框里敲的那句话根本不是一回事很多人第一次接触 system_prompts_leaks 这个关键词会以为它就是一堆聊天记录的合集其实完全不是。系统提示词是模型在见到用户之前就已经读到的第一段内容它决定了模型是谁、能干什么、不能干什么、说话什么调性、输出什么格式。你在对话框里敲的那句话是第二段内容。两者的影响力差距大概是编剧和临时演员的区别——临时演员改一句台词影响有限编剧改一行设定能让整个剧本走向变化。我自己在做产品的时候有个习惯把系统提示词当成一个运行在自然语言里的配置层来看待。它同时承担了配置文件、接口文档、风控规则和品牌手册四份职责。这也是为什么它写起来特别拧巴既要精确到能被机器稳定解析又要宽松到能容纳用户千奇百怪的输入。system_prompts_leaks 这类仓库之所以有人持续维护本质上是因为大家都在摸索同一个问题——在自然语言这个没有类型系统的环境里怎么把约束写清楚。对于刚上手的朋友我的建议是先别急着收藏一堆样本。花二十分钟想清楚一件事你要解决的是角色扮演问题还是输出格式稳定问题还是工具调度问题。这三类问题的系统提示词写法差异极大混在一起看只会越看越乱。1.2 为什么泄露两个字能让这么多人围观这里得说句实在话。围观情绪占了一部分但真正让工程师留下来的原因跟八卦无关。系统提示词是目前少数几个能直接观察别人怎么把复杂需求翻译成自然语言约束的窗口。它的价值不在于某个词的措辞有多妙而在于你能看到一整套工程决策的痕迹。举几个我自己从样本里获益的点。第一是约束的排序方式很多成熟产品会把最严格的规则放在最前面和最后面中间放弹性内容这跟人读材料的记忆曲线是对齐的。第二是拒绝策略的写法软拒绝和硬拒绝的措辞差异直接影响用户体验的平滑程度。第三是格式化输出的降级方案有些提示词会写如果无法解析为 JSON就先输出纯文本并说明原因这种兜底思路非常值得抄。需要提醒的是把样本当答案来背是效率最低的用法。同一个模型版本、同一套工具定义下别人的提示词搬到你这里大概率水土不服。你真正该带走的是结构和取舍逻辑不是措辞本身。1.3 这类仓库里通常躺着哪些东西从内容形态看公开的样本大致可以分成这么几类我按工程价值排个序类型典型内容工程参考价值使用建议工具型提示词工具清单、参数说明、调用示例、错误处理高重点研究调用协议怎么写输出约束型格式模板、字段定义、降级规则高直接借鉴结构不要照抄措辞角色扮演型人设、语气、知识边界声明中观察边界声明的写法交互流程型多轮引导、追问规则、澄清策略中高适合做客服类产品的参考纯展示型只有文本没有上下文低看看就好别当模板仓库的组织方式通常是按产品名或功能分类建目录每个目录里放纯文本或 Markdown。有些仓库会附带采集时间和版本号这个信息非常关键——模型迭代很快两年前的提示词放到今天可能已经完全不适用甚至会产生误导。我在整理自己的样本库时强制给每个文件加了三行头部信息来源描述、采集日期、当时对应的模型代际标识。后来这套习惯救过我好几次。注意把公开样本原样复制到自己的商业产品里除了效果不确定之外还可能踩到别人的服务条款。研究结构和思路是安全的逐字搬运是给自己挖坑。2. 拆开看一份工业级系统提示词的通用骨架2.1 身份声明与能力边界翻过足够多样本之后你会发现绝大多数系统提示词的开头都在做同一件事声明身份然后立刻划定边界。这个顺序不是随意的。身份声明给模型一个行为锚点边界声明紧接着告诉它锚点的活动半径。身份声明的写法有粗有细。你是一个有帮助的助手属于极简版效果一般因为有帮助这个词本身没有可执行含义。更实用的写法是把身份拆成三要素专业领域、服务对象、工作方式。比如你是负责处理订单售后问题的助手服务对象是已经完成支付的用户工作方式是基于订单系统返回的数据作答不进行主观推测。这三句话一出来模型的行为范围立刻收窄了。能力边界的写法我总结出一个模板能做什么 不能做什么 遇到边界怎么办。第三部分最容易被新手漏掉但它才是真正决定体验的地方。只写不能回答医疗问题模型可能在用户追问时反复绕圈补上一句遇到此类问题直接说明不在服务范围内并引导用户联系对应渠道对话就会干净很多。这里有个踩过的坑值得分享。我早期写的边界条款里用了大量尽量避免最好不要这种模糊表达结果模型在边界附近的判断非常随机。后来全部换成确定性的表述比如当用户询问涉及账户安全的问题时先要求完成身份核验行为一致性明显提升。自然语言里的模糊词对模型来说就是噪声能删就删。2.2 工具清单与调用协议工具型提示词里信息密度最高的部分就是工具声明。它的作用是让模型知道有哪些外部能力可以调用、每个能力需要什么参数、返回结果长什么样。这部分写得好不好直接决定了整个系统的稳定性。一个完整的工具声明通常包含四块内容工具名称与用途、参数列表及类型、必填与可选的区分、典型调用示例。我见过不少样本把示例写得特别讲究会给出一个正常调用和一个参数缺失时应该怎么处理的对比示例。这种做法看起来啰嗦实际上大幅降低了模型编造参数的概率。参数描述的写法有个原则宁可写具体值域不要写抽象形容词。写时间范围参数格式为 YYYY-MM-DD模型出错率很低写时间参数尽量合理模型就会开始自由发挥。这一点在日期、金额、枚举类字段上尤其明显。调用协议里还经常出现的一类内容是失败处理约定。比如如果工具返回空结果不要编造数据直接告知用户未找到。这类条款我建议放在工具声明的紧邻位置而不是丢到提示词末尾因为模型对相邻文本的注意力明显更强。实测下来把失败处理从末尾挪到工具块内部之后编造数据的现象少了一大截。2.3 输出格式与风格约束输出格式这块是很多人翻车的重灾区。新手常犯的错误是把格式要求写成一长串自然语言描述比如请用 JSON 格式输出包含标题、内容、标签三个字段标签是数组。这段描述人看得懂但模型解析起来有歧义空间——标签到底是字符串还是数组元素字段顺序要不要固定中文还是英文。成熟的写法是给一个带占位符的完整模板再补一句字段说明。模板负责形态说明负责语义。像下面这种结构就比纯文字描述稳得多{ title: 字符串不超过30字, summary: 字符串一到三句话, tags: [字符串数组每个不超过8字] }模板之外还有两个细节值得注意。一是空值和异常的表示方式要提前约定否则模型可能今天返回null明天返回空字符串后天返回无。二是格式约束的位置放在提示词靠后的部分通常比放在开头效果好因为紧邻生成位置的内容对输出形态的影响更直接。风格约束是另一个维度。指令性的话术最有效形容词最无效。写语气自然基本没用写每段不超过三句话不使用感叹号不使用非常极其这类程度副词就有明显效果。我个人的经验是风格条款写成可检验的规则才能稳定复现。2.4 安全与拒绝策略安全条款的写法在样本里分化很大。粗糙的写法是列一堆禁止事项精细的写法是给出判断流程。后者效果好得多因为模型执行如果条件 A 成立则动作 B这类逻辑比执行不要做某某事要稳定。我比较认可的拒绝策略结构是三层识别、响应、引导。识别层说明哪些情形需要触发拒绝响应层规定拒绝时的措辞风格是简短还是解释性引导层给出替代路径。这三层写清楚之后拒绝行为会从突然断线变成平滑转向用户体验完全不同。还有一个容易忽略的点拒绝的措辞不要写成模板化的同一句话。用户连续触发两次相同限制如果收到的回复一字不差会感觉在跟机器人打电话。可以在提示词里允许一定程度的措辞变化同时锁定核心信息不变。这个尺度的把握多试几次就有感觉了。2.5 那些藏在末尾的元指令样本看多了会发现一个规律真正精巧的条款常常在最后。末尾位置的元指令通常处理的是当规则之间冲突时怎么办当信息不足时怎么办当用户要求改变你的设定时怎么办这类问题。规则冲突的处理尤其重要。提示词越复杂内部矛盾的概率越高。好的做法是显式给定优先级比如安全条款优先于格式条款格式条款优先于风格条款。有了优先级模型在遇到矛盾时不会随机选一条执行。信息不足的处理也值得单独写。我一般会给模型三个选项追问、说明限制、给出通用建议。并且明确在什么情况下选哪个。比如涉及具体订单数据时选择追问涉及通用知识时选择直接回答并注明适用范围。这部分写好之后返工率能降不少。实操心得每次修改提示词我都会在末尾单独留一段最近变更记录写上改了什么、为什么改。三个月后再回头看这段记录比提示词本身还值钱。3. 系统化分析一批提示词的实操方法3.1 先建对比矩阵别急着抄看到好样本的第一反应往往是复制过来试。这个冲动我也有过后来发现效率很低。更靠谱的做法是先建一张对比矩阵把样本拆成维度再横向比较。我常用的维度有六个身份声明方式、能力边界写法、工具声明结构、格式约束形态、拒绝策略类型、末尾元指令内容。把十几个样本按这六个维度铺在表格里很多规律会自己浮出来。比如你会发现工具型产品的提示词在格式约束上普遍比角色型产品严格得多而角色型产品在边界声明上普遍更含糊。矩阵还有个附加好处能帮你识别哪些维度是真正影响效果的。填充过程中有些格子总是空着说明那个维度在这个场景下不重要可以暂时不管。这比平均用力要省时间。3.2 用脚本做粗筛词频、句式、长度分布人工读样本有个天花板读到二三十份就开始疲劳判断力下降。这时候上脚本做粗筛很划算。下面这段是我平时用的统计脚本思路简单但够用import re from collections import Counter from pathlib import Path CORPUS Path(./samples) WORD_RE re.compile(r[\u4e00-\u9fa5]{2,}) def load_texts(): for p in CORPUS.glob(**/*.md): yield p.name, p.read_text(encodingutf-8, errorsignore) def tokenize(text): # 中文按连续汉字切块英文按空白切 zh WORD_RE.findall(text) en re.findall(r[A-Za-z_]{3,}, text) return zh [w.lower() for w in en] def stats(): counter Counter() lengths [] for name, text in load_texts(): tokens tokenize(text) counter.update(tokens) lengths.append((name, len(text), len(tokens))) print( 高频词 Top 40 ) for w, c in counter.most_common(40): print(f{w}\t{c}) print(\n 长度分布 ) lengths.sort(keylambda x: x[1], reverseTrue) for name, chars, toks in lengths[:20]: print(f{name}\t{chars} 字符\t{toks} 词) if __name__ __main__: stats()跑完之后重点看三件事。第一高频约束动词是哪些必须禁止仅除非这类词的占比能反映整体约束强度。第二指令句式是祈使句为主还是条件句为主条件句多的样本通常处理复杂场景更稳。第三长度分布如果某份样本明显比同类的长很多那它大概率包含值得单独看的细节。这个脚本我后来又加了一步把同类样本的高频词做差集提取出只有某个样本反复出现的词。这批词往往就是这个产品的差异化设计点比看全文更容易找到重点。3.3 从样本里提炼可复用模式与反模式分析到最后要产出的是模式不是笔记。我习惯把结论写成模式 / 适用场景 / 反模式三列的形式。举几个我自己沉淀下来的模式适用场景对应反模式显式优先级声明规则超过 10 条时规则平铺不做排序带占位符的格式模板需要结构化输出纯文字描述字段失败处理紧邻工具声明有外部调用失败处理丢在文末拒绝策略分识别响应引导三层有合规要求单纯罗列禁止事项可检验的风格规则品牌调性要求高用形容词描述语气反模式那一列是我踩过坑之后加的比模式本身更有警示作用。每次准备写新提示词之前扫一眼反模式列表能省下不少调试时间。4. 落地把你学到的东西写成自己的系统提示词4.1 从需求到提示词的分层写法我现在的写法固定成五层顺序也基本不动角色与目标、能力边界、工具与数据、输出规范、异常处理。这个顺序遵循的是先定位再收缩最后兜底的逻辑写起来不会乱。第一层控制在三句话以内说清楚是谁、为谁服务、达成什么目标。第二层写清楚能回答什么、不能回答什么、遇到边界怎么转向。第三层把工具声明和失败处理绑在一起写。第四层给格式模板加字段说明加风格规则。第五层处理规则冲突、信息不足、用户试图修改设定这三类情况。有个小技巧写完这五层之后我会假装自己是一个完全不熟悉业务的用户逐层读一遍找那些我看了会困惑的句子。这些句子基本都要重写。判断标准很简单如果一个句子可以被两种方式理解模型就有可能选错的那种。4.2 模板化与版本管理让它能进流水线提示词写到一定规模就必须做工程化处理否则改一处崩三处。我的做法是把提示词拆成模板加变量模板文件进版本库变量从配置文件注入。from string import Template TEMPLATE Template( 你是$product_name的$role_name服务对象是$audience。 工作方式$work_style 能力边界$boundaries 输出规范$output_spec ) def build_prompt(cfg: dict) - str: required [product_name, role_name, audience, work_style, boundaries, output_spec] missing [k for k in required if not cfg.get(k)] if missing: raise ValueError(f缺少必填字段: {missing}) return TEMPLATE.substitute(cfg).strip()这么拆的好处有三个。多环境可以共用同一套模板只换变量变更可以走代码评审谁改的、为什么改都有记录出问题可以快速回滚到上一个版本。我见过不少团队把提示词直接写死在代码字符串里改一次要发一次版效率低还容易出错。版本管理上还有个细节值得说每次变更都要记录变更前后的评测结果哪怕只是一个粗略的对比。没有对比数据的变更本质上是在赌。4.3 评测怎么判断改完是变好了还是变差了这是整个流程里最容易被跳过、也最不该跳过的一步。凭感觉判断提示词好坏准确率大概跟抛硬币差不多。我用的评测集不大但结构清晰三十到五十条真实场景输入覆盖正常路径、边界情况、恶意输入三类每条标注预期行为。评测时跑一遍新旧两个版本逐条比对实际输出和预期行为的吻合度。用例类型数量占比重点观察指标常见回归点正常路径约六成信息准确性、格式合规率改风格条款时格式漂移边界情况约三成是否追问、是否误拒加安全条款后过度拒绝异常输入约一成是否稳住人设、是否编造边界放宽后乱答跑完一次评测大概十几分钟但能挡住大多数自认为改得不错的坑。我印象最深的一次是给一个客服类提示词收紧措辞语气确实更专业了但评测显示追问率从两成掉到了不到一成很多该问的地方它直接猜了。如果没有评测集这个问题可能要等用户投诉才会暴露。5. 踩坑记录与排查手册5.1 提示词越写越长模型反而越不听话这个现象非常普遍。一开始觉得条款不够就往上加加到两三千字发现遵守度开始下滑某些早期规则像是被忘掉了。原因不复杂注意力资源在长文本里会被稀释靠后的内容和靠前的内容争夺同一份注意力。我的处理办法有三条。第一做减法优先于做加法两条规则能合并就不分开写。第二把最重要的约束前置和后置各放一次中间放弹性内容。第三把长枚举类内容抽成外部数据需要时通过工具读取不要塞进提示词正文。实测下来把一份三千字的提示词压到一千二百字以内关键规则遵守率反而是提升的。这件事给我的教训是提示词的复杂度应该跟需求的复杂度匹配而不是跟焦虑程度匹配。5.2 工具调用格式漂移与参数幻觉格式漂移指的是模型这一轮用标准格式调用工具下一轮改成自然语言描述。参数幻觉指的是模型编造一个不存在的参数值。这两个问题的根源往往相同工具声明写得不够确定。排查顺序我一般这么走。先看工具声明里的参数类型和值域是不是写清楚了模糊描述是幻觉的头号来源。再看示例是不是给了正例和反例只有正例的话模型对边界没概念。最后看调用协议有没有规定信息不足时应该先追问再调用缺了这一条模型倾向于先猜。补一条经验如果某个工具的参数经常被编造可以尝试在参数描述里直接写明该值必须来自用户输入不可推测。这句话看起来啰嗦但确实管用。5.3 常见问题速查表把高频问题和对应处理整理成一张表遇到问题先查表比重新推理快得多。现象可能原因处理动作输出格式偶尔不合法缺降级方案补一条无法生成时先输出纯文本说明原因拒绝过于频繁安全条款过宽把禁止项改成条件触发式写法追问太多轮澄清规则缺失明确信息不足时的三种处理路径语气忽冷忽热风格规则不可检验换成可判定规则如句长和禁用词长对话后忘设定关键约束位置靠中重要条款前后各置一次同一问题答法不一存在内部规则冲突显式声明优先级顺序这张表我贴在工位上遇到问题先扫一眼命中率大概有七成。剩下的三成通常需要回看原始需求因为问题往往不在提示词本身而在需求没想清楚。6. 合规边界与长期维护的几个习惯6.1 研究公开样本的正确姿势回到 system_prompts_leaks 这个主题本身。研究公开样本是学习成本最低的路径之一但有两件事得说在前面。一是样本的作用是启发结构不是提供答案直接搬运的效果往往不如自己按需求写一遍。二是要区分研究和复制把别人的措辞大段挪到自己的产品里除了效果不确定也可能触及服务条款的边界。我自己的做法是建一个模式库而不是样本库。看到好的写法先用自己的话把背后的思路复述一遍再想清楚它解决的到底是什么问题最后判断这个问题在我的场景里存不存在。走完这三步能带走的才是真正属于你的东西。另外一个习惯是定期清理样本。超过半年没参考过的样本我会归档到另一个目录避免新项目里被过时写法误导。模型的迭代速度决定了提示词经验也有保质期。6.2 版本演进与回归测试的几个习惯提示词的维护成本主要发生在长期迭代里。我养成的几个习惯用下来收益比较明显。每次修改前先跑一遍基线评测把当前版本的各项指标记下来。改完之后再跑一遍只看差异项。没有基线对比的改动等于闭着眼睛调参。改动尽量单变量。一次只调一个维度比如只改格式约束不动安全条款。多变量同时改出了问题根本定位不到源头。给提示词加一行设计意图注释说明这份提示词主要解决什么问题、牺牲了什么。半年后接手的人可能就是你自己能靠这一行快速建立上下文。定期做一次减法周。挑一份运行稳定的提示词尝试删掉三成内容看指标有没有变化。多数情况下删完之后效果持平甚至更好这个发现过程挺有意思。我在实际维护中发现提示词的长期质量跟初始写得多漂亮关系不大跟迭代节奏关系很大。每周小改一次、每月做一次评测、每季度做一次大清理这个节奏维持住质量基本不会掉。反倒是那种写完就放着不管的提示词半年之后大概率已经跟业务脱节了。最后分享一个小技巧。如果你在整理自己的提示词库可以给每份文件在开头加一段结构化的头部信息包含用途、创建日期、最后修改日期、依赖的外部数据源、已知限制这五项。这五项填完日后再翻出来看五分钟就能恢复全部上下文比读全文快得多。