はじめに
レバレジーズ株式会社エンジニアのカラバージョ(Caraballo)です。今回は、8言語(*1)で求人情報を提供しているメディアであるWeXpats Jobsで実装した多言語検索のコスト最適化についてご紹介します。
(*1) 2021年2月現在。
なぜコストの最適化が必要だったのか?
チームの目標として、ユーザーエクスペリエンス(UX)を向上させるために日本語で書いてある求人情報を複数の言語で検索できるようにする必要がありました。
私たちのチームでの最初のアプローチは、Google translate APIを使用して各求人情報を翻訳し、Elasticsearchにインデックスを付ける予定でした。これは簡単なアプローチのようにみえますが、APIの費用が100万文字あたり$20USDであり費用対効果が低いことに気付きました。 月額だと約 $4,000USDの費用がかかる計算です。
この問題にどのように取り組んだのか?
まずはじめに、ブレインストーミングを行い問題を根本的なものに集約しました。つまり、「日本語のテキストデータを元にして他の言語での検索を効率的に行う方法は何か」ということです。
たとえば、次のテキストのように 「東京でReactを使用したフロントエンドエンジニアとしての職務」の中から、仕事を探すという文脈で意味を伝えたい重要な部分は [東京、React、使用、フロントエンドエンジニア、職務 ] の名詞であり、[で,を,した,としての]を省略しても他の言語に翻訳したときに元のテキストの意味をほとんど反映できます。
したがって、各求人情報の名詞を抽出して翻訳することで翻訳の必要があるAPI呼び出しの数が減る、さらに記事の間で何度も使われている名詞の翻訳結果をキャッシュすることでさらに翻訳の数を減らすことができました。 その結果、翻訳されるデータが多くなるほど、辞書が増え必要なAPI呼び出しが少なくなっていきます。
計画は次のとおりでした。
- 日本語のテキストをtokenizeし、名詞のみを抽出する。
- 抽出した名詞を共通の辞書に保存し、必要に応じて各言語に翻訳を追加する。
- 翻訳された名詞を準備して、Elasticsearchの各言語のインデックスを作成する。
実装
上記の要件を実装するために、今回はGolangを利用しました。
- 日本語の原文を取り込む
- トークナイザーを使用して名詞のみを抽出する
- 新しい単語がある場合、辞書に保存する
- 翻訳されていない単語を翻訳する
- 複数の言語でのテキストBLOBを作成する
- Logstashを使ってElasticsearchにデータを取り入れてインデックスを作成する
日本語をトークン化するために、次のgolangライブラリを使用しました。
github.com/ikawaha/kagome/tokenizer
Kagome Japanese Morphological Analyzer(https://github.com/ikawaha/kagome/tree/master)
例:
package main import ( "fmt" "github.com/ikawaha/kagome/tokenizer" ) func main() { nouns := GetTokens("東京でReactを使用したフロントエンドエンジニアとしての職務") fmt.Printf("%v", nouns) } func GetTokens(content string) []string { t := tokenizer.New() tokens := t.Analyze(content, tokenizer.Normal) var nouns []string for _, token := range tokens { if token.Class == tokenizer.DUMMY { continue } feature := token.Features()[0] switch feature { case "名詞": nouns = append(nouns, token.Surface) } } return nouns }
output
[東京 React 使用 フロントエンドエンジニア 職務]
まとめ
今回は、多言語検索のためのコスト最適化の例をご紹介しました。 翻訳された名詞の辞書を作成することで、API呼び出しの数を大幅に減らすことができ、将来的にはWeXpats Jobs以外のサービスでも多言語検索サポート機能を使用できるように拡張していく予定です。
レバレジーズ株式会社では現在、サービスを開発し、優れたユーザーエクスペリエンスを作成するための新しい仲間を探しています。興味のある方は、こちらのリンクに応募してください。
https://recruit.jobcan.jp/leverages/