Context Engineering 实战 02|System Prompt 是架构决策,不是写说明书

Context Engineering 实战 02|System Prompt 是架构决策,不是写说明书

Config Risk Assessment 系统上线第一周,指令遵循率 67%。System prompt 4000 token,把风险评估的所有规则、所有场景定义、所有输出格式都写在一起------一份完整的"操作手册"。

团队做的第一件事:排查模型具体在哪些指令上不遵循。

复制代码
指令遵循情况分析(200 条配置变更评估):

指令位置              遵循率
─────────           ──────
前 500 token 的指令    89%  ← 系统身份、输出格式
500-2000 token        71%  ← 高风险规则
2000-3500 token       48%  ← 中风险规则、边界条件
最后 500 token         81%  ← 安全兜底提示

中间 1500 token 的遵循率只有 48%------接近抛硬币。而这 1500 token 恰好放着最细致的评估规则:"数值类配置变化超过 50% 视为高风险""开关类配置的核心功能关闭标记高风险"。

注意力 U 形曲线:开头高、结尾高、中间凹。4000 token 的 prompt 里,中段是注意力凹陷区------模型"看到了"这些规则,但分配的注意力权重不够,执行就打折。

这不是措辞问题。就算把中段规则的用词改得再精确,只要它还在这个物理位置,遵循率就上不去。


第一次错误的修复方向

看到中间规则遵循率低,团队的第一反应是"强调"。在中间规则前面加上"以下规则非常重要,必须严格遵循:"

没用。遵循率从 48% 到 52%------模型确实稍微多注意了一点,但加了强调语后,其他规则的遵循率反而降了 3 个百分点。总体效果:67% → 66%。

复制代码
修复尝试              中间段遵循率    总体遵循率
──────              ──────────    ─────────
原始                  48%           67%
加"非常重要"强调语      52%           66%  ← 此消彼长

注意力是零和的。给中间段加权,就从其他地方抢了注意力。这不是优化措辞能解决的------是信息排布的结构性问题。

需要换个思路:不是把 4000 token 的 prompt 写得更好,而是把 4000 token 砍成 1500 token,把不需要每次都出现的内容移走。


分层架构:Base / Task / Guard

把 system prompt 拆成三层,像拆软件架构一样------每层职责单一,变化频率不同:

复制代码
┌─────────────────────────────────────┐
│         Guard Layer                 │ ← 安全红线,放 prompt 末尾
│   "不确定时标注需人工复核"             │    50-100 tokens,很少变化
│   "不输出原始配置值"                  │
├─────────────────────────────────────┤
│         Task Layer                  │ ← 当前任务的具体规则
│   按配置类型动态注入                  │    200-500 tokens,每次不同
│   只注入跟当前输入相关的规则           │
├─────────────────────────────────────┤
│         Base Layer                  │ ← 系统身份 + 输出格式
│   "你是配置风险评估系统"              │    200-300 tokens,部署时固定
│   "输出:风险等级 + 理由 + 建议"      │
└─────────────────────────────────────┘
层级 放什么 不放什么 变化频率 预算
Base 系统身份、输出格式、核心流程定义 具体评估规则、示例 部署时固定 200-300 tokens
Task 跟当前输入类型相关的规则 所有其他类型的规则 每次请求不同 200-500 tokens
Guard 安全红线、fallback 策略 功能性规则 很少变化 50-100 tokens

为什么 Guard 放在最后?利用 U 形曲线------prompt 末尾的注意力权重是第二高的。安全红线是"不管什么情况都不能违反"的约束,放在末尾比放在中间更有效。

为什么 Task Layer 在中间?因为 Task Layer 的内容跟当前输入高度相关。就算中间段的注意力稍低,模型在处理当前输入时自然会去参考跟输入类型匹配的规则------相关性弥补了位置劣势。


重构实录:四步从 4000 到 1200

Step 1:Base Layer --- 从 800 token 到 120 token

原来的 prompt 开头:

复制代码
你是一个专业的配置变更风险评估系统。配置变更风险评估是运维安全的重要
环节。你需要分析每一条配置变更记录,评估其风险等级。风险等级分为高、
中、低三级。高风险是指可能导致线上事故或严重性能下降的变更。中风险
是指可能影响部分功能但不会导致全局事故的变更。低风险是指常规变更,
不会影响系统稳定性。你需要综合考虑变更的幅度、影响范围、变更时间、
变更人历史记录等因素来做出判断...

800 token 说了一大堆。模型需要从中提取的有效信息:我是什么系统、输入是什么、输出是什么。

重构后:

复制代码
你是配置变更风险评估系统。
输入:一条配置变更记录(含变更前后值、配置项名称、变更人)。
输出 JSON:{"risk": "高|中|低", "reason": "一句话理由", "action": "建议操作"}

三行。120 token。信息密度提升了 6 倍。模型不需要知道"配置变更风险评估的重要性"------它只需要知道输入什么、输出什么。

Step 2:Task Layer --- 35 条规则变成 5-8 条动态规则

原来写在 prompt 里的 35 条规则:

复制代码
- 数值类配置变化幅度超过 50% 标记为高风险
- 数值类配置变化幅度在 20%-50% 之间标记为中风险
- 生产环境数值归零标记为高风险
- 开关类核心功能关闭标记为高风险
- 开关类灰度开关变更标记为中风险
- 文本类配置 URL 变更到外部域名标记为高风险
  ... 还有 29 条

35 条规则约 2400 token。但评估一条"数值类配置变更"时,文本类和开关类的规则完全不需要出现------它们只是噪声。

移到规则库,运行时按配置类型注入:

python 复制代码
RULE_STORE = {
    "数值类": [
        "变化幅度超过 50% → 高风险",
        "变化幅度 20%-50% → 中风险",
        "生产环境数值归零 → 高风险",
        "重试次数超过 10 → 需人工确认",
        # ... 共 12 条
    ],
    "开关类": [...],  # 8 条
    "文本类": [...],  # 9 条
    "通用": [...],    # 6 条(所有类型都适用)
}

def get_task_rules(config_change):
    config_type = classify_config_type(config_change)
    specific = RULE_STORE.get(config_type, [])
    general = RULE_STORE["通用"]
    return specific + general  # 通常 5-8 条

评估一条数值类配置变更时,Task Layer 只注入数值类的 12 条 + 通用的 6 条中最相关的几条 ≈ 8 条规则,约 200 token。比 35 条全注入省了 90% 的 token。

Step 3:Guard Layer --- 提取安全约束

原来散落在 prompt 各处的安全约束:

复制代码
第 15 行:"如果不确定,不要强行给出结论"
第 28 行:"不要在输出中暴露原始配置值"
第 33 行:"涉及安全密钥的变更一律标记高风险"

统一提取到 Guard Layer,放在 prompt 末尾:

复制代码
安全约束(必须遵守):
- 不确定时标注"需人工复核",不给确定结论
- 不输出原始配置值(脱敏处理)
- 涉及密钥/凭证的变更一律高风险

60 token。三条红线。放在 prompt 最后------U 形曲线的右端高注意力区。

Step 4:动态拼装

python 复制代码
def build_prompt(config_change):
    base = BASE_LAYER                           # 固定 120 tokens
    rules = get_task_rules(config_change)        # 动态 200-400 tokens
    task = f"当前评估规则:\n" + "\n".join(f"- {r}" for r in rules)
    guard = GUARD_LAYER                          # 固定 60 tokens
    return f"{base}\n\n{task}\n\n{guard}"

重构结果:

复制代码
指标               V1(全量 prompt)    V2(分层 prompt)
──────            ──────────────     ──────────────
总 prompt 长度      4000 tokens        380-580 tokens(动态)
规则数              全部 35 条          5-8 条(相关的)
指令遵循率          67%                82%
格式正确率          73%                94%
中间段规则遵循率     48%                79%

格式正确率从 73% 到 94%------因为 Base Layer 里的 JSON 格式定义现在稳稳待在开头高注意力区,不再被 2400 token 的规则挤到中段。

中间段遵循率从 48% 到 79%------因为中间现在只有 5-8 条相关规则,每条分到的注意力权重是之前的 4-7 倍。


位置策略:放哪比写什么更重要

重构过程中发现了一个反直觉的现象。

Guard Layer 里有一条:"不确定时标注为需人工复核"。这条规则原来放在 prompt 第 15 行(大约第 400 token 的位置),遵循率 61%。移到 prompt 最后(Guard Layer 末尾),遵循率到 87%。

同一句话,同样的措辞,只是换了位置,遵循率差 26 个百分点。

这验证了一个设计原则:在 system prompt 里,位置策略比内容策略重要。你应该先决定"什么信息放哪",再去考虑"怎么写这条信息"。

几个经验法则:

复制代码
位置                 适合放什么                  原因
────                ────────                 ────
prompt 开头          系统身份、输出格式            注意力最高区
prompt 中段          动态注入的规则               跟输入相关性高可弥补位置劣势
prompt 末尾          安全红线、硬约束              U 形曲线右端的高注意力区
紧邻用户输入的位置     对当前输入的特殊处理指令       距离近=注意力高

负面约束比正面指令更有效。 "不要在不确定时给出确定结论"比"在不确定时表示不确定"更好。原因跟注意力无关------是负面约束的边界更清晰。模型更容易理解"什么不能做",因为违反条件是具体的;"应该做什么"的执行标准模糊,模型容易用自己的理解替代。


每层独立测试:分层的工程价值

分层架构的另一个好处:每层可以独立变更和测试。

Config Risk 团队后来新增了"IP 地址类配置"的规则。如果是全量 prompt,加 5 条新规则意味着重跑全部 eval------因为你不知道加了新内容后对已有规则的遵循率有没有影响。

分层后,只需要:

  1. 在 RULE_STORE 里加一个 "IP地址类" 条目(5 条规则)

  2. 写 20 条 IP 地址类配置变更的测试用例

  3. 只跑这 20 条 eval + 抽检其他类型各 10 条

    全量 prompt 的回归测试成本:200 条 eval × 每条 0.03 = 6.0
    分层 prompt 的回归测试成本:40 条 eval × 每条 0.03 = 1.2

    更关键的是时间:
    全量 prompt 跑完 eval 需要 25 分钟
    分层 prompt 只需要 5 分钟

改一条规则从"25 分钟全量回归"变成"5 分钟定向回归"。迭代速度提升了 5 倍。

这跟软件工程的道理一样:单体应用改一个功能要全量回归,微服务架构改一个服务只需要测那个服务 + 接口兼容性。System prompt 的分层就是 prompt 领域的"微服务化"。


什么时候不需要分层

如果你的 system prompt 短于 800 token,不需要分层。

800 token 以内的 prompt,注意力衰减不明显------开头到结尾的遵循率差距通常在 5% 以内。分层反而增加了工程复杂度。

一旦超过 1500 token,或者你发现某些指令"时灵时不灵"------检查一下这些指令在 prompt 里的位置。如果它们在中段,大概率是注意力凹陷的问题,该考虑分层了。

复制代码
prompt 长度            分层必要性
──────────           ──────────
< 800 tokens          不需要,一个文本文件就够
800-1500 tokens       可选,看遵循率是否波动
> 1500 tokens         强烈建议分层
> 3000 tokens         不分层几乎一定有注意力问题

System Prompt 不是告诉模型"你是谁",是定义系统"哪些信息在什么条件下出现"。把它当架构图设计,不要当说明书写。

相关推荐
薛定猫AI1 小时前
【深度解析】Memo 2.5 Pro:面向长程 Agent 工作流的 MoE 大模型架构与实战接入
架构
sinat_255487811 小时前
数组·学习笔记
java·javascript·笔记
江离w1 小时前
codex等vibe coding初始化后端项目指令
java
Paxon Zhang1 小时前
JavaEE 初阶大师之路之*线程,多线程编程,Thread类,变量捕获,中断线程* 一文全部搞懂!!
java·java-ee
逻辑驱动的ken1 小时前
Java高频面试考点场景题16
java·开发语言·面试·职场和发展·求职招聘
DukeMr.Lee2 小时前
有声书实现
java·开发语言
SamDeepThinking2 小时前
秒杀系统的幂等,只做一层Redis判重远远不够
java·后端·架构
csdn2015_2 小时前
lambdaQuery 加 or
java·linux·服务器
Ribou2 小时前
Kubernetes v1.35.2 基于 Cilium Gateway API 的服务访问架构
架构·kubernetes·gateway