You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NER场景下带位置与相似度返回的近似字符串匹配替换高效方法

你需要的功能可以直接通过RapidFuzz库实现,不需要自己手动写滑动窗口逻辑,这个库本身支持返回匹配的相似度、起止位置,完全匹配你的需求。

实现方案

1. 依赖安装

执行命令安装RapidFuzz:
pip install rapidfuzz

2. 核心代码实现

from rapidfuzz import process, fuzz

def fuzzy_entity_replace(input_text: str, entity_mapping: dict, similarity_threshold: int = 80) -> str:
    """
    模糊匹配实体并替换为指定标签
    :param input_text: 预处理后的小写输入文本
    :param entity_mapping: 实体到替换标签的映射,比如 {"google": "COMPANY_NAME"}
    :param similarity_threshold: 匹配相似度阈值,0-100,低于阈值的匹配会被忽略
    :return: 替换后的文本
    """
    # 收集所有合法匹配
    match_records = []
    for entity, replace_tag in entity_mapping.items():
        # 查找当前实体在文本中的匹配结果,自动过滤低于阈值的结果
        match_results = process.extract(
            query=entity,
            choices=[input_text],
            scorer=fuzz.partial_ratio,
            score_cutoff=similarity_threshold
        )
        if not match_results:
            continue
        # 提取匹配的分数和起止位置
        similarity_score, (start_idx, end_idx) = match_results[0][1], match_results[0][2]
        match_records.append((start_idx, end_idx, similarity_score, replace_tag))
    
    # 处理匹配重叠的情况:优先保留分数更高、长度更长的匹配
    match_records.sort(key=lambda x: (-x[2], -(x[1] - x[0])))
    used_indexes = set()
    valid_matches = []
    for start, end, score, tag in match_records:
        # 检查当前匹配区间是否已经被其他更高优先级的匹配占用
        if not any(idx in used_indexes for idx in range(start, end)):
            valid_matches.append((start, end, tag))
            # 标记占用的位置
            for idx in range(start, end):
                used_indexes.add(idx)
    
    # 从后往前替换,避免前面的替换改变后面字符的索引位置
    valid_matches.sort(reverse=True)
    result_text = input_text
    for start, end, tag in valid_matches:
        result_text = result_text[:start] + tag + result_text[end:]
    
    return result_text

3. 使用示例

首先定义你的实体映射表:

company_entity_map = {
    "google": "COMPANY_NAME",
    "microsoft": "COMPANY_NAME",
    "facebook": "COMPANY_NAME",
    "international business machine": "COMPANY_NAME"
}

测试效果:

# 测试1:普通匹配
print(fuzzy_entity_replace("s/he works at google", company_entity_map))
# 输出:s/he works at COMPANY_NAME

# 测试2:多实体匹配
print(fuzzy_entity_replace("google and microsoft are big companies", company_entity_map))
# 输出:COMPANY_NAME and COMPANY_NAME are big companies

# 测试3:拼写错误的模糊匹配
print(fuzzy_entity_replace("i work at internatonal business machin", company_entity_map, similarity_threshold=75))
# 输出:i work at COMPANY_NAME

优化建议

如果你的实体量级超过1万条,或者需要处理大批量文本,可以做以下优化:

  • 用process.cdist批量计算所有实体和所有输入文本的相似度,比逐一遍历实体快3-10倍
  • 如果匹配精度要求更高,可以先对文本和实体做分词,改为基于token序列的模糊匹配,减少无关字符的干扰
  • 对于长度差异极大的实体,可以先按实体的token长度分组,减少匹配时的无效计算

内容的提问来源于stack exchange,提问作者hafiz031

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:27:08