最近在折腾一个微信小程序项目,叫《见格MBTI》,从名字就能看出来,这东西想做的是把传统五行和MBTI人格类型放到同一个对话场景里。实际动工之后才发现,最难的既不是前端交互,也不是后端接口,而是怎么设计一套足够稳的提示词架构,让大模型既懂五行、又懂MBTI,还能把两套话语体系缝成一个连贯的“跨界人格解读”。
如果你也在做类似的事——不管是用大模型做传统文化咨询、心理测试,还是做智能对话角色,这篇内容都值得看一下。我会把《见格MBTI》里沉淀下来的提示词设计思路、微信小程序端的调用方案、多轮对话的上下文管理,以及踩过的一些坑,全部拆开讲清楚。这东西听起来有点玄,但落到工程上其实是一套很具体的方法,掌握了以后复制到其他跨界对话场景也能用。
1. 整体设计:为什么“五行+MBTI”不能只靠一句“你是大师”来完成
1.1 用户场景决定提示词边界:从测评到对话的产品定位
做一个跨界对话小程序,第一步不是写提示词,而是想清楚用户到底要什么。《见格MBTI》的目标用户画像很典型:年轻人,对MBTI有一定了解,想知道自己是什么人格类型,又对传统文化里的五行有好奇心。他们不是来求神问卜的,而是想要一种“自我认知工具”——既希望结果有点仪式感,又希望得到看起来有理有据的分析。
这个定位直接决定了提示词的边界。如果你是往“算命”方向做,提示词就要模糊、开放、模棱两可;但《见格MBTI》的方向是“性格观察和认知参考”,所以提示词必须明确告诉模型:不要下断言、不要预测命运、不要做心理诊断,所有输出都要落在“参考”和“倾向”的措辞上。
具体来说,我在系统提示词里写死的三条规定是:
- 输出内容必须使用“可能”“倾向”“通常来说”等弱化绝对性的表达;
- 不得涉及疾病、医疗、投资、婚恋决策等敏感建议;
- 两套体系出现矛盾时,需要坦诚说明“不同维度存在差异”,而不是强行圆过去。
这三条表面上是在做内容合规,本质上是在给模型划定输出的“安全区域”。大模型本身没有价值判断,它只会顺着提示词的语境走,你不把边界写清楚,它很可能就会在某个奇怪的地方开始发挥。
1.2 三层提示词架构:角色、知识、对话各司其职
我在实践中把《见格MBTI》的提示词拆成了三层,这是整个架构的核心逻辑,也是和“一句开场白就上”最大的区别。
第一层是角色层。这一层定义模型“是谁”。比如“你是一位融合中国传统文化与西方心理学的解读顾问,熟悉五行学说和MBTI人格类型”,同时还要加上性格风格设定,比如“用词温和、逻辑清晰、善于把抽象概念打成生活化比方”。
第二层是知识层。这一层是把五行和MBTI的系统知识注入进去。这里有个很关键的技巧:不是把百科全书的五行理论一股脑塞进去,而是只保留和“人格观察”相关的部分。比如五行里的“木火土金水”对应的性格倾向、情感模式、行为习惯,而MBTI则聚焦在四个维度的含义和16种人格的描述。知识层的作用是让模型在对话中调用这些概念时不至于胡编乱造。
第三层是对话层。这一层负责控制具体的对话流程和输出格式,比如开场语怎么说、用户回答后怎么接、结论要怎么结构化呈现、结尾怎么引导行动。
这三层在代码里最终会被拼成一个完整的system prompt,但开发和调试时一定要分开维护。原因很简单:角色层基本不怎么变,知识层会随领域内容持续更新,对话层则经常根据用户体验来回调。你合在一起写,改一次就得动整个prompt,慢慢地就没人敢碰了。分开以后,每个层可以独立测试,出问题也容易定位。
2. “五行-MBTI”映射体系与领域知识的提示词注入
2.1 显式声明知识范围:先立规矩,再做解读
跨界对话最容易出现的问题,就是模型把五行和MBTI的概念混在一起讲。比如用户问“我属土,是不是就是ISTJ?”模型可能直接来一句“是的,土行对应ISTJ”——这就属于典型的知识幻觉。
要解决这个问题,必须在知识层里显式声明映射规则。我在提示词里给了模型一张简化版映射表,但不是让模型死记硬背,而是让它理解“这两套体系是观察人格的不同侧面,不构成严格的一一对应关系,只有宽泛的类比参考价值”。
实际提示词文件里大概是这么写的:
{ "instructions": [ "五行侧重个体与自然环境的能量互动倾向,MBTI侧重认知偏好和行为模式", "当用户询问具体对应关系时,使用类比句式,例如:'从五行角度看,你的表达方式带有木的舒展感,类似MBTI中ENFP的外向直觉特质'", "严禁输出类似'土行等于ISTJ'的绝对映射结论", "如果用户坚持要求精确对应,可以给出数据分析结论:'基于你的回答,你表现出了偏土的能量特质和偏J的判断倾向'" ] }这套指令的核心是“各说各的,再找交叉点”。五行有能量倾向的语言,MBTI有认知偏好的术语,两者在一个人身上确实会呈现出某种相似性,但这种相似不是等式,而是一种观察视角的重叠。你把这个逻辑写清楚,输出的内容就专业了,不会滑向迷信。
另外,一定要在提示词里给模型一些“我不知道”的出口。比如:
- 如果用户提供了超出MBTI经典理论的问题,模型可以回答“MBTI框架在学术界存在一些争议,我的解读仅供参考”;
- 如果五行的推算涉及生辰等敏感信息,模型需要自动转化问题,例如“我没有办法做传统命理推演,但你可以告诉我最近状态的自我感受,我来做性格倾向分析”。
这一招能大幅减少模型的胡言乱语。很多时候模型不是因为不聪明而出错,而是因为它没有承认无知的权限。
2.2 少样本示例怎么写:平衡文化隐喻与心理学框架
提示词工程里,少样本示例的作用是给模型“打样”。但跨界对话的示例比普通问答难写,因为它需要同时照顾两种话语体系的气质:五行偏意象、隐喻、抽象,MBTI偏理性、结构、分类。如果示例里只有一边的风格,模型生成的文字就会失衡。
我常用的示例是“对比式示例”,即同一件事,先写五行视角,再写MBTI视角,最后做整合。比如:
用户说“我不太喜欢人多的地方,待久了觉得累。”
- 五行视角示例:这像“金”收敛的特质,对外界喧嚣保持距离,更看重内心的秩序感,独处不是孤僻,而是一种恢复能量的方式。
- MBTI视角示例:从MBTI看,你在社交场景中消耗能量,可能是内向偏好(I)的表现,倾向于通过独处来恢复精力。
- 整合视角示例:两种体系都指向你是一个内在驱动型的人,区别在于五行偏重描述你与环境的能量交换,MBTI偏重描述你获取能量的方式。
这样的示例写3组就够用,但最好覆盖不同的性格组合。比如一组偏向“外向+火”,一组偏向“内向+水”,一组偏向“理性+金”。示例不用太长,关键是让模型看到呼应的方式。
2.3 冲突兜底机制:当两套体系互相打架时
“打架”是跨界对话里一定会出现的情况。比如MBTI判断用户偏理性(T),而五行分析显示用户当前状态偏“火”的冲动,这两句话放在一起,用户难免困惑。
我的方案是在提示词里预设一个“冲突处理模板”:
当五行分析和MBTI判断出现明显张力时,输出结构建议: 1. 先各表一枝:坦诚说明两套体系分析的角度不同; 2. 指出张力本身是一种信息:'这种张力恰恰说明你处在一种内在调整期'; 3. 给一个中性的行动建议:比如'大部分人在不同情境下都会展现出不同侧面,这正是了解自己的起点'。这就像谈判里先划定共识再处理分歧。模型不会真的“懂”五行和MBTI,但如果你给了它明确的处理结构,它至少能表现得像一个成熟的跨学科顾问,而不是一个自相矛盾的糊弄大师。
我自己实测下来,加入这段兜底机制后,用户对结果的接受度提升很明显。很多用户反而觉得“矛盾”才是真实水平,比那种所有线索都在硬圆的结果更可信。
3. 微信小程序端的工程落地:请求、流式输出与上下文管理
3.1 request封装:带上身份、会话和鉴权
提示词再复杂,最终还是要通过小程序端的大模型API调用跑起来。微信小程序的环境跟普通Web很不一样,比如它没有直接的fetch标准、对跨域限制严格、鉴权依赖openid体系,所以请求封装不能照搬后端项目那套。
我在项目里做的是两层封装。第一层是通用request工具,负责把method、header、data统一规整,并处理公共错误码;第二层是会话请求的专用封装,会在每次调用时自动拼接三样东西:
- 用户的openid(由微信登录后从后端换取,前端只存临时token);
- 当前的sessionId(用于后端检索历史消息);
- 本次对话的消息数组(从上下文管理器读取)。
一个简化的核心请求示例长这样:
const chatWithModel = async (sessionId, userMessage, historyMessages) => { const res = await wx.request({ url: `${config.baseUrl}/api/v1/chat`, method: 'POST', data: { sessionId, messages: [ ...historyMessages, { role: 'user', content: userMessage } ] }, header: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, timeout: 30000 }); return res.data; };这里要特别提醒几个细节:
- timeout要设置到30秒以上,因为大模型接口的首字延迟通常不低,尤其在模型做大段分析时;
- 不要在前端拼装完整的system prompt,否则容易被篡改,也容易造成前端包体膨胀。正确做法是前端只传messages,后端在调用大模型API时再把system prompt注入进去;
- token要从后端签发,不能在前端写死,否则别人抓包之后可以白嫖你的API额度。
3.2 流式接入:WebSocket还是SSE
回答“五行MBTI解读”这种任务性输出,内容可能长到几百字。如果走普通请求-响应,用户盯着一个转圈动画等5秒,体验基本就废了。《见格MBTI》早期版本就是这么伤过一批用户。
后来我改了流式输出。微信小程序里实现流式大致有两条路:
一条是WebSocket方式。小程序原生支持WebSocket,连接建立后,后端把模型生成的文字按片段推送过来,前端拿一段渲染一段。优点是兼容性好、控制力强,还能顺带做心跳保活;缺点是需要自己处理连接生命周期,后端要多维护一条长连接。
另一条是SSE方式(Server-Sent Events)。严格来说小程序没有原生EventSource API,但可以通过wx.request开启enableChunked,在onChunkReceived回调里拿数据流。用这种方式的好处是协议更轻,但坑也比较多,比如在iOS低版本上对分块接收的兼容性不理想。
我在项目里选择的是WebSocket方案。核心原因有两个:一是需要双向通信,不仅仅是接收生成结果,还有一些“打断生成”的操作,比如用户中途说“好了,重新分析”,这个指令要能实时传到后端;二是WebSocket的接收回调更稳定,更容易做到逐字打印的效果。
前端接流式数据时需要注意的是“拼接时机”。模型输出的片段通常不是完整的文本边界,你直接把它推到textContent里可能在某个字上卡出白边。我是在onMessage回调里,先把JSON解析出来,取data字段里的增量文本,再追加到当前文案变量里,最后用throttle更新到页面视图上。
socket.onMessage((res) => { const json = JSON.parse(res.data); if (json.type === 'content') { partialText += json.delta; throttleUpdateTextarea(partialText); } });3.3 上下文预算:token的循环窗口与摘要压缩
大模型上下文窗口再大,也架不住多轮对话无限堆积。尤其是这种“咨询式”场景,用户可能来回聊十几轮,每轮模型回复还特别长,如果用前几年的老模型,一两轮就把窗口塞满了。
我的上下文管理策略分两级。一级是会话级窗口,用滑动窗口控制发送给模型的token总量。假设模型支持16K上下文,系统提示词占掉约1500token,那么对话历史最多留12000token左右,剩下的留给当前问题和模型生成空间。滑动窗口的逻辑很简单:如果历史消息总量超过阈值,就丢掉最早的一组对话,但保留用户的基本信息摘要。
第二级叫“摘要压缩”。每次对话结束时,我会在后台另起一个轻量任务,用一段压缩提示词把整段对话提炼成结构化摘要,存到会话记录里。下次用户回来继续聊的时候,前端发送的就不是原始历史,而是这段摘要加上最近几轮完整对话。这样做有两个好处:既节省上下文空间,又不会丢失最关键的用户信息。
摘要压缩提示词示例: 你是对话记录整理器。请将以下对话压缩成一份结构化摘要,包含: - 用户的基本情况(自述的职业、年龄、近况等) - 用户表现出的五行倾向关键词 - 用户表现出的MBTI维度线索 - 已经给出的结论和建议 - 尚未回答或需要追问的问题 输出格式为JSON,总字数控制在300字以内。这个设计让长期会话的成本大幅降低,也让“过了三天回来接着聊”变成了可能,用户体感上更像一个记得住自己的真人顾问。
4. 复杂对话任务的状态编排与参数调优
4.1 把“人格画像”拆成子任务
如果只做单轮问答,提示词再复杂也只是“花哨的聊天”。但《见格MBTI》要完成的是一个“人格画像”的闭环:从收集信息到给出结论,中间涉及十几轮对话。这已经不是单纯靠一个系统提示词能搞定的了,得在业务流程层面做任务编排。
我采用的方法是把整个画像过程拆成四个子任务:
- 信息收集:通过有限轮次提问,获取用户在决策习惯、社交偏好、情绪表达、工作风格等方面的状态描述;
- 倾向分析:基于已收集的信息,推导五行侧重和MBTI维度判断的过程性分析;
- 结论生成:综合所有线索,输出结构化的五行MBTI跨界解读;
- 对话反思:如果用户对结论提出异议,则重新回到信息收集或倾向分析阶段。
子任务之间的切换不能靠“模型心情”,要靠明确的状态标记。我在对话消息中塞了一个系统字段,比如当前阶段标识,后端在调用模型前会根据当前阶段选择不同的system prompt子片段。
4.2 会话状态机:收集信息、生成结论、追问澄清
做过多轮对话的人都知道,最怕的不是模型笨,而是流程乱。用户说了一句话,模型不知道应该追问还是应该总结,于是随便聊,最后给一个驴唇不对马嘴的结论。
我设计了一个简单的状态机,一共四个状态:
- COLLECT(信息收集)
- ANALYZE(分析中)
- CONCLUDE(给出结论)
- CLARIFY(澄清异议)
每个状态都配置了一套独立提示词和判定条件。比如状态是COLLECT时,模型角色被设定为“积极倾听的顾问,一次只追问一个维度”,同时要求它在用户回答后判断是否还缺少关键信息,如果缺,就继续保持COLLECT;如果够了,就自动切换到ANALYZE。
这里有个很实用的实现技巧:不要让模型自己决定“我现在是什么状态”,而是在每次调用前,由后端根据上一轮返回的state字段确定本轮状态,再选择对应的提示词。相当于把状态机放在程序逻辑里,而不是完全交给大模型判断。模型只负责在当前状态下输出,状态迁移由规则控制。这样稳定性高得多。
实际代码里我维护了一个当前状态值,并定义一个状态流转配置:
const stateMachine = { COLLECT: { shouldTransit: (lastReply) => lastReply.done === true, next: 'ANALYZE' }, ANALYZE: { shouldTransit: (lastReply) => lastReply.confidence > 0.6, next: 'CONCLUDE' }, CONCLUDE: { shouldTransit: (lastReply) => lastReply.needClarify === true, next: 'CLARIFY' }, CLARIFY: { shouldTransit: (lastReply) => lastReply.round >= 2, next: 'CONCLUDE' } };这种设计让产品流程是可控的,你可以在任何一个节点插桩、打点、埋数据,而不是全凭模型的随机发挥。上线之后做数据分析也要依赖这种确定性。
4.3 temperature与top_p怎么配合
参数调优这部分,网上聊的人少,但实际影响特别大。五行对话和MBTI解读,本质上需要模型在“创意性表达”和“逻辑一致性”之间找平衡。如果你把temperature调得太高,输出就飘,满嘴跑火车;调得太低,输出又干巴巴,像在念词典。
我在《见格MBTI》里经过多轮测试,最终把核心对话的temperature定在0.7,top_p定在0.9。这个组合的体感是:既有一定语言丰富度,又不会偏离人格分析的基本框架。
更细的说法是分阶段处理。信息收集阶段我更喜欢偏低的参数,比如temperature设到0.4,保证追问的问题在逻辑上稳妥;进入结论生成阶段,再调高到0.75左右,让语言更具画面感和温度;而摘要压缩这种纯任务型调用,temperature直接压到0.2,确保输出格式稳定。
这些数值不是拍脑袋定的,而是基于一个简单评测流程。我准备了一批测试对话集,每次调参后跑一遍,看输出的变异度、重复率、用户问题完成率三个指标。如果变异度过大,就往下调;如果重复套话太多,就往上调。你必须建立属于自己的“手感”。
5. 常见问题与排查技巧实录
5.1 回答空泛、像保险推销
这是提示词类项目里最普遍的问题。模型说了一大段话,每个字都正确,但组合在一起感觉什么都没说。比如用户问“我老是想太多怎么办”,模型答“您是一个善于思考的人,想太多也有它的价值,建议您平衡放松与思考……”
这个问题出在提示词知识层不够具体。解决思路是给模型限定“必须引用至少一个来自对话的具体细节”。我在对话层提示词里加了硬性要求:
在你给出任何建议或结论前,必须引用用户在对话中使用过的原话或关键情况,引用格式为:'你刚刚提到……'。加了这一条之后,输出质量提升非常明显,因为模型被强制做了“用细节说话”,空泛话就很难混过去。
5.2 五行和MBTI结论打架
前面讲了兜底机制,但调试过程中还是会遇到模型把两者强行融合成一句别扭话的案例。比如“你属金,金又对应INTP,建议你去学编程”——这明显是胡扯。
排查这类问题时,我先检查知识层提示词中的映射表是否过度简化。映射表是给模型参考的,但模型容易把它当作硬规则,所以要在映射表前面加一句“这里的对应关系是比喻和参考,不是规则”。等这句改掉以后,打架问题基本减少三分之二。
如果还打架,就在少样本示例里故意加一条“冲突示例”,让模型看标准示范是怎么处理矛盾的。模型其实很擅长模仿格式,你给它看了“标准答案”,它就大概率按那个模板走。
5.3 小程序端延迟和中断
小程序端流式输出的核心痛点有两个。第一个是请求发起后首字延迟太长,用户觉得卡死。我排查下来发现,很多时候不是模型慢,而是后端没有做好“提前返回”。打个比方,你后端是先等模型完整跑完再统一返回,那前端拿到第一个字当然要等很久。正确做法是一拿到模型回包的第一段增量,立刻就推给前端。
第二个痛点是WebSocket在弱网环境下频繁断开。我的应对是加了心跳机制和自动重连。心跳每30秒发一次,断线后自动进入重连等待,最多重试3次,同时如果重连失败,就给用户一个“连接不稳定,已切换为完整对话模式”的降级体验。
5.4 过审时的内容合规细节
跨界内容最容易在小程序审核环节出问题。尤其是涉及传统五行,审核人员可能第一时间联想到封建迷信。我的处理方式是在产品文案和提示词里都做了“自我认知工具化”的表达。所有界面文案用“性格观察”“能量倾向”“自我了解”这类中性表达,不使用“命理”“运势”“预测”等词。
同时,在内部检测逻辑上加了一层拦截:如果用户提问方向涉及运势、财运、姻缘等敏感词,系统回复统一引导到积极方向,然后自动切回“人格讨论”的正轨。这一层逻辑要放在提示词之前,也就是入口处过滤,否则单纯靠提示词答应“不聊这些”还不够稳。
6. 数据回流与迭代闭环
6.1 定义可量化的对话质量指标
提示词工程不能永远是“凭感觉调”。我在项目中建立了三个核心指标:
- 用户追问率:用户在拿到第一次结论后,多少比例会追问“为什么”。比例高说明结论有说服力,但也可能说明结论没讲透。
- 重新生成率:用户点击“重新分析”的次数占比。这个指标降低,说明提示词架构稳定性在上升。
- 满意度评分:每次对话结束后让用户对结果打分,1到5星,低于3星会弹一层简短的反馈原因。
这三个指标相互制衡。比如你不能只看满意度,因为用户可能出于礼貌打了4星,但重新生成率依然很高。我个人的习惯是优先盯“重新生成率”,它更客观,更像用户在用脚投票。
6.2 用户反馈如何自动回流到提示词优化
用户反馈是天然的宝藏,但用起来要谨慎。最简单的做法是把低于3星的对话样本保存下来,人工翻看,找出共性,提炼成新的少样本示例。这个流程我每隔一两周就会做一次。
再进一步,可以用大模型做粗筛。我会用一段短提示词给一条对话样本打标签,比如“是否是模型幻觉”“是否解释过于复杂”“是否没有引用用户原话”。然后按标签聚合,优先处理出现频率最高的问题类型,再针对性地修改对应提示词层级。整个闭环听起来不复杂,但在持续迭代里效果拔群。
6.3 对新手的一条建议
最后说一条我自己的经验,也是给准备做类似项目的人的建议:不要一开始就追求巨复杂的一条提示词。先把产品流程跑通,哪怕只用最朴素的提示词,然后一点点把角色层、知识层、对话层加进去。每加一层,都配套一组测试对话,保证老功能不退化。
跨界对话的魅力,就在于两套完全不同的知识体系在同一个模型里碰撞。这个碰撞需要架构来托底,而不是靠模型碰运气。提示词架构做得有多稳,产品的底线就有多高。
我个人在实际操作中的体会是:五行和MBTI的对话本质上是在做“翻译”工作,把抽象的传统文化符号翻译成现代人能理解的心理语言。这个过程既要用到提示词的技术,也需要一点点产品感。如果你正在做类似的小程序,建议先把用户真实对话录下来,多听几遍,再回去改提示词——很多你觉得写得挺明白的规则,在真实对话里根本不是那么回事。