瞬维AI踩过的坑:AI获客智能体线索去重与分级的实现细节

我们团队在做 AI 获客智能体的时候,有段时间被线索重复的问题搞得头大。同一个用户,在抖音评论问一句、私信问一句、视频号又留个言,后台就生成了三条线索,销售一天到晚打重复电话,客户都被打烦了,还浪费了大量人力。
后来我们花了一个多月做线索去重和分级系统,把重复线索率从最开始的 38 % 降到了 3 % 以下,今天把踩过的坑和实现细节写出来,给做同类系统的团队做个参考。

一、最开始用手机号去重,为什么完全不够用

最开始我们的去重逻辑特别简单:同一个手机号就算同一个线索。跑了一周就发现问题太大了:

  • 很多用户根本不留手机号,只留微信号或者抖音号,按手机号去重完全识别不出来
  • 同一个用户用不同的手机号咨询,也识别不出来
  • 用户留的手机号经常写错,少一位多一位,匹配不上
  • 同一个用户在不同平台留的联系方式不一样,根本对不上

最严重的时候,我们后台一周生成了一千两百多条线索,其中有近一半是重复的,销售打过去一半都是"我已经问过了",体验特别差。

二、多维度指纹去重:不能只靠联系方式

后来我们改成了多维度指纹去重,不再只看手机号,而是综合多个维度给每个用户生成唯一的身份指纹:
第一维是平台账号 ID。同一个平台的同一个用户,账号 ID 是唯一的,这个是最准的,优先用这个匹配。
第二维是联系方式。包括手机号、微信号、QQ 号,做归一化处理之后匹配,比如手机号去掉空格和横杠,微信号去掉大小写差异。
第三维是设备指纹。通过用户的设备信息、IP 地址、浏览器特征生成设备指纹,同一个设备的不同账号也能关联上。
第四维是行为相似度。比如用户的提问内容高度相似、咨询的时间接近、所在地区一样,就算联系方式不一样,也判定为同一个用户。

# 用户身份指纹生成逻辑
def generate_user_fingerprint(user_data):
    fingerprint = {}
    # 平台账号ID优先
    if user_data.get('platform_uid'):
        fingerprint['uid'] = user_data['platform_uid']
    # 联系方式归一化
    if user_data.get('phone'):
        fingerprint['phone'] = normalize_phone(user_data['phone'])
    if user_data.get('wechat'):
        fingerprint['wechat'] = user_data['wechat'].lower()
    # 设备指纹
    fingerprint['device'] = generate_device_fp(user_data['device_info'])
    # 行为特征
    fingerprint['behavior'] = {
        'region': user_data['region'],
        'intent': user_data['intent'],
        'consult_time': user_data['consult_time'].date()
    }
    return hash(fingerprint)

用了多维度指纹之后,重复线索率直接从 38 % 降到了 8 %,效果好了很多,但还是有漏网之鱼。

下面是完整的指纹匹配与线索合并逻辑,包括指纹存储结构、匹配判定和合并策略:

# 指纹存储结构:以指纹哈希为 key,value 保存该用户的所有线索
# 用 Redis 或内存表存储均可,生产环境建议加 TTL 防止无限膨胀
fingerprint_index = {}  # {fingerprint_hash: user_profile}

# 用户档案结构
def create_user_profile(lead):
    return {
        'user_id': None,          # 合并后分配的统一用户 ID
        'fingerprints': set(),    # 该用户的所有指纹哈希
        'leads': [lead],          # 关联的线索列表
        'first_seen': lead['consult_time'],
        'last_seen': lead['consult_time'],
    }

# 指纹匹配逻辑:按优先级逐维尝试,命中即判定为同一用户
def match_and_merge(new_lead, fingerprint_index):
    new_fp = generate_user_fingerprint(new_lead)

    # 1. 先按平台账号 ID 精确匹配(最准,优先)
    if new_fp.get('uid'):
        for fp_hash, profile in fingerprint_index.items():
            if new_fp['uid'] in profile['fingerprints']:
                return merge_lead(profile, new_lead, new_fp, 'uid')

    # 2. 再按归一化后的联系方式匹配
    for key in ('phone', 'wechat'):
        if new_fp.get(key):
            for fp_hash, profile in fingerprint_index.items():
                if new_fp[key] in profile['fingerprints']:
                    return merge_lead(profile, new_lead, new_fp, key)

    # 3. 最后按设备指纹 + 行为相似度做模糊匹配
    for fp_hash, profile in fingerprint_index.items():
        if new_fp['device'] in profile['fingerprints']:
            if behavior_similar(new_fp['behavior'], profile['behavior']):
                return merge_lead(profile, new_lead, new_fp, 'device+behavior')

    # 4. 都没命中,创建新用户档案
    profile = create_user_profile(new_lead)
    profile['user_id'] = new_lead['lead_id']
    profile['fingerprints'].add(hash(new_fp))
    fingerprint_index[hash(new_fp)] = profile
    return profile

# 合并策略:把新线索并入已有用户,并更新指纹集合与最近活跃时间
def merge_lead(profile, new_lead, new_fp, matched_by):
    profile['leads'].append(new_lead)
    profile['fingerprints'].add(hash(new_fp))
    profile['last_seen'] = max(profile['last_seen'], new_lead['consult_time'])
    # 记录命中维度,便于后续排查误判/漏判
    new_lead['matched_by'] = matched_by
    return profile

下面是线索从进入系统到完成去重和分级的完整流程:

flowchart TD A["线索进入系统"] --> B["多维度指纹生成"] B --> C["指纹匹配判定"] C --> D{"是否命中已有指纹"} D -- "是" --> E["合并为同一用户"] D -- "否" --> F["创建新用户档案"] E --> G["线索分级"] F --> G G --> H{"规则 + 小模型打分"} H --> I["S 级:高意向,24 小时内跟进"] H --> J["A 级:明确需求,48 小时内跟进"] H --> K["B 级:泛泛询问,一周内跟进"] H --> L["C 级:低意向,进入公海"]

三、线索分级:不要让销售在低意向用户上浪费时间

去重解决之后,我们又发现一个问题:销售的时间是有限的,一天打不了多少电话,但很多线索其实是低意向的,比如只是随便问一句,根本没有购买意向,销售把时间花在这些用户身上,转化率特别低。
所以我们又加了线索分级系统,根据用户的行为把线索分成 S / A / B / C 四个等级:

  • S 级:明确问价格、问服务内容、主动留联系方式,意向最高,24 小时内必须跟进
  • A 级:问了具体的功能问题,有明确需求,48 小时内跟进
  • B 级:只是泛泛问一下,没有明确需求,一周内跟进一次就行
  • C 级:纯闲聊、问无关问题,直接进公海,不用跟进

分级的规则是基于用户的对话内容、提问深度、是否留联系方式、咨询时长这些维度,用规则+小模型打分实现的,不用大模型,成本低速度还快。

下面是线索分级的具体实现,基于对话内容关键词、是否留联系方式、咨询时长等维度计算意向分数,再按阈值判定 S / A / B / C 四级:

# 意向关键词表:命中即加分,权重越高代表购买意向越强
HIGH_INTENT_KEYWORDS = ['多少钱', '价格', '怎么收费', '套餐', '怎么合作', '能试用吗']
MID_INTENT_KEYWORDS = ['怎么用', '支持哪些功能', '能对接吗', '有没有案例', '部署方式']

# 线索分级主函数:输入对话内容、是否留联系方式、咨询时长等特征,输出 S/A/B/C 等级
def grade_lead(conversation_text, left_contact, consult_minutes):
    score = 0

    # 1. 对话内容关键词打分
    for kw in HIGH_INTENT_KEYWORDS:
        if kw in conversation_text:
            score += 30          # 问价格/合作,意向最强
    for kw in MID_INTENT_KEYWORDS:
        if kw in conversation_text:
            score += 15          # 问功能/对接,有明确需求

    # 2. 是否留联系方式:主动留联系方式是强意向信号
    if left_contact:
        score += 25

    # 3. 咨询时长:聊得越久,意向越高
    if consult_minutes >= 10:
        score += 20
    elif consult_minutes >= 5:
        score += 10

    # 4. 按阈值判定等级,并给出对应的跟进策略
    if score >= 70:
        return 'S', score, '高意向,24 小时内必须跟进'
    elif score >= 45:
        return 'A', score, '明确需求,48 小时内跟进'
    elif score >= 20:
        return 'B', score, '泛泛询问,一周内跟进一次'
    else:
        return 'C', score, '低意向,直接进公海,不用跟进'

# 使用示例
grade, score, strategy = grade_lead(
    conversation_text='你们这个怎么收费?能试用吗?',
    left_contact=True,
    consult_minutes=12
)
print(grade, score, strategy)  # 输出:S 105 高意向,24 小时内必须跟进

四、实测效果和边界

上线去重和分级系统之后,我们跑了一个月的数据:

  • 重复线索率从 38 % 降到了 3.2 %
  • 销售的有效通话率从 42 % 提升到了 78 %
  • 线索转化率比之前提升了 60 % 多
    当然这个方案也有边界:如果用户完全用不同的设备、不同的联系方式、不同的账号来咨询,还是会识别成不同的用户,但这种情况在实际业务里占比不到 1 %,影响不大。另外行为相似度的阈值要根据自己的业务调,太松了会误判,太紧了会漏判。

写在最后

做获客系统,不要只盯着前端的对话智能,后端的线索处理其实更影响最终的转化效果。线索去重和分级看起来是小功能,但做好了能直接提升销售的人效,比多搞几个花里胡哨的对话功能有用多了。
做工程嘛,把基础细节做扎实,比什么都强。

本文为技术实践分享,不构成任何商业建议。

posted @ 2026-10-08 11:11  陆陆陆六  阅读(2)  评论(0)    收藏  举报