13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AWS Lambda で MeCab + NEologd 辞書を Node.js で動かす

Last updated at Posted at 2018-12-01

この記事はNextremer Advent Calendar 2018の2日目の記事です。

表題の通り、mecab-ipadic-NEologd を AWS Lambda で使えるようにしたという内容です。

困難

  • NEologd 辞書が標準で 900 MB 程度ある
  • Lambda にはデプロイパッケージを zip で上げることが可能であるが、unzip 後、250 MB 以下でなければいけないという制限がある
  • Lambda には実行時、一時ファイル領域(/tmp)が用意されているが、容量 512 MB までである
  • NEologd を縮小版(--eliminate-redundant-entry オプション)で生成しても 400 MB 程度になる

既存のソリューション: s3 に辞書を置いておく

こちらに、s3 使った方法がまとまっています。
https://speakerdeck.com/satorukadowaki/aws-apigateway-plus-python-lambda-plus-neologddezuo-rusabaresuri-ben-yu-xing-tai-su-jie-xi-api

が、この記事では違う方法を取ります。

この記事でのやりかた

縮小版 neologd 辞書を zip で固めると 100MB 以下になるため、デプロイパッケージに含めることができると考えました。

手順

デプロイパッケージはAmazon が公開している Lambda 用の AMI上で作ります。
(この記事執筆時点で amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2 を使いました。)
EC2 インスタンスを上記の AMI で立ち上げます。
以下は EC2 インスタンス上での作業になります。

いろいろインストール。

$ sudo yum install gcc gcc-c++ git patch
$ sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
# 以下は NEologd インストール時に必要
$ sudo yum install perl-App-cpanminus
$ sudo cpanm autodie

MeCab をビルド。

$ mkdir ~/mecab-service
$ curl -L "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE" -o mecab-0.996.tar.gz
$ tar zxvf mecab-0.996.tar.gz
$ cd mecab-0.996
$ ./configure --prefix=$HOME/mecab-service/local --enable-utf8-only
$ make
$ make install

mecab-ipadic もビルド。

$ cd ~
$ curl -L "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM" -o mecab-ipadic-2.7.0-20070801.tar.gz
$ tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz
$ cd mecab-ipadic-2.7.0-20070801
$ export PATH=$HOME/mecab-service/local/bin:$PATH
$ export LD_LIBRARY_PATH=$HOME/mecab-service/local/lib:$LD_LIBRARY_PATH
$ ./configure --prefix=$HOME/mecab-service/local --enable-utf8-only --with-charset=utf8
$ make
$ make install

mecab-ipadic-NEologd をビルド。

$ cd ~
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -y -p $HOME/neologd -n --eliminate-redundant-entry

ここで、正しくビルドできたかチェック。

$ echo 東京スカイツリー | ~/mecab-service/local/bin/mecab -d ~/neologd
東京スカイツリー	名詞,固有名詞,一般,*,*,*,東京スカイツリー,トウキョウスカイツリー,トーキョースカイツリー
EOS

必要なファイルを zip 化します。

$ cd ..
$ zip -r mecab-service/neologd.zip neologd
$ zip -r ~/mecab-service.zip mecab-service

ここからローカルでの作業になります。
mecab-service.zip を scp でローカルに落としてきてください。
これで EC2 は不要になります。

mecab-service.zip を解凍してください。

解凍した mecab-service フォルダに index.js を追加します。内容は以下の通り。

const exec = require('child_process').exec;
const MeCab = new require('mecab-async');
const fs = require('fs');

const mecab = new MeCab();
mecab.command = '/var/task/lambda_neologd/local/bin/mecab -d /tmp/neologd/';

exports.handler = async (event) => {
  try {
    fs.accessSync('/tmp/neologd');
  } catch(e) {
    await new Promise((resolve, reject) => {
      exec('unzip -d /tmp/ /var/task/lambda_neologd/neologd.zip', (err, stdout, stderr) => {
        if (err) {
          console.error(err);
          reject(err);
        }
        console.log(stdout);
        resolve(stdout);
      });
    });
  }
  const res = mecab.parseSync(normalize("僕の名前はラルセイです。"));
    const response = {
        statusCode: 200,
        body: JSON.stringify(['Hello', res])
    };
    return response;
};

function normalize(text) {
  return text.normalize("NFKC").toLowerCase();
}

そして再び mecab-servicemecab-service.zip に圧縮してください。
zip を s3 へ上げます。
AWS Lambda コンソールで新しい関数を追加します。ランタイムは Node.js 8.10 を指定。
関数コードとして s3 上に上げた mecab-service.zip を指定して保存します。

環境変数を以下のように設定。

LD_LIBRARY_PATH=/var/task/local/lib
MECABRC=/var/task/local/etc/mecabrc

タイムアウトを10秒以上に設定してください。

保存してテストすると、5秒くらい経って成功すると思います。
一度実行すれば、/tmp/ に辞書が展開されるので、2度目からは早いです。

おわりに

これで、s3 に辞書置かずに NEologd を使うことができました。
s3 からの転送は8秒程かかり、unzip は5秒かかるので若干のアドバンテージがあります。といっても、時間がかかるのは初回呼び出しだけですが…。

あと、--eliminate-redundant-entry オプションで辞書を縮小しているので、表記ゆれが吸収されません。MeCab に掛ける前にテキストの正規化が必要なことに注意してください。
このように NFKC 正規化と小文字化が必要です。

text.normalize("NFKC").toLowerCase();

Lambda で動かす以上、こればかりはどうしようも無いですね…。

13
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?