前文介绍了如何使用 LangChain 简化大模型接口调用,并实现了一个智能聊天机器人例子。想实现更复杂的智能应用,我们往往需要识别用户的意图,并根据意图采取不同的行动。
本文将介绍如何使用大模型分析对话上下文,并识别用户的意图。
意图识别
意图识别,顾名思义,就是识别用户的意图。用户输入一句话,系统需要结合对话历史,从中识别出这句话的意图,并给出相应的回复。
假设我们想实现一个智能客服系统,为用户查询相关数据,比如:
- 查询订单
- 查询物流
- 查询账户余额
- 查询积分
- 查询优惠券
- 查询商品
- 查询商品
系统需要根据用户提问,识别出用户意图,再调用对应工作流来查询数据。在这个过程中,用户意图识别是关键。由于用户提问千变万化,传统基于固定规则的意图识别方法,很难满足需求。
以最简单的积分查询为例,用户可能的提问方式包括:
block-beta
columns 2
U1(["👤 user"]) UM1("我的积分还有多少?")
A1(["🤖 assistant"]) AM1("查询积分")
space space
U2(["👤 user"]) UM2("我还有积分没兑换吗?")
A2(["🤖 assistant"]) AM2("查询积分")
space space
U3(["👤 user"]) UM3("我的积分会过期吗?")
A3(["🤖 assistant"]) AM3("查询积分")
显然,这种基于自然语言的提问方式,很难用固定规则来识别,只能借助大模型来分析对话上下文。
提示词
想用大模型识别用户意图,提示词的设计是关键。我们需要设计一个提示词模板,并根据对话历史,生成提示词。以最简单的角色设定为例,我们可以通过 system 消息,对大模型进行提示:
|
|
这是一份典型的角色设定提示词,系统通过这份提示词,告诉大模型:
- 角色,即大模型在对话中的身份
- 任务,即大模型需要完成的任务
- 限制,即大模型需要遵守的规则,比如输出格式约定等
接下来,我们写一些代码,来实现意图识别功能,看看这份提示词的效果。
|
|
这个例子很简单,只是在前面聊天机器人的基础上,优化了 system 角色设定提示词而已。虽然代码很简单,但实际测试的效果还可以:
block-beta
columns 2
U1(["👤 user"]) UM1("积分什么时候过期?")
A1(["🤖 assistant"]) AM1("查询积分")
space space
U2(["👤 user"]) UM2("我有订单没收到?")
A2(["🤖 assistant"]) AM2("查询物流")
space space
U3(["👤 user"]) UM3("我的积分会过期吗?")
A3(["🤖 assistant"]) AM3("查询积分")
space space
U4(["👤 user"]) UM4("我的生日是?")
A4(["🤖 assistant"]) AM4("unknown")
space space
U5(["👤 user"]) UM5("查询")
A5(["🤖 assistant"]) AM5("unknown")
space space
U6(["👤 user"]) UM6("积分怎么兑换?")
A6(["🤖 assistant"]) AM6("查询积分")
基本上,我们定义的几种预设意图,都能识别出来;对于不明确或者预设以外的情况,都能稳定输出 unknown 。注意到最后一个场景可能不太准确,系统没有提供兑换积分的预设,被误识别为查询积分了。不过不要紧,接下来我们为其加上一些样本提示,进一步提升它的准确性。
少样本提示
为提高大模型输出结果的准确性,我们可以为其提供一些样本提示,这就是所谓的 少样本提示(Few-shot Prompting)。 提示样本的格式很简单,只需要提供用户输入和意图标签即可,结构如下:
block-beta
columns 2
U1(["👤 user"]) UM1("用户输入")
A1(["🤖 assistant"]) AM1("意图标签")
如果用户意图需要根据多轮对话来判断,则可以提供包含多轮对话的样本,例如:
block-beta
columns 2
U1(["👤 user"]) UM1("用户输入①")
A1(["🤖 assistant"]) AM1("大模型提示")
U2(["👤 user"]) UM2("用户输入②")
A2(["🤖 assistant"]) AM2("意图标签")
设计好的提示样本,同样作为 messages 数组的一部分,提供给大模型即可:
block-beta
columns 2
S1(["👤 system"]) SM1("系统提示")
space space
U1(["👤 user"]) UM1("用户输入①")
A1(["🤖 assistant"]) AM1("意图标签①")
U2(["👤 user"]) UM2("用户输入②")
A2(["🤖 assistant"]) AM2("意图标签②")
U3(["👤 user"]) UM3("用户输入n")
A3(["🤖 assistant"]) AM3("意图标签n")
space space
U4(["👤 user"]) UM4("对话输入①")
A4(["🤖 assistant"]) AM4("大模型回答①")
U5(["👤 user"]) UM5("对话输入n")
A5(["🤖 assistant"]) AM5("大模型回答n")
U6(["👤 user"]) UM6("用户输入")
space Arrow<["LLM"]>(down)
A6(["🤖 assistant"]) AM6("意图标签")
如上图,整个 messages 数组包含三部分,从上到下依次是:
- 系统提示
- 样本提示
- 用户输入(包含对话历史及当前输入)
接下来,我们写一些代码,来实现意图识别功能,验证少样本提示的效果。
|
|
执行程序,可以看到大模型输出的意图标签,准确率比之前高了不少。起码,对于积分兑换的场景,大模型已经能正确识别成 unknown 了:
block-beta
columns 2
U1(["👤 user"]) UM1("积分怎么兑换?")
A1(["🤖 assistant"]) AM1("unknown")
space space
U2(["👤 user"]) UM2("积分兑换商城在哪?")
A2(["🤖 assistant"]) AM2("unknown")
后续,我们还可以继续增加和优化样本提示,进一步提升大模型的准确性。
总结
本文介绍了如何使用大模型识别用户意图,并给出了一个简单的例子。通过少样本提示,我们可以显著提升大模型的准确性。
【小菜学AI】系列文章首发于公众号【小菜学编程】,敬请关注: