はじめに
日本語自然言語処理ライブラリとして有名な GiNZA を、HTTP APIとして簡単に呼び出せるようにするために、ginzaserver というPythonパッケージを作りました。
GiNZAはspaCyベースの日本語NLPライブラリで、形態素解析、品詞情報、係り受け解析などを扱うことができます。
通常はPythonコードから次のように使います。
import spacy
nlp = spacy.load("ja_ginza")
doc = nlp("今日はいい天気です。")
しかし、Javaや他の言語から使いたい場合や、複数のプログラムから共通のNLP処理として呼び出したい場合には、HTTP APIとして起動できると便利です。
そこで、GiNZAをHTTPサーバーとして起動し、GETまたはPOSTで日本語テキストを送ると、解析結果をJSONで返す簡易サーバーを作りました。
ginzaserverとは
ginzaserver は、GiNZAをHTTP APIとして利用するための小さなサーバーです。
主な特徴は次の通りです。
- GiNZAによる日本語解析をHTTP API化
- GET / POST の両方に対応
- JSON形式で解析結果を返す
-
ja_ginzaとja_ginza_electraを切り替え可能 - Python以外の言語からも呼び出しやすい
-
pip installでインストール可能 - マルチスレッドHTTPサーバーとして動作
インストール
次のようにインストールします。
pip install ginzaserver
もしGiNZAモデルが入っていない場合は、必要に応じて次のようにインストールします。
pip install -U ginza ja_ginza
高精度モデルを使いたい場合は、次もインストールします。
pip install -U ja_ginza_electra
サーバーを起動する
インストール後、次のコマンドでサーバーを起動できます。
ginzaserver 8888 0
引数は次の意味です。
ginzaserver <port> <option>
| 引数 | 意味 |
|---|---|
port |
HTTPサーバーのポート番号 |
option |
使用するGiNZAモデル |
option には次の値を指定します。
| option | 使用モデル | 特徴 |
|---|---|---|
0 |
ja_ginza |
通常モデル。比較的高速 |
1 |
ja_ginza_electra |
高精度モデル。メモリ使用量は大きめ |
通常は、まず次のコマンドで十分です。
ginzaserver 8888 0
起動すると、例えば次のようなURLでアクセスできます。
http://127.0.0.1:8888/?text=これはテストです。
curlでPOSTする
POSTでJSONを送る場合は、次のようにします。
curl -X POST \
-H "Content-Type: application/json" \
-d "{\"text\":\"今日はいい天気です。\"}" \
http://localhost:8888/
LinuxやmacOSのシェルであれば、次のように書けます。
curl -X POST \
-H "Content-Type: application/json" \
-d '{"text":"今日はいい天気です。"}' \
http://localhost:8888/
GETで呼び出す
GETリクエストでも呼び出せます。
curl "http://localhost:8888/?text=今日はいい天気です。"
URLエンコードした文字列を渡しても動作します。
curl "http://localhost:8888/?text=%E4%BB%8A%E6%97%A5%E3%81%AF%E3%81%84%E3%81%84%E5%A4%A9%E6%B0%97%E3%81%A7%E3%81%99%E3%80%82"
レスポンス例
例えば、次のテキストを送ります。
今日はいい天気です。
レスポンスはJSONで返ります。
{
"type": "doc",
"sents": [
{
"tokens": [
{
"i": 0,
"orth": "今日",
"tag": "名詞-普通名詞-副詞可能",
"pos": "NOUN",
"lemma": "今日",
"head.i": 3,
"dep": "obl"
},
{
"i": 1,
"orth": "は",
"tag": "助詞-係助詞",
"pos": "ADP",
"lemma": "は",
"head.i": 0,
"dep": "case"
}
]
}
]
}
実際の出力は、GiNZAやspaCyのバージョン、使用するモデルによって多少変わることがあります。
レスポンスに含まれる情報
各トークンには、次のような情報が含まれます。
| フィールド | 意味 |
|---|---|
i |
トークンのインデックス |
orth |
表層形 |
tag |
詳細品詞 |
pos |
Universal POS |
lemma |
原形 |
head.i |
係り先トークンのインデックス |
dep |
依存関係ラベル |
例えば、orth は元の文字列中の語、lemma は原形、pos は大まかな品詞を表します。
Pythonクライアントから呼び出す
PythonからHTTP APIとして呼び出す例です。
import urllib.request
import json
url = "http://localhost:8888"
method = "POST"
headers = {
"Content-Type": "application/json"
}
obj = {
"text": "今日はいい天気です。"
}
request_body = json.dumps(obj).encode("utf-8")
request = urllib.request.Request(
url,
data=request_body,
method=method,
headers=headers
)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode("utf-8")
result = json.loads(response_body)
print(json.dumps(result, indent=2, ensure_ascii=False))
サーバーを起動した状態でこのスクリプトを実行すると、GiNZAによる解析結果がJSONで出力されます。
python examples/ginzaclient.py
モデルを切り替える
ginzaserver では、起動時の第2引数でモデルを切り替えます。
通常モデルを使う場合です。
ginzaserver 8888 0
高精度モデルを使う場合です。
ginzaserver 8888 1
option=0 では ja_ginza を使います。
spacy.load("ja_ginza")
option=1 では ja_ginza_electra を使います。
spacy.load("ja_ginza_electra")
ja_ginza_electra は高精度ですが、メモリ使用量が大きくなるため、環境によっては ja_ginza の方が扱いやすいです。
GPUについて
環境にGPUがあり、spaCy側でGPUが利用可能な場合は、GPUを優先して利用します。
ただし、GPUを使うにはCUDA対応版のspaCyや、環境に合ったCUDA設定が必要です。
例えばCUDA対応のspaCyを入れる場合は、環境に合わせて次のようにインストールします。
pip install -U "spacy[cuda115]"
CUDAのバージョンは環境によって異なるため、自分の環境に合わせて選ぶ必要があります。
GPUが利用できない場合でも、CPUで動作します。
Javaなど他の言語から使う
ginzaserver はHTTP APIなので、Python以外の言語からも利用できます。
例えばJavaからであれば、HTTPクライアントで次のようなJSONをPOSTすればよいです。
{
"text": "今日はいい天気です。"
}
返ってくるJSONをパースすれば、Javaアプリケーション内でGiNZAの解析結果を利用できます。
PythonのNLPライブラリを、Javaや他のシステムから疎結合に使える点が、この形式のメリットです。
WSLやコンテナで使う場合の注意
WSLやDockerコンテナ内でサーバーを起動する場合、127.0.0.1 で待ち受けていると、外部からアクセスしにくい場合があります。
その場合は、サーバー側の待ち受けアドレスを 0.0.0.0 にする必要があります。
ip = "0.0.0.0"
ただし、0.0.0.0 で待ち受けると、環境によっては外部ネットワークからアクセス可能になる場合があります。
信頼できる環境でのみ使う、ファイアウォールで制限する、リバースプロキシ側で認証を入れるなどの対策を検討してください。
簡単な動作確認手順
まとめると、最小の動作確認は次のようになります。
まずインストールします。
pip install ginzaserver
サーバーを起動します。
ginzaserver 8888 0
別のターミナルからPOSTします。
curl -X POST \
-H "Content-Type: application/json" \
-d '{"text":"今日はいい天気です。"}' \
http://localhost:8888/
JSONが返ってくれば成功です。
使いどころ
ginzaserver は、次のような場合に便利です。
- JavaやNode.jsなど、Python以外のプログラムからGiNZAを使いたい
- GiNZAのロード処理を毎回行わず、常駐プロセスとして使いたい
- 複数のアプリケーションから共通の日本語解析APIとして使いたい
- 日本語テキストの品詞、原形、係り受け情報を簡単にJSONで取得したい
- ローカル環境で軽量な日本語NLP APIを立てたい
特に、GiNZAはPythonライブラリですが、HTTP APIにしておくことで、他の言語やツールから呼び出しやすくなります。
まとめ
ginzaserver を使うと、GiNZAによる日本語自然言語処理をHTTP APIとして利用できます。
インストールは次の通りです。
pip install ginzaserver
起動は次の通りです。
ginzaserver 8888 0
POSTで日本語テキストを送ると、解析結果がJSONで返ります。
curl -X POST \
-H "Content-Type: application/json" \
-d '{"text":"今日はいい天気です。"}' \
http://localhost:8888/
Pythonだけでなく、Javaや他の言語からGiNZAを使いたい場合にも便利です。
今後は、サーバーのオプション追加、レスポンス形式の拡張、Docker対応なども検討したいと思います。