模块二:不仅是分门别类——构建用户的“全息影像”
写在前面: 如果说模块一里的 BERT 是我们的“眼睛”,帮我们看清了文字的坐标。那这一章我们要讲的就是“大脑”里的分类格。 很多时候,我们觉得 AI 笨,不是因为它“看不懂”,而是我们教它的分类方式太单一了。
2.1 拒绝“贴标签”,我们要的是“全息影像”
以前做 App,我们喜欢给用户贴一个标签。比如用户说“我要去跑步”,我们贴个标签 运动,完事。
但这远远不够。
想象一下,你是个私人管家。当主人说“我要去跑步”时,如果你只知道这是运动,你是不合格的。
你需要瞬间捕捉到以下信息:
-
什么事? 跑步(Topic)
-
心情咋样? 挺积极的,不是被迫营业(Sentiment)
-
急吗? 不急,随时能去(Urgency)
-
多难? 对主人来说是小菜一碟(Difficulty)
-
是去为了啥? 是为了健康维系(ActionType: Lifestyle)
看,本来扁平的一句话,通过这就变成了立体的全息影像。
我们在系统设计中引入了 5 个新维度(紧急度、时间视窗、行动类型、难度、具体度),就是为了让手机能像这个老管家一样,通过一句话,通过这 7 个维度的交叉定位,彻底读懂用户当下的状态。
2.2 举一反三:把这套逻辑搬到别的地方 (Domain Transfer)
这套“全息”的思路,不仅仅能用来做目标管理。如果你是做其他 App 的,完全可以照猫画虎。
关键在于:你要把你那个领域的“专家直觉”,拆解成几个独立的判断维度。
案例 A:如果你是做“记账软件”的
别只分“餐饮、交通”了,试试加上这几个维度:
- 必要性 (Necessity):
-
分类:
生存必须vs提升生活vs奢侈浪费。 -
价值:帮用户分析“钱都花哪了”。
- 消费情绪 (Mood):
-
分类:
冲动解压vs理智规划vs社交被迫。 -
价值:如果发现用户都在心情不好时乱花钱,可以弹窗提醒。
- 预算归属 (Budget Type):
-
分类:
个人vs家庭vs工作垫付。
案例 B:如果你是做“医疗问诊”的
别只分科室,试试加上:
- 疼痛程度 (Severity):
- 分类:
微痛vs剧痛vs隐痛。
- 持续时间 (Duration):
- 分类:
突发vs间歇vs长期。
- 情绪状态 (Anxiety):
-
分类:
极度恐慌vs平静咨询。
核心心法:不要试图训练一个巨大的模型一次性输出所有结果。把任务拆得越细,每一个小分类器(Head)就越准,训练也越容易。
2.3 老师,我想加个“新分类”怎么办?(Data Updates & Retraining)
这是大家最关心的问题。
“我现在只有工作和生活,要是明天我想加个滑雪怎么办?”
或者“我觉得现在的分类不够准,我想重新教它,怎么操作?”
这里必须明确一个概念:所有的训练都在响应用户的交互。
不是只有点了“训练”按钮才叫训练。用户的每一次修正、每一次确认,甚至每一次不修改(默认认可),都是在为 AI 喂数据。
在我们的扇出架构里,这事儿变得特别简单,这就像换灯泡,不用拆房子。
第一步:准备“课本” (Data Preparation)
你不需要去搞那种几百万条的大数据。对于端侧微调,你只需要准备“小而精”的数据。
比如你想教它识别“滑雪”,你只需要在表格里填上:
| 文本内容 | 标签 (Label) |
|---|---|
| “周末去崇礼滑雪” | 滑雪 |
| “买了新的单板” | 滑雪 |
| “在这个雪道摔惨了” | 滑雪 |
| ... | ... |
注意:为了防止它“为了学滑雪忘了跑步”,你最好再一次性把之前的“跑步”、“游泳”数据也带上,混合在一起。
第二步:重新训练“小脑瓜” (Retrain the Head)
2.3.1 什么是“纠错数据”?
当用户把一条本来被识别为“工作”的任务,手动改成了“滑雪”,这一瞬间,一条黄金数据诞生了。
在代码中,它长这样:
struct TrainingSample {
let id: UUID
let text: String // "周末去崇礼滑雪"
let embedding: [Float] // [0.12, -0.55, ... 768维坐标]
let correctLabel: String // "滑雪" (用户修正后的真实意图)
let timestamp: Date
}
这些 TrainingSample 会被悄悄保存在手机的一个安全角落(Core Data 或 SQLite),等待着夜深人静时被用来“特训”模型。
2.3.2 训练过程
-
不动大脑袋:那个几百兆的 BERT (Feature Extractor) 完全不用动!不用重新下载,不用重新部署。
-
只换灯泡:
-
把上面的数据喂给训练脚本。
-
脚本会只训练那个负责
Topic的小分类器。 -
因为这个小分类器极小(几十 KB),在电脑上可能几秒钟就训练完了。
第三步:热更新 (Hot Update)
训练好了一个新的 TopicClassifier.mlmodel 文件后,你把它放到服务器上。
App 启动时检测到更新,下载这个几十 KB 的小文件,替换掉本地旧的。
用户完全无感,但下一秒,他的 App 就突然能听懂“滑雪”了。
这就是模块化和扇出架构带来的最大红利:灵活、低成本、随时进化。