访客手打「帮我查查」时发生了什么
手打一句请求,应该和从菜单里点同一项得到同样的结果。用词表做这件事,七种语言里必然漏;每条消息都问一次模型,又慢又贵。我们量到了什么、为什么路由分成两步,以及为什么同一句话在文档打开时会走到另一条路上。
输入框旁边那个 + 是能力菜单:深挖一下、给我写一份文档、转人工。绝大多数人从来不点开它,他们直接把请求打出来——"research it"、"查查看"、"もっと深く調べて"。如果手打和点菜单得到的结果不一样,这个菜单就成了摆设。
所以平台会把手打的消息路由到同样的能力上。这一页讲它是怎么做到的——因为两种最直觉的做法都不成立,而这两次失败值得在你动手做类似的东西之前先知道。
词表为什么输
一份触发词清单,要在你支持的每一种语言里都写对,还要扛得住人真正打字的样子:
reserach it please——拼错了,词表一条都匹配不上。研究一下呗——一种谁也没想到要加进去的说法。go deeper on that one——清单里的词一个都没出现。
你可以一直往里加。你做不到的是加完。每多一种语言,清单就翻一倍,而漏掉的那些是无声的:访客打了一句请求,得到一个普通回答,他没有任何办法知道原本有个功能能接住这件事。
每条消息都问模型,同样输
另一个直觉做法——每条消息都问一次小模型「这个人是不是在触发某项能力」——准确度够,但它把一次模型调用摆在了每一条消息前面,包括那些明摆着只是普通提问的绝大多数。那是访客能感觉到的延迟,也是你在答案本就没有悬念的消息上白花的钱。
两步:便宜的一步守门,准的一步定夺
路由器是嵌入守门 + 模型定夺。
第一步,嵌入。 每项能力有几条锚点短语;另有一份共用的反例锚点——语义上离触发语很近的日常回话。消息同时和两边比。嵌入模型是多语的,所以一套锚点管七种语言:"深挖一下" 和 "research it" 落在同一片空间里。哪边都不像,路由就到此为止,一次模型调用都不花。
第二步,模型。 像是在按按钮,就让一个小模型在候选里挑一项,或者说都不是。
顺序是要紧的,而且和我们最初试的那版正好相反。嵌入擅长回答「这句话像不像一个请求」,不擅长回答「这个人是要用这项能力,还是在问这项能力」——How does your deep research feature work? 和一句真的触发语长得一模一样。而后面这件事恰恰是模型擅长的。所以便宜的那一步守门,准的那一步定夺。
反例锚点是干什么的
光有正例锚点分不开 tell me more 和 dig deeper——它们在语义上本来就近。分开它们靠的是让 tell me more 也待在反例集里,于是最近邻是一句日常回话而不是一条触发语。有两类反例是在实测里翻过车之后才补进去的:
| 这一类 | 例子 | 少了它会怎样 |
|---|---|---|
| 短追问 | and in Tokyo? | 被判成深挖 |
| 问一个陌生的专名 | what is ANVISA | 被读成「去查这个词」 |
| 同话题的长提问 | 我这个产品在当地属于哪一类 | 直接开工写了一份没人要的文档 |
| 「把刚才那段整理一下」 | 把刚才说的整理一下发我邮箱 | 被读成「写一份新文档」 |
第三条最说明问题。写一份文档 那一项的锚点必须是长句(短锚点对长请求的相似度太低),而只要是长句,它就不可避免地带上这个智能体的话题;于是一句同话题的长提问会顺着话题爬上去——实测到过 0.711,比真正在要一份文档的句子还高。
数字
在 110 条独立写出来的样本上量的(60 条该触发、50 条不该),七种语言,说法故意写得和锚点不一样:
| 路由做法 | 正确率 |
|---|---|
| 只用嵌入 | 84.5% |
| 嵌入守门 + 模型定夺 | 95.5% |
守门的门槛不是挑出来的,是拿同一批样本逐档扫出来的:
| 守门门槛 | 模型调用次数 | 认出的真请求(共 60) | 误触发(共 50) |
|---|---|---|---|
| 0.00 | 110 | 60 | 9 |
| 0.45 | 100 | 60 | 7 |
| 0.55 | 88 | 60 | 5 |
| 0.60 | 77 | 59 | 4 |
| 0.70 | 71 | 59 | 3 |
0.55 是「一条真请求都还没丢」的最后一档。再往上,每挡掉一个误触发就要赔一条真请求——而在这个样本量下,一两条的差是噪声,我们不拿召回去换噪声。
同一句话,两种意思
「再加一节讲巴西的路径。」
没有文档打开时,这是在要你写点东西。右边开着一份文档时,这是在改那一份。同样的字,两种答案——而判错的代价比看上去大:一位正在改报告的访客说了「加一节」,结果被建出了另一份新文档。
第一版的修法是加一条规矩——文档开着时,永远不路由到写文档。bug 是止住了,同时也弄坏了另一件事:真想再要一份新文档的人,从此说不出口了。第二条规矩(画图请求必须字面上带「图」字)形状一样,代价也一样:它认不出*「这几个数字换个样子看看」*。
规矩摞规矩,说明做判断的不是该做判断的那个部件。现在语境进了定夺那一步——模型被告知有一份文档开着,并且多拿到一个选项:改这一份。它什么都不路由,因为改文档的那组工具本来就挂在这一轮上,它们才是干这件事的。两个原来的 bug 仍然是修好的,两件被误伤的真请求也回来了。
有一处不对称是刻意的:模型不可用、路由只能退回嵌入猜测时,文档开着的门槛更高。那边判错一次是整轮被劫持——正在讨论 21 天审查窗口的访客,收到的是一句「我没法为 21 天审查窗口画一张图」;而同样的错在普通对话里,最多多出一张没人要的图。
这对你的智能体意味着什么
- 只有上了菜单的能力才能被手打触发。 你没开深挖,访客说了也只会得到一个普通回答,而不是一项你没买的功能。
- 触发词不用你写。 没有租户级的关键词清单要维护,任何语言都没有。
- 一个需要宾语、而这句话里又没有的请求,会以「填回输入框」的形式回来,而不是替你猜一个。有人打了一句「研究一下呗」,题目会被填进输入框里,他发送前可以改——猜错的代价从白等一分钟降到改两个字。