通用向量搜索服务
faiss是个高效的向量搜索解决方案,经过测试对比,可以感受到它的飞速,关于faiss性能测试的见这里:faiss包装与性能对比
这次开源的是使用faiss搭建的通用向量搜索服务。
项目开源地址:https://github.com/xmxoxo/vector_server
通用向量搜索服务 VectorServer
基于faiss搭建的通用向量搜索服务,服务加载向量持久化文件, 同时可指定加载数据文件;通过faiss索引到内存,再通过flask提供API通用接口。
- API接口提供:
- 按向量搜索向量;
- 按索引号搜索向量;
- 计算两个向量的余弦距离;
- 如果指定了数据文件,接口同时还会返回向量索引号对应的数据内容;
- 支持GPU
向量搜索服务应用广泛,可以应用在词库搜索,文档搜索,智能机器人等各种场景。
文件说明
文件名 | 文件说明 |
---|---|
VecSearch_faiss_server.py | 服务主程序 |
test.py | 测试程序 |
/images | 截图目录 |
使用说明
向量搜索服务启动时需要两个参数:
- 向量文件。格式为.npy文件,即把向量直接用
np.save(filename,v)
命令保存的文件; - 数据文件。数据文件为可选,如果没有指定数据文件,则接口只会返回索引号;
当指定了数据文件后,接口会同时使用txt字段返回对应的文本数据;
数据文件格式为纯文本格式,内容按行分隔,与向量文件的顺序对应,
例如对应的句子,词语,或者其它的业务信息。
服务程序
服务端主程序使用说明
usage: VecSearch_faiss_server.py [-h] [-npy NPY] [-datfile DATFILE][-port PORT] [-metric {L2,INNER_PRODUCT}][-debug DEBUG] [--gpu GPU]faiss向量搜索服务 V-1.0.1optional arguments:-h, --help show this help message and exit-npy NPY 向量数据文件名,默认vector.npy-datfile DATFILE 文本数据文件名-port PORT 监听端口,默认7800-metric {L2,INNER_PRODUCT}计算方法:L2=欧式距离;INNER_PRODUCT=向量内积(默认)-debug DEBUG 是否调试模式,默认=1--gpu GPU 使用GPU,-1=不使用(默认),0=使用第1个,>0=使用全部
注明
当使用内积的方式时,服务会自动对向量进行归一化处理,
这样输出的结果可以认为就是余弦相似度;
测试程序
usage: test.py [-h] [-test_total TEST_TOTAL] [-test_dim TEST_DIM][-test_times TEST_TIMES] [-test_topn TEST_TOPN]faiss向量搜索服务端测试 V-1.0.2optional arguments:-h, --help show this help message and exit-test_total TEST_TOTAL测试数据条数,默认10万-test_dim TEST_DIM 测试数据维度,默认768-test_times TEST_TIMES测试次数,默认1000-test_topn TEST_TOPN 测试返回条数,默认5
运行测试程序后,会自动生成向量文件,保存为test_dat.npy
,
默认参数下 10万条768维度的向量文件大小约为585MB
python test.py
使用案例: 腾讯词向量搜索服务
源码地址: https://github.com/xmxoxo/Tencent_ChineseEmbedding_Process/upload
腾讯词向量说明
如果不想自己提取数据,可以直接下载1万条数据,进入第二步启动向量搜索服务
腾讯AI Lab开源大规模高质量中文词向量数据,800万中文词
说明页面:https://ai.tencent.com/ailab/nlp/zh/embedding.html
下载地址 :https://ai.tencent.com/ailab/nlp/zh/data/Tencent_AILab_ChineseEmbedding.tar.gz
这个数据集提供了880万左右的词向量,维度为200
文件下载后大小为6.31G , 解压缩后大小为: 15.5G
向量提取处理
由于文件是文本格式,需要进行一下处理,把词和向量分别保存到数据文件和向量文件中,以便于向量搜索服务加载。
这里提供了一个转换工具,可直接对数据进行提取,
把上面解压后的文本文件Tencent_AILab_ChineseEmbedding.txt
放到dat目录下即可;
以下是使用说明:
11:55:48.15|F:>python dataprocess.py -h
usage: dataprocess.py [-h] -datfile DATFILE [-outpath OUTPATH][-dofilter DOFILTER] [-topn TOPN]腾讯词向量提取工具optional arguments:-h, --help show this help message and exit-datfile DATFILE 数据文件名-outpath OUTPATH 输出目录-dofilter DOFILTER 是否过滤非中文,默认=0不过滤-topn TOPN 截取前N个向量,默认=0不截取
由于数据量很大,这里用下面的命令提取前1万条,作一个示例:
python dataprocess.py -outpath=./top1w -dofilter=1 -topn=10000
运行结果:
11:59:30.66|F:>python dataprocess.py -outpath=./top1w -dofilter=1 -topn=10000
运行参数: Namespace(datfile='./dat/Tencent_AILab_ChineseEmbedding.txt', dofilter=1, outpath='./top1w', topn=10000)
开始转换向量,请稍等...
总记录数:8824330
[进度: 0.11% 已过滤: 196] 第9999 行: 债务
正在保存字典文件...
正在保存向量文件...
转换完成, 处理10000行,过滤196行,输出9804行。
为了便于测试,这里把1万条数据打包上传了,文件名:top1w.zip
下载1万条测试数据
启动向量搜索服务
使用向量搜索服务进行加载,以10万条数据为例子:
cd /mnt/sda1/transdat/sentence-similarity/vector_server
python VecSearch_faiss_server.py -npy='../tx_vector/top10w/vector.npy' -datfile='../tx_vector/top10w/keywords.txt'
服务端运行结果:
[2020-09-16 10:21:30,711]INFO 正在加载数据文件...
[2020-09-16 10:21:30,719]INFO 加载数据文件完成: ../tx_vector/top10w/keywords.txt
[2020-09-16 10:21:30,719]INFO 正在加载向量并创建索引器...
[2020-09-16 10:21:30,754]INFO 向量文件:../tx_vector/top10w/vector.npy
[2020-09-16 10:21:30,754]INFO 数据量:97115, 向量维度:200
[2020-09-16 10:21:30,754]INFO 距离计算方法:INNER_PRODUCT
[2020-09-16 10:21:30,754]INFO 监听端口:7800
[2020-09-16 10:21:31,402]INFO 索引创建完成,用时:0.682604秒
[2020-09-16 10:21:31,403]INFO Used Memory: 410.160 MB
[2020-09-16 10:21:31,413]INFO Running under Linux...
[2020-09-16 10:21:32,889]INFO 查询用时:2.20 毫秒
192.168.40.11 - - [2020-09-16 10:21:32] "POST /api/v0.1/sim HTTP/1.1" 200 225 0.008786
[2020-09-16 10:21:51,705]INFO 查询用时:1.49 毫秒
192.168.40.11 - - [2020-09-16 10:21:51] "POST /api/v0.1/sim HTTP/1.1" 200 227 0.002830
[2020-09-16 10:24:08,024]INFO 查询用时:1.80 毫秒
192.168.40.11 - - [2020-09-16 10:24:08] "POST /api/v0.1/sim HTTP/1.1" 200 227 0.003219
880万向量全部加载大约需要120秒,内存28G,请注意环境并耐心等待。
加载后可以使用CURL命令或者浏览器插件 PostWoman进行调用
搜索结果图:
命令行实时查询工具
使用CURL或者浏览器调用向量搜索服务实在是不方便,也不直观,补充了一下命令行查询工具,做一下交互。 这里做了一些优化:对代码进行了优化:去掉加载数据,全部从接口读取;直接使用命令行交互方式
启动命令为:
python online_search.py -api=http://192.168.15.111:7801
其中:api参数指向向量搜索服务端;
以下是运行结果:
17:52:22.41|F:>python online_search.py -api=http://192.168.15.111:7801
[2020-11-02 17:52:25,831]INFO Used Memory: 40.707 MB
----------------------------------------
腾讯词向量搜索工具
可输入多个词语,词语之间用","分隔;
输入1个词:查询相似的词;
输入2个词:查询两个词的相似度;
输入3个词:计算A-B+C,例如:国王-男人+女人=皇后----------------------------------------
请输入词语(Q退出):用餐
[2020-11-02 17:52:31,831]INFO 查询词语的近义词:用餐
[2020-11-02 17:52:32,085]INFO 查询结果:
('用餐', 1.0)
('就餐', 0.8778643608093262)
('进餐', 0.7902611494064331)
('餐厅', 0.7464025616645813)
('餐厅里', 0.7445648312568665)
[2020-11-02 17:52:32,100]INFO 整体用时:268.50 毫秒
----------------------------------------
请输入词语(Q退出):晚餐,晚饭
[2020-11-02 17:52:37,661]INFO 查询 晚餐 与 晚饭 的相似度:
[2020-11-02 17:52:37,877]INFO 相似度:0.80474603
[2020-11-02 17:52:37,878]INFO 整体用时:217.50 毫秒
----------------------------------------
请输入词语(Q退出):国王,男人,女人
[2020-11-02 17:52:51,102]INFO 向量加减:国王+男人-女人
[2020-11-02 17:52:51,381]INFO 查询结果:
('王后', 0.7049502730369568)
('爵士', 0.6559655666351318)
('王子', 0.6505959033966064)
('骑士', 0.650031566619873)
[2020-11-02 17:52:51,389]INFO 整体用时:288.00 毫秒
----------------------------------------
请输入词语(Q退出):麻花,天津,上海
[2020-11-04 13:40:50,917]INFO 向量加减:麻花-天津+上海
[2020-11-04 13:40:51,197]INFO 查询结果:
('小笼包', 0.5818970203399658)
('粽子', 0.5648482441902161)
('的麻', 0.5591018795967102)
('油条', 0.5550578832626343)
[2020-11-04 13:40:51,214]INFO 整体用时:297.00 毫秒
----------------------------------------
请输入词语(Q退出):麻花,天津,哈尔滨
[2020-11-04 13:41:07,838]INFO 向量加减:麻花-天津+哈尔滨
[2020-11-04 13:41:08,156]INFO 查询结果:
('糖葫芦', 0.5892667174339294)
('冰棍', 0.5745514631271362)
('冰糖葫芦', 0.5584374666213989)
('烤肠', 0.5485786199569702)
[2020-11-04 13:41:08,166]INFO 整体用时:328.50 毫秒
----------------------------------------
请输入词语(Q退出):北京,中国,法国
[2020-11-04 13:41:22,350]INFO 向量加减:北京-中国+法国
[2020-11-04 13:41:22,881]INFO 查询结果:
('巴黎', 0.6858187317848206)
('在巴黎', 0.6453583836555481)
('法国巴黎', 0.611520528793335)
[2020-11-04 13:41:22,889]INFO 整体用时:539.50 毫秒
----------------------------------------
请输入词语(Q退出):码头,轮船,飞机
[2020-11-04 15:52:58,290]INFO 向量加减:码头-轮船+飞机
[2020-11-04 15:52:58,570]INFO 查询结果:
('机场', 0.7212138772010803)
('停机坪', 0.7156717777252197)
('直升机', 0.6654086112976074)
('起降', 0.6607031226158142)
[2020-11-04 15:52:58,581]INFO 整体用时:291.00 毫秒
----------------------------------------
请输入词语(Q退出):美女,女人,男人
[2020-11-04 15:54:09,246]INFO 向量加减:美女-女人+男人
[2020-11-04 15:54:09,527]INFO 查询结果:
('帅哥', 0.8955133557319641)
('妹子', 0.7441977262496948)
('小美女', 0.7396756410598755)
('漂亮妹子', 0.7382819652557373)
[2020-11-04 15:54:09,537]INFO 整体用时:291.00 毫秒
----------------------------------------
请输入词语(Q退出):
结束语
使用faiss通用向量搜索服务可以很方便地对向量进行搜索,在CPU上也可以得到比较好的速度,服务器内存已经不再是瓶颈了。后续还将继续推出:
- 腾讯词向量搜索WEB服务端,配上界面;
- simBERT+faiss 实现语义搜索;
欢迎加入群讨论:
QQ群:BERT模型爱好者 891629665
扫描下面的二维码加入。