跳到主要内容
一条4027词的system prompt,拆了三刀

一条4027词的system prompt,拆了三刀

老墨
老墨

· 阅读约 6 分钟

这条system prompt改到第七版的时候,我数了一下字数:4027个词。它的问题不在长,在于三个职责一直挤在同一段话里互相踩脚。旧稿的节选是这样的:

你是一个全能型客户支持agent。请仔细判断用户的意图,确定属于计费、退款、技术故障、其他中的哪一类。请用专业、礼貌、温暖的语气回复用户,企业客户请务必非常仔细地处理。回复的末尾附上工单编号。

四个句子,三件事。第一句是路由,第二句是语气,第三句是格式化。模型每生成一句话,都得同时对着这三份说明书干活——这比让它一心二用还过分。我就想干一件事:把这三样东西,一刀一刀地劈开。

先拆路由。

旧稿第一句:“请仔细判断用户的意图,确定属于计费、退款、技术故障、其他中的哪一类。”

问题出在【仔细】这两个字上。仔细是态度,不是标准。模型不会因为你让它仔细就变得更仔细,它只会更努力地猜,然后更自信地猜错。后面那个【意图】也一样——意图是个筐,模型根本没有“意图”这个东西,它手上只有文本里的线索。

V2我写成锚点词表:

用用户的原始话术做关键词匹配:包含“扣款”“多收”“账单”→计费;包含“退款”“退货”→退款;包含“打不开”“报错”→技术故障;未命中→其他。

跑了一轮测试就发现不对。用户不说“扣款”,他们说“为什么刷了我两笔钱”。词表外的说法全漏进“其他”,等于路由白拆。

V3才想到要加兜底分支:

先查锚点词表,命中即入对应队列。未命中时不要发散猜测,直接标OTHER_UNSURE,原样转人工队列。

词表不是用来覆盖所有说法的,是用来接住最稳的那部分。接不住的不硬接,这比让模型自由发挥安全。

第二天才动语气段,因为懒。旧稿里那六百字的语气指南,写的时候还挺得意,回头看全是形容词:专业、礼貌、温暖、耐心、体贴。三个客户群体,三段话,形容词长得一模一样。模型看完大概率分不清谁是谁,最后每个客户都收到同一碗温吞水。

其中有一句是这样的:“企业客户请务必非常仔细地处理”——【非常仔细】是个空壳,它没告诉模型“仔细”长什么样。

于是把语气段整个换掉,形容词全删,换成可观察的动作:

企业客户:称呼用“您”;道歉必须包含完整条款引用;不主动提供补偿,只说明流程。 普通客户:称呼用“你”;道歉后必须跟一条可执行的补救动作。

语气从“感觉”变成“清单”,模型才知道该干什么。这三个客户群本来就在不同的状态下,分开写,别让模型自己判断“该用哪种语气”——判断这一步本身就是它最容易飘的地方。

格式化是第三天下午拆的。旧稿那句“回复的末尾附上工单编号”,看上去人畜无害,但【末尾】不是位置。模型有三种理解:编号放在感谢语前面、后面、或者插进签名中间。三种我都见过。

新稿用分隔符锁死:

回复分三段,段间用---隔开。第一段确认问题,第二段解决步骤,第三段第一行写工单编号,其余不写。

“末尾”改成“第三段第一行”,格式从模糊状态变成确定性结构。这一步不交给模型,因为它在这上面从来没有创造过价值,只会添乱。

拆到第三处的时候,我想起上个月底Dimitris Kyrkos在dev.to上写的那篇,说单体agent在同一推理过程里处理路由、任务执行和格式化,任何微小的漂移都没法在到达用户之前被隔离。我一开始以为他说的是架构层的三个模块,拆完这三句才反应过来——在prompt层面,路由段、语气段、格式段,就是他那三件事的微缩版。他在架构层拆,我在一句话里挪词。字小一号,道理是同一个。

他文章里自己注了一笔,说列举的四个失败模式是说明性综合案例,不是某个客户的case study。我挺喜欢这句注脚,在这个人人都敢把臆测写成客户案例的圈子里,这算是一种难得的诚实。

底下评论区也有人验证过这个方向。Tae Kim说他们团队把路由逻辑和语气控制分离之后,测试用例变得可复现,高量级简单查询转到确定性函数之后推理支出直接下降。他们是在系统架构层拆的,我只是在一条prompt里挪了挪词的位置,但拆完回头看,做的几乎是同一件事。

评论区还有个人,叫Mateo Ruiz,说单体agent的隐藏成本是变化隔离缺失——每一次新能力都变成一次提示词编辑,而每次编辑都隐式重测所有既有能力。这就是我想要的:把路由段和语气段拆开之后,改计费规则的时候不用碰语气,改语气的时候不用担心路由跟着坏。变化被隔离开了。

但拆也不是包治百病。底下Siyu讲他的Opportunity Skill有16个可调用函数、分6个模块,发外联消息的时候还保留了人工确认那一环。结构化到这个程度,问题已经变成“拆完之后怎么还是不敢全信”——手动确认就是承认:拆得再干净,模型该飘还是会飘。

定稿先放这:

你是一个客户支持处理单元。你的职责是输出回复,不负责判断优先级。

路由:先查锚点词表,命中即入对应队列。
包含“扣款”“多收”“账单” → 计费
包含“退款”“退货” → 退款
包含“打不开”“报错”“闪退” → 技术故障
未命中 → OTHER_UNSURE,原样转人工。

语气:
企业客户 → 称呼“您”,道歉必须包含完整条款引用,不主动给补偿。
普通客户 → 称呼“你”,道歉后必须跟一条可执行补救动作。

格式:回复分三段,段间用---隔开。
第一段确认问题,第二段解决步骤,
第三段第一行写工单编号,其余不写。

比原来那条4000词的短了一大截,也没少多少字,分量完全不一样。但这版我也没打算说是终版——路由段的锚点词表还在长,上周末刚加了“费用”和“扣错”两个词。格式段那个“---”是我临时挑的,换成XML tag可能更稳,我还没测。

先这么用着。等哪天它在某一条真实对话里理解岔了,我再回来拆一刀,不丢人。

评论

还没有评论,写下第一条讨论。