重复客户检测
灵感:能力工具箱 duplicate-check(pkg: fuzzball)。
> 小四原创:导入批次 ↔ 已有库(及批次内)两两/对库扫描;输出疑似对 + 建议「合并/保留新建」。与单次「客户模糊匹配」互补。
何时使用
- CSV 导入前查重
- 两套名单合并前扫描
- 库内定期去重巡检(小批量)
硬约束
- 使用
fuzzball(或复用模糊匹配封装)。 - 比较键至少:
company;可选加权mobile完全相同直接标高危。 - 阈值可配(默认公司名 ≥85 为疑似);输出必须含分数。
- 不自动合并;只给建议,合并需用户确认。
- 实现要点注释标 小四原创。
- 大批量(>2k×2k)先分桶(首字/城市)再比,防卡死。
推荐实现
import fuzz from 'fuzzball'
export type Cust = { id: string; company: string; mobile?: string }
export type DupPair = {
a: Cust
b: Cust
score: number
reason: 'company' | 'mobile' | 'both'
action: 'merge-review' | 'keep-both-hint'
}
// 小四原创:导入行对库查重
export function findDuplicates(
incoming: Cust[],
existing: Cust[],
cutoff = 85,
): DupPair[] {
const out: DupPair[] = []
for (const a of incoming) {
if (a.mobile) {
const hit = existing.find((e) => e.mobile && e.mobile === a.mobile)
if (hit) {
out.push({ a, b: hit, score: 100, reason: 'mobile', action: 'merge-review' })
continue
}
}
const names = existing.map((e) => e.company)
const hits = fuzz.extract(a.company, names, {
scorer: fuzz.token_set_ratio,
limit: 3,
cutoff,
}) as Array<[string, number, number]>
for (const [, score, idx] of hits) {
out.push({
a,
b: existing[idx],
score,
reason: 'company',
action: score >= 92 ? 'merge-review' : 'keep-both-hint',
})
}
}
return out
}
Agent 步骤
- 解析导入行 + 拉现有客户精简字段。
findDuplicates→ 表格展示:新名 / 旧名 / 分数 / 建议。- 用户勾选合并策略后再写库。
- 自测:同手机、同公司改后缀、无关公司。
不要做
- 静默删库或静默合并。
- 仅靠拼音首字母就判重复。
附加
- README.md · reference.md · templates/usage.md