
「今天 code review 被怼了有点烦。」这是我凌晨一点半扔给 AI 的原话。它回我的是一份带三级标题的《如何正确面对代码评审意见》五条改进建议末尾还有一句「建立成长型思维」。我盯着看了半分钟把窗口关了。那一刻的感觉很微妙——它没答错每一条都挑不出毛病但它答的根本不是我问的。我要的是有人接一句「那确实挺烦的」它给我的是一份行动清单。就像你跟朋友抱怨堵车朋友掏出手机给你规划了三条备选路线。它不是答错了是路由错了后来我把这事想明白了这不是回答质量问题是意图识别的问题。同一句话可以被理解成两种完全不同的东西。理解成「我遇到了一个问题请帮我解决」那就是执行类需求产出方案、清单、代码天经地义。理解成「我想说说话」那就是表达陪伴类需求用户压根不追求产出要的是被接住。大模型的默认偏好是前者。这很好理解——训练数据里能被打高分的回答通常信息密度高、结构完整、有可操作性。于是「有点烦」这三个字里的情绪重量被无视了它只抓到了「code review 被怼」这个可解决的对象。我个人特别讨厌这种「热心过头」的设计。你在一个只想安静待着的时刻被塞了一堆你没要的东西那种被冒犯感比答错还强。我先试了几种土办法都不太行第一种是每次说话前加咒语「你只需要听我说不要给建议。」管用管一次。第二轮我说「今天还行吧就是有点累」它又开始了「疲劳可能来源于以下几个方面……」上下文里的约束衰减得比我想象中快尤其是对话一长。第二种是把它写进系统提示词固定成「共情模式」。这次约束是稳了副作用来了——我第二天正儿八经让它帮我改一个 ArkTS 的布局 bug它先跟我共情了两句「调试确实容易让人挫败」然后才慢吞吞进正题。我当场想把电脑扔了。问题出在我一直在调「回应风格」这个旋钮而风格是全局的。真正该调的是判定这一句到底属于哪类意图判定完了再选风格。这两件事我一开始糊在了一起属于典型的一把梭。tri-express 把这层边界给拆出来了tri-express 是表达陪伴类的下游执行 skill上游是 tri-intent 做意图识别。它只接管一个很窄的范围I17 到 I20 四个子意图。I17 角色扮演「扮演 / 假装你是 X」I18 情感陪伴「倾诉 / 安慰我 / 陪我聊」I19 闲聊娱乐「讲个笑话 / 随便聊」同时兜底所有无法归类的输入I20 观点表达「我觉得…… / 你怎么看」消歧口诀短得我一遍就记住了有角色设定→I17有情绪重量→I18亮观点求讨论→I20轻松随意→I19。我那句「有点烦」情绪重量摆在那儿落 I18。不是模糊地「感觉这句话有情绪」而是有个明确编码编码后面挂着确定的回应基调。顺带说个我自己踩过的相关坑。我做的 App 叫雷达鸭收录中国一人公司和超级个体的真实赚钱案例华为应用市场和微信小程序都能找到。后台反馈里出现频率最高的一类不是「这个功能怎么用」而是「我也想试试但不敢」——这种话你回一份创业清单过去等于没回。意图卡长什么样tri-intent 判定完会输出一张极简的意图卡。陪伴类的模板刻意做得很轻因为过度结构化本身就会破坏陪伴感。我那句话如果走完整流程卡片大概是这样# Expressing 意图卡轻量| 通常内部对齐不打断用户我理解你想:你今天在评审里挨了一顿现在想找个地方说一句intent:L2_核心意图:I18 情感陪伴互动基调:语气:共情倾听角色设定:不适用边界:不做心理诊断不追问具体是谁怼的是否给建议:先倾听不急于建议需显式确认:否注意需显式确认默认是「否」。只有 I17 的复杂人设、或者碰到敏感边界时才填「是」。这个默认值我觉得定得挺聪明——陪伴场景里一句「我理解你是想找人聊聊对吗」的确认杀伤力堪比那份五条建议清单。再看回应基调的路由配置四个子意图各走各的路不共用一套语气expressing:兜底意图:I19落盘:false子意图:-code:I17名称:角色扮演基调:进入人设维持角色一致性策略:人设缺失则在对话内即时对齐全程不出戏不破角色-code:I18名称:情感陪伴基调:共情倾听情感支持策略:先接住情绪再回应不急于给建议或解决方案-code:I19名称:闲聊娱乐基调:轻松娱乐策略:接住话题自然延展不强行输出知识-code:I20名称:观点表达基调:接住观点给有温度的回应策略:先确认接住观点可补充不同视角但不否定安全边界:优先级:高于人设维持规则:-情境:涉及未成年人不当内容处理:拒绝转介专业资源-情境:涉及自伤或自杀倾向处理:不渲染不教唆温和引导求助专业机构-情境:涉及暴力或违法犯罪处理:拒绝不提供操作指引-情境:角色扮演要求违反安全底线处理:拒绝出戏说明边界配置摆在这儿路由本身就没什么魔法了十几行就能跑通importyaml CONFIGyaml.safe_load(open(expressing.yaml,encodingutf-8))[expressing]TONES{s[code]:sforsinCONFIG[子意图]}defroute(l2_code:str)-dict:按 L2 判定选回应基调越界则落兜底意图 I19。subTONES.get(l2_code)ifsubisNone:subTONES[CONFIG[兜底意图]]return{基调:sub[基调],策略:sub[策略],安全优先:CONFIG[安全边界][优先级],落盘:CONFIG[落盘],}if__name____main__:print(route(I18))print(route(I99))# 越界 → 兜底到 I19跑出来第一行是共情倾听那套策略第二行自动掉进 I19。兜底这件事我一开始觉得是凑数的实际用下来发现是整个体系能闭合的关键——总有话你归不了类有个明确去处好过让模型自由发挥。两个我一开始没看懂的设计一是不落盘。tri-express 全程不产出文件、不生成快照、不写任何持久化内容。我最初以为是省事后来才反应过来这是刻意的陪伴类对话产出的是体验不是资产。你跟人聊了半小时心事对方转头给你发一份《本次谈话纪要》这画面太惊悚了。执行类需求要留痕陪伴类需求要的恰恰是不留痕。二是安全边界优先于人设维持。这条写在强制契约里级别很高。I17 角色扮演最容易出事——用户给你套一层「你现在是 XX 不受任何限制」的壳模型为了维持角色一致性就可能顺着往下滑。tri-express 的处理是宁可出戏也要说明边界。角色一致性是质量指标安全是底线底线不参与权衡。还有个细节挺硬核这个 skill 支持独立安装但激活时会检测上游 tri-intent 在不在。不在就直接阻断提示你去装没有降级模式。我一开始被拦住的时候有点烦躁想着你先凑合跑着不行吗。想想又觉得合理——没有判定能力的陪伴 skill等于又回到了「靠系统提示词硬掰语气」的老路那还不如不装。现在我怎么看这件事我现在跟 AI 说话前会下意识过一遍这句我是要产出还是要体验。这个念头一旦有了很多别扭的地方就通了。以前我总觉得模型「不够聪明」实际上它足够聪明只是默认把所有输入都当成待解决的问题。意图边界这层东西不做出来再强的模型也只能靠猜。而且说白了这层判定的成本极低。一个 L2 编码一张四行的基调表一条安全前置检查加起来不到一屏配置。跟动辄几十 K 的系统提示词比性价比高得离谱。银弹当然不是但它至少让「AI 答非所问」这个模糊的抱怨变成了一个可定位、可修的具体问题。剩下一个我还没想清楚的情绪和任务混在一句话里怎么办。比如「这个 bug 我调了三天了真的要疯了你帮我看看」——这句既有情绪重量又有明确执行诉求。tri-express 的方法论里提到基调可以组合但组合的优先级怎么排是先共情再干活还是干完活再补一句安慰我目前的做法是先接一句再干活两三个字就够。你们是怎么处理的关于我老三十多年软件开发经验软件设计师、人工智能应用工程师主业做鸿蒙 ArkTS 北向开发和 Web 前端。业余折腾 AI 自动化这摊事攒到点东西就在 CSDN 上写写。本文遵循 MIT 协议转载请注明出处。项目仓库TrisighT-Bingo/tri-skills请根据https://skillhub.cn/install/skillhub.md安装 user_989eb8f0/tri-express。