日本語の自然言語処理APIを提供するモジュールJNLPを公開しました

こんにちは。スタジオ・ウミの大野です。この記事は、日本語検索シリーズの第3弾です。前々回の「Drupalの日本語検索、ちゃんと動いてる?N-gramの課題と自然言語処理での改善策」で日本語検索の課題を解説しました。そして前回の「Drupalの日本語検索を改善!自然言語処理を活用したSearch API Japanese Tokenizerモジュールの紹介」で、その解決策として開発したモジュールを紹介しました。
前回のモジュールを公開したあと、日本語の自然言語処理という機能は検索だけでなく、もっといろいろな場面で活用できると考えるようになりました。そこで、Search API Japanese Tokenizerの中に組み込まれていた日本語処理のエンジン部分を、単体で再利用できる基盤モジュールとして切り出しました。それが今回紹介するJapanese Natural Language Processing(JNLP)
モジュールです。
なお、この切り出しにともなってSearch API Japanese Tokenizerも内部的にJNLPを使う形へと作り直し、2.0.0-beta1として公開しました。こちらの変更点については、また別の記事で紹介する予定です。
Japanese Natural Language Processing(JNLP)
モジュールとは
JNLPは、日本語の自然言語処理を汎用的に行うための機能を提供するDrupalモジュールです。ひとことで言うと、日本語を単語ごとに分割したり、品詞を判別したりする機能を、他のモジュールから再利用できる形で提供する基盤モジュールです。
前回紹介したSearch API Japanese Tokenizerは、その名のとおりSearch APIと連携して検索インデックスを作成することに特化したモジュールでした。しかし、日本語を意味のある単位に分割する処理そのものは、検索以外にもさまざまな用途が考えられます。たとえば、本文からキーワードを自動抽出したり、読み仮名を生成したりといった機能も、根っこの部分では同じ「日本語を解析する」という処理を必要とします。
JNLPは、この「日本語を解析する」という共通の土台だけを担当します。JNLP単体では表立った機能はほとんどありませんが、他のモジュールがJNLPを呼びだすことで、日本語処理の実装を一から書かずに済みます。
4つの自然言語処理に対応
JNLPは、利用する自然言語処理ライブラリごとにサブモジュールが分かれています。使いたいものだけを有効化して利用します。
- jnlp_igo_php: Igo-php(今回新たに対応)
- jnlp_sudachi: Sudachi
- jnlp_mecab: MeCab
- jnlp_tinysegmenter: TinySegmenter
(PHP実装)
Sudachi・MeCab
・TinySegmenter
の3つは前回の記事でも紹介したとおりです。今回はこれらに加えて、新たにIgo-phpに対応しました。これが個人的にいちばんの推しポイントです。
推しポイント1:外部インストール不要で形態素解析できるIgo-php
前回の記事では、各処理系の特徴を次のように比較しました。ざっくり言うと、TinySegmenterは手軽なものの品詞が分からず精度も低い、MeCab
やSudachi
は高機能だがサーバーへの外部インストールが必要、という住み分けです。
| TinySegmenter | MeCab | Sudachi | |
|---|---|---|---|
| 方法 | 機械学習 | 形態素解析 | 形態素解析 |
| 品詞解析 | なし | あり | あり |
| 外部インストール | 不要 | 必要 | 必要 |
ここで気になるのが、「品詞解析ができて、なおかつ外部インストールが不要」という選択肢がないという点です。TinySegmenterは外部インストール不要でお手軽ですが、あくまで分かち書き(単語の区切り)を行うだけで、品詞の判別や単語の正規化はできません。一方で品詞解析ができるMeCab
・Sudachi
は、PHPアプリケーションではないため、サーバーに別途インストールする必要があります。VPSなど、アプリケーションを自由にインストールできる環境でないと使えません。
この空白を埋めてくれるのがIgo-phpです。Igo-phpは、Javaで書かれた形態素解析器「Igo」をPHPに移植したライブラリで、composer require logue/igo-phpでインストールできます。純粋なPHP実装なので外部アプリケーションのインストールは不要でありながら、MeCabやSudachi
と同じように品詞の判別まで行えます。
先ほどの表にIgo-phpを加えると、次のようになります。
| TinySegmenter | Igo-php | MeCab | Sudachi | |
|---|---|---|---|---|
| 方法 | 機械学習 | 形態素解析 | 形態素解析 | 形態素解析 |
| 品詞解析 | なし | あり | あり | あり |
| 速度 | 速め | 普通 | 速い | 遅い |
| 精度 | 低い | 普通 | 普通 | 高い |
| 正規化機能 | なし | あり(基本形) | あり(基本形) | あり |
| 外部インストール | 不要 | 不要 | 必要 | 必要 |
このように、Igo-phpは外部インストールが不要でありながら品詞解析までできるという、これまでになかった立ち位置のプロセッサーです。共用レンタルサーバーのようにアプリケーションのインストールが難しい環境でも、Composerさえ使えれば形態素解析による日本語処理を導入できるようになりました。
ただし、Igo-phpにも制限があります。Igo-phpモジュールはライブラリに同梱されたIPA辞書のみを使用し、カスタム辞書の切り替えには対応していません。Igoのバイナリー辞書のビルドには本家のJava版Igoが必要ですが、すでに配布が終了しているため、事実上IPA辞書のみが利用可能という事情によるものです。新語や固有名詞への対応を重視する場合は、辞書をカスタマイズできるMeCabやSudachi
を選ぶのがよいでしょう。
さらに注意したいのが、開発状況です。ベースとなったオリジナルのIgoは配布がすでに終了しており、Igo-php自体も活発なメンテナンスが続いているとはいえません。開発が事実上止まっているライブラリである点は、採用にあたっての難点として理解しておく必要があります。
推しポイント2:どのモジュールからでも使える汎用的な設計
もう1つの推しポイントは、JNLPが特定の解析器や特定の用途に縛られない、汎用的な設計になっている点です。
プロセッサーリゾルバで解析器を意識せずに使える
JNLPを利用するモジュールは、個別の解析器を直接指定するのではなく、jnlp.processor_resolverというサービス経由でプロセッサーを取得できます。
$resolver = \Drupal::service('jnlp.processor_resolver');
// 管理画面で設定されたデフォルトのプロセッサーを取得する。
$processor = $resolver->getProcessor();
$result = $processor->process('東京都の猫たちが暮らしています');
$tokens = $result->getTokens();
デフォルトのプロセッサーは管理画面(/admin/config/regional/jnlp)から選べます。「Automatic」を選んでおくと、その環境で利用可能なプロセッサーのうち、もっとも優先度の高いものが自動的に選ばれます。優先度は高い順にSudachi、MeCab、Igo-php、TinySegmenterです。つまりJNLPの利用側は、どの解析器が入っているかを意識せず日本語処理を呼びだせます。
サードパーティーも独自のプロセッサーを追加できる
JNLPのプロセッサーは、サービスにjnlp_processorというタグを付けることで登録される仕組みになっています。この仕組みを使えば、JNLP本体に手を入れなくても、サードパーティのモジュールが独自の解析器をプロセッサーとして追加できます。
services:
mymodule.processor:
class: Drupal\mymodule\Service\MyProcessor
tags:
- { name: jnlp_processor, priority: 5 }
このように、JNLPは日本語処理の「共通の窓口」として振る舞い、その裏側にどんな解析器がぶら下がっていても、利用側は同じインターフェイスで扱えるようになっています。
実は最近、Jagger・Vibrato
・Vaporetto
という、MeCabに近い高速な形態素解析ツールがあることを知りました。JaggerはC++で書かれ、MeCab互換の出力形式を採用しています。Vibrato
とVaporetto
はどちらもRustで書かれており、VibratoはMeCab互換の高速なトークナイザ、Vaporettoは点予測ベースのトークナイザです。どれもMeCabに匹敵する、あるいはそれ以上の処理速度をうたっています。こうした新しい解析器も、JNLPの仕組みならプロセッサーとして無理なく組み込めます。反響があれば、いずれ対応したいと考えています。
まとめ
今回は、日本語の自然言語処理をDrupalで汎用的に扱うための基盤モジュール「Japanese Natural Language Processing(JNLP)」を紹介しました。ポイントは次の2つです。
- 外部インストール不要でありながら品詞解析までできるIgo-phpに新たに対応した
- 検索に限らず、さまざまなモジュールから日本語処理を再利用できる基盤として設計した
日本語処理という共通の土台がモジュールとして整うことで、これから作られる日本語向けのDrupalモジュールが、少しでも作りやすくなればうれしいです。
実は、このJNLPを活用した新しいモジュールも準備中です。Drupalは、日本語のラベルから生成するマシンネームやURLエイリアスで、漢字を中国語(ピンイン)読みにしてしまいます。たとえば「日本語」は nihongo としたいところが ribenyu になってしまいます。JNLPの形態素解析で得た読みを使えば、こうした文字列を正しいローマ字で音訳できます。そんなモジュールも近日公開する予定ですので、どうぞご期待ください。
JNLPは現在ベータ版として公開しています。ぜひお試しいただき、ご意見をお寄せいただければ幸いです。
謝辞
本モジュールは、多くの外部ライブラリやソフトウェアの上に成り立っています。Igo、Sudachi、MeCab
、TinySegmenter
をはじめ、日本語の自然言語処理を支えてくださっているOSSの開発者の皆様に、心より感謝申し上げます。




