前言
用户在输入商品名称时,可能会因为拼写错误、同音字、形似字等问题而导致搜索结果不准确,影响用户体验。本文提出了一种通用的基于AI向量搜索的方案,旨在提高搜索词和商品名称之间的匹配度,从而避免零召回现象。
示例
对错误的搜索词,本方案给出的最近似纠正结果如下:
- 单氨胖光酸
-
Request:
GET /search?word=单氨胖光酸&top=1&pinyin=1
-
Response:
{ "code": 1, // 1: 成功,其他:失败 "message": "success", "result": [ { "index": "WORD", // 索引名称 "code": "15273", // 字典中的词条代码 "word": "甘草酸单铵半胱氨酸氯化钠注射液", // 字典中的词条名称 "score": 5, // 评分 "distance": 0.375848472118378 // 向量距离 } ], "micro": 110706 // 耗时,单位:微秒 }
-
- 阿代那非
-
Request:
GET /search?word=阿代那非&top=1&pinyin=1
-
Response:
{ "code": 1, // 1: 成功,其他:失败 "message": "success", "result": [ { "index": "WORD", // 索引名称 "code": "24317", // 字典中的词条代码 "word": "阿伐那非片", // 字典中的词条名称 "score": 7, // 评分 "distance": 0.395916491746902 // 向量距离 } ], "micro": 154205 // 耗时,单位:微秒 }
-
- 霜瓜唐安
-
Request:
GET /search?word=霜瓜唐安&top=1&pinyin=1
-
Response:
{ "code": 1, // 1: 成功,其他:失败 "message": "success", "result": [ { "index": "PINYIN", // 索引名称 "code": "4598", // 字典中的词条代码 "word": "双瓜糖安胶囊", // 字典中的词条名称 "score": 4, // 评分 "distance": 0.0730657055974007 // 向量距离 } ], "micro": 129010 // 耗时,单位:微秒 }
-
方案
基本思路
- 收集商品名称,生成字典
- 对字典中的每个词条,用AI模型计算其向量
- 将结果保存为一个向量索引
- 用AI模型对搜索词计算向量
- 在向量索引中找到和搜索词向量最相似的一条
- 取回结果对应的字典词条
创建索引
流程
切词
- 用jieba切词器对词条进行切词,提升匹配度
- 用ngram(可设置)方式切词,提升对错误搜索词的匹配度
- 拼音化,计算搜索词的拼音,以应对字同音词的情况
向量化
选用 sentence-transformers/distiluse-base-multilingual-cased-v1 模型,计算向量
向量索引
- 选用 faiss 保存向量索引文件
- 同时构建字符向量索引和拼音向量索引
向量搜索
流程
向量化
用AI模型,计算搜索词及其拼音的向量
近似搜索
- 用字符索引和拼音索引查找与搜索词及其拼音的向量最近似的结果
- 从字典中取出近似结果对应的字典词名称
- 合并搜索结果
评分排序
- 搜索词中的字符,在字典词中出现,加分
- 字典词中出现的两个搜索词字符,出现的顺序与其在搜索词中一致的,加分
- 字典词中出现的两个搜索词字符,出现的间隔与其在搜索词中一致的,加分
- 按评分倒序、向量距离正序、字典词长度正序排列
- 取出 top-n 条结果
问题与解决方案
在没有做切词评分前,本方案基本不可用;不对字典词做切词时,面对用户输入的各种奇怪的错误搜索词,有相当概率找不到匹配的字典词;不对搜索结果评分,则找到的最近似字典词往往并不是最优解;例如用户搜索:左旋维c油,我们的词库中最近似的是: 左旋维生素CE淡纹亮肤精华液,但其在评分前并非排在最前列:
-
字符搜易搜索结果
索引词 向量距离 字典词 左旋肉碱脂 0.4264 魔纤左旋肉碱脂流奶茶 橄榄油维 0.4400 橄榄油维E霜 左旋维 0.4463 左旋维生素CE淡纹亮肤精华液 茯苓左旋 0.4494 荷叶茯苓左旋肉碱胶囊 榄油维 0.4732 橄榄油维E霜 右旋噻 0.4872 马来酸右旋噻吗洛尔滴眼液 -
拼音索引搜索结果
索引词 向量距离 字典词 左旋右碱咖 0.0662 左旋右碱咖啡固体饮料 左旋右碱 0.0706 左旋右碱咖啡固体饮料 左旋右 0.0908 左旋右碱咖啡固体饮料 左西替利嗪 0.1184 盐酸左西替利嗪口服溶液/盐酸左西替利嗪分散片/盐酸左西替利嗪胶囊/盐酸左西替利嗪颗粒/盐酸左西替利嗪片/盐酸左西替利嗪口服滴剂 左西替利 0.1240 盐酸左西替利嗪口服溶液/盐酸左西替利嗪分散片/盐酸左西替利嗪胶囊/盐酸左西替利嗪颗粒/盐酸左西替利嗪片/盐酸左西替利嗪口服滴剂 用替硝唑 0.1266 注射用替硝唑
无论是字符搜索还是拼音搜索,相似度最高的都不是直觉上最近似的,所以本方案引入了一个简单的相似度评分逻辑对向量搜索的结果再次排序,以期得到更好的结果;
代码
Talk is cheap. Show me the code.
本方案的代码在:dict-vector-search
可以在 release页面 下载打包好的windows版可执行程序