别让用户选模式:会猜意图的搜索
一个接受三种文字输入的词典,可以让用户去选,也可以自己推断。让用户选更好做,也更难用。这里讲的是我们如何让这个推断变得可靠。
KoiSpeak 在一个输入框里接受三种输入:越南语、拼音和汉字。显而易见的设计是加一个模式切换。我们刻意没有那样做,而其中的道理远不止适用于词典。
模式切换为什么失败
切换开关看起来人畜无害。它只让用户多点一下。但它每次都要多点一下,而且它会以一种非常具体、非常令人恼火的方式失效:模式选错时,你得到零结果,而零结果看起来和"这个词不存在"一模一样。
用户真实的心智模型不是"我现在要执行一次拼音搜索",而是"这是什么意思"。夹在这个意图和答案之间的每一个界面元素都是摩擦,而在一个人们每天打开四十次的工具里,摩擦会累积。
这里藏着一条通用规则。如果系统能从输入中判断出某件事,它就不该去问用户。 一个模式开关,是界面在承认它不想干这份活。
三种文字比看上去更可分
好消息是它们占据的空间基本互不重叠。
汉字的检测极其简单
汉字位于已知的 Unicode 区块,主要是 CJK 统一表意文字,从 U+4E00 到 U+9FFF,另有扩展区。如果输入里含有这些范围内的字符,用户输入的就是中文。这几乎是确定,而不是猜测。
越南语有拼音不用的附加符号
越南语用拉丁字母书写,带有自己的一套符号:角符 (ơ, ư)、扬抑符 (â, ê, ô)、短音符 (ă)、带横的 đ,以及包括下点 (ạ) 和钩号 (ả) 在内的声调符号。
拼音用的是长音符、锐音符、抑扬符和重音符,而且只出现在 a、e、i、o、u、ü 上。两套几乎不重叠。含有 đ、ơ、ư 或下点的字符串就是越南语,没有别的可能。
拼音是一个小而封闭的集合
这是人们低估的部分。普通话只有几百个合法音节。zhang、xue、qiong 合法;blorp 和 strem 不合法。
所以你可以做校验:尝试把输入切分成合法的拼音音节。如果切得干净,那多半就是拼音。这一招也能抓住不带声调的拼音,而那正是大多数人实际会打的。
难的是重叠部分
清晰的情况下检测很容易,模糊的情况下才有意思。真实的冲突包括:
- 又是这个又是那个的短字符串。
ma既是合法拼音,也是合法的越南语词。ba、co、can同理。 - 不带附加符号的越南语。 相当多的人打越南语不带符号,而这抹掉了你最强的信号。
- 英语。 学习者会打英文词,而英语不属于你的三种语言中的任何一种。
试图用更多规则去解决是一场必输的战争。规则会越写越长、互相矛盾,而且照样出错。
不要分类。全都搜,然后排序。
真正奏效的设计,是不再把这当成分类问题。
与其判断输入是什么再去搜一个索引,不如把查询跑遍所有可能的解释,然后用一个考虑了每种解释可信度的分数把结果合并起来。
大致是:
- 给每种解释打分:是否含汉字、是否带越南语独有符号、能否切分为合法拼音。
- 查询这些解释所指向的各个索引。
- 合并,按解释的分数、匹配的精确程度和词频给每条结果加权。
用户看到的是一个列表。输入 ma 时,他们同时得到拼音结果和越南语结果,常用词排在前面,无论他们要的是哪一边,答案都在屏幕上。歧义不再是错误状态,而变成一个有序列表。
分类逼你做一个可能出错的决定。排序允许你不确定,同时仍然有用。当系统无法确定时,优先选择那种会退化成"几个合理答案"而不是"一个自信的错误答案"的设计。
代价是什么
诚实地说说这笔交易:每次按键你要跑更多查询。这是真的,也正因如此,这个设计的生死取决于性能。
让它变得划算的因素:
- 便宜的解释先跑。 汉字检测只是对前几个字符做范围判断。一旦命中,后面全部跳过。
- 每种文字各有前缀索引, 于是每次单独查询都是一次便宜的查找,而不是全表扫描。
- 词频预先烘进索引, 于是排序不需要再遍历一遍结果。
- 防抖,并在输入变化时取消在途查询。 大多数按键根本不会产生一次完成的搜索。
仍然需要逃生门的地方
自动识别不应该是唯一的通路。有两种情况确实需要别的东西:
- 你根本打不出那个字。 那是手写输入和部首检索的职责。
- 你想强制一个方向。 偶尔用户确实只想要越南语到中文。我们提供明确的方向控件,但它是需要时可用的覆盖项,而不是一上来就强迫做的决定。
这个先后顺序才是真正的原则。默认猜得好,并让人能纠正这个猜测。 而不是:拒绝猜测,逼所有人自己声明。
通用的教训
每个产品都有那么一个时刻:最省事的实现方式,是去问用户一个系统本可以自己回答的问题。文件类型。国家。货币。搜索模式。
每一个都很小。加在一起,它们就是"一个人们不假思索就伸手去用的工具"和"一个人们必须去操作的工具"之间的差别。