首页 / 资讯中心 / 文章详情

System、User、Assistant三角色分离:大模型提示词可控性实战指南

System、User、Assistant三角色分离:大模型提示词可控性实战指南 ★ FEATURED ARTICLE
很多人调大模型提示词上来就噼里啪啦写一大段 User 消息模型效果不稳定一会儿好用一会儿不好用。直到我把 System、User、Assistant 三个角色彻底分开用之后才感觉提示词这东西终于“可控”了。这仨角色不是 API 里随便填的字段它们各自管着一层完全不同的逻辑。System 负责定规矩User 负责给任务Assistant 负责承接历史。理解这三者的边界比背一万个提示词模板都管用。这篇就把我的实际操作经验、踩过的坑、以及一些可以直接抄走的写法一次性讲清楚。1. 三个角色的本质分工搞懂这个就成功了一半先说底层逻辑。大模型聊天接口里的消息列表本质上就是一个“多角色剧本”。模型看到的是带有不同角色的历史对话它根据这些角色来推断自己该以什么身份、什么规则、什么上下文来生成回复。这就是角色机制的底层运作方式。1.1 System全局规则的制定者System 消息是整场对话的最高优先级指令。它设置在对话的最开头用来描述模型扮演的身份、必须遵守的规则、输出的格式要求、不能触碰的边界。你可以把它理解成“给演员的剧本总纲”演员模型后面再怎么临场发挥也不能跳出总纲的约束。在我实际测试过的大量案例里System 消息最关键的并不是“写得多”而是“写得多清楚”。同样一句“你是客服”跟一句“你是电商平台的售后客服你的回复必须包含订单号引用只能使用简体中文每次回答不超过 80 字如果遇到退款问题必须引导用户前往售后页面”效果差距是肉眼可见的。System 还有一个容易被忽略的特性它的优先级高于 User 和 Assistant 消息。当对话进行到多轮以后模型可能会逐渐“忘掉”System 里的要求特别是在长上下文场景下。这时候需要策略性的在后续消息中强化规则或者把关键约束写进每轮 User 消息里。这点在后面的实操章节会展开说。1.2 User每一轮的真实输入User 消息代表用户的输入也就是我们每一次真正丢给模型的具体请求。区别于 System 的“立法”角色User 是“执法”角色它是当前要完成的任务本身。好的 User 消息往往包含三个要素明确的任务指令、必要的背景信息、期望的输出形式。比如“用表格列出这三种方案的性价比对比包含维护成本、上手难度、稳定性三项指标”就比“帮我比较一下这三个方案”要好得多。但很多人在 User 消息上最容易犯的错是恨不得把所有规则全塞进去。我见过有同学在 User 里写了 800 字的限制条件结果模型为了满足 User 里的十条要求顾此失彼每条都完成得稀碎。正确做法是把那些全局的、长期有效的规则放进 SystemUser 只负责“这一轮我需要什么”这个单一目标。1.3 Assistant既是答案也是老师的角色Assistant 消息最容易被误解很多人以为它只是模型的回复。实际上Assistant 消息在两个地方起着不可替代的作用。第一在多轮对话中它是模型历史输出的载体。模型会参考自己之前说过的话来维持一致性。如果你在代码里手动拼接对话历史一定要把模型的输出存成 Assistant 消息下次连同历史一起传回去。第二在提示词工程里最妙的一个用法——可以“伪造”Assistant 消息来给模型做示范。什么意思就是在问题后面不写模型该回复的完整内容而是写半段 Assistant 消息让模型接着你的半段话说下去。这个技巧在控制回复节奏、指定回复开头、或者做思维链引导的时候特别有效。举个最简单的例子你想让模型按“先说结论再列依据最后给建议”的结构回复。你可以在 User 消息抛出问题后直接在 Assistant 消息里写“结论”或者“先说结论”模型看到你起头了就会顺着这个格式往下写。这比在 System 里反复强调“你要先说结论”有效得多。提示Assistant 消息不只是“记录”它是一个你可以主动利用的“前向引导工具”。把你想让模型说的话的前半句放到这里。2. 为什么要区分角色不区分会怎么样有人可能觉得我把所有要求一起写进 User 消息不就行了吗我测试过短期看好像也行但一旦对话变长、任务变复杂不区分角色带来的问题就会集中爆发。2.1 不区分角色的四个典型症状第一个症状是规则漂移。System 和 User 混在一起时模型对“哪些是长期约束、哪些是本次任务”的判断会模糊。第三轮还能遵守到了第八轮就开始放飞自我因为长期的规则被大量单轮任务信息稀释了。第二个症状是上下文污染。每一轮 User 消息都重复粘贴规则看起来是“强化记忆”实际是让模型的注意力被重复文本绑架。上下文窗口里全是重复规则留给真正对话信息的空间就少了。关键信息反而被挤掉。第三个症状是输出不稳定。同样的输入可能这次给表格、下次给段落、再下次给列表。因为模型的每个生成时刻都在重新理解“用户到底要我干嘛”没有 System 这个固定锚点的情况下每次理解都可能微调。第四个症状是最隐蔽的——安全失效。如果内容过滤规则和真实请求混在同一个 User 消息里模型更容易被后续的“紧急请求”带偏。而独立的 System 约束相当于一道独立的防线被攻破的概率低得多。2.2 三个角色本质是三层边界我习惯把三个角色理解成三层嵌套的边界System 是“墙”框定整个对话的可行区域无论用户说什么都不能越出这堵墙。User 是“任务书”在墙内指定具体要做什么。Assistant 是“脚印”前一步的输出直接影响下一步的去向。搭好了这三层边界模型的每一次生成就不再是“从零开始猜”而是沿着你铺好的轨道走。这也是为什么同样的模型、同样的参数量有人调出来的效果像换了个模型。2.3 一个对照实验告诉你差距有多大我做过一个很典型的测试模拟客服对话要求模型最后一律附加“祝您生活愉快”。A 组把这条要求放在 System 里B 组把这条要求加在每一轮 User 消息的末尾。跑了 20 轮对话后A 组有 19 轮都正确附加了B 组在第七轮之后就开始漏掉。原因不复杂B 组的 User 消息每轮内容都不一样规则容易被新信息淹没A 组的 System 是稳定不变的模型在后端处理时System 始终占据一个固定的高注意力位置。所以我的基础建议是凡是“全局性”“长期性”“稳定不变”的规则一律放 System凡是“这一轮”“临时性”“针对性强”的要求一律放 User凡是“你要控制的输出方向”的引导一律放 Assistant。3. 实操我日常用的几种高价值组合模式下面这些组合是我在实际项目里验证过稳定性、效果都不错的核心模式。每个模式我都附了简化示例你可以直接参考改造。3.1 模式一System 定框架 User 给素材这个模式适合总结、翻译、信息抽取这类场景。System 负责把所有输出规则给定死User 只负责丢进来新的原始材料。我记得有一次做一个多语言客服工单分类System 里明确规定了分类标签集合只有“产品问题、物流问题、退款问题、其他”四类、置信度输出格式JSON 对象包含 label 和 confidence、以及语言要求无论用户用什么语言标签一律用中文输出。User 消息则每次只传一条新工单原文。效果非常稳定无论用户消息怎么千奇百怪输出永远是规范的 JSON。这就是 System 定框架的力量——它负责让输出进入一条“管道”User 只管往管道里倒东西。3.2 模式二多轮角色扮演与长对话一致性做角色扮演类应用比如虚拟助手、游戏 NPC、情感陪伴时最容易出现的问题就是角色“崩了”。模型前几轮还很高冷聊久了突然变热情或者反过来。这时候 System 是最关键的。它需要写得足够具体包括角色的性格标签、语言习惯、绝对不能做的事、以及面对不同类型话题时的响应倾向。而 User 每次输入的时候不该让用户直接面对一个空白的输入框——在 System 里预先定义场景在 User 里拼接用户的具体输入。Assistant 在这个模式下的作用就是“记忆”。你必须把每一轮模型的回复都原样存成 Assistant 消息并且在后续请求中完整携带。一旦丢掉了 Assistant 历史角色会瞬间失忆之前的人设全白搭。3.3 模式三Assistant 半句引导法我的压箱底技巧这是最实用也最容易被忽略的一招。具体操作是构造请求时在 Assistant 消息里预先填上半句话让模型顺着往下写。我举一个实际场景。之前做代码审查助手我希望模型先输出“风险等级”再输出“问题列表”。但实测下来模型有时候先分析代码逻辑有时候直接给修改建议格式不统一。后来我在 Assistant 消息里写风险等级高/中/低结论如下模型接下去就会乖乖先输出风险等级然后才展开。因为语言模型本质上在做“接龙”看到已经有头了它会顺着惯性补全后半段。这一招在控制输出结构上比任何 System 里的“你必须先输出等级”都管用。3.4 模式四System 里做“少样本示例”少样本提示Few-shot很多人会在 User 里给示例其实把示例放进 System 效果更好。特别是分类、改写、格式化这类任务把几个“输入→输出”的成对示例放进 System模型会在整个会话里持续参考这个格式。我常用的一种写法是在 System 里放一个“输出示例”区用明确的标记区分示例和实际任务。比如输出格式必须是 JSON {意图: 退款, 紧急程度: 高}然后在 User 里丢进新输入。这样模型每次生成时都会下意识地参照这个格式而且因为它在 System 里是稳定不变的不会被多轮对话冲淡。3.5 模式五多角色协作的复杂任务拆解遇到复杂任务时我会在 System 里设计一个“多角色协作”的框架。比如做一个技术方案分析助手System 里定义了两个角色视角一个叫“架构师”偏重技术合理性和可扩展性一个叫“项目经理”偏重工期、成本和风险。User 提出需求后模型会自行切换视角给出综合结论。这个其实利用了 System 里对“角色输出顺序”的控制。我在 System 里写了三段第一段定义全局背景第二段定义架构师视角的输出规则第三段定义项目经理视角的输出规则并强制要求先输出架构师视角再输出项目经理视角。实测下来生成的内容结构和逻辑层次明显优于单视角一锅炖的写法。4. 角色信息的优先级与冲突解决规则三个角色放在一起时如果它们之间发生了矛盾谁说了算这个问题看起来基础但在复杂应用里会直接影响调试方向。4.1 角色优先级的经验法则按我大量测试的经验冲突时的大致优先级是System Assistant最近一轮 User直接指令 历史对话信息。注意这是经验法则不是数学公式不同模型会略有差异但总体趋势是这样。为什么会这样排序System 在每轮处理时都会被模型重新读取它带有“元指令”属性本身就被赋予了更高的遵循权重。Assistant 最近一轮输出是紧接着要续写的上下文模型具有很强的近因偏好。User 的直接指令会因为穿插在历史里而被削弱一部分。这条法则的实操价值在于当你发现模型的输出不听话时不要只盯着 User 消息改。先想想是不是 System 里有反向指令在捣乱或者是不是 Assistant 历史里埋了雷。4.2 冲突场景的实际处理方案场景一System 说“回复要简洁不超过 50 字”但 User 说“请详细分析每个步骤”。这是我见过最多的冲突。处理方案不是删掉其中一个而是在 System 里补充一条“如果用户明确要求详细输出可突破简洁限制但仍保持结构化”。给规则留优先级出口。场景二System 里禁止讨论某话题但用户在后续对话里执意追问。此时模型有很大概率会拒绝回答。但如果你在 System 里只写了“禁止讨论某话题”却没写“如遇此类问题应如何回应”模型可能会直接僵硬地回复“我不能回答”。这个体验很差。正确做法是给一个“接线话术”——“关于这个话题我不太了解但我们可以聊聊别的”。也就是给拒绝行为也要设计出口。场景三Assistant 历史信息与 System 规则矛盾。比如之前模型不小心回答了一个违规问题这段 Assistant 历史会被记入上下文。后续对话中模型可能会延续之前的错误。处理方案是清空相关 Assistant 历史或显式地在 User 消息中告诉模型“忽略此前不合适的回答重新按照系统规则执行”。注意当模型输出明显异常时优先排查最近几轮 Assistant 回了什么。模型会“继承”自己上一轮的风格和内容这是很普遍的近因效应。4.3 我自己总结的三条“定海神针”写法其一System 里写规则时用“必须/禁止/允许”这种强约束词不要用“尽量/通常/可能”这类模糊词。模型对模糊词的权重判断远低于强约束词。其二当存在多条 System 规则时给规则编号。我实测下来编号能显著提升规则的遵循率。因为编号给了模型一个显式的优先级参考系模型在处理多约束时更倾向于按编号顺序逐一满足。其三所有负面约束禁止怎么做都要配一个正面替代应该怎么做。只告诉模型“不要做什么”它往往不知道怎么“正确地做”但给了替代方案它的行为空间就被收窄了。5. 实际调试中的坑与排查技巧最后这部分写一写我在真实项目里遇到过的问题以及我现在排查异常的固定打法。5.1 坑一System 失效但不知道为什么表现是 System 里的规则前期有效后期失效了。最典型的原因是对话轮次过多上下文窗口接近临界点。模型在处理长上下文时对靠前的 System 文本注意力会自然衰减。解法有两类。一类是压缩历史把旧的对话做摘要替换掉原始多轮消息。摘要后传给模型的对话长度短了System 占比自然高了。另一类是“双保险”在后续每一轮 User 消息前用一句极短的提醒重复核心规则比如“记住输出必须为 JSON 格式”。实测对长对话稳定性很有帮助。5.2 坑二Assistant 里塞了不该塞的东西很多人会把模型的原始输出直接存成 Assistant这没错。但有个隐蔽问题如果模型输出包含了类似“我上一条说得不对”这样的含糊内容这些内容也会成为后续的上下文模型可能会陷入自我怀疑越说越乱。解法是如果你想要更可控的输出可以不完全依赖模型的自我修正。在创建 Assistant 历史时只保留经过清洗的最终回复。在需要拼接代码或固定格式的场景里甚至可以把模型的回复做结构化抽取后再作为 Assistant 内容存回历史。5.3 坑三User 消息里混入了前一轮的 Assistant 内容有些框架的会话封装逻辑不严谨可能会导致角色标记错乱。我排查过某项目中一个诡异问题模型总是重复上一轮说的话。后来发现原因是封装层把上一轮的 Assistant 回复又作为 User 消息的一部分发出了模型感觉自己“被复述”就下意识地继续重复原文。排查方式很简单打印出每次请求的实际消息数组逐条核验 role 是否正确交替。这是一条成本极低的检查习惯建议所有做 LLM 应用开发的人都养成。5.4 我的固定排查四步法当我发现某个对话效果突然变差时我按以下顺序检查检查 System 消息是否有逻辑冲突尤其是新加的规则是否和旧规则互斥。检查最近三轮 Assistant 消息看模型是否已经进入了某个错误风格。检查 User 消息里是否有多余的历史信息、过期的格式要求。简化测试把 System 缩到只有一条核心规则把 User 缩到一句话看问题是否复现。如果不复现了说明是上下文里的某段内容在捣乱再逐步加回定位。这套方法帮我解决过大量“看似玄学”的问题其实背后都是角色信息的管理混乱。最后分享一个长期主义的小建议Prompt 工程里三个角色用得好不好本质上是“信息架构”问题。你放在 System 里的每条规则都会变成模型心跳的一部分你放在 User 里的每个请求都必须足够聚焦你放在 Assistant 里的每段历史都要承担“引导下一步”的责任。想清楚这三件事你手里的模型就真的变成你的执行力了。
阅读完成 · 觉得有帮助?
咨询建站