意图识别模型使用 基于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

相关推荐
YDS82920 分钟前
DeepSeek RAG&MCP + Agent智能体项目 —— 集成ELK日志管理系统和Prometheus监控系统
java·elk·ai·springboot·agent·prometheus·deepseek
Resistance丶未来24 分钟前
管控用量,降本增效,MAI Gateway:助力企业搭建 Tokens 统一管理体系
人工智能·大模型·api·claude·ai安全·魔芋ai·maigateway
GIS数据转换器25 分钟前
无人机车载巡检系统
大数据·数据库·人工智能·数据挖掘·数据分析·无人机
逸模8 小时前
告别熬夜手工整理台账,逸模智能归集实现项目数据自动化存档
大数据·运维·人工智能·笔记·其他·信息可视化·自动化
fanly118 小时前
AgentForge 智能体组件:与云驿插件平台构建全生态化的微服务一体化智能开发引擎
微服务·ai·agent
weixin_397574098 小时前
生产管理和设备管理:制造执行层的AI痛点
人工智能·制造
冬奇Lab8 小时前
Agent 系列(16):工具链设计——让 LLM 用对工具的五个原则
人工智能·llm·agent
冬奇Lab8 小时前
每日一个开源项目(第125篇):taste-skill - 给 AI 装上审美,让前端不再千篇一律
人工智能·开源·agent
Ajie'Blog9 小时前
Copilot Agent Tasks API 开放:AI 编程开始进入后台任务时代
服务器·前端·javascript·人工智能·copilot·ai编程