あんパン

こしあん以外は認めない

dokku上で動作する係り受け解析APIサーバの作り方

係り受け解析はあくまで例なので、これに関して詳しく知りたい人は他をあたってください。本稿はdokku(Bashスクリプトで作られたHerokuライクなオンプレミスPaaS環境)上でCaboChaを用いて係り受け解析をする簡単なAPIを作成する、というシナリオで、システムコマンドをインストールするような複雑なアプリケーションの作成方法を解説するものです。

といっても、その方法はお粗末なものなので、より良い方法があるかもしれません。あくまで手軽に実験することができる、程度で読んでください。

dokkuについて

dokkuはBashスクリプトで作られたHerokuライクなオンプレミスPaaS環境です。Dockerコンテナを作成し、Herokuが提供しているbuildpackを利用してアプリケーションをデプロイします。インストールやHTTPS化などについては以下を御覧ください。

masawada.hatenablog.jp

係り受け解析について

係り受け解析というと馴染みのない方もいらっしゃると思います。ある文中の文節間にどのような修飾(係)・被修飾(受)関係があるかを解析するものです。形態素解析では文を品詞に分解するところまでを行いますが、係り受け解析をすることにより、自然言語の文をよりシステムが理解しやすいように落としこむことができます。

日本語ではCaboChaを使うのが一般的ではないかと思います。今回はこのCaboChaを用いて係り受け解析をするAPIサーバを作成する、ということを目標にします。

本題

というわけで、ここからはcabocha-apiという名前のアプリケーションを作成してdokkuにデプロイするまでを解説していきます。Herokuで少し複雑なアプリケーションを作ったことがある方はすぐに理解できるかと思います。

dokkuでheroku-buildpack-multiを使う

buildpackとは、言語やフレームワーク、アプリケーション等を手軽に利用できるようパッケージ化したものです。Herokuによって作られたものや、ユーザによって作られたものが存在します。

通常、Herokuにアプリケーションをデプロイする際は1つのbuildpackが自動的に選択されます。ffmpegやmecab等のbuildpack使いたい場合は言語のbuildpackとあわせて複数のbuildpackを利用できるようにする必要があります。複数のbuildpackを扱うには、buildpackとしてheroku-buildpack-multiを指定します。

$ dokku apps:create cabocha-api
$ dokku config:set cabocha-api BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

これでdokkuのアプリケーション作成と複数buildpackを扱う設定がおわりました。

buildpackを設定する

MacにHomebrewがあるのと同じく、LinuxにはLinuxbrewがあります。LinuxbrewはHomebrewのforkです。そのため、Homebrewで入れられるアプリケーションのほとんどはLinuxbrewでも入れることができます。本稿ではLinuxbrewを用いてCaboChaをインストールします。

ところが、本家のLinuxbrewではCaboChaをインストールすることができません。素直にインストールしようとするとlibiconvがない、とエラーを吐いてデプロイプロセスが強制終了します。そこで、独自のCaboChaインストーラを利用するために修正を施したheroku-buildpack-linuxbrewを用います。また、APIサーバをRubyで書くのでRubyのbuildpackも設定します。

以下を.buildpacksに記述してください。

https://github.com/masawada/heroku-buildpack-linuxbrew.git
https://github.com/heroku/heroku-buildpack-ruby.git

CaboChaのインストールを設定する

heroku-buildpack-linuxbrewは.cellarというファイルにアプリケーション名を記述するだけで、デプロイ時にそのアプリケーションを自動的にインストールします。ところが、本家のheroku-buildpack-linuxbrewでは独自のHomebrew formulaを利用することができません(brew tapすることができない)。そこでmasawada/heroku-buildpack-linuxbrewではtapをすることができるよう改良を施しています。

CaboChaのformulaにはlibiconvのオプションを設定している箇所があり、これが悪さをしているため、オプションを外した独自formulaをGitHub上に用意し、これを利用することにします。

以下のように.cellarを記述することで修正したCaboCha formulaを利用することができます。

tap masawada/cabocha-without-iconv
install cabocha-without-iconv

環境変数を設定する

ここからはdokkuのアプリケーションに環境変数を幾つか設定していきます。これを行わないとLinuxbrewでのビルドがうまくいかなかったり、サーバに用いるcabocha.gemのインストールがうまくいかなかったりします。

$ dokku config:set cabocha-api LIBRARY_PATH=/app/.linuxbrew/lib
$ dokku config:set cabocha-api LD_LIBRARY_PATH=/app/.linuxbrew/lib
$ dokku config:set cabocha-api LD_INCLUDE_PATH=/app/.linuxbrew/include
$ dokku config:set cabocha-api C_INCLUDE_PATH=/app/.linuxbrew/include
$ dokku config:set cabocha-api CPLUS_INCLUDE_PATH=/app/.linuxbrew/include
$ dokku config:set cabocha-api PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/app/.linuxbrew/bin

デプロイ後に環境変数を設定してからrebuildするとうまく設定されないようなので、必ず最初に設定するようにしてください。

APIサーバを書く

ここからはRubyとSinatraを用いてAPIサーバを書いていきます。

  • Gemfile: 依存ファイル
  • server.rb: 本体
  • Procfile: dokku上でアプリケーションを起動するためのスクリプト
    • web: commandという形式で書くことで、アプリケーションを起動し、リバースプロキシを設定する

また、事前にbundle installを実行してGemfile.lockを生成してください。これがない場合、デプロイ時にプロセスが強制終了します。

Gemfile

source 'https://rubygems.org'

gem 'sinatra'
gem 'cabocha'

server.rb

require 'sinatra'
require 'cabocha'

get '/' do
  parser = CaboCha::Parser.new
  tree = parser.parse(params["q"])
  @result = tree.toString(CaboCha::OUTPUT_RAW_SENTENCE)
  erb :index
end

__END__

@@index
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>pre { font: normal 14px/20px courier; }</style>
</head>
<body>
  <pre>
<%= @result %>
</pre>
</body>
</html>

Procfile

web: ruby server.rb -p $PORT

デプロイする

ここまできたらいつもどおりデプロイするだけです。上記までの作業をgit commitし、git remote add dokkuでdokkuの情報を登録します。

$ git push dokku master

でデプロイが始まります。幾つかのファイルをビルドするので、全作業を終えるのに数分かかります。作業を終えたらサーバにアクセスしてみましょう。ルートに?q=文章とクエリをつけることで、その文章の係り受け解析を行うことができます。

f:id:masawada:20150922174750p:plain

このように表示されれば成功です。

まとめ

多少手順は複雑でしたが、作業量としてはそんなに多くないのではないかと思います。Herokuの場合でも環境変数の設定をうまく行えば全く同じリポジトリをデプロイできるような気がしますが、なぜか失敗しました。今回はdokkuで動かすまで、ということでここまでにしておきます。

最後に、ここで作成したアプリケーションを以下のリポジトリに置いていますので、よろしければご活用ください(そのまま使うのは良くないです、アクセス制限をかける、入力文字列を制限するなどしたほうが良いかもしれません)。

github.com