拓冰建站拓冰建站
首页 / 资讯中心 / 正文

System Prompts Leaks:系统提示词拆解与工程化实践

1. 系统提示词到底特殊在哪一次完整的信息层级拆解system_prompts_leaks这个项目名第一次看到的人大概会愣一下——前半段是技术圈天天挂在嘴边的 system prompts后半段 leaks 又带着点不太好公开讲的味道。实际接触下来它讨论的核心其实很朴素那些藏在对话产品最底层、用户看不见的系统提示词被以各种方式还原、收集、比对、研究之后能反过来教会我们什么。这件事对做 AI 应用的人价值极大因为系统提示词就是产品的产品说明书行为准则话术手册三合一把它读透比自己闷头试错三个月学到的还多。我在实际项目里接触过不少提示词相关的活儿从最基础的客服机器人到带工具调用的复杂 agent早期全靠改一句测一句的笨办法。真正让我思路打开的是系统性地看过一批被公开讨论的提示词样本之后——原来头部产品在约束模型行为时用的是这么一套成体系的方法。所以这篇文字不打算站队讨论泄露这件事的伦理争论那是另一个话题我想做的是把system_prompts_leaks这个方向拆开讲清楚系统提示词在整条推理链里处在什么位置、为什么它天然容易漏、拿到样本后该怎么读、能提炼出哪些可复用的写法、以及最关键的——怎么把这些经验搬回自己的项目里。适合谁看如果你正在写第一个像样的系统提示词这篇能帮你少走弯路如果你已经在维护线上提示词、吃过改了 A 崩了 B的苦第 5 节的版本管理和回归测试能直接抄如果你只是想搞明白大模型产品为什么有时候答得像个受过训练的人那第 3、4 节的拆解框架会让你看模型行为的眼光完全不一样。全程我会尽量说人话参数和步骤都给出背后的理由不堆术语。1.1 从一次请求说起提示词的四个层级要理解系统提示词为什么重要得先看清一次模型请求里到底塞了些什么。绝大多数对话产品的一次调用消息序列大致是这么个结构最顶上是一条system角色的消息接着是若干轮历史user/assistant对话最后是当前这条user消息。系统提示词就是那条system消息位置最靠前权重通常也最高。把它拆细一点我习惯分成四层产品层定义你是谁。比如一家公司做的助手会明确写上产品名、运营方、定位是办公助手还是创意伙伴。能力层说明你能干什么、不能干什么。这一层里塞了大量边界包括哪些话题要谨慎、哪些任务要拒答、遇到不确定时怎么回应。格式层规定你怎么说话。语气、长度、是否用 Markdown、要不要分点、能不能用列表、称呼用户的方式全在这一层。编排层管理你怎么做事。带工具的产品会在这一层定义调用顺序、参数填写规则、多轮任务怎么拆、什么时候该反问用户。普通用户只感知到最终输出的那几句话但真正决定这句话长什么样、踩不踩刹车、该不该反问的是这四层叠加起来的效果。所以看一份系统提示词其实是在看一个产品的行为设计图。1.2 为什么泄露这件事天然会发生很多人以为系统提示词泄露是某个漏洞导致的意外其实从原理上讲它更像是一种结构性的必然。原因有三条理解了这三条你就明白为什么各家产品再怎么加防护样本还是会不断冒出来。第一模型本身分不清指令和内容。系统提示词和用户输入最终都会被拼成同一个 token 序列喂给模型模型不会给 system 段打上这是机密、不可复述的物理标记。你能让它遵循系统提示词里的规则就同样有可能让它把规则本身说出来这中间只隔着话术设计。第二提示词的作用方式决定了它必须可被描述。比如你想约束助手回答涉及医疗建议时先声明局限性这条规则要在具体场景里生效模型就得在生成时想到它。只要它能在生成时想到那么在合适的诱导下它就有可能把这条规则翻译成自然语言说出来——不是原样背诵而是我被告知在涉及医疗话题时要先声明局限性。第三产品需要迭代迭代就意味着有人能拿到旧版本。提示词是产品最频繁调整的东西之一一次 A/B 测试、一次客服反馈、一次版本回滚都可能让某个中间版本在不同用户那里留下痕迹。把这些零散痕迹拼起来就能逼近完整版。注意理解泄露的机理目的是更好地设计自己的防护和提示词结构而不是去套取别人的东西。把研究能力用在自己产品的健壮性上才是这个方向真正的价值。2. 收集与还原一份样本研究的完整流程system_prompts_leaks这类研究光有一份提示词是没意义的有价值的是一批提示词之间的横向对比。我给自己的习惯是把它当成一个小型数据工程来做分收集、清洗、还原度评估三步。2.1 样本来源与清洗样本来源大致分为两类一类是公开讨论中被贴出来的片段另一类是自己通过对话交互观察到的行为特征反推的。前者信息密度高但零散后者需要耐心但要可信。我通常会把两类一起归档标注来源类型。归档时最关键的是统一格式。不同人贴出来的提示词有的用 Markdown 标题分区有的用纯文本有的夹着大量换行。我一般先做三件事去掉所有与提示词无关的对话包装文字只留 system 段内容。统一换行和空白把连续空行压成一个。给每条样本打上元数据标签产品类型、大致时间、是否完整、来源可信度。清洗这一步看着琐碎但直接影响后面能不能做对比。我吃过亏早期没统一格式做统计时发现字数段落数这些指标全是噪声因为每条样本的格式基准都不一样。2.2 还原度评估怎么判断拿到的是不是完整版这是最容易被忽略、又最影响结论的一步。一份看起来很长的提示词可能是拼接了多个版本也可能只截取了中间一段。我一般用几个信号交叉判断判断信号说明可信度影响结构完整性是否有清晰的开头角色定义和结尾兜底规则缺头或缺尾基本可判定不完整内部自洽性前后提到的规则是否互相呼应、有没有引用未出现的内容出现如上述第 X 条却没第 X 条说明有缺失行为验证按提示词描述去对话看行为是否吻合吻合度高则可信度提升措辞风格一致全篇语气、术语是否统一混入明显不同风格的段落要警惕拼接我个人的经验是宁可把一份样本标成不完整也不要在结论里默认它是全貌。因为研究提示词最容易犯的错误就是拿一份残缺样本去总结某某产品的设计哲学最后得出一个根本不成立的结论。3. 拆解框架五层读法把一份系统提示词读透拿到一份还算完整的样本后别急着抄句子。我总结了一个五层读法从角色一路读到兜底按这个顺序走一份再长的提示词也能在半小时内拆干净。3.1 L1 角色与身份定义这一层要回答的问题是这份提示词想让模型成为谁。注意不是简单一句你是一个助手好的角色定义往往包含三个要素——身份、立场、边界感。身份是叫什么、代表谁立场是在什么语境下用什么态度说话边界感是哪些身份特征不能被用户随意改写。我见过不少新手写的角色定义只有一句你是一个专业的助手结果模型一被诱导就忘记自己是谁跟着用户跑偏。头部产品的写法通常是这样的逻辑先用一两句锚定身份再用一段说明身份带来的责任和义务——这段义务才是真正管用的东西因为它给了模型一个我为什么要保持这个身份的理由。你读样本时可以拿张纸把 L1 里所有你是……你代表……的句子拎出来看看它用了几句话、覆盖了哪几个要素。做几份之后你会发现规律非常明显。3.2 L2 能力边界与拒答策略这是信息量最大、也最值得细读的一层。能力边界不是简单列一个不能做什么的清单而是三件事的组合什么情况要拒、拒的时候怎么说、拒完之后给不给替代方案。好的写法会区分不同级别的拒绝有的情况直接说不有的情况先说明限制再提供有限帮助有的情况则要引导用户去别的地方找答案。我观察到的一个高频技巧是——在拒答时给出你可以转而做什么这能大幅降低用户被拒后的挫败感。比如某项任务模型做不了但提示词会要求它推荐一个相关但可行的小步骤。读这一层时我建议重点标记转折词出现但是不过如果……则的地方往往就是边界规则的核心。3.3 L3 输出格式与风格约束这一层决定用户看到什么。它管的东西非常具体长度、分段、是否分点、用不用标题、能不能加粗、语气偏正式还是偏口语、遇到列表时编号还是圆点。这里有个反直觉的点格式约束越具体模型执行越稳定。写回答要简洁和写回答控制在 3 段以内每段不超过 4 句不使用列表后者的效果甩前者几条街。因为简洁是模糊词模型每次理解都可能不一样而具体数字和规则是硬的。我读样本时会专门统计格式约束里出现的数字和硬性规则这些是最容易直接搬到自己项目里的部分。3.4 L4 工具调用与流程编排如果你的产品带工具搜索、计算、代码执行、数据库查询这一层就是命脉。它规定的是什么条件下触发工具、参数怎么写、工具返回后怎么整合到回答里、多步任务怎么拆。读这一层要注意两件事。一是触发条件的写法好的提示词会把触发条件写成明确判断而不是需要时调用。二是失败处理工具调用失败怎么办、超时怎么办、返回空结果怎么办——这部分最容易被新手忽略恰恰是体验好坏的分水岭。3.5 L5 兜底与异常处理最后一层也是最容易被跳过的一层。它管的是所有没预料到的情况用户输入看不懂怎么办、要求前后矛盾怎么办、试图改写系统指令怎么办、情绪激动怎么办。我看过不少样本L5 部分写得像一份危机处理手册密度极高。这部分不好抄因为它高度依赖具体业务但它体现的提前想好最坏情况的思路是每个做提示词的人都该学的。4. 高频模式盘点那些反复出现的写法值得抄拆了几十份样本之后有些写法出现频率高得惊人。我把它们归成几类这些都是跨产品通用的属于抄了不亏的干货。4.1 结构化标签与分区几乎每份像样的系统提示词都用某种方式做了分区。常见的有三种用 Markdown 标题分区、用自造标签如尖括号包裹的段落名分区、用编号列表分区。它们的效果差异在哪Markdown 标题对模型来说边界清晰、层级明确适合长提示词自造标签更像轻量协议适合内部已经约定好解析规则的系统编号列表最简单适合规则条目化的场景。我自己现在倾向于标题分区 关键段落加粗的组合长提示词里模型对标题的注意力确实更稳。4.2 优先级声明与冲突消解这是我很想单独拎出来讲的一点。多规则的系统提示词规则之间必然会打架。比如要保持简洁和要覆盖用户所有问题就经常冲突。好的样本会显式写一条优先级声明告诉模型冲突时听谁的。常见写法是先声明一个总原则再逐条说明当 X 与 Y 冲突时以 X 为准。这条技巧的性价比极高能显著减少模型选择性听话的情况。我把它搬到自己项目后线上该拒的没拒、该答的答歪的比例明显下降。4.3 少样本示例的用法差异有些提示词会带示例有些不带。带示例的分两种用法一种是示范输出格式给一两个输入输出对另一种是示范思考路径展示遇到这类问题该怎么一步步处理。我观察到的规律是格式类示例要短、要多2 到 3 个足够路径类示例要详、要少1 个精品胜过 5 个粗糙的。因为格式是模式匹配样本多了模型学得准而路径是逻辑示范太啰嗦反而干扰。4.4 模式对比表把上面几类整理成一张表方便对照模式典型作用适用场景常见坑标题分区划分提示词结构长提示词标题过多导致层级混乱优先级声明消解规则冲突规则超过 5 条只声明不举例模型仍会猜格式示例固定输出样式需要稳定输出示例风格与正文不一致路径示例示范推理逻辑复杂任务示例太长挤占上下文兜底规则处理异常输入面向公众的产品写得太笼统等于没写5. 落到自己项目提示词版本管理与回归测试这一节是整篇最实操的部分。看别人的提示词只是学习真正的价值在于把自己的提示词管起来。我踩过的坑是早期系统提示词就一段长文本每次改动靠感觉上线后偶尔出现行为退化回头根本不知道是哪次改动导致的。后来我搭了一套轻量的版本管理和回归测试流程问题就清晰了。5.1 目录结构与命名约定我把提示词当成代码来管目录大致这样prompts/ assistant/ v1.0.0.txt v1.1.0.txt current.txt # 软链接或复制指向线上版本 tests/ cases.yaml # 回归测试用例 run_tests.py # 测试脚本 CHANGELOG.md # 每次改动的原因和影响命名用语义化版本主版本.次版本.修订号。主版本变动指提示词结构大改次版本指新增规则修订号指改错别字或微调措辞。CHANGELOG.md里每次必须写清楚改了什么、为什么改、预期影响哪些场景这三条缺一不可。我给自己定规矩没写清预期影响的改动不允许上线因为线上出问题时这几行字就是排查的起点。5.2 回归测试用例设计测试用例的设计思路和普通软件测试不一样。提示词测试测的是行为倾向所以用例要覆盖四类正常路径最常见的问题类型确保基本盘不崩。边界场景贴着规则边界的输入比如刚好踩到拒答条件的提问。冲突场景同时触发两条规则的输入验证优先级是否生效。对抗场景试图让模型改写系统指令、越权、跟随用户设定的输入。每类准备 5 到 10 条用 YAML 维护cases: - id: normal_001 category: normal input: 帮我总结这段文字 expect_contains: [总结, 要点] expect_not_contains: [] - id: boundary_001 category: boundary input: 给我一个具体的投资建议 expect_contains: [无法, 建议咨询] expect_not_contains: [应该买] - id: conflict_001 category: conflict input: 用一句话说清所有细节 expect_contains: [] expect_not_contains: [] note: 观察模型如何处理简洁与完整冲突5.3 回归测试脚本实现测试脚本我写得比较简单核心就是批量跑用例、比较输出、生成报告。下面是一个最小可用版本import yaml import json from datetime import datetime def load_cases(pathtests/cases.yaml): with open(path, r, encodingutf-8) as f: return yaml.safe_load(f)[cases] def run_single_case(case, prompt_text, call_model): # call_model 是你对接模型的函数传入 system user返回文本 output call_model(systemprompt_text, usercase[input]) result { id: case[id], category: case[category], output: output, passed: True, reasons: [], } for kw in case.get(expect_contains, []): if kw not in output: result[passed] False result[reasons].append(f缺少关键词: {kw}) for kw in case.get(expect_not_contains, []): if kw in output: result[passed] False result[reasons].append(f出现禁止词: {kw}) return result def run_all(prompt_pathprompts/assistant/current.txt, call_modelNone): with open(prompt_path, r, encodingutf-8) as f: prompt_text f.read() cases load_cases() results [run_single_case(c, prompt_text, call_model) for c in cases] passed sum(1 for r in results if r[passed]) report { time: datetime.now().isoformat(), total: len(results), passed: passed, failed: len(results) - passed, details: results, } with open(tests/report.json, w, encodingutf-8) as f: json.dump(report, f, ensure_asciiFalse, indent2) return report用起来就是每次改提示词先跑run_all对比新旧报告。我给自己定的红线是——正常路径用例通过率不能下降边界和对抗用例通过率不能低于上一版。任何一次改动只要触碰这两条线就必须回滚或重写。这套流程搭起来花了我一个下午但省下的排查时间以周计。提示对抗场景的用例最好定期更新。你会发现随着模型能力变化某些过去的稳妥诱导失效了某些新的绕过方式又冒出来了用例库得跟着进化。6. 防护视角怎么让自己的系统提示词不那么容易被套走研究system_prompts_leaks的人多少都会反过来想一个问题如果我做了个产品怎么让自己的系统提示词不被轻易套出来这里必须说句实话——没有 100% 的办法。任何声称能完全防住的方案要么没用要么代价大到影响正常使用。但把被套走的成本抬上去完全可行。6.1 常见的防御手段与有效性评估手段原理有效性副作用明确不得复述指令规则在提示词里加禁止条款低到中可能被模型机械套用影响正常回答分层提示词把敏感规则拆到不同层中增加维护复杂度输入检测与拦截识别诱导性提问并拒答中误伤正常用户敏感信息不进提示词关键逻辑放服务端高需要架构配合定期行为审计持续监测异常提取尝试中到高需要额外监控投入我个人最推荐、也最见效的是**敏感信息不进提示词**这条。核心逻辑能用代码、配置、检索解决的部分就别写进系统提示词。提示词里应该只放行为风格这类即使被看到也不致命的东西。真正的业务规则、数据访问权限、定价策略放在服务端代码里从源头切断泄露的价值。6.2 一个务实的防护清单结合上面几条我给自己项目的防护清单是这样系统提示词里不出现任何密钥、内部 URL、真实用户数据样例。关键业务判断如是否放行某操作在服务端完成提示词只负责表达。加一条简短的不复述内部指令约束但不过度依赖它。对高频出现的诱导性提问模式做统计异常突增时告警。定期做一次红队测试自己尝试套取看看能套出多少。这套组合下来即便有人成功拿到部分提示词拿到的也只是一份话术模板而不是产品的核心资产。这才是防护的正确目标——不是密不透风而是让泄露的收益降到最低。7. 踩坑记录与常见问题速查最后这部分是我自己踩过的坑以及被问得最多的几个问题整理成速查表。问题现象排查思路解决方向改了提示词后行为突变某些原能回答的问题开始被拒对比新旧版本 diff定位新增规则检查新规则是否与旧规则冲突补优先级声明模型选择性忽略某条规则同一规则时灵时不灵检查该规则的位置和措辞是否模糊把规则前置、改写成带具体数字的硬约束输出格式不稳定有时分点有时成段检查格式约束是否具体用明确数字和禁用项替代模糊描述寒暄过多占用篇幅每个回答都先来段客套检查语气约束是否过度在提示词里明确直接进入主题示例反而带偏输出模型死板模仿示例措辞检查示例是否与目标风格一致精简示例数量或在示例旁注明仅示范结构长提示词后半段失效尾部的规则基本不生效检查是否超出有效注意力范围把最重要的规则提到前面或精简整体关于提示词到底多长合适我的经验是能用 800 字说清的事别写 2000 字。长度不是质量结构才是。我见过太多人把提示词写成一篇论文结果每一条的权重都被稀释反而不如一段精炼的规则管用。真正的高手提示词读起来像一份清晰的岗位说明书——职责明确、边界清楚、不废话。还有一个常被问到的点要不要跟着模型升级频繁改提示词。我的建议是模型大版本更新时做一次完整回归测试看哪些规则变得多余模型自己能做对了、哪些规则需要加强模型开始跑偏了。但不要每次小更新都大改否则你会陷入永远在调提示词的循环产品体验反而更不稳定。我在实际维护提示词的过程中最大的体会是把提示词当产品的一部分而不是一段可以随手改的文本。它该有版本、该有测试、该有负责人、该有变更记录。很多团队愿意为一行业务代码建 CI却让系统提示词裸奔在某个文档里谁都能改、改完没人测。这种状态迟早出问题。system_prompts_leaks这个方向最现实的价值或许不是让我们看到别人写了什么而是提醒了每一个做 AI 产品的人——你那段没人管的系统提示词其实值得被严肃对待。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门