系统提示词归档实战:六层结构拆解、版本追踪与模板复用

📅 发布时间:2026/9/18 4:44:46
系统提示词归档实战:六层结构拆解、版本追踪与模板复用
系统提示词这个话题最近两年在提示词工程圈子里热度一直没降过。所谓system prompts leaks说白了就是一群人把各家 AI 产品背后那套“系统提示词”——也就是模型在正式对话前收到的第一段、也是最重要的一段指令——通过公开可观测的输出、官方文档、开发者接口说明、社区众包等方式收集起来按产品分门别类归档成仓库。这个项目标题指向的正是这类归档仓库本身它不是某个单一软件而是一套持续维护的“语料库 版本追踪机制”。它能帮你搞清楚一件很实在的事——为什么同样是接大模型 API有的产品回答得像客服有的像严谨的技术文档编辑有的一言不合就拒绝。差别很多时候不在模型参数而在那段你根本看不到的提示词。写这篇文章是想把我在整理和使用这类归档时踩过的坑、总结出的结构拆解方法、以及一套可复现的采集归档流程讲清楚。不管你是刚接触提示词的新手还是已经在做 Agent 产品的开发者下面这些内容都能直接拿去用。1. 这个仓库到底在收集什么为什么值得看1.1 系统提示词不是“隐藏彩蛋”它是产品定义书很多人第一次听说这个概念以为系统提示词就是一句“你是一个乐于助人的助手”。实际打开一份完整的系统提示词你会发现它更像一份产品需求说明书被翻译成了自然语言。它通常包含身份设定、能力边界、可用工具清单、调用规则、输出格式约束、安全策略、语言风格要求末尾还会塞几个示例。长度从几百字到上万字都有我自己见过最长的一份拆分下来接近二十个模块。为什么值得看因为它把“产品经理脑中的规则”变成了可读文本。你想知道某个产品的回答为什么总是分点列出、为什么总在结尾追问一句、为什么拒绝某些请求时措辞固定答案基本都在这份文本里。对做产品的人来说这是一份免费的竞品规则说明书对做提示词工程的人来说这是一份高密度的写法参考。我自己的习惯是每整理完一份就在笔记里标出三个“可以借鉴的写法”半年下来攒了几十条直接用在项目里省了非常多试错成本。1.2 一份归档文件通常长什么样成熟的归档仓库不会只有一堆纯文本它有固定的组织方式。我见过的做法大致是这样按厂商分组按产品建子目录产品目录下按采集日期存快照再配一份元数据文件记录来源和可信度。这样做的好处是能看出“演化”——同一个产品三个月前的提示词和现在的差在哪往往能反推出产品团队当时的调整意图。举个我常用的目录结构示例prompt-archive/ ├── vendors/ │ └── vendor-a/ │ └── assistant-main/ │ ├── meta.yaml │ ├── snapshots/ │ │ ├── 2024-08-14.md │ │ ├── 2024-11-02.md │ │ └── 2025-02-19.md │ └── notes/ │ └── observed-changes.md ├── schema/ │ └── meta.schema.json ├── tools/ │ ├── snapshot_hash.py │ └── diff_report.py └── CHANGELOG.md这种结构最实用的地方在于snapshots目录天然就是一条时间线。你随手diff两个文件就能看到新增了哪条约束、删掉了哪个工具说明、语气描述从“友好”改成了“简洁专业”。这类细微变化往往对应着产品侧真实发生的调整。1.3 谁在用用在哪我接触过的使用人群大概分四类。第一类是提示词工程师把归档当写法参考库学的是“别人怎么把一个模糊需求拆成可执行条款”。第二类是 Agent 开发者重点看工具调用部分看别人怎么描述函数、怎么约束调用时机、怎么处理调用失败。第三类是评测和研究者用这些文本做对照实验验证同一任务在不同指令风格下的表现差异。第四类是产品经理看的是规则设计思路比如如何在不影响体验的前提下设置边界。需要说清楚的是这类仓库的价值不在“抄”而在“对照”。你直接把某家的系统提示词原封不动搬进自己的产品大概率效果很差因为你的模型版本、上下文长度、业务场景都不一样。我自己试过一次直接套用结果输出风格严重水土不服后来改成“提取结构 重写内容”效果才正常。这也是我在后面章节会重点讲的部分。2. 拆开看系统提示词的六层结构2.1 身份层定义“我是谁”和“我不是谁”身份层通常出现在最前面作用是把模型从“通用助手”收窄成一个具体角色。写法上一般包含三个要素角色名称、服务对象、语气基调。比如“你是 XX 产品的技术支持助手面向企业客户语气专业但不生硬”。这句话看着简单实际决定了后面所有输出的底色。我见过写得好的身份层会额外加一句否定描述比如“你不是通用聊天助手不回答与产品无关的闲聊”。这句否定的价值很高它提前关闭了一大类无效请求减少后续安全层的压力。新手常犯的错误是只写正面定义不写反面边界结果模型在遇到边缘问题时自由发挥风格飘忽。实操上建议身份层控制在三到五句话超过这个长度模型对后面的指令注意力会被稀释。2.2 能力边界层把“做不到”提前说清楚这一层负责声明模型能做什么、不能做什么、不确定时怎么办。典型写法包括知识截止范围、不臆测未知信息、涉及实时数据时如何回应、遇到超出范围的问题如何引导。这一层看起来像“免责声明”实际上是提升体验的关键。举个具体写法差异带来的效果区别。写法 A 是“如果你不知道答案就说不知道”。写法 B 是“当问题超出你的知识范围时先说明你不确定再给出你能提供的相关方向并建议用户通过什么渠道获取准确信息”。实测下来写法 B 的用户满意度明显更高因为它没有把对话终结掉而是给了下一步动作。这类细节就是从归档对比里最容易学到的部分——同样一个意图不同产品用了不同措辞效果差距肉眼可见。2.3 工具与调用层Agent 产品的重头戏只要产品带工具调用能力这一层就会占很大篇幅。它需要说清楚有哪些工具、每个工具什么时候用、参数怎么填、调用前要不要确认、失败后怎么处理、多个工具怎么排序。我整理过的样本里这一层的信息密度最高也最容易出问题。一个常见坑是工具描述写得过于笼统。比如只写“用于查询订单”模型就不知道该在用户说出订单号时立刻调用还是先确认身份。写得清楚的版本会补上触发条件“当用户提供订单编号且明确表达查询意图时调用若未提供编号先追问编号再调用。”这种精确到触发时机的描述能显著降低误调用率。另外工具数量超过一定规模后建议在提示词里做分组比如“信息查询类”“状态变更类”并在开头说明分组逻辑帮助模型建立索引。2.4 格式与风格层决定输出“长什么样”这一层管的是形式用什么格式、多长、要不要分点、代码块怎么标、表格怎么用、语气怎么调、语言如何跟随。很多产品的“辨识度”就来自这一层。有的要求“默认不超过三句话”有的要求“复杂问题先给结论再展开”有的强制“所有步骤用有序列表”。我自己在写这一层时有个经验能用量化指标就别用形容词。“回答要简洁”这种描述模型理解得很随机改成“常规问答控制在 150 字以内涉及步骤说明时不超过 8 条”就稳定得多。另一个经验是把格式规则按场景拆开写而不是一句“回答要清晰”包打天下。比如“定义类问题用一段话解释 一个例子”“对比类问题用表格”“操作类问题用有序列表”。2.5 安全与拒答层措辞需要克制安全层的写法差异非常大。写得好的版本通常不会罗列大量“禁止事项”而是给出一个判断逻辑先判断请求是否在服务范围内不在范围内则简短说明并引导回正题不展开解释理由。这种写法比逐条列举禁忌更稳因为逐条列举总有覆盖不到的情况而判断逻辑可以泛化。注意这一层最忌讳的是“情绪化措辞”和“过度解释”。我见过一些写法在拒绝时反复强调规则结果模型在正常问题上也开始紧张动不动就声明自己不能做什么体验很差。克制、简短、给出替代路径是实测下来最稳的组合。2.6 示例层少而准别堆量示例层一般在末尾作用是“用具体案例锚定前面的抽象规则”。经验是示例要少而准两到三个高质量示例比十个泛泛的更有用。挑示例的标准是优先覆盖最容易出错的场景而不是最容易的场景。比如格式约束里要求“对比类问题用表格”那就专门放一个对比类示例并且故意选一个容易被模型写成段落的问题类型。还有个细节示例最好覆盖“拒绝场景”。很多人写示例只写成功回答结果模型在边界问题上没有参照。加一个简短的边界示例拒答风格和主提示词保持一致能明显提升整体一致性。3. 从零搭一套采集与归档流程3.1 采集思路区分“官方公开”和“推断还原”先讲原则。采集路径大致两类一类是官方主动公开的内容比如开发者文档里给出的提示词模板、公开的示例配置、产品说明里明确写出的行为规则另一类是社区通过观察输出推断出来的还原稿。这两类必须分开标注不能混在一起。原因很简单可信度完全不同。我自己在归档里会给每份文件打一个来源标签比如official-template、observed-inference、community-contributed并在元数据里写清楚推断依据。推断还原的做法是设计一组探针问题覆盖前面讲的六层结构然后从回答的措辞一致性里反推约束。比如连续问三个同类问题如果回答的结构、长度、结尾方式高度一致说明这一层有明确约束如果每次都不同说明约束较松。这种方法的局限很明显——你只能看到“约束的结果”看不到“约束的原文”。所以我在归档时一律加一句说明本文件为观察推断稿非原文。3.2 元数据设计没有它三个月后就是垃圾堆归档能不能长期用全看元数据。建议至少包含以下字段字段类型说明idstring唯一标识建议vendor-product-日期productstring产品名collected_atdate采集日期必填source_typeenumofficial / inference / contributedconfidenceenumhigh / medium / lowmodel_versionstring采集时对应的模型版本languagestring提示词主体语言sectionslist识别出的结构模块清单notesstring采集方法与注意事项model_version这个字段特别重要也是最多人忽略的。同一个产品换了底层模型之后行为可能大变如果你不记录版本后面做对比分析时会把“模型变化”误判成“提示词变化”。我就吃过这个亏花了半天分析某份提示词的新增条款最后发现是模型换代导致的行为差异白忙一场。对应的 schema 用 JSON Schema 描述可以用脚本自动校验{ $schema: http://json-schema.org/draft-07/schema#, title: PromptArchiveMeta, type: object, required: [id, product, collected_at, source_type, confidence], properties: { id: { type: string, pattern: ^[a-z0-9-]$ }, collected_at: { type: string, format: date }, source_type: { enum: [official, inference, contributed] }, confidence: { enum: [high, medium, low] }, sections: { type: array, items: { type: string } } } }3.3 版本追踪用哈希和 diff 自动抓变化人工比对两份上千字的提示词是不现实的。我的做法是给每个快照算一个内容哈希存进索引文件发现哈希变了就触发一次 diff 报告。这样日常维护成本几乎为零只在真正有变化时才需要人工介入。import hashlib import json import pathlib import difflib from datetime import date ROOT pathlib.Path(prompt-archive/vendors) INDEX pathlib.Path(prompt-archive/index.json) def sha256_of(text: str) - str: return hashlib.sha256(text.encode(utf-8)).hexdigest()[:16] def scan_snapshots(): result {} for path in ROOT.rglob(snapshots/*.md): text path.read_text(encodingutf-8) key str(path.parent.parent.relative_to(ROOT)) result.setdefault(key, []).append({ file: str(path), date: path.stem, hash: sha256_of(text), }) for key in result: result[key].sort(keylambda x: x[date]) return result def report_changes(index): lines [] for key, items in index.items(): if len(items) 2: continue prev, curr items[-2], items[-1] if prev[hash] curr[hash]: continue old pathlib.Path(prev[file]).read_text(encodingutf-8).splitlines() new pathlib.Path(curr[file]).read_text(encodingutf-8).splitlines() diff difflib.unified_diff(old, new, lineterm, n2) lines.append(f## {key}: {prev[date]} - {curr[date]}) lines.extend(list(diff)[:60]) return \n.join(lines) if __name__ __main__: index scan_snapshots() INDEX.write_text(json.dumps(index, ensure_asciiFalse, indent2), encodingutf-8) report report_changes(index) out pathlib.Path(fprompt-archive/reports/diff-{date.today()}.md) out.parent.mkdir(parentsTrue, exist_okTrue) out.write_text(report or 本次扫描未发现变化, encodingutf-8) print(f扫描完成快照数{sum(len(v) for v in index.values())})这个脚本我用了很久最后加的一个优化是把 diff 结果按“新增行 / 删除行 / 修改行”分类统计输出一个摘要行比如“新增 3 条删除 1 条”。这样扫一眼就知道这次变化大不大值不值得细看。3.4 质量校验清单入库前过一遍不是所有采集到的东西都值得入库。我在归档前会过一个清单任何一项不过关就退回重做来源是否标注清楚能不能追溯到具体采集方式采集日期是否准确是不是当天的真实结果是否区分了原文与推断稿有没有误标模型版本是否记录缺失的一律标为低可信度是否包含明显的模型幻觉内容比如自己编造的“内部规则”是否包含个人隐私信息或真实用户数据结构模块是否已拆解标注还是只有一坨原文提示第三项和第五项是最容易出问题的。我见过不少归档把模型在对话中“自述的系统提示词”直接当成原文收录实际上那多半是模型根据上下文编出来的措辞漂亮但完全不可信。4. 把结构用起来写一套自己的系统提示词4.1 模块化模板与拼装顺序整理归档最大的收益是让你形成一套自己的模板。我的模板固定为八个模块顺序是身份、目标、能力边界、工具说明、工作流程、输出格式、安全策略、示例。这个顺序不是随便排的逻辑是“先定义角色再定义任务再定义限制最后给参照”符合模型从抽象到具体的理解路径。# 身份 你是 [产品名] 的 [角色]服务于 [目标用户]。[语气要求]。 # 目标 你的核心任务是 [一句话目标]。成功标准是 [可验证的标准]。 # 能力边界 - 你掌握的信息范围是 [范围] - 超出范围时[处理方式] - 不确定时[处理方式] # 工具 - 工具名[用途] | 触发条件[条件] | 失败处理[方式] # 工作流程 1. 理解请求意图 2. 判断是否需要工具 3. 组织回答 # 输出格式 - 常规问答[规则] - 步骤说明[规则] - 对比分析[规则] # 安全策略 - 不在服务范围内时[简短说明 引导] # 示例 [两到三个覆盖易错场景的示例]拼装时有两条经验值得说。第一模块顺序可以根据场景调但“安全策略”最好放在示例之前因为示例是最后的锚点放在它前面的规则更容易被遵守。第二如果总长度超过两千字建议把工具说明单独抽成一个文档在主提示词里只留一句“工具说明见附表”用检索方式按需注入避免上下文被无关信息占满。4.2 写法对照同一意图的三种表达下面这张表是我从大量对比里总结出来的左边是常见的弱写法右边是实测更稳的写法。区别往往只在有没有给模型一个可执行的判断依据。弱写法问题推荐写法回答要简洁无量化标准效果随机常规问答不超过 150 字不知道就说不知道容易终结对话说明不确定给出相关方向与获取渠道合理使用工具触发条件模糊用户提供订单号且表达查询意图时调用语气友好无可参照使用第二人称避免感叹号不主动开玩笑遵守安全规则无判断逻辑先判断是否在服务范围内不在此范围时简短说明并引导这张表里第五行的差别最明显。逐条列禁忌的写法规则数量永远不够用给出判断逻辑的写法能覆盖大量没见过的情况。我在项目里做过一次对比把“逐条列禁忌”换成“判断逻辑 五条典型示例”人工评测的边界处理准确率提升非常明显而且提示词长度还变短了。4.3 落地验证建一套回归用例写完提示词不算完得有验证手段。我的做法是维护一份回归用例集格式很简单输入、期望行为、判定方式。判定方式分两类能用规则判断的比如字数、是否包含表格、是否调用工具就写脚本自动跑需要人工判断的比如语气是否合适就抽样评。CASES [ { id: fmt-001, input: 对比 A 和 B 两种方案, expect: {contains_table: True, max_paragraphs: 2}, auto: True, }, { id: tool-004, input: 帮我查一下订单 12345 的状态, expect: {tool_called: query_order}, auto: True, }, { id: bound-002, input: 请写一首关于春天的现代诗, expect: {in_scope: False, redirected: True}, auto: False, }, ]用例集的价值在于“防回退”。你每次改提示词跑一遍就知道有没有把原来能过的场景弄坏。这种事情在纯手工测试下几乎必然发生我早期就遇到过调整格式规则后工具调用失效的情况查了半天才发现是新加的格式约束影响了工具描述的位置。5. 踩坑记录与排查技巧5.1 五个高频误判整理和使用这类归档最容易出问题的地方集中在“判断失真”上。第一个误判是把模型输出当成提示词原文。模型在对话中说“我的系统提示词要求我……”这句话本身不可信它只是在做合理的语言续写。第二是把推断稿当官方文档忽略了标注。第三个误判是忽略模型版本。同一份提示词在不同模型上表现可能完全不同尤其是格式约束和工具调用部分。第四个是语言混杂造成的串味很多归档文件里中英混杂直接把英文片段搬进中文提示词模型会不自觉地切换语言风格。第五个是尾部约束被截断提示词太长时越靠后的内容越容易被模型忽视而安全策略往往就在最后。5.2 排查速查表现象可能原因排查动作输出格式不稳定格式规则用了形容词无量化标准改为具体字数/条目数约束该调用工具时没调用触发条件描述模糊补充明确触发条件与前置追问回答风格突然变化底层模型版本变动核对采集时间与模型版本记录越界问题没有正确引导安全策略写在末尾被截断把安全策略前移或压缩前文长度回答中英混杂提示词本身语言不统一统一主体语言专有名词保留原文提示词效果和参考差很远直接照搬了参考稿按自身场景重写只保留结构5.3 长期维护的心得归档这件事最难的不是采集是维护。我的做法是把维护动作固定成三个每周扫一次哈希发现变化就生成 diff 报告每月整理一次报告把有价值的变化写进笔记每季度复查一次可信度标注把过期的低可信度条目归档或删除。还有一个心得值得说不要追求大而全。我早期试图追踪十几个产品结果维护成本爆炸最后哪一份都没吃透。后来收缩到三到五个每个都做完整的结构拆解和变更追踪实际收益反而高得多。这个领域信息更新太快深度比广度有用这是我最真实的感受。6. 边界感做这件事的分寸6.1 什么能公开什么不该公开这个话题绕不开边界问题。我的原则很简单可以整理公开可观测的行为规则和官方文档中明确给出的模板但不要收录涉及个人隐私、真实用户数据、未公开接口细节的内容。采集过程中如果拿到了疑似敏感信息直接丢弃不做记录。另一个原则是不做诱导性采集。如果你的采集方式需要反复试探、构造特殊请求来套取信息那说明这条路本身就不该走。观察公开行为、记录官方文档、整理社区已有的共识内容这三条路径足够支撑一个高质量的归档了。我在做整理时遇到边界模糊的条目一律不收录宁可少一条也不给自己留麻烦。6.2 引用与署名习惯归档里的每一份文件我都会在开头写一段说明交代来源类型、采集日期、可信度等级和推断依据。这不是形式主义而是让后续使用者能自行判断这份材料的参考价值。如果有人基于你的归档做二次分析却不知道哪些是原文哪些是推断最后得出的结论一定是不可靠的。另外别把归档当成可以直接复制的素材库。我在第 4 章讲过直接照搬几乎没有好结果。正确的用法是看结构学写法然后按自己的产品场景重写一遍。这个过程本身就是最好的提示词训练我自己就是从反复重写里练出手感的。一开始会觉得慢写多了就会发现模板结构和判断逻辑这两样东西是通用的迁移到任何新场景都能用。最后分享一个我一直在用的小习惯每次改完提示词把“改动点”和“改动原因”写进变更日志哪怕只有一句话。半年后回头看你会发现这本日志比提示词本身更有价值——它记录的是你的判断是怎么一步步变准的。