こんにちは、ヤフーで自然言語処理の研究開発をしている颯々野です。今回は、Yahoo! JAPAN研究所と言語処理のエンジニアリングチームと共同で進めているAPI共通化の取り組みを紹介します。
なぜ共通化するのか?
私たちは形態素解析やキーワード抽出など多くの機能を自分たちで開発、リリースしています(その一部はYahoo!デベロッパーネットワークでもテキスト解析Web APIとして公開)。
今まで実際に多くのサービスで利用されています。
ところが提供する言語処理機能が増え、提供形態が多様化すると以下のような状況が発生し、大変になってきました。
開発者: 「形態素解析のPHPラッパー、PHPのバージョンが上がったから更新しないと。形態素解析の機能追加や性能改善もしたいのに時間が取れない…。やっと完成させても導入してもらうのも一苦労。Javaのラッパーも用意しなくては。次はキーワード抽出も…」
運用者:「形態素解析とキーワード抽出と…のAPIサーバーの脆弱性対応をしないと。それぞれ違うところも多いし、保守だけでもやることいっぱい…」
利用者:「形態素解析やキーワード抽出がしたい。社内の言語処理ライブラリやAPIを利用しようと思ったけど、仕様が複雑そうでよく分からないな。調べて使うの、面倒くさい…」「提供している言語処理機能の数」✕「提供形態(C/C++ライブラリ,ラッパー,Web API)」分の手間がかかっていました。この手間を削減し、できるだけ早くそして簡単に提供するために、まずはインターフェースの共通化に取り組むことにしました。
JSON-RPC 2.0による言語処理のインターフェースの共通化
先ほども述べましたが、私たちは形態素解析やスペラー(つづり間違いや表記の揺れの訂正を行う)を内製で開発し、それらの機能を社内向けにライブラリやWeb APIの形で提供しています。
下の画像は共通化後のリクエスト(入力)とレスポンス(出力)の例です。リクエストとレスポンスがいずれもJSONで記述されています。この例では、形態素解析とスペラーでリクエストがほぼ同じ形式になっています。どちらも処理対象となる文字列を"q"で指定しています。
私たちが進めようとしている共通のインターフェースとはJSON-RPC 2.0に基づくものです。言語処理の各機能の入出力のインターフェースをできるだけ共通にしようとしています。先のリクエストとレスポンスの例はいずれもJSON-RPC 2.0に従う下記の形式になっています。
例えばC++では上記の入出力を標準ライブラリのstd::stringで行い、Web APIではJSON-RPC 2.0のリクエストをHTTPのPOSTでアクセスします。
これらの共通化を進める目的は大きく二つあります。一つは、開発・保守運用・利用の際のコストの削減です。もう一つは、新規開発時の全社メリットの最大化です。
インターフェース共通化を推進するプロジェクト「Azuki」
上に書いた目的を達成するために「Azuki」を開始しました。インターフェースを始めとする各種の共通化を推進するものです。まずライブラリやWeb APIのインターフェースから始めますが、ゆくゆくは設定ファイルや各種のデータの書式でも共通部分を増やしていきたいと考えています。
このプロジェクトでは、共通の言語処理の各機能が備えるべき基本的なインターフェースを定めようとしています。全てのインターフェースをこれに統一できるとは考えていません。過去に開発したものはこのインターフェースではありませんし、このインターフェースが最も処理効率がよいものでもありません。独自のインターフェースが存在してもよいのですが、基本的な機能は共通のインターフェースでも利用できることを目指します。
現在までの取り組み
昨年度までに共通のインターフェースの基本仕様の検討、策定を進めました。C++でJSON-RPC 2.0のリクエスト・レスポンスを処理するコア部分(共通処理マスタハンドラ)を作り、Web APIサーバへの組み込みも行いました。同時に、この同じコア部分を利用するJavaやPythonのラッパーも試作しました。Web APIサーバと通信する各言語(Python,Java,JavaScript,Node.js,PHP,Perl)のクライアントスクリプトも作成してみました。
C++インターフェースでの例
JSON-RPC 2.0をstd::stringでやりとりするためのモジュールを開発しました。
共通処理マスタハンドラと呼ぶべきモジュールがJSON-RPC 2.0のリクエスト内の“method”の指定に応じて、各処理のハンドラを呼び出す構成です。形態素解析やスペラーの各処理のハンドラを共有化ライブラリ(shared library)のプラグインとして用意します。
従来、形態素解析のライブラリAPIやWeb APIのインターフェースというと、解析対象や解析方法の指定や解析結果の利用の仕方を詳しく正確に知らなければ利用できませんでした。今回実現したJSON-RPC 2.0に基づく方法では、処理を指定する“method”の名前とリクエスト、レスポンスのJSONを理解すればよく、処理を実行し結果を得るところまでの手順は易しくなりました。この流れを理解すれば、形態素解析以外の他の処理(例 スペラー)を利用する場合でも同じ方法が使えます。
Web APIサーバーの概要
JSON-RPC 2.0を満たすリクエストをHTTPのPOSTで受け付けます。Apacheの拡張モジュールでC++の共通処理マスタハンドラを組み込んでいます。各言語処理のハンドラの管理はJSONによる設定ファイルで管理します。各言語処理のハンドラは独立したRPMパッケージとして作成、管理します。
このように構成したWeb APIサーバーによって、開発者自身や同じ部署の同僚、社内全体でも使い始めるのが非常に容易になります。
まずインストールが不要です。辞書等の更新も不要になります。入出力やエラーの仕様は一度理解すればよくなります。デモや検討用の一時的な提供も簡単になりました。
これらは徐々に実際に利用され始めています。Yahoo! デベロッパーネットワークの係り受け解析APIをJSON-RPC 2.0ベースのインターフェースに変更し、合わせて内部も一新しました。
また、あるサービス用にスペラー提供もしています。別の機能の提供も準備中です。これから1年程度かけて仕様や実装を詰めて完成度を上げて行きたいと思います。また既に提供済みの各ライブラリ、APIにも共通のインターフェースを提供していきたいと考えています。
インターフェースを含む各種共通化によるメリット
「Azuki」プロジェクトの推進で次のメリットが得られると考えています。
このインターフェースを満たせばラッパーやWeb APIサーバーの開発負担が共通化され軽減されます。特にAPIサーバーなら新規に開発された成果の反映や提供も楽です。
また、提供するラッパーやAPIサーバーの共通化で保守や運用する対象も減らせます。
加えて、利用する側でも覚えることが減り、新規に開発された機能を新たに利用する場合も学習コストが安くすみます。
開発、運用、利用のすべての面で負担が減らせます。新規開発の成果がすばやく簡単に広く提供できる点も優れています。
おわりに
言語処理機能のインターフェースの共通化の取り組みの概要を紹介しました。私たちは優れた性能や機能を持つ技術を開発するのに加えて、それを実際のサービスでも役に立つところまで持っていきたいと真剣に考えています。今回の共通化の取り組みを通じて、サービスの改善にたずさわる幅広いエンジニアの活動が効率化され、よりよいサービスの実現につながることを期待しています。
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました