言語を判別するRust製ライブラリーWhatlangのRubyバインディングをリリースした

言語を判別するRubyGem Whatlangをリリースしました。ここで言語と言っているのは、プログラミング言語ではなく1、自然言語のことです(この文脈ではエスペラントも自然言語)。

こんな感じで使えます。

require "whatlang"

text = "これは日本語のテキストです。"

info = Whatlang.detect(text)
info.lang.code     # => "jpn"
info.lang.name     # => "日本語"
info.lang.eng_name # => "Japanese"
info.script        # => "Hiragana"
info.confidence    # => 1
info.reliable?     # => true

検出対象の言語を絞ることもできます。

text = "Jen la trinkejo fermitis, ni iras tra mallumo kaj pluvo."
list = ["eng", "ita"]
Whatlang.detect(text, whitelist: list).lang.code # => "ita"
Whatlang.detect(text, blacklist: list).lang.code # => "epo"

「ラテン文字(ローマ字)」とか「キリル文字」とか「アラビア文字」とかいう言い方は知っていたけど、それらを「script」というのはこれ作ってて初めて知りました。

ユースケース

実は必要に迫られて作ったわけではないので、ユースケースを把握しているわけではありません。

様々な言語で書かれるようなサービスをRailsで作っていて、言語によって適切なフォントとか検索機能を出しわける場合なんかに使えるのかな。

ベンチマーク

同目的のライブラリーに、ピュアRubyのWhatLanguageというのがあるので、ベンチマークを比較してみました。

require "benchmark"
require "json"
require "whatlanguage"
require "whatlang"

EXAMPLES_PATH = File.join(Dir.home, "src/github.com/greyblake/whatlang-rs/misc/data.json")
EXAMPLES =JSON.load_file(EXAMPLES_PATH).collect {|_, langs|
  langs.collect {|_, text| text}
}.flatten

WL = WhatLanguage.new(:all)
Benchmark.bmbm do |x|
  x.report "WhatLanguage" do
    EXAMPLES.each do |ex|
      WL.process_text ex
    end
  end
  x.report "Whatlang" do
    EXAMPLES.each do |ex|
      Whatlang.detect ex
    end
  end
end

実行すると:

Rehearsal ------------------------------------------------
WhatLanguage   0.841290   0.000917   0.842207 (  0.842248)
Whatlang       0.046201   0.000000   0.046201 (  0.046205)
--------------------------------------- total: 0.888408sec

                   user     system      total        real
WhatLanguage   0.821383   0.000000   0.821383 (  0.821400)
Whatlang       0.041817   0.000000   0.041817 (  0.041817)

20倍速いですね!

インストール

さてこの速さの秘密は、処理の殆ど全部がRustで書かれているからです。Rust製のWhatlangというライブラリーがあって、そのRubyラッパーが今回リリースしたgemというわけです。ので速いのは当然と言えば当然。

ただ、その代償で、インストールに手間が掛かります。

Nokogiriとかの拡張ライブラリーを入れる時にはCのビルド環境が必要ですよね。それと同じ感じで、Whatlangを入れるにはRustのビルド環境が必要です。公式のインストールページを見ながら入れてみてください。基本的には以下で済むはずですが:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

これをすると必要な物を一通りインストールした上で、と押すべきPATHを教えてくれるので、通してください。これが終わればgem installとかbundle installとかで入れられるようになります。

Rustバインディングなgemの作り方

Cライブラリーのバインディングを作る方法はよく知られていると思いますが(僕は知らないのだけど……)Rustでのやりかたをメモっておきましたので、興味ある人は見てみてください:RutieでRustのライブラリーをバインドしたgemを作る

どういう仕組みなのかは全然分からん。RustでFFI用のCで作ったのと同じようなバイナリーを作ってからFiddleで読み込んでるのかしら。

1

プログラミング言語の判別には、GitHub製のLinguistがいいでしょう。