LoginSignup
2
0

More than 1 year has passed since last update.

形態素解析をするLambdaをsamでdeployしたい

Last updated at Posted at 2021-12-20

本記事はAWS LambdaとServerless Advent Calendar 2021、21日目の記事です。

ちょっと前に業務でとあるアイテムのサジェスト系のAPIのプロトタイプを作る時にMecabを使おうと思ったのですが、ちょちょいとはできずに一旦含めないことにした事があります。
でも結局の所、必要になりそうなのでやっておこう。
似たようなネタはけっこうあって、何番煎じなん?ってトコはあるのですが、samかつコンテナでやる例は見つからなかったのでセーフとします。

 何をやるのか

実際にはもうちょっと複雑なのですが、 今回は名称のDBがあって、それに対して名詞の単語のみでクエリを実行する というシンプルなシナリオとします。
例えば、 「伝説の勇者が使ったとされるひのきのぼう」で検索されたとします。

伝説  名詞,一般,*,*,*,*,伝説,デンセツ,デンセツ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
勇者  名詞,一般,*,*,*,*,勇者,ユウシャ,ユーシャ
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
使っ  動詞,自立,*,*,五段・ワ行促音便,連用タ接続,使う,ツカッ,ツカッ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
と 助詞,格助詞,引用,*,*,*,と,ト,ト
さ 動詞,自立,*,*,サ変・スル,未然レル接続,する,サ,サ
れる  動詞,接尾,*,*,一段,基本形,れる,レル,レル
ひのき   名詞,一般,*,*,*,*,ひのき,ヒノキ,ヒノキ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
ぼう  名詞,一般,*,*,*,*,ぼう,ボウ,ボウ

名詞としては、伝説、勇者、ひのき、ぼうが抜き出せました。

今回はmecabという形態素解析エンジンをLambda上で用いて名詞に分解する、ということがやりたい、という話となります。本当はLambda Layerでやってみたかったのですが、250MBの制限があったりとか、Layer with コンテナができなかったりとかで諦めました。

mecabとは

オープンソースの形態素解析エンジンです。文章を食わせると、名詞や動詞など単語に分解してくれます。分かち書きとデータベース検索を合わせて使う時になんかにも便利です。

MeCabはオープンソースの形態素解析エンジンで、奈良先端科学技術大学院大学出身、現GoogleソフトウェアエンジニアでGoogle 日本語入力開発者の一人である工藤拓[1][2]によって開発されている。名称は開発者の好物「和布蕪(めかぶ)」から取られた。

mecab-python3

pythonでmecabを使う時にはこのモジュールを使います。
https://pypi.org/project/mecab-python3/

が、mecabを使うにはこれだけでは足りず、別途mecabのライブラリ(バイナリ)や辞書をインストールしなければいけません。
requirements.txtを用意するだけでは足りず、モジュールごとアップロードするだけでも足りません。
これはlambdaをコンテナイメージとして構築する事にし、イメージ構築時にインストールする事にします。

NEologd

NEologd とはmecabで使用できる、どデカい辞書です。
比較的新しいワードにも対応しているらしく、新しいデータを対象とするサービスでは必要になりそうです。
必要なものだけに絞ったりもできるらしですが、今回は深く考えずに突っ込んでいます。

Lambdaの作成

hello worldを一回作る(テンプレ)

まず、前提としてsam cliのインストールが必要です。まだの方はググってawsへのdocumentへたどり着いていただければと思います。
※古いsam cliをお使いの方はDocker imageに対応しているversionにupgradeして下さい

で、最初はsam initでテンプレから作っておきます

$ sam init --name lambda-python-mecab-sam-example 
Which template source would you like to use?
    1 - AWS Quick Start Templates
    2 - Custom Template Location
Choice: 1
What package type would you like to use?
    1 - Zip (artifact is a zip uploaded to S3)  
    2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 2

Which base image would you like to use?
    1 - amazon/nodejs14.x-base
    2 - amazon/nodejs12.x-base
    3 - amazon/nodejs10.x-base
    4 - amazon/python3.9-base
    5 - amazon/python3.8-base
    6 - amazon/python3.7-base
    7 - amazon/python3.6-base
    8 - amazon/python2.7-base
    9 - amazon/ruby2.7-base
    10 - amazon/ruby2.5-base
    11 - amazon/go1.x-base
    12 - amazon/java11-base
    13 - amazon/java8.al2-base
    14 - amazon/java8-base
    15 - amazon/dotnet5.0-base
    16 - amazon/dotnetcore3.1-base
    17 - amazon/dotnetcore2.1-base
Base image: 4

...

(続く)

一番のポイントは What package type would you like to use?2 と答えることです。

(続き)

Cloning from https://github.com/aws/aws-sam-cli-app-templates

AWS quick start application templates:
    1 - Hello World Lambda Image Example
    2 - PyTorch Machine Learning Inference API
    3 - Scikit-learn Machine Learning Inference API
    4 - Tensorflow Machine Learning Inference API
    5 - XGBoost Machine Learning Inference API
Template selection:  1

    -----------------------
    Generating application:
    -----------------------
    Name: lambda-python-mecab-sam-example
    Base Image: amazon/python3.9-base
    Architectures: x86_64
    Dependency Manager: pip
    Output Directory: .

    Next application steps can be found in the README file at ./lambda-python-mecab-sam-example/README.md


    Commands you can use next
    =========================
    [*] Create pipeline: cd lambda-python-mecab-sam-example && sam pipeline init --bootstrap
    [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch

その他にはpythonの3.9を選んだりしつつ、とりあえずHello Worldのテンプレを選びます


上記を終えるとこんな感じの構成になってるはずです。

.
├── README.md
├── __init__.py
├── events
│   └── event.json
├── hello_world
│   ├── Dockerfile
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
├── template.yaml
└── tests
    ├── __init__.py
    └── unit
        ├── __init__.py
        └── test_handler.py

ここで編集する必要があるのは3つ

  • Dockerfile
  • app.py
  • requirements.txt

ですね。
Dockerfileではmecabやライブラリをインストールします。
app.pyではMeCabをimportしたプログラムを動かします
requirements.txtではmecab-python3を含むライブラリを管理します。

Dockerfileの作成

FROM public.ecr.aws/lambda/python:3.9

RUN yum install -y file tar gzip unzip gcc make swig gcc-c++ git

RUN curl -L 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE' -o mecab-0.996.tar.gz \
    && tar zvxf mecab-0.996.tar.gz
RUN (cd mecab-0.996 && ./configure --prefix=/var/task --enable-utf8-only && make && make install)
RUN 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
RUN (cd mecab-ipadic-2.7.0-20070801 \
    && ./configure --prefix=/var/task --with-charset=utf8 --with-mecab-config=/var/task/bin/mecab-config && make && make install)
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
RUN yum install -y which xz patch openssl
RUN ln -s /var/task/bin/* /var/lang/bin/
RUN (cd mecab-ipadic-neologd && ./bin/install-mecab-ipadic-neologd -n -a -y)

COPY app.py requirements.txt ./
RUN python3.9 -m pip install -r requirements.txt -t .

# Command can be overwritten by providing a different command in the template directly.
CMD ["app.lambda_handler"]

mecabやmecabで使用するどデカい辞書をインストールしています。
どデカいのでbuildにはけっこう時間がかかりますが、Dockerfileなので一度行えばcacheが効き、プログラムの更新などの際のbuildはさほど時間がかからなくなります。

requirements.txt

requests
wheel
mecab-python3==1.0.4

もともとあったのrequestsとmecab-python3を入れるときに必要になったwheelを入れる予定

app.py

import os
import sys
import json

# preload libmecab
import ctypes
libdir = os.path.join(os.getcwd(), '/var/task/lib')
libmecab = ctypes.cdll.LoadLibrary(os.path.join(libdir, 'libmecab.so'))

import MeCab

# IPA辞書を利用
ipadic_tagger = MeCab.Tagger('-r /dev/null -d /var/task/lib/mecab/dic/ipadic')
# NEologdを利用
neologd_tagger = MeCab.Tagger('-r /dev/null -d /var/task/lib/mecab/dic/mecab-ipadic-neologd')


def lambda_handler(event, context):

    keyword = event['queryStringParameters']['keyword']

    print (ipadic_tagger.parse(keyword))
    print (neologd_tagger.parse(keyword))
    return {
        "statusCode": 200,
        'headers':{
            'context-type':'text/plain'
        },
        "body": ipadic_tagger.parse(keyword),
    }

build

buildを行います。
sam build と実行するだけなので簡単。
※dockerに割り当ててるメモリが2GBだとコケたので3GB以上にする必要がありそうです。macだとPreferencesのResourcesから。

$ sam build
Building image for HelloWorldFunction function
Setting DockerBuildArgs: {} for HelloWorldFunction function
Step 1/13 : FROM public.ecr.aws/lambda/python:3.9
 ---> b509e4dde698
Step 2/13 : RUN yum install -y file tar gzip unzip gcc make swig gcc-c++ git

......

Step 13/13 : CMD ["app.lambda_handler"]
 ---> Running in 29ad4bb3cd30
 ---> 6aab2db8b393
Successfully built 6aab2db8b393
Successfully tagged helloworldfunction:python3.9-v1


Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided

ローカルでテスト

sam local start-api でローカルでテスト実行ができます。

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2021-12-12 22:03:37  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

ブラウザで http://localhost:3000/hello?keyword=“裏切り者は誰だ!”世界的人気!2億ダウンロード「Among Us」宇宙船を舞台にした人狼ゲーム! みたいに開くとmecabの動作を確認できるはずです。

START RequestId: 27c6e221-ecb4-4ae3-b9ca-9f0101f4cba0 Version: $LATEST
“ 記号,括弧開,*,*,*,*,“,“,“
裏切り者    名詞,一般,*,*,*,*,裏切り者,ウラギリモノ,ウラギリモノ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
誰 名詞,代名詞,一般,*,*,*,誰,ダレ,ダレ
だ 助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
! 記号,一般,*,*,*,*,!,!,!
” 記号,括弧閉,*,*,*,*,”,”,”
世界  名詞,一般,*,*,*,*,世界,セカイ,セカイ
的 名詞,接尾,形容動詞語幹,*,*,*,的,テキ,テキ
人気  名詞,一般,*,*,*,*,人気,ニンキ,ニンキ
! 記号,一般,*,*,*,*,!,!,!
2 名詞,数,*,*,*,*,2,ニ,ニ
億 名詞,数,*,*,*,*,億,オク,オク
ダウンロード  名詞,サ変接続,*,*,*,*,ダウンロード,ダウンロード,ダウンロード
「 記号,括弧開,*,*,*,*,「,「,「
Among   名詞,固有名詞,組織,*,*,*,*
  記号,空白,*,*,*,*, , , 
Us  名詞,固有名詞,組織,*,*,*,*
」 記号,括弧閉,*,*,*,*,」,」,」
宇宙船   名詞,一般,*,*,*,*,宇宙船,ウチュウセン,ウチュウセン
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
舞台  名詞,一般,*,*,*,*,舞台,ブタイ,ブタイ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
人 名詞,一般,*,*,*,*,人,ヒト,ヒト
狼 名詞,一般,*,*,*,*,狼,オオカミ,オーカミ
ゲーム   名詞,一般,*,*,*,*,ゲーム,ゲーム,ゲーム
! 記号,一般,*,*,*,*,!,!,!
EOS

“ 記号,括弧開,*,*,*,*,“,“,“
裏切り者    名詞,一般,*,*,*,*,裏切り者,ウラギリモノ,ウラギリモノ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
誰だ  名詞,固有名詞,一般,*,*,*,誰だ,ダレダ,ダレダ
! 記号,一般,*,*,*,*,!,!,!
” 記号,括弧閉,*,*,*,*,”,”,”
世界的   名詞,固有名詞,一般,*,*,*,世界的,セカイテキ,セカイテキ
人気  名詞,一般,*,*,*,*,人気,ニンキ,ニンキ
! 記号,一般,*,*,*,*,!,!,!
2 名詞,数,*,*,*,*,2,ニ,ニ
億 名詞,数,*,*,*,*,億,オク,オク
ダウンロード  名詞,サ変接続,*,*,*,*,ダウンロード,ダウンロード,ダウンロード
「 記号,括弧開,*,*,*,*,「,「,「
Among   名詞,固有名詞,組織,*,*,*,*
  記号,空白,*,*,*,*, , , 
Us  名詞,固有名詞,組織,*,*,*,*
」 記号,括弧閉,*,*,*,*,」,」,」
宇宙船   名詞,一般,*,*,*,*,宇宙船,ウチュウセン,ウチュウセン
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
舞台  名詞,一般,*,*,*,*,舞台,ブタイ,ブタイ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
人狼ゲーム 名詞,固有名詞,一般,*,*,*,人狼ゲーム,ジンロウゲーム,ジンロウゲーム
! 記号,一般,*,*,*,*,!,!,!
EOS

END RequestId: 27c6e221-ecb4-4ae3-b9ca-9f0101f4cba0

さくさくいきますね。Dockerfile使えるの便利すぎる

deploy

最後にdeployして完了です。 sam deploy --guided でdeployが実行できます。2回目からは sam deploy だけでいいです。

$ sam deploy --guided

Configuring SAM deploy
======================

    Looking for config file [samconfig.toml] :  Not found

    Setting default arguments for 'sam deploy'
    =========================================
    Stack Name [sam-app]: lambda-python-mecab-sam-example
    AWS Region [ap-northeast-1]: 
    #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
    Confirm changes before deploy [y/N]: y
    #SAM needs permission to be able to create roles to connect to the resources in your template
    Allow SAM CLI IAM role creation [Y/n]: 
    #Preserves the state of previously provisioned resources when an operation fails
    Disable rollback [y/N]: y
    HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
    Save arguments to configuration file [Y/n]: y
    SAM configuration file [samconfig.toml]: 
    SAM configuration environment [default]: 

    Looking for resources needed for deployment:
     Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-b1r5p8i4foj1
     A different default S3 bucket can be set in samconfig.toml
     Image repositories: Not found.
     #Managed repositories will be deleted when their functions are removed from the template and deployed
     Create managed ECR repositories for all functions? [Y/n]: Y

......


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

あとは待つだけ!
1GB超えの巨大なアプリケーションになってしまうのですが、ECR上にイメージが作られることになり、サイズ的な問題はクリアできます。

スクリーンショット 2021-12-12 22.12.08.png

 完成

スクリーンショット 2021-12-12 22.47.10.png

そんなわけで無事にmecabの使用できる、巨大なLambdaをsam cliでbuildからdeployまでできました!

今回のコードはこちら
https://github.com/ikegam1/lambda-python-mecab-sam-example

参考にさせていただいたサイト(多謝!)

2
0
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
2
0