大家好,我是小林。
话说大家国庆回老家,亲戚三缺一,被拉上桌凑人头的同学应该不少吧。
然后可能还不太会打,最怕的就是嘴比手快:「打个九条吧,不对,还是打东风」,话还没说完,九条已经扔出去了。
不过古人云「天行健,君子以自强不息」,回来我就自己搓了个麻将陪练。每次轮到我出牌,它就在旁边盯着我的牌,告诉我该打哪张。
你看,它让我打东风,我就乖乖打东风,大脑直接放空,躺着胡牌,此事其实早在当年柯洁被阿尔法狗拿下时就有所记载
那这时就有同学要问了「小林小林,你这个是怎么搞的,教教我呗😘」
我这人向来最惦记大家了,这就安排上!
话说今年 9 月 15 日 TypeSafe AI 放出了决策模型 Jev,三天后开源的 Laya 也跟着登场,两家主打的都是一件事:判断用户想干什么,不用每次都请大模型出马,小模型也能又快又准。
到了十月,中电信人工智能科技有限公司星辰通用人工智能实验室(下文简称星辰实验室)也带着 Xing4.0-29B-Intent 杀进来了。
Xing4.0-29B-Intent 是星辰实验室专门为意图理解练出来的。说人话就是,听懂你这句话想干嘛,再把里面的关键信息抠出来。
是基于 Xing4.0-29B-A4B 微调,开源项目叫 Xing USP,我的麻将陪练也是用它搞的。
那它判断用户意图到底怎么样?官方拿了 5606 道题,让几个模型一起做,成绩是这样的。Xing4.0-29B-Intent 拿了 70 分,Jev 是 56 分,GPT-6-Luna 是 65 分,这里比的是意图判断,还没考到提取参数。
大家可以留意下「多选题」和「负例」这两列。用户一句话交代了好几件事,它更不容易漏掉,没有匹配的意图时,它也更少硬猜一个出来。
────Xing4.0-29B-Intent 跟 Jev 有什么区别?────
要说区别,得先看看它的对手 Jev。
翻 Jev 的官方文档会发现,它能答的题就三种:choice 是从几个选项里挑一个,score 是在几档里打个分,noul 是判断是或者不是。
一次请求可以连问好几道,每道题的答案都得从你事先写好的选项里出,Jev 会给每个选项报一个概率。
说白了,Jev 就是个做选择题的高手嘛。
我们上学的时候做选择题,靠的是「三短一长选最长,参差不齐就选 C」,Jev 可是真把题读懂了再选的哈。
可现实里的用户,不会照着你的选项说话。
拿客户群里常见的一句话来说:「下周三下午方便来做个演示吗?顺便发一下企业版 50 个账号的报价」。
交给 Jev,按它的题型你得先出两道 noul(是否为真),要不要演示,要不要报价,最后它能告诉你,演示要,报价也要。
可然后呢?「下周三下午」你没法提前写进选项吧,50 个账号,总不能把 1 到 1000 挨个列一遍吧。所以 Jev 只知道客户要啥,至于哪天要、要多少,它只能两手一摊。
但如果交给 Xing4.0-29B-Intent,回来的就是两组数据:预约演示,下周三下午。询价报价,企业版,50 个账号。
这样程序拿到 JSON,就知道该约哪天、该报多少个账号的价了,不用只拿着一个「询价」标签,再回聊天记录里找半天。
有一点得说清楚,Xing4.0-29B-Intent 回的就是一个确定的结果,没有 Jev 那种每个选项的概率,相当于它帮你做了填空的样子。
区别讲清楚了,接下来看看怎么把它接进自己的项目里。
────怎么接入 Xing4.0-29B-Intent?────
我这里接入走的是 OpenAI 兼容接口,base_url 填 https://api-maas.teleai.com.cn/v1,模型名填 Xing4.0-29B-Intent。
Key 在天翼 AI 开放平台的「API Key 管理」页面点「创建应用」生成。
天翼 AI 开放平台:https://console.teleai.com.cn
对了,平台送了 1 亿 tokens 的免费额度,3 个月内有效,白嫖党狂喜。拿来跑自己的业务场景绰绰有余,领取的方式看下面的操作。
接下来就得给它交代活儿了。你想让它认出什么,还要顺手带回哪些信息,都写进 schema 里。比如客户说想约个演示,光知道「他要演示」还不够,约在哪天也得一起拿回来。
● ● ●[{"category": "预约演示",
"category_description": "客户想约我们给他们演示产品,或者约时间开会看方案。",
"args": [{"name": "时间", "description": "客户提出的演示时间,如下周三下午。"}]},
{"category": "其他意图",
"category_description": "与上述类别都无关的消息。", "args": []}]
最费心思的是每个意图的说明。你得跟它讲明白,什么话算这个意图,跟隔壁的意图又怎么分。参数倒简单,想要啥就列啥。最后千万记得留个「其他意图」兜底,不然客户发句「在吗」,它也会硬着头皮塞进某个意图里,主打一个不懂装懂。
schema 写好之后,把它和用户原话一起套进官方给的模板,拼成一条 user 消息发出去,模板照抄就行。
● ● ●client =OpenAI(base_url="https://api-maas.teleai.com.cn/v1",api_key="你的 Key")
content=(TEMPLATE# 官方模板:### 任务说明 / ### 字段说明 / ### 输入内容
.replace("{intent_descriptions}",json.dumps(schema,ensure_ascii=False))
.replace("{user_input}",user_text))
resp=client.chat.completions.create(
model="Xing4.0-29B-Intent",
messages=[{"role":"user","content":content}], # 只发这一条,不传 system
temperature=0,
max_completion_tokens=512,
extra_body={"chat_template_kwargs":{"enable_thinking":False}},
)
intents=json.loads(resp.choices[0].message.content.strip())
这里有两个地方要注意。
第一,别传 system 消息。平时写提示词,第一句都习惯写「你是一个资深的 xxx 专家」,那你得忍住,system 是官方预置好的,文档里写明了不许改也不许传。
别传 system!别传 system!别传 system!
第二,schema 里的键名一个都别动,category 那一层也好,args 里的 name 和 description 也好,改了它就可能认不出来了。
多轮对话也放进同一条消息里,按「Human:」「AI:」一轮一行往下写,它会按最后那句判断意图,如果有缺少的参数也会从前面几轮里找。
────实测 Xing4.0-29B-Intent────
麻将陪练:帮我判断打哪张
那我们先来试试开头那张牌桌。
每次轮到我出牌,程序就把我的手牌写成一段文字发给 Xing4.0-29B-Intent,右边马上显示它建议打哪张,那张牌上面也标好了「建议打出」。
别人打出的牌我能碰能胡时也一样,它会判断碰还是胡。当然最后点哪张,还是我自己来。
我给它定了三类意图,出牌、碰、胡。出牌要它告诉我打哪张,怎么挑我直接写进说明里,先打凑不成搭子的孤张,字牌最优先,其次是一和九。碰和胡也得说清楚是哪张牌。
然后回到牌桌这里,它叫我打出九万,那么一二三万和五六七万都成了顺子,剩下的牌就听二条了
上家打了张五筒,我手里正好一对,牌桌上弹出碰和过,它判断碰,碰的按钮也很贴心给我圈出来了,我直接大手一挥即可:
最后我上家放了张二条,那么没啥好说的,直接胡牌了:
当然也不是回回都对。我随手拿了几十手牌试,十手里大概能对九次。陪练陪练,陪着练嘛,最后打哪张还得自己拿主意,但是已经对我的赌神之路有很大的帮助了哈哈。
而且注意每次判断基本半秒就回来,完全跟得上牌桌的节奏,不等你反应过来它就给出指示了。
飞书客户群:一句话里的两件事
相信做 ToB 的同学应该都有几个这样的客户群,客户想到什么就发什么,又是约演示的,又是要报价的,然后又来个报故障的,全混在一个群里。
比如假设现在小林在群里当商务,客户是马老板。我给它定了五类意图,马老板每发一条,Xing4.0-29B-Intent 就判断一次。
马老板先来了刚才那句,消息一进群,后台就把它和 schema 一起发给 Xing4.0-29B-Intent,请求和返回是这样的:
不过总不能让商务对着一堆 JSON 找时间、数账号吧。我顺手给它做了张卡片,就放在聊天框旁边,要干什么、哪天干,扫一眼就知道:
时间、账号数都是从马老板原话里直接抠出来的,商务扫一眼就知道该干嘛,哪天去演示、报几个号的价。
然后马老板来了一句我们最怕的:「上次那个方案再发我一下」
做过乙方的都懂,「上次那个」这四个字有多吓人,我电脑里叫方案的文件,从「最终版」一路排到「最最终版」和「打死不改版」。
我回问了一句是哪一份,马老板补了一句:「周一那份私有化的,改成 30 人」
这句话单拿出来,可能就是一头雾水,谁也不知道在说啥。但是它结合前面两轮,判断出是询价报价,版本是私有化,账号数 30。
想起来 GitHub 上有人给 Jev 做了个中文体验台 jev-demo,里面有道「工单分派」预设,客户说 Stripe 连了三天都失败。
我把这句原样搬进了群里:「你好,我已经尝试连接 Stripe 账户三天了,集成一直失败。我正在损失订单。请尽快帮忙处理。」
Jev 在体验台里要答的只能是三道选择题:归哪个部门,客户有多生气,急不急。
而 Xing4.0-29B-Intent 这边直接判成投诉故障,关键信息也一个没落:出问题的是 Stripe 账户,已经三天,正在损失订单,紧急程度标成紧急。售后一看就知道这单得马上处理,不用再回去翻聊天记录。
最后马老板回了一句「哈哈好的👌」。
它判成确认收到,我就没再回话,事情终于告一段落了,不容易啊,模型有的选,我们牛马没得选。
面经抽成题库
然后说回我的老本行,小林超级无敌大面筋
如果我现在想去牛客上找每天的新面经的话,会遇到一个头疼的问题,题目全混在一大段文字里,想整理成题库,只能一道道手动复制。
比如我挑了一篇「抖音用户产品-后端一面面经」,作者一口气写了 12 道题。
这篇帖子丢给 Jev,它顶多告诉你,嗯,这是篇后端面经。然后呢?没有然后了。
于是我给 Xing4.0-29B-Intent 的 schema 只定一个「面试题」意图,外加兜底的其他意图,参数里除了题目原文和考点,还带上公司和岗位这类帖子信息。
我把整篇面经直接贴了进去。刚才还混在一大段话里的公司、岗位、题目、面试轮次,这下都给我分出来了:
我让程序把它一条条写进了飞书多维表格。
到这一步,题目已经一道道躺在表格里了,省得我来回复制粘贴。接下来就轮到小林加狠活,给它们配上解答,再整理到网站上。科技与狠活制作的大面筋,喜不喜欢✌️。
不过可惜的是原帖作者最后说「感觉挂了,好多都不太清楚」。兄弟别灰心,这波面经算是帮大家攒了人品,祝你 offer 多多。
接进 MewHelp 客服
最后拿个企业的生产级别项目来。
MewHelp 是小林的AI Agent 智能客服实战配套项目。它里面有个意图识别是九类意图里选一个,假如现在有判断退款订单号的意图,我们可以试试这个模型能不能正确辨别。
现在把意图模块换成 Xing4.0-29B-Intent。schema 还是填写原来那九类意图,加上要抽的参数,比如订单号和退款原因。
核心改动就是分类节点这一段。
● ● ●async def_classify_intent_xing(state)->dict:
intents=awaitxing_intent.parse(_user_text(state),_history_pairs(state)) \
or[{"category":"其他","args":[]}]
first=intents[0]
args={k:vforainfirst.get("args",[])fork,vina.items()}
# 一件事照旧按九类分流,几件事一起交给主力 Agent 按顺序办
route="business"iflen(intents)>1elseINTENT_TO_ROUTE.get(first["category"],"business")
out={"intent":first["category"],"intents":intents,"route":route}
ifoid:=xing_intent.normalize_order_id(args.get("订单号")): # 订单号直接从参数里拿
out["order_id"]=oid
return out
再拿这句话试一遍,发给 Xing4.0-29B-Intent,回来的是两组:
分类节点拿到这两组,整理成任务清单交给主力 Agent:
物流 1001,退款 1003,两个单号分得清清楚楚。又准又快,还比大模型便宜不少,我是真有点心动,打算认真考虑接进生产项目了。
到聊天页上我们也能看到,物流说完之后,1003 的退款工单入口也一起给出来了。
────写在最后────
最后一句话总结,Jev 做的是选择题,告诉你用户大概率想干嘛。Xing4.0-29B-Intent 是选择题加填空题,想干嘛、具体要啥,一次全给你。
做客服和群机器人的同学,很推荐去试试,又或者你也想让ai辅助打游戏,和女朋友聊天,都是可以的🌝。
开源地址放在下面:
这次开源的也不只有模型,训练语料和一套推理引擎也一起放出来了。
意图识别这种小赛道,现在也有人专门做模型,还把语料一起开源,后来的人能少攒不少数据,这对做应用的我们是实打实的好事👍。
好了,今天就到这里,我先去练习麻将了,拜拜!