
本文介绍一种基于正则表达式的高效方法,用于识别并提取文本中非连续但模式一致的重复词组(如asr输出中的循环幻觉),支持可变长度短语匹配,并提供可直接运行的python实现与实用优化建议。
本文介绍一种基于正则表达式的高效方法,用于识别并提取文本中非连续但模式一致的重复词组(如asr输出中的循环幻觉),支持可变长度短语匹配,并提供可直接运行的python实现与实用优化建议。
在自动语音识别(ASR)后处理中,模型幻觉常表现为同一语义片段的多次重复(如 "i wont be going to" 连续出现6次),这类错误虽不总相邻,但具有高度结构一致性。单纯依赖 r"(\w+)\s+\1" 只能捕获单个词重复,无法应对多词短语的周期性复现。我们需要的是可变长度、大小写不敏感、支持空格归一化的子串重复检测机制。
以下是一个稳健的解决方案:
import re
def find_repeated_phrases(text, min_words=2, max_words=8, min_repeats=2):
"""
检测文本中重复出现的词组(长度为 min_words ~ max_words 的单词序列)
返回所有匹配的完整重复片段及其基础单元
"""
# 预处理:统一空白符,转小写便于忽略大小写差异
cleaned = re.sub(r"\s+", " ", text.strip().lower())
results = []
# 尝试不同长度的词组(从短到长,优先返回更紧凑的模式)
for n in range(min_words, max_words + 1):
# 构建正则:匹配 n 个单词组成的短语,后跟至少 (min_repeats-1) 次相同短语(允许中间有空格)
# 使用 \b 确保单词边界,避免子串误匹配
pattern = r"((?:\b\w+\b\s+){" + str(n) + r"}\b\w+\b)(\s+\1){" + str(min_repeats - 1) + r",}"
matches = re.finditer(pattern, cleaned)
for m in matches:
full_match = m.group(0).strip()
phrase = m.group(1).strip()
if len(phrase.split()) == n: # 二次校验长度
results.append({
"full": full_match,
"phrase": phrase,
"repeats": len(re.findall(r"\b" + re.escape(phrase) + r"\b", full_match))
})
# 去重:保留最长匹配(更可能为真实意图),或按首次出现排序
seen = set()
unique_results = []
for r in results:
key = (r["phrase"], r["repeats"])
if key not in seen:
seen.add(key)
unique_results.append(r)
return unique_results
# 示例使用
text = "I'm not well, I think I wont be going to i wont be going to i wont be going to i wont be going to. Maybe tomorrow..."
for item in find_repeated_phrases(text, min_words=3, min_repeats=3):
print(f"重复片段: '{item['full']}'")
print(f"基础短语: '{item['phrase']}' (共 {item['repeats']} 次)")
print("---")关键设计说明:
- ✅ 长度可控:通过 min_words/max_words 限定候选短语长度(推荐 2–5 词),避免过短(易误报)或过长(漏检)。
- ✅ 鲁棒预处理:re.sub(r"\s+", " ", ...) 统一空白符,.lower() 忽略大小写,提升 ASR 文本兼容性。
- ✅ 边界保护:正则中使用 \b 确保匹配完整单词,防止 "go" 匹配 "going"。
- ⚠️ 注意局限:该方法假设重复是近似连续的;若重复片段被标点、停顿词(如 “um”, “like”)隔开,需先做轻量清洗(如移除常见填充词)。
进阶建议:
- 对于高噪声 ASR 输出,可结合 difflib.SequenceMatcher 计算短语相似度,容忍轻微拼写变异;
- 将检测结果作为后处理信号:自动折叠重复、触发人工审核,或反馈至模型微调阶段;
- 在生产环境建议添加超时控制(如 regex.compile(..., timeout=1))防止复杂正则导致阻塞。
此方法无需外部NLP模型,轻量、可解释、易于集成,是ASR流水线中低成本提升文本可信度的有效最后一道防线。

















