0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GiNZAをHTTPサーバーとして使える「ginzaserver」を作りました

0
Posted at

はじめに

日本語自然言語処理ライブラリとして有名な 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_ginzaja_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対応なども検討したいと思います。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?