从零到一:用BERT与规则槽位快速构建机票预订意图识别系统
最近在帮一个朋友搭建一个智能客服的原型,核心需求是要能快速理解用户想订机票的意图,并且把出发地、目的地、日期这些关键信息给“抠”出来。时间紧,任务急,不可能从零开始训一个大模型。我的思路很直接:用现成的、强大的BERT模型来搞定“意图分类”这个核心判断,再用轻量、可控的规则来处理“槽位填充”这种结构化信息提取。没想到,从环境搭建到跑通第一个可用的Demo,前后真的没花太多时间。如果你也面临类似的需求——需要一个能快速验证、代码清晰、且效果不错的意图识别模块,这篇文章或许能给你一条清晰的路径。我们不谈空洞的理论全景,就聚焦于如何用最少的代码,搭建一个能实际运行、效果可接受的机票预订意图识别系统。
1. 环境准备与数据构造
在开始写任何代码之前,我们需要先把“战场”布置好。意图识别,尤其是基于深度学习的方案,对运行环境有一定要求。同时,由于我们做的是一个特定领域(机票预订)的Demo,可能没有现成的、标注好的大数据集,因此学会快速构造一份高质量的模拟数据至关重要。
1.1 搭建Python开发环境
我强烈建议使用 conda 或 venv 来创建一个独立的Python环境,避免包版本冲突。这里以 conda 为例:
# 创建一个名为 intent_demo 的 Python 3.9 环境
conda create -n intent_demo python=3.9
conda activate intent_demo
接下来安装核心依赖。我们将主要依赖 transformers 库来使用BERT模型,torch 作为深度学习框架,同时需要一些数据处理工具。
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 如果无GPU,使用CPU版本
pip install transformers pandas scikit-learn
注意:
transformers库版本迭代较快,如果遇到接口报错,可以尝试指定一个稍旧的稳定版本,例如pip install transformers==4.30.0。
安装完成后,可以在Python中快速测试一下关键库是否就绪:
import torch
import transformers
print(f"PyTorch version: {torch.__version__}")
print(f"Transformers version: {transformers.__version__}")
1.2 构造高质量的模拟训练数据
在真实的业务中,数据标注是耗时耗力的大工程。但对于我们的Demo和原型验证阶段,完全可以手动构造一份小而精的模拟数据。关键在于覆盖用户表达的核心多样性。
用户不会总是说“我要订一张从北京到上海的机票”。他们会用各种方式表达相同的意思。我们的数据需要尽可能模拟这些情况。我整理了几个构造数据的核心原则:
- 句式多样性:包含陈述句、疑问句、祈使句。
- 词汇多样性:使用“预订”、“购买”、“订一张”、“搞一张”等同义或近义表达。
- 口语化与简写:如“明天飞北京”、“京沪线有票吗”、“帮我弄张去伦敦的票”。
- 关键信息位置随机:目的地、出发地、日期在句子中的位置不固定。
- 引入少量负样本:加入非订票意图的语句,帮助模型更好地学习边界。
基于这些原则,我们可以用代码快速生成一份数据集:
import pandas as pd
import random
# 定义种子数据
origins = ['北京', '上海', '广州', '深圳', '成都']
destinations = ['上海', '北京', '杭州', '西安', '伦敦', '纽约']
dates = ['今天', '明天', '后天', '下周一', '下周五', '这个周末']
verbs = ['预订', '订一张', '买一张', '查一下', '看看', '帮我订']
patterns = [
"{verb}从{origin}到{destination}的机票",
"我想{verb}{date}去{destination}的航班",
"{date}从{origin}飞{destination},有票吗?",
"去{destination}的机票,{date}的",
"帮我{verb}{origin}到{destination}{date}的票"
]
# 生成正样本(订票意图)
positive_samples = []
for _ in range(150): # 生成150条订票意图样本
pattern = random.choice(patterns)
text = pattern.format(
verb=random.choice(verbs),
origin=random.choice(origins),
destination=random.choice(destinations),
date=random.choice(dates)
)
positive_samples.append({'text': text, 'intent': 'book_flight'})
# 生成负样本(其他意图)
other_intents = ['weather_query', 'music_play', 'greeting', 'joke']
negative_samples = [
{'text': '今天天气怎么样', 'intent': 'weather_query'},
{'text': '播放一首周杰伦的歌', 'intent': 'music_play'},
{'text': '你好', 'intent': 'greeting'},
{'text': '讲个笑话', 'intent': 'joke'},
{'text': '明天会下雨吗', 'intent': 'weather_query'},
{'text': '我想听摇滚乐', 'intent': 'music_play'},
# ... 可以继续补充更多
]
# 合并数据集
all_samples = positive_samples + negative_samples
df = pd.DataFrame(all_samples)
# 打乱数据顺序
df = df.sample(frac=1, random_state=42).reset_index(drop=True)
print(f"数据集大小: {len(df)}")
print(df['intent'].value_counts())
print("\n前5条数据:")
print(df.head())
这份模拟数据虽然简单,但已经具备了训练一个基础意图分类器所需的关键特征:明确的意图标签和足够丰富的文本表达变体。我们将把它保存下来,供后续步骤使用。
df.to_csv('flight_intent_data.csv', index=False, encoding='utf-8-sig')
2. 基于BERT的意图分类模型训练
有了数据,我们就可以开始构建模型的核心——意图分类器。这里我们选择BERT,因为它能很好地理解上下文,并且有高质量的中文预训练模型可以直接使用,省去了我们从零预训练的巨量成本。
2.1 数据预处理与加载
使用BERT前,需要将文本转换成模型能理解的数字ID(Token IDs)和注意力掩码(Attention Mask)。transformers 库中的 BertTokenizer 帮我们完成了这一切。
import pandas as pd
from sklearn.model_sel

1万+

被折叠的 条评论
为什么被折叠?



