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

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

我们在开发AI-Agent智能体时,通常会使用提示词工程设置场景的带入,在实际项目中会有很多场景,如果所有提示词都放一起就会超过Token限制,则不得不拆分很多场景的提示词。

很多场景下,用户就必须要选择一个场景进入聊天,这样很不智能,意图识别用来做前置处理,判断用户输入的意图,然后帮用户选择场景。

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

在问答对话中,准确理解用户的意图是构建有效回答的关键。意图识别,即判断用户想要什么 ,相当于为系统定向选择场景,帮助系统更精确的选择回复路径。

例如:当用户询问:"查询电影票" 时,系统必须确定用户是想查询电影票,而不是演唱会票,飞机票等。

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

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

基于BERT的对话意图

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

pycharm开发工具导入项目

数据准备

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

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

数据样例如下:

shell 复制代码
 {
    "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代码,然后运行

python 复制代码
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 复制代码
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程序,准备识别用户输入的意图

python 复制代码
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

相关推荐
远方16092 小时前
14-Oracle 23ai Vector Search 向量索引和混合索引-实操
数据库·ai·oracle
Blossom.1182 小时前
使用Python和Scikit-Learn实现机器学习模型调优
开发语言·人工智能·python·深度学习·目标检测·机器学习·scikit-learn
scdifsn4 小时前
动手学深度学习12.7. 参数服务器-笔记&练习(PyTorch)
pytorch·笔记·深度学习·分布式计算·数据并行·参数服务器
DFminer4 小时前
【LLM】fast-api 流式生成测试
人工智能·机器人
郄堃Deep Traffic4 小时前
机器学习+城市规划第十四期:利用半参数地理加权回归来实现区域带宽不同的规划任务
人工智能·机器学习·回归·城市规划
何双新4 小时前
第23讲、Odoo18 邮件系统整体架构
ai·架构
海盗儿5 小时前
Attention Is All You Need (Transformer) 以及Transformer pytorch实现
pytorch·深度学习·transformer
GIS小天5 小时前
AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月7日第101弹
人工智能·算法·机器学习·彩票
阿部多瑞 ABU5 小时前
主流大语言模型安全性测试(三):阿拉伯语越狱提示词下的表现与分析
人工智能·安全·ai·语言模型·安全性测试
cnbestec5 小时前
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
人工智能·线性代数·触觉传感器