Дубли в CRM: как я сдался на Левенштейне и пришёл к эмбеддингам + ИНН

Дубли в CRM: как я сдался на Левенштейне и пришёл к эмбеддингам + ИНН

Как всё начиналось

Открываешь карточку клиента, звонишь, договариваешься — а через пару дней выясняется, что с ним уже полгода работает соседний отдел. Две цены, два договора, клиент в недоумении. У меня на одном внедрении в дистрибуции было именно так: 18 400 записей, после чистки осталось 11 200. Почти 40 % — дубли.

Воронка врёт, LTV завышен, отчёты в мусор. РОП каждое утро вручную склеивает карточки. Классика.

Что вообще бывает с названиями

Я разметил пару тысяч пар и увидел полный зоопарк:

  • «ООО Ромашка», «Ромашка ООО», «Общество с ограниченной ответственностью Ромашка»
  • ИП в трёх вариантах написания ФИО
  • разные кавычки, пробелы, «Ромашко» вместо «Ромашка»
  • холдинги, где «Торг» и «Логистика» — это два разных юрлица, хотя названия почти одинаковые

ИНН заполнен только у 41 %. Оставшиеся 59 % — пустые уже три года. Так что «просто сверим по ИНН» не работает.

Первая попытка — нормализация + Левенштейн

Сделал простую функцию: lower, убрал кавычки и оргформы, посчитал расстояние. На тесте получилось 71 % точности и 58 % полноты.

Левенштейн радостно склеивал «Ромашка-Торг» и «Ромашка-Логистика», но пропускал «ИП Иванов И.И.» и «ИП Иванов Иван Иванович». Потому что он смотрит на символы, а не на смысл.

Эмбеддинги: стало лучше, но появились новые проблемы

Перешёл на pgvector и русские модели эмбеддингов. Косинусная близость выше 0.92. Точность выросла до 84 %, полнота до 79 %.

Зато начал склеивать «Тёплый дом, ООО» и «Тёплый домик, ИП» — семантически близко, а юридически разные компании. Цена ошибки высокая.

Гибридный подход, который пошёл в прод

Сейчас у меня работает каскад:

  1. HNSW по эмбеддингам быстро отдаёт топ-10 кандидатов.
  2. Если ИНН совпал и валидный — дубль с уверенностью 0.99.
  3. Если ИНН разный — разные юрлица, точка.
  4. Если ИНН пустой — отдаём в небольшую LLM с жёстким промптом (400 токенов + few-shot).

Плюс добавил правило по телефону директора — сильный сигнал.

Результат на той же базе: точность 96.4 %, полнота 93.1 %. РОП тратит 40 минут в неделю вместо 6–8 часов. Две крупные сделки всплыли именно из «потерянных» дублей.

Сейчас при создании новой карточки триггер сразу ищет соседей и, если confidence > 0.85, показывает предупреждение.

Где всё ещё ломается

Холдинги с десятками однофамильных юрлиц — оставляю на ручную проверку. Иностранные контрагенты — отдельный канал. Старые CRM, где в названии лежит «Иванов И.И. (тел. +7...)» — сначала чистим регулярками.

Вывод

Одна метрика никогда не даёт больше 85 %. Нормально работает только каскад: быстрый отбор эмбеддингами, жёсткие правила по ИНН, LLM на спорных случаях и человек как арбитр. Всё остальное — либо дорого, либо опасно.