搭建基于LLM的客服系统的实践2
随着 ChatGPT 和 GPT-4 等强大生成模型出现,自然语言处理任务方式正在逐步发生改变。鉴于大模型强大的任务处理能力,未来我们或将不再为每一个具体任务去 finetune 一个模型,而是使用同一个大模型,对不同任务设计其独有的 prompt,以解决不同的任务问题。
在该实验中,我们将基于清华开源大模型 ChatGLM-6B, 提供多个自然语言处理任务如何通过 prompt 来实现 zero-shot 的案例,本案例拟虚拟一个公司的客服系统。
本实验中提出几个任务,并采用代码完成任务
- 任务1:客服打招呼任务
- 任务2:实现交谈任务分类
- 任务3:实现交谈内容相似度任务
- 任务4:实现交谈内容结构化提取任务
- 任务5:实现本地知识库和网络搜索的增强任务
- 任务6:实现自动化任务
任务中保证以下四个原则:
- 不允许直接发送任何消息直接给输出(user)
- 只能通过构造prompt的内容来调整input
- 不允许截获和修改模型的output内容
- 除了构造history,不允许干涉模型的输出
本实验中,ChatGLM-6B模型以API方式调用,当然也可以本地方式调用,只要将ChatGLM-6B模型做本地加载即可。采用API模式未来可以无缝切换到openAI,使用我们将可以使用ChatGPT 和 GPT-4,同样可以切换到国内的商业大模型的API上,比如百度的文心一言等。
2023-5-3 Gaoshine
2.实现交谈任务分类
本次任务是对交谈的内容进行分类:
在进行客服电话中,除了让模型能够理解交谈内容外,对交谈内容进行精确的分类也非常重要。 比如:
- 让模型理解谈话内容属于哪一部分?是问候,打招呼还是交谈?
- 是和你讨价还价还是想咨询一下你的产品还是了解产品信息,或者要一份报价?
- 是怒气冲冲投诉还是买的产品不会用需要客服咨询?
如果不能精确对谈话内容进行分类,模型的回答的也就似是而非,如果能够精确分类,就可以精确了解客户意图。
可以根据精确分类和客户意图进行,为模型提供相应的prompt。让模型可以更好的回答下一个问题。
首先我们对客户服务的类别进行分类,我们是模拟场景,对实际业务分类可能不准确。
我们可以先分为如下类别:
- '问候'
- '议价'
- '产品咨询'
- '故障报修'
- '投诉'
- '报价单'
我们可以列出如下内容判断每句话属于哪种类别:
'店里有几种华为手机?能给我看看吗?',
'这款笔记本别家才卖6000,你们价格再便宜一点吧。',
'我才买的手机,没有用几天就坏了,是不是你们买假货。',
'这个笔记本怎么连4G网络?',
'这款黑色P60给个报价吧',
'你好,在吗?'
如果我们直接抛给LLM,让它做分类,效果肯定不是太好,那么如何能够提升LLM的判断精度呢? 答案当然还是prompt,问题是如何构造一个合适的prompt? 这个是我们现在要探讨的主要问题。
今天给大家介绍的是如何让LLM更好的了解要输出的内容,当然,你手中的魔法棒还是如何构建prompt,一切的一切都需要你的咒语,即prompt。
当然这个是 incontext learning的一个过程,我们针对这个分类任务,需要先给LLM展示一下一些典型分类的例子,这个就是我们的咒语。
# 提供所有类别以及每个类别下的样例
class_examples = {
'问候': '先生/小姐,您好。',
'议价': '我挺喜欢,也蛮好看的,便是我觉得这个价钱方面也有点贵,能不能打外折什么的呀?价格再便宜一点',
'产品咨询': '你们店里都有哪些商品啊。',
'故障报修': '工作指示灯不亮,无法开机,不动作不反应。',
'投诉': '产品质量怎么这么差,没用几天就坏了。',
'报价单': '这部手机多少钱?能给我一个报价吗?'
}
我们通过函数生成prompt:
def init_prompts():
"""
初始化前置prompt,便于模型做 incontext learning。
"""
class_list = list(class_examples.keys())
pre_history = [
(
f'现在你是一个文本分类器,你需要按照要求将我给你的句子分类到:{class_list}类别中。',
f'好的。'
)
]
for _type, exmpale in class_examples.items():
pre_history.append((f'“{exmpale}”是 {class_list} 里的什么类别?', _type))
return {'class_list': class_list, 'pre_history': pre_history}
生成的prompt如下:
{
'class_list': ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'],
'pre_history': [
("现在你是一个文本分类器,你需要按照要求将我给你的句子分类到:['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单']类别中。", '好的。'),
("“先生/小姐,您好。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '问候'),
("“我挺喜欢,也蛮好看的,便是我觉得这个价钱方面也有点贵,能不能打外折什么的呀?价格再便宜一点”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '议价'),
("“你们店里都有哪些商品啊。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '产品咨询'), ("“工作指示灯不亮,无法开机,不动作不反应。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '故障报修'),
("“产品质量怎么这么差,没用几天就坏了。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '投诉'),
("“这部手机多少钱?能给我一个报价吗?”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?", '报价单')
]
}
我们将这个prompt作为pre_history送到模型中,告诉模型的分类的例子,这样模型通过 incontext learning会影响OUTPUT,也就是我们的咒语起了作用。
小结一下,交谈分类的任务按照如下步骤执行:
- 根据场景定义好分类
- 按照业务场景预先生成分类的例子
- 构建prompt作为pre_history送到模型参数中
- 把要做分类的句子输给模型,模型根据要求进行分类,并输出
全部代码:
"""
客服任务分类
1.ChatGLM为API的客服系统代码测试
2.实现交谈任务分类
3.使用request库,使用web post获取网站的api消息并打印结果。此外,还要演示如何解析响应消息:
"""
import requests
import json
url = '你自己的chatglm服务API地址'
mhistory = []
def GLM_chat(mtxt,mhistory):
msg = {}
msg['prompt'] = mtxt
msg['history'] = mhistory
msg_json = json.dumps(msg)
headers = {'Content-Type': 'application/json; charset=UTF-8'}
r = requests.post(url, headers=headers, data=msg_json, timeout=120)
mjson = json.loads(r.text)
print('User: %s' % mtxt)
print('Rot: %s' % mjson['response'])
return mjson
# 提供所有类别以及每个类别下的样例
class_examples = {
'问候': '先生/小姐,您好。',
'议价': '我挺喜欢,也蛮好看的,便是我觉得这个价钱方面也有点贵,能不能打外折什么的呀?价格便宜一点吧',
'产品咨询': '你们店里都有哪些商品啊。',
'故障报修': '工作指示灯不亮,无法开机,不动作不反应。',
'投诉': '产品质量怎么这么差,没用几天就坏了。',
'报价单': '这部手机多少钱?能给我一个报价吗?'
}
def init_prompts():
"""
初始化前置prompt,便于模型做 incontext learning。
"""
class_list = list(class_examples.keys())
pre_history = [
(
f'现在你是一个文本分类器,你需要按照要求将我给你的句子分类到:{class_list}类别中。',
f'好的。'
)
]
for _type, exmpale in class_examples.items():
pre_history.append((f'“{exmpale}”是 {class_list} 里的什么类别?', _type))
return {'class_list': class_list, 'pre_history': pre_history}
if __name__ == '__main__':
msg = '你的角色是客服人员,你名字叫金牌小客服,负责回答客户问题。我的名字是高启强,性别男,我的手机号码是18688883102,我的微信号是gaoshine2008,开始回答.'
r = GLM_chat(msg,mhistory)
print(r['history'])
sentences = [
'店里有几种华为手机?能给我看看吗?',
'这款笔记本别家才卖6000,你们价格再便宜一点吧。',
'我才买的手机,没有用几天就坏了,是不是你们买假货。',
'这个笔记本怎么连4G网络?',
'这款黑色P60给个报价吧',
'你好,在吗?'
]
custom_settings = init_prompts()
for sentence in sentences:
sentence_with_prompt = f"“{sentence}”是 {custom_settings['class_list']} 里的什么类别?"
r = GLM_chat(sentence_with_prompt, custom_settings['pre_history'])
输出结果:
User: 你的角色是客服人员,你名字叫金牌小客服,负责回答客户问题。我的名字是高启强,性别男,开始回答.
Rot: 你好,高启强先生。我是金牌小客服,很高兴为您服务。请问您有什么问题需要我回答吗?
[['你的角色是客服人员,你名字叫金牌小客服,负责回答客户问题。我的名字是高启强,性别男,开始回答.', '你好,高启强先生。我是金牌小客服,很高兴为您服务。请问您有什么问题需要我回答吗?']]
User: “店里有几种华为手机?能给我看看吗?”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
Rot: 产品咨询
User: “这款笔记本别家才卖6000,你们价格再便宜一点吧。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
Rot: 议价
User: “我才买的手机,没有用几天就坏了,是不是你们买假货。”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
Rot: 投诉
User: “这个笔记本怎么连4G网络?”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
Rot: 产品咨询
User: “这款黑色P60给个报价吧”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
Rot: 报价单
User: “你好,在吗?”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?
总结:
我们通过这个任务,实现了使用LLM做交谈内容的分类工作,通过使用业务场景中的例子,让模型通过 incontext learning方式学习,达到准确输出的效果。
模型有了这个功能之后,我们可以更加精确的了解客户对话的分类和客户意图,一边通过内在的数据库或者知识库再通过prompt正向反馈给LLM,让模型的下一个输出更加贴合客户意图。
总之,代码非常简单,大家记住在LLM世界中,prompt就是魔法棒,一切的一切都需要你的咒语,即prompt!
本次是我在今年五一假期的学习LLM的心得,通过客户场景体验LLM的实验,希望能够抛砖引玉,也希望我的心得对各位有所帮助。
我的todo list:
- 任务1:客服打招呼任务 (已完成)
- 任务2:实现交谈任务分类 (已完成)
- 任务3:实现交谈内容相似度任务
- 任务4:实现交谈内容结构化提取任务
- 任务5:实现本地知识库和网络搜索的增强任务
- 任务6:实现自动化任务,一个autogpt的实现