搭建基于LLM的客服系统的实践2

搭建基于LLM的客服系统的实践2

随着 ChatGPT 和 GPT-4 等强大生成模型出现,自然语言处理任务方式正在逐步发生改变。鉴于大模型强大的任务处理能力,未来我们或将不再为每一个具体任务去 finetune 一个模型,而是使用同一个大模型,对不同任务设计其独有的 prompt,以解决不同的任务问题。

在该实验中,我们将基于清华开源大模型 ChatGLM-6B, 提供多个自然语言处理任务如何通过 prompt 来实现 zero-shot 的案例,本案例拟虚拟一个公司的客服系统。
本实验中提出几个任务,并采用代码完成任务

  • 任务1:客服打招呼任务
  • 任务2:实现交谈任务分类
  • 任务3:实现交谈内容相似度任务
  • 任务4:实现交谈内容结构化提取任务
  • 任务5:实现本地知识库和网络搜索的增强任务
  • 任务6:实现自动化任务

任务中保证以下四个原则:

  1. 不允许直接发送任何消息直接给输出(user)
  2. 只能通过构造prompt的内容来调整input
  3. 不允许截获和修改模型的output内容
  4. 除了构造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,也就是我们的咒语起了作用。

小结一下,交谈分类的任务按照如下步骤执行:

  1. 根据场景定义好分类
  2. 按照业务场景预先生成分类的例子
  3. 构建prompt作为pre_history送到模型参数中
  4. 把要做分类的句子输给模型,模型根据要求进行分类,并输出

全部代码:

"""
客服任务分类
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: “你好,在吗?”是 ['问候', '议价', '产品咨询', '故障报修', '投诉', '报价单'] 里的什么类别?

Screenshot 2023-05-03 at 11.29.59.png

总结:
我们通过这个任务,实现了使用LLM做交谈内容的分类工作,通过使用业务场景中的例子,让模型通过 incontext learning方式学习,达到准确输出的效果。
模型有了这个功能之后,我们可以更加精确的了解客户对话的分类和客户意图,一边通过内在的数据库或者知识库再通过prompt正向反馈给LLM,让模型的下一个输出更加贴合客户意图。

总之,代码非常简单,大家记住在LLM世界中,prompt就是魔法棒,一切的一切都需要你的咒语,即prompt!

本次是我在今年五一假期的学习LLM的心得,通过客户场景体验LLM的实验,希望能够抛砖引玉,也希望我的心得对各位有所帮助。

我的todo list:

  • 任务1:客服打招呼任务 (已完成)
  • 任务2:实现交谈任务分类 (已完成)
  • 任务3:实现交谈内容相似度任务
  • 任务4:实现交谈内容结构化提取任务
  • 任务5:实现本地知识库和网络搜索的增强任务
  • 任务6:实现自动化任务,一个autogpt的实现
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容