利用faiss和flask提供矢量搜索服務(wù)API

需求背景

上一篇文章已經(jīng)完成了對(duì)該開源庫的調(diào)研,對(duì)于一些性能和使用姿勢(shì)來說也有了一些基本的了解。在調(diào)研期內(nèi)也通讀了faiss的官方wiki,現(xiàn)在,準(zhǔn)備開始動(dòng)手了。有興趣了解的同學(xué)可以戳鏈接faiss的一些相關(guān)調(diào)研
動(dòng)手之前還是需要再次靜靜,好好思考這一次任務(wù)要輸出的是什么內(nèi)容。emm,本打野選手在讀條時(shí)已經(jīng)養(yǎng)成了為整局游戲?qū)憚”镜牧?xí)慣了。這次繼續(xù)以流程圖的方式來輸出,流程圖的好處除了能讓你理清思路以外,更重要的是能讓你確定你的思路是不是和leader在同一條線上,確定這次任務(wù)的分界線(這個(gè)很重要),也是工作結(jié)果的痕跡。


上圖中主要表達(dá)了一個(gè)使用faiss來進(jìn)行搜索的API接口的流程,不同于以往的跟數(shù)據(jù)互動(dòng)的方式(結(jié)構(gòu)數(shù)據(jù)庫,非結(jié)構(gòu)數(shù)據(jù)庫,圖數(shù)據(jù)庫等),faiss只是一個(gè)比較簡(jiǎn)陋的開源庫,他并沒有完整的提供一套解決方案。類比的話就好像elasticsearch和solr中的lucene包一樣,而我要做的就是在此基礎(chǔ)上二次開發(fā),提供一套可用的解決方案??紤]到faiss是一個(gè)C++的開源工具庫,它只提供了python的接口,所以只能使用python來做這次接口開發(fā)??疾爝^后決定技術(shù)選型為flask+uwsgi+faiss來完成這個(gè)接口。

環(huán)境依賴

  • faiss的庫
  • python2.7
  • uwsgi
  • pycharm

吃井不忘挖水人

專門開一個(gè)標(biāo)題來感謝一下這哥們plippe faiss-web-service。他開源的這個(gè)demo滿足了我百分60以上的需求,本次的開發(fā)基本就是在讀懂他的代碼以后才能這么胸有成竹。

過程復(fù)盤

也不想嘮嘮叨叨的復(fù)盤整個(gè)開發(fā)過程,就只復(fù)盤幾個(gè)比較棘手的點(diǎn)

python的API如何開發(fā)

本身比較習(xí)慣于使用Java,對(duì)于python更多的是會(huì)用來做一些小運(yùn)維的腳本,所以對(duì)于python中的web開發(fā)會(huì)比較模糊。短時(shí)間內(nèi)我不太愿意再投入學(xué)習(xí)成本在flask的所有細(xì)節(jié)上,因?yàn)橐院罂赡茉俅沃胤甑木壏植⒉欢唷D敲丛趺纯焖俚挠胒lask開發(fā)一個(gè)web接口呢,如果你是Java工程師你可以參考下我的思路,大概兩部就可以完成一個(gè)簡(jiǎn)單可拓展的接口,首先是主入口

# -*- coding: UTF-8 -*-

from flask import Flask
from faiss_index import blueprint as FaissIndexBlueprint

app = Flask(__name__)


app.config.from_pyfile('config.py')

app.register_blueprint(FaissIndexBlueprint.blueprint)


if __name__ == '__main__':
    app.run()

其次是在主入口中注冊(cè)的模塊(Blueprint)

# -*- coding: UTF-8 -*-

from jsonschema import validate, ValidationError
from flask import Blueprint, jsonify, request
from werkzeug.exceptions import BadRequest
from faiss_index import FaissIndex
import json

try:
    import uwsgi
except ImportError:
    print('Failed to load python module uwsgi')
    print('Periodic faiss index updates isn\'t enabled')

    uwsgi = None

blueprint = Blueprint('faiss_index', __name__)

@blueprint.route('/ping')
def ping():
    return "pong"

OK直接運(yùn)行app.py就可以用flask自帶的wsgi服務(wù)器啟動(dòng)app,看到這里是否會(huì)覺得和springboot非常相似?以及包括@blueprint.route('/ping')這樣的路由方式,讓我覺得像極了springmvc的路由注解方式,所以幾乎不需要耗費(fèi)特別多的學(xué)習(xí)成本投入到這上面,節(jié)省了比較多的時(shí)間。余下的工作就是開始慢慢拓展開程序。

搜索的參數(shù)

API調(diào)用方要提供的參數(shù)是一維向量,目的是搜索距離最近的K個(gè)向量,向量具體在程序中怎么表示呢?就是一維數(shù)組。比如[1,2,3,4,5],但是在拿到向量后不能馬上進(jìn)行搜索,要進(jìn)行處理,如下

        vectors = [np.array(vectors, dtype=np.float32)]
        vectors = np.atleast_2d(vectors)

部署的方式-Docker

相比其他python web API來說,faiss搜索有一點(diǎn)特殊的地方,就是它最重要的依賴faiss本身。而faiss本身安裝有兩種方式

  • 通過下載源代碼進(jìn)行編譯 非常麻煩
  • 通過anconda進(jìn)行安裝 一行代碼完成
    但是服務(wù)器上本身是可能有其他python環(huán)境在運(yùn)行的。不可能專門的讓我為了部署我的工程而去改動(dòng),可能還能通過env的方式解決?但是我不夠熟悉python,所以選擇了我擅長的隔離方式Docker。原理就是從ubunt的image開始構(gòu)建,首先構(gòu)建出一個(gè)faiss運(yùn)行環(huán)境的image,然后在第二個(gè)image上打包自己的flask程序。附上構(gòu)建運(yùn)行環(huán)境的Dockerfile
ARG IMAGE
FROM ${IMAGE}

ARG FAISS_CPU_OR_GPU
ARG FAISS_VERSION

RUN apt-get update && \
    apt-get install -y curl bzip2  && \
    curl https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh > /tmp/conda.sh && \
    bash /tmp/conda.sh -b -p /opt/conda && \
    /opt/conda/bin/conda update -n base conda && \
    /opt/conda/bin/conda install -y -c pytorch faiss-${FAISS_CPU_OR_GPU}=${FAISS_VERSION} && \
    apt-get remove -y --auto-remove curl bzip2 && \
    apt-get clean && \
    rm -fr /tmp/conda.sh

ENV PATH="/opt/conda/bin:${PATH}"

以及我打包到dockerhub上的鏡像faiss-docker
可以在docker中搜索我的鏡像pull下來使用

docker search huangqq
docker pull huangqq/faiss-docker:1.2.1-cpu

總結(jié)

最麻煩的使用姿勢(shì)其實(shí)已經(jīng)在上一篇調(diào)研中理清的差不多了,本篇主要是在探討faiss在工程化應(yīng)用的一些實(shí)踐,如果有需要交流的歡迎右手邊微信~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 22年12月更新:個(gè)人網(wǎng)站關(guān)停,如果仍舊對(duì)舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,399評(píng)論 22 257
  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個(gè) Awesome - XXX 系列...
    aimaile閱讀 26,835評(píng)論 6 427
  • 連接數(shù)據(jù)庫# 創(chuàng)建表# INSERT操作# SELECT操作# UPDATE操作# DELETE操作#
    Flannery閱讀 397評(píng)論 0 2
  • 文/敬言安然 《天堂的路上有狗》 尿窩兒終于反應(yīng)過來,撲上去就把彪哥按在床上。 曲大炮:“對(duì)!弄他,把他褲子扒了,...
    敬言安然閱讀 515評(píng)論 28 18
  • 先前我在朋友圈里轉(zhuǎn)發(fā)了一張美國同學(xué)發(fā)來的圖片,上面顯示《紐約時(shí)報(bào)》在周六商業(yè)版上刊登了一條“中國擁抱精釀啤酒”的文...
    Avari閱讀 635評(píng)論 0 0

友情鏈接更多精彩內(nèi)容