自学内容网 自学内容网

意图识别模型使用 基于BERT的对话意图和槽位联合识别 CPU运行BERT模型-亲测成功

意图识别模型使用 基于BERT的对话意图和槽位联合识别 CPU运行BERT模型-亲测成功

我们在开发AI-Agent智能体时,通常会使用提示词工程设置场景的带入,在实际项目中会有很多场景,如果所有提示词都放一起就会超过Token限制,则不得不拆分很多场景的提示词。
很多场景下,用户就必须要选择一个场景进入聊天,这样很不智能,意图识别用来做前置处理,判断用户输入的意图,然后帮用户选择场景。

意图识别:理解用户需求的第一步

在问答对话中,准确理解用户的意图是构建有效回答的关键。意图识别,即判断用户想要什么,相当于为系统定向选择场景,帮助系统更精确的选择回复路径。
例如:当用户询问:“查询电影票” 时,系统必须确定用户是想查询电影票,而不是演唱会票,飞机票等。

意图识别的难点:
    1. 多意图问题;用户的表达可能含有多个含义
    1. 语义模糊:用户输入不规范,或语言表达不标准,如错别字等。
    1. 上下文理解:不同场景和时间节点下相同的表达可能具有不同的意图。
常用的意图识别方法:
    1. 规则模板匹配:通过人工设定模板,如"从[地点]到[地点]的航班",将用户输入与模板匹配,从而判断意图。虽然精确度高,但需大量人力维护,不易推广。
    1. 统计机器学习: 通过提取文本特征,如词性标注和词向量化表示,借助支持向量机等模型进行分类。适合简单的分类,但在复杂意图下效果有限。
    1. 深度学习: 借助神经网络和预训练模型,无需人工设计特征,自动完成意图分类。尽管效果好,但需要大量标注数据。

在RAG系统中,意图识别是基础的前置任务,它将用户输入映射到最可能的意图,为后续的回答生成奠定基础。

基于BERT的对话意图

运行环境
Python 3.8
下载代码
git clone https://github.com/Linear95/bert-intent-slot-detector.git

pycharm开发工具导入项目

数据准备

示例代码里自带了测试数据在:data/SMP2019下,我们这里直接使用,先了解是怎么样使用,然后在根据自己的需求去训练数据

  1. 训练数据:
    以json格式给出,每条数据包括三个关键词:
    text表示待检测的文本,
    intent代表文本的类别标签,
    slots是文本中包括的所有槽位以及对应的槽值,以字典形式给出。
    在data/路径下,给出了SMP2019数据集作为参考。

数据样例如下:

 {
    "text": "开微信",
    "domain": "app",
    "intent": "LAUNCH",
    "slots": {
      "name": "微信"
    }
  }

利用data/SMP2019/split_data.py,我们可以再将SMP2019的所有数据拆分成一个训练集split_train.json和一个测试集split_test.json

运行split_data.py程序 报错:

UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 35: illegal multibyte sequence

在这里插入图片描述

增加编码格式:encoding=‘utf-8’

open('train.json', 'r', encoding='utf-8') as f

在这里插入图片描述

  1. 生产意图标签和槽位标签

运行extract_labels.py程序, 同样报错:

UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 35: illegal multibyte sequence

同样也是要增加编码格式:encoding=‘utf-8’

open('train.json', 'r', encoding='utf-8') as f
  1. 意图标签:

以txt格式给出,每行一个意图,未识别意图以[UNK]标签表示。以SMP2019/intent_labels.txt为例:

[UNK]
LAUNCH
QUERY
ROUTE
...
  1. 槽位标签:

与意图标签类似,以txt格式给出。包括三个特殊标签: [PAD]表示输入序列中的padding token, [UNK]表示未识别序列标签, [O]表示没有槽位的token标签。对于有含义的槽位标签,又分为以’B_'开头的槽位开始的标签, 以及以’I_'开头的其余槽位标记两种。
以SMP2019/slot_labels.txt为例:

[PAD]
[UNK]
[O]
I_ingredient
B_ingredient
...
根据示例数据,训练意图模型

可以直接修改train.py代码,然后运行

if __name__ == '__main__':
    # 训练示例数据,生成意图模型
    parser = argparse.ArgumentParser()

    # environment parameters
    parser.add_argument("--cuda_devices", type=str, default='0', help='set cuda device numbers')
    parser.add_argument("--no_cuda", action='store_true', default=False, help='whether use cuda device for training')

    # model parameters
    parser.add_argument("--tokenizer_path", type=str, default='bert-base-chinese',  help="pretrained tokenizer loading path")
    parser.add_argument("--model_path", type=str, default='bert-base-chinese',  help="pretrained model loading path")

    # data parameters
    parser.add_argument("--train_data_path", type=str, default='D:\PycharmProjects\\ai\\bert-intent-slot-detector\data\SMP2019\split_train.json',  help="training data path")
    parser.add_argument("--test_data_path", type=str, default='D:\PycharmProjects\\ai\\bert-intent-slot-detector\data\SMP2019\split_test.json',  help="testing data path")
    parser.add_argument("--slot_label_path", type=str, default='D:\PycharmProjects\\ai\\bert-intent-slot-detector\data\SMP2019\slot_labels.txt',  help="slot label path")
    parser.add_argument("--intent_label_path", type=str, default='D:\PycharmProjects\\ai\\bert-intent-slot-detector\data\SMP2019\intent_labels.txt',  help="intent label path")

    # training parameters
    parser.add_argument("--save_dir", type=str, default='D:\PycharmProjects\\ai\\bert-intent-slot-detector\saved_model',  help="directory to save the model")
    parser.add_argument("--max_training_steps", type=int, default=0, help = 'max training step for optimizer, if larger than 0')
    parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="number of updates steps to accumulate before performing a backward() pass.")
    parser.add_argument("--saving_steps", type=int, default=300, help="parameter update step number to save model")
    parser.add_argument("--logging_steps", type=int, default=10, help="parameter update step number to print logging info.")
    parser.add_argument("--eval_steps", type=int, default=10, help="parameter update step number to print logging info.")
    parser.add_argument("--saving_epochs", type=int, default=1, help="parameter update epoch number to save model")

    parser.add_argument("--batch_size", type=int, default=128, help = 'training data batch size')
    parser.add_argument("--train_epochs", type=int, default=10, help = 'training epoch number')

    parser.add_argument("--learning_rate", type=float, default=5e-5, help = 'learning rate')
    parser.add_argument("--adam_epsilon", type=float, default=1e-8, help="epsilon for Adam optimizer")
    parser.add_argument("--warmup_steps", type=int, default=0, help="warmup step number")
    parser.add_argument("--weight_decay", type=float, default=0.0, help="weight decay rate")
    parser.add_argument("--max_grad_norm", type=float, default=1.0, help="maximum norm for gradients")

    args = parser.parse_args()

    train(args)

在这里插入图片描述

也可以使用命令行动态传参的方式运行

可以使用以下命令进行模型训练,这里我们选择在bert-base-chinese预训练模型基础上进行微调:

python train.py \
       --cuda_devices 0 \
       --tokenizer_path "bert-base-chinese" \
       --model_path "bert-base-chinese" \
       --train_data_path "xxx\bert-intent-slot-detector\data\SMP2019\split_train.json" \
       --test_data_path "xxx\bert-intent-slot-detector\data\SMP2019\split_test.json" \
       --intent_label_path "xxx\bert-intent-slot-detector\data\SMP2019\intent_labels.txt" \
       --slot_label_path "xxx\bert-intent-slot-detector\data\SMP2019\slot_labels.txt" \
       --save_dir "xxx\bert-intent-slot-detector\saved_model" \
       --batch_size 32 \
       --train_epochs 5

运行成功后会在saved_model生成微调后的模型
在这里插入图片描述

运行模型 测试意图识别

运行detector.py程序,准备识别用户输入的意图

if __name__ == '__main__':
   
    model_path = 'saved_model/model/model_epoch2'
    tokenizer_path = 'saved_model/tokenizer/'
    intent_path = 'data/SMP2019/intent_labels.txt'
    slot_path = 'data/SMP2019/slot_labels.txt'

    model = JointIntentSlotDetector.from_pretrained(
        model_path=model_path,
        tokenizer_path=tokenizer_path,
        intent_label_path=intent_path,
        slot_label_path=slot_path
    )

    while True:
        text = input("input: ")
        print(model.detect(text))

下图能正确的识别输入的意图。
在这里插入图片描述

参考链接:https://github.com/Linear95/bert-intent-slot-detector


原文地址:https://blog.csdn.net/yinjl123456/article/details/144356846

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!