アーキテクチャ

モジュール構成

lindera-analysis/src/
├── lib.rs                          # パブリックAPIの再エクスポート、CLIフラグ解析ヘルパー
├── character_filter.rs              # CharacterFilter trait、OffsetMapping、CharacterFilterLoader
├── character_filter/
│   ├── unicode_normalize.rs         # Unicode正規化(NFC/NFD/NFKC/NFKD)
│   ├── japanese_iteration_mark.rs   # 日本語の踊り字(繰り返し記号)正規化
│   ├── mapping.rs                   # マッピングによるテキスト置換
│   └── regex.rs                     # 正規表現によるテキスト置換
├── token_filter.rs                  # TokenFilter trait、TokenFilterLoader
├── token_filter/
│   ├── japanese_base_form.rs
│   ├── japanese_compound_word.rs
│   ├── japanese_kana.rs
│   ├── japanese_katakana_stem.rs
│   ├── japanese_keep_tags.rs
│   ├── japanese_number.rs
│   ├── japanese_reading_form.rs
│   ├── japanese_stop_tags.rs
│   ├── keep_words.rs
│   ├── korean_keep_tags.rs
│   ├── korean_reading_form.rs
│   ├── korean_stop_tags.rs
│   ├── length.rs
│   ├── lowercase.rs
│   ├── mapping.rs
│   ├── remove_diacritical_mark.rs
│   ├── stop_words.rs
│   ├── tags.rs                      # keep/stop系タグフィルタが共有するヘルパー(非公開)
│   └── uppercase.rs
└── tokenizer.rs                      # Tokenizer、TokenizerBuilder

主要コンポーネント

CharacterFilter

セグメンテーション前にテキストを前処理するフィルタのtraitです。各実装はname()と、textをその場で書き換えて実施した変換内容をOffsetMappingとして返すapply(&self, text: &mut String) -> LinderaResult<OffsetMapping>を提供します。

OffsetMappingTransformationレコードのリストから構築される)により、複数のフィルタを順に適用した後でも、Tokenizerはフィルタ後のテキストに対して計算されたトークンのバイトオフセットを、元の入力テキストにおけるバイトオフセットへ変換できます。BoxCharacterFilterは任意のCharacterFilter実装をボックス化・クローン可能なトレイトオブジェクトとしてラップし、CharacterFilterLoaderkind文字列とserde_json::Valueの引数からフィルタを構築します(YAML設定の読み込みとCLIフラグ解析の両方で利用されます)。

TokenFilter

Segmenterが生成したトークンを後処理するフィルタのtraitです。各実装はname()と、トークンをその場で変換・結合・並べ替え・除去するapply(&self, tokens: &mut Vec<Token<'_>>) -> LinderaResult<()>を提供します。BoxTokenFilterは任意のTokenFilter実装をボックス化・クローン可能なトレイトオブジェクトとしてラップし、TokenFilterLoaderCharacterFilterLoaderと同様に、kind文字列とserde_json::Valueの引数からフィルタを構築します。

Tokenizer / TokenizerBuilder

Tokenizerは、文字フィルタ、lindera::segmenter::Segmenter、トークンフィルタを1つの解析パイプラインとして組み合わせます。tokenizeを呼び出すと、入力テキストに文字フィルタを適用し、フィルタ後のテキストをセグメンテーションし、得られたトークンにトークンフィルタを適用したうえで、記録済みのOffsetMappingを使って各トークンのバイトオフセットを元のテキストに対する値へ補正します。

TokenizerBuilderTokenizerConfigserde_json::Value)からTokenizerを組み立てます。この設定はプログラムから直接構築することも、YAMLファイルから読み込むこと(TokenizerBuilder::from_file、または環境変数LINDERA_CONFIG_PATH経由で自動的に読み込むTokenizerBuilder::new)も、set_segmenter_modeset_segmenter_dictionaryappend_character_filterappend_token_filterで段階的に組み立てることもできます。YAMLファイルの形式は設定を、フィルタの完全なリファレンスはフィルタを参照してください。

AnalysisWorker

AnalysisWorkerTokenizer::new_workerまたはTokenizer::into_workerで作成)は、解析チェーン全体に対する再利用可能なセッションです。呼び出しごとのバッファ — Viterbiラティスとバックトレース用スクラッチ(SegmentWorker経由)、文字フィルタが操作する正規化テキストバッファ、オフセットマッピング用スクラッチ — をすべて所有するため、tokenizeを繰り返し呼び出してもTokenizer::tokenizeが支払う呼び出しごとのアロケーションを回避できます。文字フィルタが設定されている場合、トークンのsurfaceはトークンごとのStringにコピーされる代わりにワーカーのバッファを借用します。返されるトークンはワーカーを借用するため、次の呼び出しの前に消費する必要があります。マルチスレッドで使う場合はスレッドごとにワーカーを作成してください(あるいはlindera-binding-coreのようにMutexで保護します)。基盤となるSegmentWorkerと自動メモリ縮小ポリシーについてはSegmenterのページを参照してください。

AnalysisWorkerの主なpublicメソッド:

  • tokenize(&mut self, text: &str) — ワーカーの内部バッファを再利用しながら、解析チェーン全体を通してtextをトークナイズします。同じ入力・設定であればTokenizer::tokenizeとまったく同じトークンを返します。
  • tokenize_nbest(&mut self, text: &str, n, unique, cost_threshold) — ワーカーの内部バッファを再利用しながら、コスト付きの上位N件の結果をトークナイズして返します。Tokenizer::tokenize_nbestとまったく同じ結果を返します。
  • set_mode(&mut self, mode: Mode) — 以降の呼び出しで使用するセグメンテーションモードを設定します。
  • set_keep_whitespace(&mut self, keep: bool) — 以降の呼び出しで空白トークンを出力に残すかどうかを設定します。
  • shrink_to(&mut self, text_len_hint: usize) — ワーカーの内部バッファを、text_len_hintバイトの入力に必要なサイズまで直ちに縮小します。
  • reset(&mut self) — すべての内部バッファを破棄し、新しいバッファに置き換えます。(例えばワーカーを保持するMutexがパニックでpoisonedになった場合の)リカバリ用途を想定しており、設定(辞書・フィルタ・モード)は保持されます。

Feature フラグ

Feature説明デフォルト
embed-ipadicIPADIC辞書をバイナリに埋め込む(lindera/embed-ipadicへ委譲)No
embed-ipadic-neologdIPADIC-NEologd辞書をバイナリに埋め込む(lindera/embed-ipadic-neologdへ委譲)No
embed-unidicUniDic辞書をバイナリに埋め込む(lindera/embed-unidicへ委譲)No
embed-sudachidictSudachiDict辞書をバイナリに埋め込む(lindera/embed-sudachidictへ委譲)No
embed-ko-dicko-dic辞書をバイナリに埋め込む(lindera/embed-ko-dicへ委譲)No
embed-cc-cedictCC-CEDICT辞書をバイナリに埋め込む(lindera/embed-cc-cedictへ委譲)No
embed-jiebaJieba辞書をバイナリに埋め込む(lindera/embed-jiebaへ委譲)No