entity_dedup

3 downloads 0 likes on ModelScope updated

Model card

Entity Dedup · 实体判重与合并命名

同一实体在不同对话中可能具有不同名称,导致信息重复或分散。基于BERT 二分类 + Qwen3.5-2B LoRA 命名的推理项目。输入两个候选实体,判断是否合并;合并时生成名称并合并描述。本项目包含推理代码及选定的 BERT、LoRA 适配器权重,不包含Qwen 基座权重,需要单独准备Qwen3.5-2B基座。

模型流程

flowchart TD
    IN["输入 JSON:A / B"] --> VALID["字段校验与白名单"]
    VALID --> RULE["现有推理规则:号码拦截优先,其次强制合并"]
    RULE -->|未命中| BERT["BERT:名称、类型、别名"]
    BERT --> SEM["CLS 768 → MLP 128 → 64 维"]
    VALID --> FEAT["Python:32 维硬特征"]
    FEAT --> SCALE["长度及计数 log1p + 标准化;其余保持原值"]
    SEM --> CONCAT["拼接 96 维 → MLP 128 → 1 → Sigmoid"]
    SCALE --> CONCAT
    CONCAT --> AVG["A/B 与 B/A 概率平均"]
    AVG --> DECISION["阈值判断,默认 0.5"]
    RULE -->|命中| DECISION
    DECISION -->|不合并| DROP["should_merge=false;合并字段为 null"]
    DECISION -->|合并| PROMPT["名称 + 可选描述;清洗描述日志时间戳"]
    PROMPT --> LORA["Qwen3.5-2B + LoRA:仅生成名称"]
    LORA --> PY["Python:别名并集、描述直接拼接"]
    PY --> OUT["输出 JSON"]

目录

.
├── config.json                 # 相对路径以配置文件所在目录为基准
├── predict.py                  # JSON / JSONL 推理入口
├── verify_artifacts.py         # 模型文件 SHA-256 校验
├── entity_merge/                # 独立推理实现、硬特征、词表和 prompt
├── models/
│   ├── bert/                   # 完整分类器、tokenizer、特征元数据
│   ├── lora/                   # LoRA 适配器及配套 tokenizer
│   └── manifest.json           # 模型文件摘要
├── examples/                   # 虚构示例
└── tests/                      # 无须权重的接口与规则测试

安装与配置

已验证环境为 Python 3.13.5、NVIDIA GPU、torch 2.9.0+cu128。先按设备环境安装 CUDA 版 PyTorch,再安装依赖。项目默认离线加载,不自动下载基座。

python -m pip install -r requirements.txt
python verify_artifacts.py

编辑 config.json 的 lora.base_model_path,指向完整的 Qwen3.5-2B 模型目录,目录中须包含 config、权重及其索引。可使用绝对路径,也可使用相对于配置文件的路径。例如 Linux 使用 /opt/models/Qwen3.5-2B,Windows 使用 C:/models/Qwen3.5-2B。

{
  "bert": {
    "checkpoint_dir": "models/bert",
    "device": "cuda:0",
    "threshold": 0.5,
    "batch_size": 16
  },
  "lora": {
    "base_model_path": "models/Qwen3.5-2B",
    "adapter_dir": "models/lora",
    "device": "cuda:0",
    "dtype": "bfloat16",
    "attn_implementation": "sdpa",
    "max_new_tokens": 96
  }
}

threshold 允许 0–1,概率大于等于阈值预测合并。LoRA 按需加载,全部不合并时不会加载基座。两个模型常驻同一进程;显存不足时可以让 BERT 使用 cpu,LoRA 仍用 GPU。纯 CPU 使用时将两处 device 改为 cpu、LoRA dtype 改为 float32,速度较慢。batch_size 用于 BERT 两种顺序的计算,当前 CLI 按候选对顺序推理。

输入格式

单条 JSON 对象、JSON 数组均支持;输入文件扩展名为 .jsonl 时逐行解析。可选 sample_id 原样回传,不进入模型。

{
  "sample_id": "demo-merge",
  "A": {
    "name": "蓝色收纳箱",
    "entity_type": "物品设备",
    "aliases": ["储物箱"],
    "description": "蓝色的收纳箱"
  },
  "B": {
    "name": "带盖收纳箱",
    "entity_type": "物品设备",
    "aliases": ["储物箱", "带盖箱"],
    "description": "有盖子的收纳箱"
  }
}
字段 类型 约束
A / B object 必填
name string 必填,非空
entity_type string 必填,非空,保持业务类别名称
aliases string[] 可省略,默认 []
description string / null 可省略,只进入 LoRA
sample_id string 可省略,调用方请求标识

其他字段不传入模型,尤其不使用 description_summary、标签、审核答案或召回分数。

输出格式

合并示例:

{
  "sample_id": "demo-merge",
  "should_merge": true,
  "merge_score": 0.9,
  "bert_probability": 0.9,
  "decision_source": "bert",
  "name_containment": 0,
  "new_name": "蓝色带盖收纳箱",
  "merged_aliases": ["储物箱", "带盖箱"],
  "description_merge": "蓝色的收纳箱;有盖子的收纳箱"
}
字段 说明
should_merge 最终是否合并
merge_score BERT 合并概率;规则拦截为 0,规则合并为 1。规则值不是模型置信度
bert_probability 实际 BERT 概率;规则跳过模型时为 null
decision_source bert、number_guard、action_wrapper 或 lead_customer
name_containment 原始名称相等或互为子字符串为 1,否则为 0;仅诊断标签
new_name LoRA 生成的名称;不合并时 null
merged_aliases Python 计算的别名并集;不合并时 null
description_merge Python 拼接原始描述;不合并时 null

执行推理

在项目根目录运行:

python predict.py --config config.json --input examples/input.json --output outputs/result.json

JSONL 示例:

python predict.py --config config.local.json --input requests.jsonl --output outputs/results.jsonl

输出形状随输入:对象对应对象、数组对应数组、JSONL 对应 JSONL。已有结果文件会被覆盖;只有整批成功后才原子替换文件,失败时保留原有文件并返回非零退出码。不会将错误生成结果当成“不合并”。日志写入终端,不进入结果 JSON。

Python 调用:

from entity_merge.runtime import load_pipeline

pipeline = load_pipeline("config.json")  # 进程内初始化一次并复用
result = pipeline.predict({
    "A": {"name": "蓝色收纳箱", "entity_type": "物品设备", "aliases": []},
    "B": {"name": "带盖收纳箱", "entity_type": "物品设备", "aliases": []}
})

输出名称可能存在遗漏,单行格式校验不代表语义完整性。此包提供推理接口,不将历史实验指标视为当前端到端链路的上线评估。

验证

python -m unittest discover -s tests -v
python verify_artifacts.py

单元测试覆盖不合并跳过 LoRA、合并字段、别名去重、描述保留、日志时间戳清洗、规则优先级、包含关系仍走 LoRA、输入白名单及生成失败行为。真实权重加载和端到端测试需要安装依赖并提供基座。

交付前已在真实 GPU 上通过随包示例完成一次端到端推理,实际结果见 examples/output.actual.json。