跳到主要内容

动态系统提示词组装:请求时可组合的 AI 行为

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数团队一开始都用一个单一的、庞大的系统提示词。在演示时效果不错。然后产品不断增长:你添加了付费用户层级、企业客户的合规模式、模型可以调用的新工具,以及增长团队想要 A/B 测试的功能开关实验。所有这些都被塞进同一个提示词里。六个月后,你有了 4000 个词的指令,没有人能完全理解,编辑某个部分时行为会不可预测地改变,而调试过程不过是"改点什么看看会发生什么"。

大多数团队会转向可组合的、动态组装的系统提示词——在请求时从模块化组件构建提示词,而不是维护一个静态文本文件。这是一个合理的架构直觉,但实现的复杂度比看起来要大得多。可组合提示词引入了一类静态提示词根本不存在的新型故障模式。

动态组装的真正含义

动态组装的系统提示词是指:最终交给模型的文本在请求时由一组组件计算生成,而不是存储在代码库某处的固定字符串。

最简单的版本是字符串插值:将用户姓名或账户层级插入模板。这是最基本的要求。真正的可组合提示词组装意味着根据运行时状态选择、组合和排序离散的指令块。组装过程的典型输入包括:

  • 用户角色和权限 — 免费层级用户获得受限的工具集;企业管理员获得附有额外约束的更高权限
  • 功能开关 — 实验可能换入另一种人设,或启用尚未正式发布的功能
  • 任务上下文 — 编程助手提示词和客服提示词截然不同;同一产品可能同时服务两种流程
  • 检索到的上下文 — RAG 结果、用户历史记录或工具输出,注入到提示词的特定插槽中

组装层位于应用逻辑和模型调用之间。它的职责是接收当前请求状态并生成一个有效、连贯的提示词。"连贯"这个限定词正是大多数团队投入不足的地方。

提示词组件库的架构

将提示词组件视为一等制品会改变你的构建和维护方式。组件库不是一个 .txt 文件夹——它是一个带版本控制的、有定义契约的类型化块集合。

每个组件都应有明确的语义角色。一个实用的分类方法包含六个类别:角色设定(模型在此上下文中是谁)、指令(应该做什么)、上下文注入(需要了解什么)、输出结构(如何格式化响应)、约束(不得做什么)和示例支持(期望行为的演示)。大多数组件都能清晰地归入其中一类。

版本控制很重要,因为提示词组件是依赖项。如果你更新了一个共享的"语气"组件,你需要知道哪些组装提示词使用了它,并在发布前全部测试。把提示词组件当作字符串处理的团队,最终会面临与代码库中无版本控制的共享可变状态同样的依赖追踪问题。

缓存是将组件保持为结构化对象而非字符串的另一个原因。提示词缓存——模型提供商为静态前缀存储中间计算状态——在实践中可降低 50–90% 的成本,但它要求提示词中可缓存的部分既是静态的,又位于组装的早期位置。组件库使得自然地分离高频静态组件(角色定义、持久工具描述)和低频动态组件(用户特定上下文、会话状态)成为可能。你将前者放在前面,标记为可缓存,让后者变化而不使缓存前缀失效。

组件冲突时的故障模式

这是最让团队头疼的故障模式:来自不同组件的矛盾指令会被模型静默地解决,而不会触发错误。

当模型从一个组件收到"在采取任何行动之前始终要求澄清",又从另一个组件收到"立即响应用户请求,不要中断"时,它不会抛出异常。它会根据训练预测最可能意图的内容来推断一个解决方案,而且这种推断足够一致,你可能永远不会注意到——直到你在某个特定上下文中观察行为时才会发现冲突。

这造成了一类与传统软件中任何问题都不同的 bug:行为错误、前后一致、可因果追溯到输入中的冲突,却不产生任何错误信号。在一项对大型生产 Agentic 系统的研究中,研究人员识别出提示词子部分之间的 21 种干扰模式,其中 4 个是直接矛盾——一条指令明确否定了另一条。在推理时,没有任何一个产生了可观察到的错误。

根本原因通常是组织性的。通用提示词子系统倾向于做出普遍性声明——"始终做 X"——而特定工作流子系统则添加例外和覆盖。当这些子系统由不同团队在不同时间线上编写,且没有共享的指令审查流程时,冲突就会悄然积累。

还有一个指令层级问题。直觉上,系统提示词指令应该优先于用户指令,用户指令应该优先于检索文档中的内容。但实际上,模型并不能可靠地遵守这一层级。衡量"优先级遵守率"——即在冲突出现时模型正确服从更高优先级指令的比例——的研究发现,某些模型的这一比率低至 14%,最佳模型也仅为 47%。如果你的提示词组装依赖于后面的组件覆盖前面的组件,你可能依赖的是比你想象中更不可靠的行为。

组装面越大,提示词注入面越大

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates