Agent意图识别技术解析:从原理到工程实践

1次阅读
没有评论

共计 2636 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点:为什么需要更智能的意图识别?

在构建对话系统时,我们最早尝试用正则表达式和关键词列表来做意图识别。这种方式在简单场景下运行良好,比如:

Agent 意图识别技术解析:从原理到工程实践

  • 用户输入 ” 查看余额 ”,系统匹配关键词 ” 余额 ” 触发查询功能
  • 用户输入 ” 重置密码 ”,通过正则 / 重置 | 忘记.* 密码 / 匹配

但随着业务复杂化,我们遇到了典型问题:

  1. 语义模糊:用户说 ” 钱不见了 ” 可能是查询余额,也可能是投诉盗刷
  2. 表达变异:” 怎么还款 ” 和 ” 我要还信用卡 ” 需要识别为同一意图
  3. 长尾问题:每月新增约 15% 的未覆盖表达方式,规则维护成本指数上升

技术方案对比:从规则到 AI 的演进

规则引擎:高精准但难扩展

早期金融领域常用 Drools 等规则引擎,其优势在于:

  • 100% 准确率(在规则覆盖范围内)
  • 可解释性强,符合审计要求

但维护成本令人头疼:

# 典型规则维护场景
rule "贷款咨询"
when
    $input: String() 
    (matches(".* 怎么贷款.*", $input) || 
     matches(".* 借钱条件.*", $input))
then
    setIntent("LOAN_INQUIRY");
end

每新增一个表达方式都需要:

  1. 业务分析
  2. 规则编写
  3. 回归测试
  4. 生产部署

传统机器学习:特征工程的噩梦

采用 SVM/RandomForest 时,90% 精力花在特征工程:

  • 词袋模型(Bag-of-Words)
  • TF-IDF 权重
  • 人工设计对话特征(句子长度、是否含疑问词等)

主要问题:

  • 需要标注大量数据(万级样本)
  • 难以捕捉上下文关系
  • 准确率通常卡在 82-88% 的瓶颈

深度学习:Transformer 的突破

BERT 等预训练模型带来质变:

指标 规则引擎 传统 ML BERT-base
准确率 100%* 85% 93%
召回率 62% 83% 91%
维护成本

* 注:规则引擎准确率仅针对已覆盖场景

实战:基于 HuggingFace 的意图识别

数据准备

典型的银行场景意图分类数据集:

import pandas as pd

data = [["如何申请信用卡", "card_apply"],
    ["信用卡怎么办理", "card_apply"],
    ["还款日是哪天", "payment_query"],
    # 至少 2000 组样本...
]

df = pd.DataFrame(data, columns=["text", "intent"])

# 标签编码
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df["label"] = le.fit_transform(df["intent"])

模型微调

使用 DistilBERT 平衡精度与效率:

from transformers import DistilBertTokenizer, DistilBertForSequenceClassification

# 1. 加载预训练模型
tokenizer = DistilBertTokenizer.from_pretrained("distilbert-base-uncased")
model = DistilBertForSequenceClassification.from_pretrained(
    "distilbert-base-uncased", 
    num_labels=len(le.classes_)
)

# 2. 数据预处理
def encode_text(texts):
    return tokenizer(texts.tolist(), 
        padding=True, 
        truncation=True, 
        max_length=64,
        return_tensors="pt"
    )

# 3. 训练循环(简化版)for epoch in range(3):
    for batch in dataloader:
        inputs = encode_text(batch["text"])
        outputs = model(**inputs, labels=batch["label"])
        loss = outputs.loss
        loss.backward()
        optimizer.step()

关键技巧

  1. Attention Mask 处理

    # 标记真实文本长度(避免 pad 干扰)inputs = {
        "input_ids": tokens, 
        "attention_mask": (tokens != tokenizer.pad_token_id).int()}

  2. 类别不平衡解决方案

    # 使用加权损失函数
    from torch.nn import CrossEntropyLoss
    weights = torch.tensor([1.0, 2.0, 0.5])  # 根据样本数调整
    criterion = CrossEntropyLoss(weight=weights)

生产环境优化

模型量化

将 FP32 转为 INT8 提升推理速度:

from transformers import convert_graph_to_onnx

convert_graph_to_onnx.convert(
    framework="pt",
    model=model,
    output_path="intent_model.onnx",
    opset=12,
    quantization=True
)

实测效果:

  • 模型大小:从 260MB → 65MB
  • 推理速度:从 120ms → 28ms

Fallback 机制设计

处理低置信度预测:

probs = torch.softmax(outputs.logits, dim=-1)
top_prob, pred_label = torch.max(probs, dim=-1)

if top_prob < 0.7:  # 阈值可调
    return "FALLBACK"
else:
    return le.inverse_transform([pred_label])[0]

避坑指南

  1. 数据不平衡
  2. 对少样本意图进行数据增强(同义词替换、回译)
  3. 采用分层抽样(Stratified Sampling)划分数据集

  4. 过拟合

  5. 早停机制(Early Stopping)
  6. 冻结底层参数只微调顶层

    for param in model.base_model.parameters():
        param.requires_grad = False

  7. 版本控制

  8. 使用 MLflow 记录模型版本
  9. A/ B 测试新模型效果

开放问题

当用户输入完全超出预设意图(如银行场景下问 ” 怎么煮咖啡 ”),你的系统会:

  1. 直接回复 ” 不理解 ”?
  2. 引导用户重新表达?
  3. 触发人工客服?

建议尝试:

  • 用 RoBERTa-large 替换当前模型对比效果
  • 测试少样本学习(Few-shot Learning)应对新意图

欢迎在评论区分享你的解决方案!

正文完
 0
评论(没有评论)