电话实现大规模姓名匹配02
上一讲,我们讲到通过ner命名实体识别,实现信息提取。
当我们分析完用户说的话,提取出对应的名称,接下来就是问题的重中之重。
如果用户说的内容asr翻译的是李命薄,或者用户不记得对方名字,只有他的昵称。鸵鸟。我们如何去解决这类问题。
多种方案
1:使用es做相似查询搜索
es及elasticsearch,熟悉es的人清楚,es将文本内容解析成token之后,使用倒排索引方式存储。
如果我们使用es进行相似匹配,效果可能不好,因为姓名此类,如何使用分词呢?按字分词检索?
2:使用词向量来做相似匹配。
我个人采用词向量方式。
什么是词向量,embedding 最近大模型爆火,很多人使用chatgpt,或者其他开源大模型时候,经常接触embedding。就是将文本转化为可以计算的向量。
词向量-可以使用对汉字的词向量,方式很多。
可以调用chatgpt的embedding接口
可以使用bert-embedding方式,甚至可以使用Word2vec等等经典方式处理。
解析出对应的embedding向量之后,将向量存储起来,形成embedding库,可以是内存,也可以其他。
然后根据用户的输入-ner结果,向量化后,计算相似度。
将输入和 embedding库进行匹配,查询出最相近的top-n,就是你要的结果。
import torch
from transformers import BertTokenizer, BertModel
from scipy.spatial.distance import cosine
# 加载BERT模型和tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
# 输入文本
text1 = "I like cats"
text2 = "I love dogs"
# 文本预处理和编码
input_ids = tokenizer.encode(text1, text2, add_special_tokens=True)
input_ids = torch.tensor(input_ids).unsqueeze(0) # 添加批次维度
# 计算BERT嵌入
with torch.no_grad():
outputs = model(input_ids)
embeddings = outputs.last_hidden_state # 获取最后一层隐藏状态的输出
embeddings = torch.mean(embeddings, dim=1) # 对序列维度求平均值得到句子级别嵌入
# 计算相似度
embedding1 = embeddings[0].numpy()
embedding2 = embeddings[1].numpy()
similarity = 1 - cosine(embedding1, embedding2)
print("Similarity:", similarity)
这样就可以完成了吗?
如果你做的这一步,其他很多场景已经满足了,但是? 上述的embedding词向量方式,是基于语义的,我们的姓名等大多数是无意义场景。
解释一下,使用深度学习训练的embedding在语义方面有很强大能力,比如女子和千金,字面上是无法相似的,但是语义上是相近的。
使用深度学习的embedding在此方面很有优势,但是并不试用此类场景。
我们可以采用,拼音方式,因为很多asr翻译字不准确和口音的问题,并不会很大程度影响拼音的概率。
比如-李贵-厉鬼,ligui、ligui,在拼音上是很相似的。
我们可以使用,因此使用拼音方式,将拼音转为embedding,再计算。