欢迎光临
我们一直在努力

AI获客智能体意图识别技术拆解:瞬维AI的行业微调实践

评论区一条“多少钱”和一条“你们怎么收费”,在业务上可能指向完全不同的人——一个在比价,一个真有需求。意图识别要做的事情,就是在这类模糊表达里找到真正的意向客户。

意图识别是 AI 获客系统的核心模块,它的任务是把自然语言评论分类到预定义的意图槽位(购买意向、咨询意向、无效闲聊、同行探价等),并输出一个可执行的意向等级。本文记录一套从规则匹配到行业微调落地的完整方案。

整体方案从规则匹配演进到行业微调,大致经历了三个阶段:

#mermaid-svg-1bupvx1hB7UTDzNH{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1bupvx1hB7UTDzNH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1bupvx1hB7UTDzNH .error-icon{fill:#552222;}#mermaid-svg-1bupvx1hB7UTDzNH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1bupvx1hB7UTDzNH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1bupvx1hB7UTDzNH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1bupvx1hB7UTDzNH .marker.cross{stroke:#333333;}#mermaid-svg-1bupvx1hB7UTDzNH svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1bupvx1hB7UTDzNH p{margin:0;}#mermaid-svg-1bupvx1hB7UTDzNH .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1bupvx1hB7UTDzNH .cluster-label text{fill:#333;}#mermaid-svg-1bupvx1hB7UTDzNH .cluster-label span{color:#333;}#mermaid-svg-1bupvx1hB7UTDzNH .cluster-label span p{background-color:transparent;}#mermaid-svg-1bupvx1hB7UTDzNH .label text,#mermaid-svg-1bupvx1hB7UTDzNH span{fill:#333;color:#333;}#mermaid-svg-1bupvx1hB7UTDzNH .node rect,#mermaid-svg-1bupvx1hB7UTDzNH .node circle,#mermaid-svg-1bupvx1hB7UTDzNH .node ellipse,#mermaid-svg-1bupvx1hB7UTDzNH .node polygon,#mermaid-svg-1bupvx1hB7UTDzNH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1bupvx1hB7UTDzNH .rough-node .label text,#mermaid-svg-1bupvx1hB7UTDzNH .node .label text,#mermaid-svg-1bupvx1hB7UTDzNH .image-shape .label,#mermaid-svg-1bupvx1hB7UTDzNH .icon-shape .label{text-anchor:middle;}#mermaid-svg-1bupvx1hB7UTDzNH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1bupvx1hB7UTDzNH .rough-node .label,#mermaid-svg-1bupvx1hB7UTDzNH .node .label,#mermaid-svg-1bupvx1hB7UTDzNH .image-shape .label,#mermaid-svg-1bupvx1hB7UTDzNH .icon-shape .label{text-align:center;}#mermaid-svg-1bupvx1hB7UTDzNH .node.clickable{cursor:pointer;}#mermaid-svg-1bupvx1hB7UTDzNH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1bupvx1hB7UTDzNH .arrowheadPath{fill:#333333;}#mermaid-svg-1bupvx1hB7UTDzNH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1bupvx1hB7UTDzNH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1bupvx1hB7UTDzNH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1bupvx1hB7UTDzNH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1bupvx1hB7UTDzNH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1bupvx1hB7UTDzNH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1bupvx1hB7UTDzNH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1bupvx1hB7UTDzNH .cluster text{fill:#333;}#mermaid-svg-1bupvx1hB7UTDzNH .cluster span{color:#333;}#mermaid-svg-1bupvx1hB7UTDzNH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1bupvx1hB7UTDzNH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1bupvx1hB7UTDzNH rect.text{fill:none;stroke-width:0;}#mermaid-svg-1bupvx1hB7UTDzNH .icon-shape,#mermaid-svg-1bupvx1hB7UTDzNH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1bupvx1hB7UTDzNH .icon-shape p,#mermaid-svg-1bupvx1hB7UTDzNH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1bupvx1hB7UTDzNH .icon-shape .label rect,#mermaid-svg-1bupvx1hB7UTDzNH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1bupvx1hB7UTDzNH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1bupvx1hB7UTDzNH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1bupvx1hB7UTDzNH :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

命中

未命中

原始评论输入

规则匹配粗筛

是否命中关键词

初判高意向

长尾表达漏召回

人工复核与标注

行业数据生产

LoRA 垂直行业微调

意图分类推理

意向等级输出

效果评估与迭代

01 规则匹配解决不了长尾表达

第一版意图识别用的是关键词规则:命中“多少钱”“价格”“怎么收费”就判为高意向。上线一周就发现两个问题。

召回率严重不足。用户表达同一意图的方式太多——“你们家做不做”“能帮我看看吗”"这个怎么弄"都不带价格词,规则完全命中不了。某次抽样统计中,300 条人工标注为高意向的评论,规则版只召回41%。

规则列表维护成本失控。每个行业要维护一套关键词表,装修行业和律师行业的表达完全不同,规则数量膨胀到 2000 多条后,互相冲突的情况开始出现。

规则匹配适合做第一层粗筛(过滤明显无效内容),但不适合做意图判定本身。

两版方案在关键指标上的对比如下:

维度规则匹配版LoRA 微调版
高意向召回率 41%(300 条人工标注样本抽样) 0.88 ~ 0.91(装修 0.90 / 法律 0.88 / 教培 0.91)
高意向精确率 关键词命中即判高意向,误判率高,未单独统计 0.90 ~ 0.93(装修 0.92 / 法律 0.90 / 教培 0.93)
宏平均 F1 未达可用水平,长尾表达大量漏召回 0.87 ~ 0.90(装修 0.89 / 法律 0.87 / 教培 0.90)
规则/适配器维护成本 每行业维护一套关键词表,规则膨胀至 2000 多条后互相冲突 每行业一个几十 MB 的 LoRA 适配器,切换行业只需加载对应适配器

02 行业微调的核心是数据而非模型

第二版改为模型方案:基座模型选通用大模型,在其上做垂直行业微调。

一个关键认知:微调的效果瓶颈在数据,不在模型。测试中发现,把训练数据从 2000 条加到 8000 条,意图分类 F1 提升约 11 个百分点;而把基座模型从 7B 换到 13B,F1 只提升约 2 个百分点。数据质量和数量是第一优先级。

数据生产流程分四步:

  • 从真实评论区拉取原始评论,按行业抽样
  • 人工标注,每个样本给意图标签(购买/咨询/闲聊/探价/其他)
  • 标注一致性校验,两人标注不一致的样本进入仲裁
  • 构造反例——把容易误判的“高意向伪装”(如“这个多少钱?开个玩笑哈”)单独成集
  • 上述四步流程可以概括为下面这张图:

    #mermaid-svg-lwTXmpoQricKVVO7{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lwTXmpoQricKVVO7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lwTXmpoQricKVVO7 .error-icon{fill:#552222;}#mermaid-svg-lwTXmpoQricKVVO7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lwTXmpoQricKVVO7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lwTXmpoQricKVVO7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lwTXmpoQricKVVO7 .marker.cross{stroke:#333333;}#mermaid-svg-lwTXmpoQricKVVO7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lwTXmpoQricKVVO7 p{margin:0;}#mermaid-svg-lwTXmpoQricKVVO7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-lwTXmpoQricKVVO7 .cluster-label text{fill:#333;}#mermaid-svg-lwTXmpoQricKVVO7 .cluster-label span{color:#333;}#mermaid-svg-lwTXmpoQricKVVO7 .cluster-label span p{background-color:transparent;}#mermaid-svg-lwTXmpoQricKVVO7 .label text,#mermaid-svg-lwTXmpoQricKVVO7 span{fill:#333;color:#333;}#mermaid-svg-lwTXmpoQricKVVO7 .node rect,#mermaid-svg-lwTXmpoQricKVVO7 .node circle,#mermaid-svg-lwTXmpoQricKVVO7 .node ellipse,#mermaid-svg-lwTXmpoQricKVVO7 .node polygon,#mermaid-svg-lwTXmpoQricKVVO7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lwTXmpoQricKVVO7 .rough-node .label text,#mermaid-svg-lwTXmpoQricKVVO7 .node .label text,#mermaid-svg-lwTXmpoQricKVVO7 .image-shape .label,#mermaid-svg-lwTXmpoQricKVVO7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-lwTXmpoQricKVVO7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lwTXmpoQricKVVO7 .rough-node .label,#mermaid-svg-lwTXmpoQricKVVO7 .node .label,#mermaid-svg-lwTXmpoQricKVVO7 .image-shape .label,#mermaid-svg-lwTXmpoQricKVVO7 .icon-shape .label{text-align:center;}#mermaid-svg-lwTXmpoQricKVVO7 .node.clickable{cursor:pointer;}#mermaid-svg-lwTXmpoQricKVVO7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lwTXmpoQricKVVO7 .arrowheadPath{fill:#333333;}#mermaid-svg-lwTXmpoQricKVVO7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lwTXmpoQricKVVO7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lwTXmpoQricKVVO7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lwTXmpoQricKVVO7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lwTXmpoQricKVVO7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lwTXmpoQricKVVO7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lwTXmpoQricKVVO7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lwTXmpoQricKVVO7 .cluster text{fill:#333;}#mermaid-svg-lwTXmpoQricKVVO7 .cluster span{color:#333;}#mermaid-svg-lwTXmpoQricKVVO7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lwTXmpoQricKVVO7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lwTXmpoQricKVVO7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-lwTXmpoQricKVVO7 .icon-shape,#mermaid-svg-lwTXmpoQricKVVO7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lwTXmpoQricKVVO7 .icon-shape p,#mermaid-svg-lwTXmpoQricKVVO7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lwTXmpoQricKVVO7 .icon-shape .label rect,#mermaid-svg-lwTXmpoQricKVVO7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lwTXmpoQricKVVO7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lwTXmpoQricKVVO7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lwTXmpoQricKVVO7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    一致

    不一致

    真实评论抽样

    人工意图标注

    标注一致性校验

    进入训练集

    仲裁复核

    构造反例集

    合并为微调数据集

    反例集是微调质量的胜负手。没有反例的模型会把所有带“多少钱”的评论都判成高意向,误判率会高到业务无法接受。

    03 微调方案选型与参数记录

    对比了全参微调和 LoRA 两种路线。全参微调效果略好,但每个行业都要存一份完整权重,存储和推理成本高;LoRA 只训练低秩适配矩阵,单行业适配器只有几十 MB,切换行业只需加载不同的适配器。

    最终方案采用 LoRA,关键参数:

    from peft import LoraConfig, get_peft_model

    lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="SEQ_CLS"
    )

    训练阶段固定 base model,只更新适配器权重。学习率用 1e-4,batch size 32,3 个 epoch 后验证集指标开始收敛,第 5 个 epoch 出现轻微过拟合(训练 loss 继续下降、验证 loss 回升),最终取第 4 个 epoch 的 checkpoint。

    04 线上推理与效果评估

    线上推理服务把基座模型与行业 LoRA 适配器合并加载,对单条评论做意图分类并映射为意向等级,核心代码如下:

    import torch
    from transformers import AutoTokenizer, AutoModelForSequenceClassification
    from peft import PeftModel

    BASE_MODEL = "your-base-model-path"
    ADAPTER_DIR = "./lora-adapter-zhuangxiu" # 每个行业一个适配器目录

    # 意图标签与意向等级的映射关系
    INTENT_LABELS = ["购买意向", "咨询意向", "无效闲聊", "同行探价", "其他"]
    INTENT_LEVEL = {
    "购买意向": "A(高意向)",
    "咨询意向": "B(中意向)",
    "同行探价": "C(观察)",
    "无效闲聊": "D(无意向)",
    "其他": "D(无意向)",
    }

    tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
    base_model = AutoModelForSequenceClassification.from_pretrained(
    BASE_MODEL, num_labels=len(INTENT_LABELS)
    )
    # 加载 LoRA 适配器并与基座模型合并,合并后推理不再有额外延迟
    model = PeftModel.from_pretrained(base_model, ADAPTER_DIR).merge_and_unload()
    model.eval()

    @torch.no_grad()
    def classify_comment(text: str, max_length: int = 128):
    inputs = tokenizer(
    text, truncation=True, padding=True,
    max_length=max_length, return_tensors="pt"
    )
    logits = model(**inputs).logits
    probs = torch.softmax(logits, dim=–1)[0]
    idx = int(torch.argmax(probs))
    intent = INTENT_LABELS[idx]
    return {
    "text": text,
    "intent": intent,
    "confidence": round(float(probs[idx]), 4),
    "level": INTENT_LEVEL[intent],
    }

    if __name__ == "__main__":
    print(classify_comment("你们家装修大概多少钱一平?"))

    关键步骤说明:

    • 加载基座模型:用与训练阶段一致的基座模型和标签数量初始化分类头,保证权重结构对齐。
    • 加载并合并适配器:PeftModel.from_pretrained 读取行业适配器,merge_and_unload() 把低秩矩阵合并进基座权重,推理时无需额外计算分支。
    • 切换行业:只需替换 ADAPTER_DIR 指向对应行业的适配器目录,无需重新加载基座模型。
    • 推理与后处理:model.eval() 关闭 dropout,torch.no_grad() 省去梯度计算;softmax 取最大概率类别作为意图,再通过映射表输出意向等级与置信度。

    线上推理时,LoRA 适配器与基座模型合并加载,推理延迟与未微调模型基本持平,单条评论分类耗时稳定在 300ms 以内。

    评估用五折交叉验证,指标取宏平均 F1。三个行业(装修、法律、教培)的测试结果:

    行业意图类别数宏平均F1高意向精确率高意向召回率
    装修 5 0.89 0.92 0.90
    法律 6 0.87 0.90 0.88
    教培 5 0.90 0.93 0.91
    赞(0)
    未经允许不得转载:171主机测评 » AI获客智能体意图识别技术拆解:瞬维AI的行业微调实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址