TAMALOG

プログラミングがあれば遠いところへ行けます。プログラムと人の共生を記録します。

NGT(高次元ベクトルデータ検索技術)をGolangでごまかして雑なJSON APIにする

類似画像検索システムに組み込むための高次元ベクトルデータ検索技術を探していました。Yahoo! Japanが開発したNGT(高次元ベクトルデータ検索技術)を見つけたので試してみます。

f:id:tamanobi:20170627025115p:plain https://www.flickr.com/photos/21001756@N06/2087512650/

表形式をJSON APIに変換する

前回は、NGTをDockerで動かすところまで紹介しました。 tamanobi.hatenablog.com

公式ドキュメントに従って検索コマンドを実行すると、表形式の出力が得られます。 github.com

 $ ngt search -n 20 index ./data/sift-query-3.tsv
  Query No.1
  Rank  ID  Distance
  1 3031    239.332
  2 4079    240.002
  3 3164    244.504
  4 3718    246.763
  5 157 251.094
  6 2422    251.185
  7 1313    251.34
  8 379 252.446
  9 3521    260.158
  10    2594    261.132
  11    4627    262.381
  12    2159    263.471
  13    3519    264.909
  14    1764    265.136
  15    4400    266.156
  16    2717    266.914
  17    3168    269.637
  18    4236    270.673
  19    4700    272.725
  20    679 272.973
  Query Time= 0.000472 (sec), 0.472 (msec)

検索システムとして利用する上では、この表示形式は使いづらいためJSONで返せるようにパッチを当てます。

JSON出力ができるようにパッチを当てる

NGTはC++で書かれているので、STLをJSONにシリアライズするライブラリを探します。今回はヘッダーを読み込むだけで利用できるライブラリを使用しました。 github.com

ngt searchコマンドにjson出力用のオプションを加えました。本家のmasterとの差分は以下のリンクを参照してください。個人向けの雑な修正なので本家にPRは送らない予定です。

Comparing yahoojapan:master...tamanobi:feature/json_output · yahoojapan/NGT · GitHub

差分を取り込んで、buildすればjsonオプションが有効になります。例えば、 ngt search -o j -n 20 index ./data/sift-query-3.tsvとoオプションにjを渡せば、JSONが出力できます。

ここまでで検索バックエンドの下準備は終わりました。JSONは出力されるものの、HTTP経由でのアクセスに対応していないので何かしらの言語でウェブサーバーを立ててAPIサーバーにします。

GolangでさくっとAPIサーバー

開発速度を鑑みて、それなりに高速でシンプルにJSON APIサーバーかける言語を採用します。今回はGolangにしました。コードはとてもシンプルです。特定のエンドポイントにファイルがPOSTされたらコマンドを実行するだけです。

https://gist.github.com/tamanobi/d10c932eebbd8c4c5ee0ca6f5143f3e9

tsv形式のファイルをいちいち送らないといけないのが、ナンセンスですが今回はよしとします。

Docker

これまでに、2つの変更を行いました。NGTにパッチを当てたこと、GoでのAPIサーバーの作成です。何も考えずに実行できるようにDockerfileを作りました。

github.com

リポジトリにDockerfileが入っているので、 docker build -t tamanobi/ngt_webapp .としてビルドを行ってください。ビルド後に、docker run -it -p 2300:8000 tamanobi/ngt_webappとすればウェブサーバーが立ち上がり、ホストOSの2300番ポートにAPIサーバーに転送されるようになります。

まとめ

NGTをHTTPを介して使うために、2つの準備を行いました。

  1. NGTにパッチを当てて、JSON出力に対応
  2. GolangでNGTコマンドを発行するウェブサーバーを立てる

次回

次回は、Golangのサーバーに対してリクエストを送ってNGTのデータベース構築や検索を行ってみます。