精准数值场景下高区分度语义相似度匹配方案咨询
精准数值场景下的语义相似度匹配优化方案
问题背景
我有100+条数据分析相关语句,需要找出与用户提示最匹配的语句。这类场景对语义精准度要求极高,细微差异会导致完全不同的意图。比如:
- 变量x过去一周的变化幅度是否至少达到5%?
- 展示变量x过去一周的变化情况
在图表分析场景中,这两个语句的意图完全不同:前者是判断型查询(验证变化幅度是否达标),后者是展示型查询(仅需呈现变化数据),但通用NLP模型(如spaCY)会因词汇高度相似给出0.9+的高相似度评分,导致无法区分。
我当前使用的spaCY代码如下:
prompt_doc = nlp(user_prompt) similarities = [] for sentence in sentences: sentence_doc = nlp(sentence) similarity = prompt_doc.similarity(sentence_doc) similarities.append(similarity) print("Sentence:", sentence) print("Similarity rating:", similarity) print()
运行后发现100+条语句的相似度都在0.8-0.9区间,与实际语义差异不符,需要优化方案实现高区分度的语义匹配。
优化方案
1. 微调专用语义匹配模型
通用预训练模型没有针对数值分析场景的优化,需要用场景内的标注数据微调模型:
- 标注数据准备:针对你的100+语句,人工标注成对语句的相似度标签(比如0=完全不同,1=完全相同,0.5=部分相似),重点标注包含数值条件(如“至少5%”“超过10”)的语句对。
- 选择适配模型:选用专注于语义匹配的模型,比如
sentence-transformers中的all-MiniLM-L6-v2,它比spaCY更适合句子级相似度任务,且支持微调。 - 微调示例:
from sentence_transformers import SentenceTransformer, InputExample, losses from torch.utils.data import DataLoader # 加载基础模型 model = SentenceTransformer('all-MiniLM-L6-v2') # 准备标注数据(示例) train_examples = [ InputExample(texts=["变量x过去一周变化是否至少5%", "变量x过去一周变化是否至少5%"], label=1.0), InputExample(texts=["变量x过去一周变化是否至少5%", "展示变量x过去一周变化"], label=0.0), # 补充更多场景内的标注对 ] # 定义损失函数和数据加载器 train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=8) train_loss = losses.CosineSimilarityLoss(model) # 微调模型 model.fit(train_objectives=[(train_dataloader, train_loss)], epochs=3, warmup_steps=100) # 使用微调后的模型计算相似度 def calculate_similarity(prompt, sentences): prompt_emb = model.encode(prompt) sentence_embs = model.encode(sentences) similarities = model.similarity(prompt_emb, sentence_embs)[0].tolist() return similarities
2. 加入数值与意图特征工程
在语义嵌入之外,提取关键特征辅助区分:
- 数值条件提取:用正则表达式提取语句中的数值阈值(如“5%”“10”)、比较运算符(“至少”“超过”“等于”),如果两个语句的数值条件或运算符不同,直接降低相似度得分。
- 意图分类:先对语句进行意图分类(如“判断型”“展示型”“统计型”),不同意图的语句直接判定为低相似度。
- 特征融合示例:
import re def extract_numeric_condition(text): # 提取数值和比较词 comp_pattern = r"(至少|超过|不低于|不高于|等于|小于|大于)" num_pattern = r"(\d+(\.\d+)?%?)" comp_match = re.search(comp_pattern, text) num_match = re.search(num_pattern, text) return (comp_match.group() if comp_match else None, num_match.group() if num_match else None) def enhance_similarity(base_similarity, prompt, sentence): # 提取特征 prompt_comp, prompt_num = extract_numeric_condition(prompt) sent_comp, sent_num = extract_numeric_condition(sentence) # 意图判断(简单示例,可扩展为分类模型) prompt_is_judge = "是否" in prompt or "有没有" in prompt sent_is_judge = "是否" in sentence or "有没有" in sentence # 特征惩罚 if prompt_is_judge != sent_is_judge: base_similarity *= 0.2 if (prompt_comp != sent_comp) or (prompt_num != sent_num): base_similarity *= 0.3 return max(base_similarity, 0.0)
3. 使用专用领域模型
选择针对数据分析/BI场景预训练的模型,这类模型已经学习到领域内的语义差异:
- 比如
FinanceBERT(针对金融数据分析)、TableBERT(针对表格数据查询),这类模型对数值条件、查询意图的区分度更高。 - 直接调用模型计算相似度,无需大量微调也能获得比通用模型更好的效果。
4. 规则与模型结合的混合方案
对于明确的数值条件差异,先用规则过滤,再用模型计算相似度:
- 先通过正则匹配,将用户查询和候选语句按是否包含数值条件、数值阈值是否一致分成不同组;
- 仅在同组内使用模型计算相似度,不同组直接排除或赋予极低得分。
效果验证
优化后,针对示例中的两个语句,应该能得到接近0的相似度得分;而意图和数值条件一致的语句对,相似度得分接近1,实现精准区分。
内容的提问来源于stack exchange,提问作者hkrlys
相关产品推荐
相关产品推荐

