Lindera
Rust製の形態素解析ライブラリです。Linderaは kuromoji-rs からフォークされ、複数言語のテキストトークナイズに対して、簡単なインストールと簡潔なAPIの提供を目指しています。
主な機能
| 機能 | 説明 |
|---|---|
| 形態素解析 | Viterbiベースの分割と品詞タグ付け |
| 多言語サポート | 日本語(IPADIC、IPADIC NEologd、UniDic)、韓国語(ko-dic)、中国語(CC-CEDICT、Jieba) |
| 辞書システム | ビルド済み辞書、ユーザー辞書、カスタム辞書学習 |
| テキスト処理パイプライン | 柔軟なテキスト正規化のための組み合わせ可能なキャラクターフィルターとトークンフィルター |
| CRF学習 | 辞書コスト推定のためのカスタムCRFモデルの学習 |
| Pythonバインディング | PyO3を介してPythonからLinderaを利用可能 |
| WebAssembly | wasm-bindgenを介してブラウザでLinderaを実行可能 |
| Pure Rust | C/C++依存なし。Rustがサポートするあらゆるプラットフォームで動作 |
トークナイズの流れ
graph LR
subgraph Your Application
T["Text"]
end
subgraph Lindera
CF["Character Filters"]
SEG["Segmenter\n(Dictionary + Viterbi)"]
TF["Token Filters"]
end
T --> CF --> SEG --> TF --> R["Tokens"]
ドキュメントマップ
| セクション | 説明 |
|---|---|
| はじめに | インストール、クイックスタート、サンプル |
| 辞書 | 利用可能な辞書とその使い方 |
| 設定 | YAMLベースのトークナイザー設定 |
| 応用的な使い方 | ユーザー辞書、フィルター、CRF学習 |
| CLI | コマンドラインインターフェースリファレンス |
| アーキテクチャ | クレート構成と設計の概要 |
| APIリファレンス | Rust APIドキュメント |
| コントリビュート | Linderaへの貢献方法 |
クイック例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "関西国際空港限定トートバッグ"; let mut tokens = tokenizer.tokenize(text)?; println!("text:\t{}", text); for token in tokens.iter_mut() { let details = token.details().join(","); println!("token:\t{}\t{}", token.surface.as_ref(), details); } Ok(()) }
上記の例は以下のように実行できます:
cargo run --features=embed-ipadic --example=tokenize
実行結果は以下のようになります:
text: 関西国際空港限定トートバッグ
token: 関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
token: 限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
token: トートバッグ 名詞,一般,*,*,*,*,*,*,*
ライセンス
Linderaは MITライセンス の下で公開されています。
アーキテクチャ
Linderaは複数のクレートで構成されるCargo workspaceとして構成されています。各クレートは、低レベルのCRF計算から高レベルのCLIや言語バインディングまで、それぞれ明確な責務を持っています。
クレート依存関係図
graph TB
CRF["lindera-crf\n(CRF Engine)"]
DICT["lindera-dictionary\n(Dictionary Base)"]
IPADIC["lindera-ipadic"]
UNIDIC["lindera-unidic"]
KODIC["lindera-ko-dic"]
CCCEDICT["lindera-cc-cedict"]
JIEBA["lindera-jieba"]
NEOLOGD["lindera-ipadic-neologd"]
LIB["lindera\n(Core Library)"]
CLI["lindera-cli\n(CLI)"]
PY["lindera-python\n(Python)"]
WASM["lindera-wasm\n(WebAssembly)"]
CRF --> DICT
DICT --> IPADIC
DICT --> UNIDIC
DICT --> KODIC
DICT --> CCCEDICT
DICT --> JIEBA
DICT --> NEOLOGD
DICT --> LIB
IPADIC --> LIB
UNIDIC --> LIB
KODIC --> LIB
CCCEDICT --> LIB
JIEBA --> LIB
NEOLOGD --> LIB
LIB --> CLI
LIB --> PY
LIB --> WASM
クレート一覧
| クレート | 種類 | 説明 |
|---|---|---|
lindera-crf | コア | Pure RustによるCRF(条件付き確率場)実装。no_stdサポート。シリアライゼーションにrkyvを使用。 |
lindera-dictionary | コア | 辞書ベースライブラリ。辞書の読み込み、ビルド、学習機能(train featureで有効化)を提供。 |
lindera | コア | メインの形態素解析ライブラリ。辞書、セグメンター、キャラクターフィルター、トークンフィルターを統合。 |
lindera-cli | アプリケーション | トークナイズ、辞書ビルド、CRF学習のためのコマンドラインインターフェース。 |
lindera-ipadic | 辞書 | IPADICベースの日本語辞書。 |
lindera-ipadic-neologd | 辞書 | IPADIC NEologdベースの日本語辞書(新語対応)。 |
lindera-unidic | 辞書 | UniDicベースの日本語辞書。 |
lindera-ko-dic | 辞書 | ko-dicベースの韓国語辞書。 |
lindera-cc-cedict | 辞書 | CC-CEDICTベースの中国語辞書。 |
lindera-jieba | 辞書 | Jiebaベースの中国語辞書。 |
lindera-python | バインディング | PyO3を利用したPythonバインディング。 |
lindera-wasm | バインディング | wasm-bindgenを利用したWebAssemblyバインディング。 |
トークナイズパイプライン
Linderaは複数段階のパイプラインでテキストを処理します:
Input Text
|
v
Character Filters -- Normalize characters (e.g., Unicode normalization, mapping)
|
v
Segmenter -- Segment text into tokens using a dictionary and the Viterbi algorithm
|
v
Token Filters -- Transform tokens (e.g., POS filtering, stop words, stemming)
|
v
Output Tokens
Segmenterがコアコンポーネントです。辞書から候補トークンのラティスを構築し、Viterbiアルゴリズムを適用して最小コストのパスを見つけ、最も適切な分割結果を生成します。
Featureフラグ
| Feature | 説明 | デフォルト |
|---|---|---|
mmap | 辞書読み込みのためのメモリマップドファイルサポート | 有効 |
train | CRFベースの辞書学習機能(lindera-crfに依存) | CLIのみ |
embed-ipadic | IPADIC辞書をバイナリに埋め込み | 無効 |
embed-cjk | IPADIC + ko-dic + Jieba辞書を埋め込み | 無効 |
embed-cjk2 | UniDic + ko-dic + Jieba辞書を埋め込み | 無効 |
embed-cjk3 | IPADIC NEologd + ko-dic + Jieba辞書を埋め込み | 無効 |
詳細
- はじめに -- インストールと最初のステップ
- 基本概念 -- 辞書、トークナイズ、フィルター
- Linderaライブラリ -- 設定、セグメンター、API
- Lindera CLI -- コマンドラインインターフェース
- 開発ガイド -- ビルド、テスト、コントリビュート
はじめに
このセクションでは、Linderaのインストールから最初の形態素解析の実行までをガイドします。
- インストール -- プロジェクトへのLinderaの追加と環境変数の設定
- クイックスタート -- わずか数行のコードで最初のテキストをトークナイズ
- サンプル -- 一般的なユースケースのサンプルプログラムを探索
インストール
Cargo.tomlに以下を追加してください:
[dependencies]
lindera = "3.0.0"
辞書のセットアップ
Linderaの実行にはビルド済み辞書が必要です。GitHub Releases から辞書をダウンロードし、読み込み時にそのパスを指定してください:
#![allow(unused)] fn main() { let dictionary = load_dictionary("/path/to/ipadic")?; }
[!TIP] 辞書をバイナリに直接埋め込みたい場合(上級者向け)は、対応する
embed-*feature フラグを有効にしてビルドし、embedded://スキームでロードしてください:#![allow(unused)] fn main() { // Cargo.toml: lindera = { version = "3.0.0", features = ["embed-ipadic"] } let dictionary = load_dictionary("embedded://ipadic")?; }詳細は Feature フラグ を参照してください。
環境変数
LINDERA_DICTIONARIES_PATH
LINDERA_DICTIONARIES_PATH 環境変数は、辞書ソースファイルをキャッシュするディレクトリを指定します。これにより以下のメリットがあります:
- オフラインビルド: 一度ダウンロードすれば、将来のビルドのために辞書ソースファイルが保存されます
- ビルドの高速化: 有効なキャッシュファイルが存在する場合、次回のビルドではダウンロードがスキップされます
- 再現可能なビルド: ビルド間での辞書バージョンの一貫性を保ちます
使用方法:
export LINDERA_DICTIONARIES_PATH=/path/to/dicts
cargo build --features=ipadic
設定された場合、辞書ソースファイルは $LINDERA_DICTIONARIES_PATH/<version>/ (<version> は lindera-dictionary クレートのバージョン)に保存されます。キャッシュはMD5チェックサムを使用してファイルを検証し、無効なファイルは自動的に再ダウンロードされます。
[!NOTE]
LINDERA_CACHEは非推奨ですが、後方互換性のために引き続きサポートされています。LINDERA_DICTIONARIES_PATHが設定されていない場合に使用されます。
LINDERA_CONFIG_PATH
LINDERA_CONFIG_PATH 環境変数は、トークナイザーの設定ファイル(YAML形式)へのパスを指定します。これにより、Rustコードを変更せずにトークナイザーの動作を設定できます。
export LINDERA_CONFIG_PATH=./resources/config/lindera.yml
設定フォーマットの詳細は 設定 セクションを参照してください。
DOCS_RS
DOCS_RS 環境変数は、docs.rsでドキュメントをビルドする際に自動的に設定されます。この変数が検出されると、Linderaは実際の辞書データをダウンロードする代わりにダミーの辞書ファイルを作成します。これにより、ネットワークアクセスや大容量ファイルのダウンロードなしでドキュメントをビルドできます。
これは主にdocs.rs内部で使用されるものであり、通常ユーザーが設定する必要はありません。
LINDERA_WORKDIR
LINDERA_WORKDIR 環境変数は、ビルドプロセス中に lindera-dictionary クレートによって自動的に設定されます。これはビルドされた辞書データファイルを含むディレクトリを指し、辞書クレートがデータファイルの場所を特定するために内部で使用されます。
この変数は自動的に設定されるため、ユーザーが変更する必要はありません。
クイックスタート
この例では、Linderaの基本的な使い方を説明します。
以下の処理を行います:
- Normalモードでトークナイザーを作成
- 入力テキストをトークナイズ(形態素解析)
- トークンを出力
まず、GitHub Releases からビルド済みIPADIC辞書をダウンロードし、ローカルディレクトリ(例: /path/to/ipadic)に展開してください。
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("/path/to/ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "関西国際空港限定トートバッグ"; let mut tokens = tokenizer.tokenize(text)?; println!("text:\t{}", text); for token in tokens.iter_mut() { let details = token.details().join(","); println!("token:\t{}\t{}", token.surface.as_ref(), details); } Ok(()) }
上記の例は以下のように実行できます:
% cargo run --example=tokenize
[!TIP]
embed-ipadicfeature を使って辞書をバイナリに埋め込む場合(上級者向け)は、ファイルパスの代わりにload_dictionary("embedded://ipadic")を使用できます。詳細は Feature フラグ を参照してください。
実行結果は以下のようになります:
text: 関西国際空港限定トートバッグ
token: 関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
token: 限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
token: トートバッグ 名詞,一般,*,*,*,*,*,*,*
サンプル
Linderaには、一般的なユースケースを示すいくつかのサンプルプログラムが含まれています。ソースコードはGitHubの examplesディレクトリ で確認できます。
サンプルを実行する前に、GitHub Releases からビルド済みIPADIC辞書をダウンロードし、ローカルディレクトリに展開してください。
利用可能なサンプル
tokenize
外部IPADIC辞書を使用した基本的なトークナイズです。入力テキストを分割し、各トークンの品詞情報を表示します。
cargo run --example=tokenize
tokenize_with_user_dict
ユーザー辞書を使用したトークナイズです。ドメイン固有の用語のために、辞書をカスタムエントリで補完する方法を示します。
cargo run --example=tokenize_with_user_dict
tokenize_with_filters
キャラクターフィルターとトークンフィルターを使用したトークナイズです。Unicode正規化、品詞フィルタリングなどの変換を含むテキスト処理パイプラインを実演します。
cargo run --example=tokenize_with_filters
tokenize_with_config
YAML設定ファイルを使用したトークナイズです。プログラムではなく宣言的にトークナイザーを設定する方法を示します。
cargo run --example=tokenize_with_config
基本概念
このセクションでは、Linderaの形態素解析システムの基本的な概念について説明します。
- 形態素解析 - Linderaがテキストを分割・解析する仕組み。
- 辞書 - Linderaがサポートする辞書フォーマット。
- トークナイズ - トークナイズモードとN-Best解析。
- ユーザー辞書 - ユーザー辞書によるカスタム単語の追加。
- キャラクターフィルター - トークナイズ前のテキスト前処理。
形態素解析
形態素解析とは
形態素解析とは、テキストを最小の意味単位(形態素)に分割し、その文法的特性を同定する処理です。日本語、中国語、韓国語のように単語がスペースで区切られない言語では、形態素解析は検索インデックス作成、テキスト分類、機械翻訳などの自然言語処理タスクにおいて不可欠な最初のステップです。
Linderaの仕組み
Linderaは辞書ベースの形態素解析器です。既知の単語とそのコストを含む事前コンパイル済みのシステム辞書を使用し、Viterbiアルゴリズムを適用して入力テキストの最適な分割を見つけます。
解析処理は以下のように動作します:
- ラティス構築: Linderaは入力テキストをスキャンし、各位置で辞書内のすべての候補単語を検索して、候補分割の有向非巡回グラフ(ラティス)を構築します。
- コスト割り当て: 各候補単語には(辞書からの)単語コストが関連付けられており、隣接する単語のペアには(連接コスト行列からの)連接コストが関連付けられています。
- 最適パス探索: Viterbiアルゴリズムがラティスを通る最小総コストのパスを見つけ、最適な分割結果を生成します。
主な用語
| 用語 | 説明 |
|---|---|
| 表層形 | 入力テキストに実際に現れるテキスト(例:"食べ")。 |
| 品詞(POS) | 単語の文法的カテゴリ(例:名詞、動詞、助詞)。Linderaの辞書は最大4階層のサブカテゴリを持つ階層的な品詞タグを提供します。 |
| 読み | 単語の発音。日本語辞書では通常カタカナで表記されます。 |
| 原形 | 単語の非活用形(辞書形)(例:表層形"食べ"に対して"食べる")。 |
| 活用 | 活用する単語の語形変化情報。活用型と活用形で構成されます。 |
コストベースの分割
Viterbiアルゴリズムは総コストが最小となる分割パスを選択します。パスの総コストは以下の合計です:
- 単語コスト: 辞書内の各単語に関連付けられたコスト。コストが低いほど、その単語が出現する可能性が高いことを意味します。一般的な単語はコストが低く、まれな単語はコストが高い傾向があります。
- 連接コスト: 隣接する2つの単語を接続するコスト。左側の単語の右文脈IDと右側の単語の左文脈IDによって決定されます。
アルゴリズムは以下を計算します:
Total cost = sum of word costs + sum of connection costs
この総コストを最小化することで、Linderaは入力テキストの最も自然な分割を見つけます。
連接コスト行列
連接コスト行列は、ある単語から別の単語への遷移コストを格納します。以下でインデックスされる2次元行列です:
- 先行する単語の右文脈ID
- 後続する単語の左文脈ID
これらの文脈IDは、単語境界に関する文法的情報をエンコードしています。例えば、名詞と助詞の間の連接コストは通常低く(自然な並び)、2つの動詞の基本形の間の連接コストは高くなります(不自然な並び)。
連接コスト行列は辞書ビルドプロセスの一部としてバイナリ形式にコンパイルされ、実行時に効率的な参照のために読み込まれます。
辞書
Linderaは、日本語・韓国語・中国語の形態素解析のための様々な辞書をサポートしています。各辞書は個別のクレートとして提供されます。
| 辞書 | 言語 | クレート | 説明 |
|---|---|---|---|
| IPADIC | 日本語 | lindera-ipadic | 日本語で最も一般的な辞書 |
| IPADIC NEologd | 日本語 | lindera-ipadic-neologd | 新語に対応したIPADIC |
| UniDic | 日本語 | lindera-unidic | 均一な単語単位定義を持つ辞書 |
| ko-dic | 韓国語 | lindera-ko-dic | 韓国語の形態素解析 |
| CC-CEDICT | 中国語 | lindera-cc-cedict | 中英辞書 |
| Jieba | 中国語 | lindera-jieba | Jiebaベースの中国語辞書 |
辞書の入手方法
ビルド済み辞書は GitHub Releases からダウンロードできます。対象言語の辞書アーカイブをダウンロードし、ローカルディレクトリに展開してください。
#![allow(unused)] fn main() { // ローカルパスから外部辞書を読み込む let dictionary = load_dictionary("/path/to/ipadic")?; }
[!TIP] 外部辞書ファイルなしの自己完結型バイナリが必要な場合は、
embed-*feature フラグを使って辞書を埋め込み、embedded://スキームでロードできます:#![allow(unused)] fn main() { let dictionary = load_dictionary("embedded://ipadic")?; }詳細は Feature フラグ を参照してください。
各辞書クレートのドキュメントで、フォーマット詳細、ビルド手順、使用例を参照してください。
トークナイズ
Linderaは複数のトークナイズモードを提供し、代替の分割候補を列挙するためのN-Best解析をサポートしています。
トークナイズモード
Normalモード
Normalモードは辞書エントリに基づく標準的なトークナイズを実行します。辞書に単一エントリとして存在する複合語はそのまま保持されます。
例 -- "関西国際空港限定トートバッグ" をNormalモードでトークナイズ:
関西国際空港 | 限定 | トートバッグ
複合名詞 "関西国際空港"(Kansai International Airport)は辞書に1つのエントリとして存在するため、単一トークンとして保持されます。
Decomposeモード
Decomposeモードは、複合語が辞書エントリとして存在する場合でも、さらに構成要素に分解します。
例 -- "関西国際空港限定トートバッグ" をDecomposeモードでトークナイズ:
関西 | 国際 | 空港 | 限定 | トートバッグ
複合語 "関西国際空港" は "関西"、"国際"、"空港" に分解されます。
モードの選択
Rustでは、Segmenterの作成時にモードを指定します:
#![allow(unused)] fn main() { use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::dictionary::load_dictionary; let dictionary = load_dictionary("embedded://ipadic")?; // Normal mode let segmenter = Segmenter::new(Mode::Normal, dictionary, None); // Decompose mode let segmenter = Segmenter::new(Mode::Decompose(Default::default()), dictionary, None); }
CLIでは、--modeフラグを使用します:
echo "関西国際空港限定トートバッグ" | lindera tokenize --dict embedded://ipadic --mode normal
echo "関西国際空港限定トートバッグ" | lindera tokenize --dict embedded://ipadic --mode decompose
N-Bestトークナイズ
N-Bestトークナイズは、総パスコスト順(低コスト = より良い分割)に上位N件のトークナイズ候補を列挙します。最良の結果が曖昧な場合や、入力テキストの代替解釈を探索したい場合に有用です。
アルゴリズム
N-Bestトークナイズは**Forward-DP Backward-A***アルゴリズムに基づいており、MeCabのN-Best実装と互換性があります。フォワードパスは動的計画法で最適コストを計算し、バックワードパスはA*探索を使用して総コストの昇順にパスを列挙します。
パラメータ
tokenize_nbestメソッドは以下のパラメータを受け付けます:
| パラメータ | 型 | 説明 |
|---|---|---|
text | &str | トークナイズするテキスト。 |
n | usize | 返すN-best結果の数。 |
unique | bool | trueの場合、同じ単語境界位置を生成する結果を重複排除します。 |
cost_threshold | Option<i64> | Some(threshold)の場合、best_cost + threshold以内のコストのパスのみを返します。 |
Rust APIの例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "すもももももももものうち"; // Get top 3 tokenization results let results = tokenizer.tokenize_nbest(text, 3, false, None)?; for (rank, (tokens, cost)) in results.iter().enumerate() { println!("--- NBEST {} (cost={}) ---", rank + 1, cost); for token in tokens { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } } Ok(()) }
実行結果は以下のようになります:
--- NBEST 1 (cost=7546) ---
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
--- NBEST 2 (cost=7914) ---
...
CLIの例
echo "すもももももももものうち" | lindera tokenize --dict embedded://ipadic -N 3
Latticeの再利用
繰り返しトークナイズを行う場合、Latticeを再利用してメモリ割り当てを削減できます:
#![allow(unused)] fn main() { use lindera_dictionary::viterbi::Lattice; let mut lattice = Lattice::default(); let results = tokenizer.tokenize_nbest_with_lattice(text, &mut lattice, 3, false, None)?; }
ユーザー辞書
ユーザー辞書は、システム辞書と併用してカスタム単語を登録できる補助辞書です。ドメイン固有の用語、ブランド名、固有名詞、またはデフォルトのシステム辞書に含まれていない単語を登録する場合に有用です。
CSVフォーマット
最もシンプルなユーザー辞書フォーマットは、3つのカラムを持つCSVファイルです:
<surface>,<part_of_speech>,<reading>
CSV内容の例
東京スカイツリー,カスタム名詞,トウキョウスカイツリー
東武スカイツリーライン,カスタム名詞,トウブスカイツリーライン
とうきょうスカイツリー駅,カスタム名詞,トウキョウスカイツリーエキ
各辞書タイプ(IPADIC、UniDic、ko-dicなど)は、文脈ID、コスト、すべての素性フィールドを完全に制御できる詳細CSVフォーマットもサポートしています。各辞書タイプの詳細フォーマットについては 辞書 セクションを参照してください。
Rust APIの例
use std::fs::File; use std::path::PathBuf; use lindera::dictionary::{Metadata, load_dictionary, load_user_dictionary}; use lindera::error::LinderaErrorKind; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let user_dict_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../resources") .join("user_dict") .join("ipadic_simple_userdic.csv"); let metadata_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../lindera-ipadic") .join("metadata.json"); let metadata: Metadata = serde_json::from_reader( File::open(metadata_file) .map_err(|err| LinderaErrorKind::Io.with_error(anyhow::anyhow!(err))) .unwrap(), ) .map_err(|err| LinderaErrorKind::Io.with_error(anyhow::anyhow!(err))) .unwrap(); let dictionary = load_dictionary("embedded://ipadic")?; let user_dictionary = load_user_dictionary(user_dict_path.to_str().unwrap(), &metadata)?; let segmenter = Segmenter::new( Mode::Normal, dictionary, Some(user_dictionary), // Using the loaded user dictionary ); // Create a tokenizer. let tokenizer = Tokenizer::new(segmenter); // Tokenize a text. let text = "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です"; let mut tokens = tokenizer.tokenize(text)?; // Print the text and tokens. println!("text:\t{}", text); for token in tokens.iter_mut() { let details = token.details().join(","); println!("token:\t{}\t{}", token.surface.as_ref(), details); } Ok(()) }
実行結果は以下のようになります:
text: 東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です
token: 東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
token: の 助詞,連体化,*,*,*,*,の,ノ,ノ
token: 最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
token: は 助詞,係助詞,*,*,*,*,は,ハ,ワ
token: とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
token: です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
CLIでのユーザー辞書ビルド
CLIを使用して、CSVからバイナリ形式のユーザー辞書をビルドできます:
lindera build --src <source_dir> --dest <dest_dir> --metadata <metadata.json> --user
バイナリとCSVのユーザー辞書
- CSVフォーマット: 実行時に読み込み・パースされます。開発時や小規模な辞書に便利です。
- バイナリフォーマット: 高速な読み込みのために事前コンパイルされます。大規模なユーザー辞書を本番環境で使用する場合に推奨されます。
どちらのフォーマットもSegmenterの作成時に指定できます。バイナリフォーマットはCSVのパースステップをスキップするため、起動時間が短縮されます。
キャラクターフィルター
キャラクターフィルターは、トークナイズ前に入力テキストに適用される前処理ステップです。文字を正規化または変換して、トークナイズの品質と一貫性を向上させます。
利用可能なキャラクターフィルター
unicode_normalize
入力テキストにUnicode正規化を適用します。全角文字を半角に変換したり、等価なUnicode表現を正規化する場合に有用です。
サポートされている正規化形式:
| 形式 | 説明 |
|---|---|
| NFKC | 互換分解の後に正準合成を行います。全角英数字を半角に変換し、カタカナのバリエーションを正規化します。 |
| NFC | 正準分解の後に正準合成を行います。 |
| NFD | 正準分解を行います。 |
| NFKD | 互換分解を行います。 |
japanese_iteration_mark
日本語の踊り字(繰り返し記号)を展開形に正規化します。踊り字は直前の文字の繰り返しを示す特殊な文字です。
| 記号 | 名前 | 例 |
|---|---|---|
| 々 | 漢字の踊り字 | 人々 (hitobito) |
| ゝ / ゞ | ひらがなの踊り字 | いすゞ (isuzu) |
| ヽ / ヾ | カタカナの踊り字 | バナナヽ |
このフィルターは2つのブール値パラメータを受け付けます:ひらがなの踊り字を正規化するかどうか、およびカタカナの踊り字を正規化するかどうかです。
mapping
ユーザー定義のマッピングテーブルに基づいて、文字レベルの文字列置換を実行します。カスタム正規化ルールに使用できます。
例えば、"リンデラ" を "Lindera" にマッピングします。
YAML設定の例
YAML設定ファイルでLinderaを使用する場合、キャラクターフィルターはcharacter_filtersセクションで指定できます:
segmenter:
mode: normal
dictionary: "embedded://ipadic"
character_filters:
- kind: unicode_normalize
args:
kind: nfkc
- kind: japanese_iteration_mark
args:
normalize_kanji: true
normalize_kana: true
- kind: mapping
args:
mapping:
リンデラ: Lindera
Rust APIの例
キャラクターフィルターはプログラムから作成してTokenizerに追加できます:
use lindera::character_filter::BoxCharacterFilter; use lindera::character_filter::unicode_normalize::{ UnicodeNormalizeCharacterFilter, UnicodeNormalizeKind, }; use lindera::character_filter::japanese_iteration_mark::JapaneseIterationMarkCharacterFilter; use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); // Create character filters. let unicode_normalize_char_filter = UnicodeNormalizeCharacterFilter::new(UnicodeNormalizeKind::NFKC); let japanese_iteration_mark_char_filter = JapaneseIterationMarkCharacterFilter::new(true, true); // Create a tokenizer and append character filters. let mut tokenizer = Tokenizer::new(segmenter); tokenizer .append_character_filter(BoxCharacterFilter::from(unicode_normalize_char_filter)) .append_character_filter(BoxCharacterFilter::from( japanese_iteration_mark_char_filter, )); // Tokenize text -- full-width "Lindera" will be normalized to "Lindera". let text = "Linderaは形態素解析エンジンです。"; let tokens = tokenizer.tokenize(text)?; for token in tokens { println!( "token: {:?}, details: {:?}", token.surface, token.details ); } Ok(()) }
実行結果は以下のようになります(NFKC正規化適用後):
token: "Lindera", details: Some(["名詞", "固有名詞", "組織", "*", "*", "*", "*", "*", "*"])
token: "は", details: Some(["助詞", "係助詞", "*", "*", "*", "*", "は", "ハ", "ワ"])
token: "形態素", details: Some(["名詞", "一般", "*", "*", "*", "*", "形態素", "ケイタイソ", "ケイタイソ"])
token: "解析", details: Some(["名詞", "サ変接続", "*", "*", "*", "*", "解析", "カイセキ", "カイセキ"])
token: "エンジン", details: Some(["名詞", "一般", "*", "*", "*", "*", "エンジン", "エンジン", "エンジン"])
token: "です", details: Some(["助動詞", "*", "*", "*", "特殊・デス", "基本形", "です", "デス", "デス"])
token: "。", details: Some(["記号", "句点", "*", "*", "*", "*", "。", "。", "。"])
Lindera CRF
Lindera CRFは、rucrfからフォークされたConditional Random Fields(CRF)のpure Rust実装です。ラティス構造をサポートしたCRFの学習器と推定器を提供します。
主な特徴
- 可変長エッジを持つラティス構造
- L1、L2、およびElastic Net正則化
- マルチスレッド学習
- rkyvによるゼロコピーデシリアライゼーション
no_stdサポート(trainfeatureなしの場合)
目次
rucrfからの変更点
- シリアライゼーションバックエンド: ゼロコピーデシリアライゼーションのため、
bincodeからrkyvに変更 - Elastic Net正則化: L1とL2のペナルティを組み合わせた
Regularization::ElasticNetを追加 - Rust 2024 edition: Rust 2024 editionに更新
- 依存クレートの更新:
argmin、argmin-math、hashbrownなどを更新
アーキテクチャ
モジュール構成
lindera-crf/src/
├── lib.rs # パブリックAPIの再エクスポート
├── feature.rs # FeatureSet, FeatureProvider
├── lattice.rs # Edge, Node, Lattice
├── model.rs # RawModel, MergedModel, Model trait
├── trainer.rs # Trainer, Regularization enum
├── errors.rs # エラー型
├── forward_backward.rs # 前向き・後向きアルゴリズム
├── math.rs # 数学ユーティリティ (logsumexp)
├── optimizers/
│ └── lbfgs.rs # L-BFGS最適化
└── utils.rs # ユーティリティtrait
主要コンポーネント
FeatureProvider / FeatureSet
ラベルごとの素性セットを管理します。各FeatureSetは、指定されたラベルのユニグラム素性と左右のバイグラム素性を保持します。FeatureProviderはFeatureSetインスタンスを集約し、素性IDから重みへのマッピングを行います。
Lattice / Edge / Node
系列ラベリングのための可変長エッジを持つラティス構造です。Edgeはラベル付きの候補スパンを表し、Nodeは特定の位置にあるエッジを集約します。Latticeは入力データから構築され、モデルが最適パスを探索するために使用されます。
Trainer
設定可能な正則化を用いたL-BFGS最適化によりCRFモデルを学習します。Trainerはラベル付きラティスの例を受け取り、前向き・後向きアルゴリズムで勾配を計算し、反復的にモデルの重みを更新します。
Regularization
設定可能な正則化戦略:
- L1: L1ペナルティによるスパースモデル
- L2: L2ペナルティによる滑らかなモデル
- ElasticNet: L1とL2を設定可能な
l1_ratioで組み合わせ
Model (trait)
ラティスを通じて最適パスを探索するためのインターフェースです。2つの実装が提供されています:
- RawModel: 素性IDでインデックスされたフラットベクトルに重みを格納
- MergedModel: 推論に最適化され、素性の重みをrkyvでシリアライズ可能なコンパクトな表現にマージ
前向き・後向きアルゴリズム
ラティス上でアルファ(前向き)とベータ(後向き)の値を計算します。学習時に期待素性カウントと勾配の計算に使用されます。
Feature フラグ
| Feature | 説明 | デフォルト |
|---|---|---|
alloc | no_std向けのallocサポート | No |
std | 標準ライブラリサポート(allocを含む) | No |
train | 学習機能(L-BFGS、マルチスレッド、ログ出力) | Yes |
APIリファレンス
APIリファレンスは以下で公開されています:
Lindera Dictionary
Lindera Dictionaryは、形態素解析辞書のベースライブラリです。辞書の読み込み、ビルド、Viterbiベースのセグメンテーション、およびCRFベースの学習機能を提供します。
主な特徴
- ファイルシステムまたは埋め込みデータからの辞書読み込み
- MeCab形式のCSVソースファイルからの辞書ビルド
- 最適なセグメンテーションのためのViterbiアルゴリズム
- N-bestパス生成(Forward-DP Backward-A*)
- メモリマップドファイルサポート
- CRFベースの辞書学習(
trainfeature使用時)
目次
アーキテクチャ
モジュール構成
lindera-dictionary/src/
├── lib.rs # パブリックAPI
├── dictionary.rs # Dictionary, UserDictionary
├── builder.rs # DictionaryBuilder
├── loader.rs # DictionaryLoader trait, FSDictionaryLoader
├── viterbi.rs # Lattice, Edge, Viterbiセグメンテーション
├── nbest.rs # NBestGenerator (Forward-DP Backward-A*)
├── mode.rs # Mode (Normal/Decompose), Penalty
├── error.rs # LinderaError, LinderaErrorKind
├── assets.rs # ダウンロードとファイル管理
├── dictionary/
│ ├── character_definition.rs # 文字種定義
│ ├── connection_cost_matrix.rs # 連接コスト行列
│ ├── prefix_dictionary.rs # ダブル配列トライ辞書
│ ├── unknown_dictionary.rs # 未知語処理
│ ├── metadata.rs # 辞書メタデータ
│ └── schema.rs # スキーマ定義
└── trainer/ # (train feature)
├── config.rs # TrainerConfig
├── corpus.rs # Corpus, Example, Word
├── feature_extractor.rs # 素性テンプレート解析
├── feature_rewriter.rs # MeCab互換リライトルール
└── model.rs # 学習済みモデル, tocost()
主要コンポーネント
Dictionary / UserDictionary
コンパイル済み辞書データを保持する主要データ構造です。Dictionaryは文字種定義、連接コスト行列、前方一致辞書(ダブル配列トライ)、および未知語辞書を含みます。UserDictionaryを使用すると、システム辞書の上にカスタム語彙を追加できます。
DictionaryBuilder
ソースCSVファイルから辞書をビルドするためのFluent APIです。MeCab形式の辞書ソースを、実行時に使用されるバイナリ形式にコンパイルします。
DictionaryLoader / FSDictionaryLoader
DictionaryLoaderはコンパイル済み辞書を読み込むためのtraitです。FSDictionaryLoaderはファイルシステムベースの実装で、ディレクトリから辞書ファイルを読み込みます。オプションでメモリマップドファイルをサポートします。
Viterbi (Lattice, Edge)
入力テキストから候補トークンのラティスを構築し、Viterbiアルゴリズムを使用して最適なセグメンテーションパスを探索します。ラティス内の各Edgeは、関連するコスト(単語コスト + 連接コスト)を持つ候補トークンを表します。
NBestGenerator
Forward-DP Backward-A*アルゴリズムを使用してN-bestセグメンテーションパスを生成します。これにより、アプリケーションは単一の最適パスを超えた代替セグメンテーションを検討できます。
Mode
トークナイゼーションの動作を制御します:
- Normal: 最適なViterbiパスを使用した標準的なトークナイゼーション
- Decompose: 設定可能な
Penalty閾値に基づいて複合名詞をさらに分割
Trainer (train feature)
lindera-crfを使用したCRFベースの辞書学習パイプラインです。学習ワークフローには以下が含まれます:
- TrainerConfig: 種辞書、
char.def、feature.def、rewrite.defを解析 - Corpus: ラベル付き例として学習データを管理
- FeatureExtractor: 素性テンプレートを解析し、素性IDを割り当て
- DictionaryRewriter: MeCab互換の3セクションリライトルールを適用
- Model: 学習結果を保持し、
tocost(weight, cost_factor)によるコスト変換で辞書ファイルを出力
Featureフラグ
| Feature | 説明 | デフォルト |
|---|---|---|
mmap | メモリマップドファイルサポート | Yes |
build_rs | 辞書ソースのHTTPダウンロード | No |
train | CRFベースの学習(lindera-crfに依存) | No |
APIリファレンス
APIリファレンスは以下で公開されています:
Lindera ライブラリ
lindera クレートは形態素解析のコアライブラリです。このセクションでは、設定、セグメンテーション、Token Filter、エラーハンドリング、APIリファレンスについて説明します。
- 設定 - YAMLベースの Tokenizer 設定
- Segmenter - Viterbi アルゴリズムを使用するコアセグメンテーションコンポーネント
- Token Filter - トークンの後処理フィルタ
- エラーハンドリング - エラー型とハンドリングパターン
- APIリファレンス - 生成されたAPIドキュメントへのリンク
設定
LinderaはYAML形式の設定ファイルを読み込むことができます。
環境変数 LINDERA_CONFIG_PATH にファイルのパスを指定してください。Rustコードでトークナイザーの動作をコーディングすることなく、簡単に利用できます。
segmenter:
mode: "normal"
dictionary: "embedded://ipadic"
# user_dictionary: "./resources/user_dict/ipadic_simple_userdic.csv"
character_filters:
- kind: "unicode_normalize"
args:
kind: "nfkc"
- kind: "japanese_iteration_mark"
args:
normalize_kanji: true
normalize_kana: true
- kind: mapping
args:
mapping:
リンデラ: Lindera
token_filters:
- kind: "japanese_compound_word"
args:
tags:
- "名詞,数"
- "名詞,接尾,助数詞"
new_tag: "名詞,数"
- kind: "japanese_number"
args:
tags:
- "名詞,数"
- kind: "japanese_stop_tags"
args:
tags:
- "接続詞"
- "助詞"
- "助詞,格助詞"
- "助詞,格助詞,一般"
- "助詞,格助詞,引用"
- "助詞,格助詞,連語"
- "助詞,係助詞"
- "助詞,副助詞"
- "助詞,間投助詞"
- "助詞,並立助詞"
- "助詞,終助詞"
- "助詞,副助詞/並立助詞/終助詞"
- "助詞,連体化"
- "助詞,副詞化"
- "助詞,特殊"
- "助動詞"
- "記号"
- "記号,一般"
- "記号,読点"
- "記号,句点"
- "記号,空白"
- "記号,括弧閉"
- "その他,間投"
- "フィラー"
- "非言語音"
- kind: "japanese_katakana_stem"
args:
min: 3
- kind: "remove_diacritical_mark"
args:
japanese: false
% export LINDERA_CONFIG_PATH=./resources/config/lindera.yml
use std::path::PathBuf; use lindera::tokenizer::TokenizerBuilder; use lindera::LinderaResult; fn main() -> LinderaResult<()> { // 設定ファイルからトークナイザーの設定を読み込む let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../resources") .join("config") .join("lindera.yml"); let builder = TokenizerBuilder::from_file(&path)?; let tokenizer = builder.build()?; let text = "Linderaは形態素解析エンジンです。ユーザー辞書も利用可能です。".to_string(); println!("text: {text}"); let tokens = tokenizer.tokenize(&text)?; for token in tokens { println!( "token: {:?}, start: {:?}, end: {:?}, details: {:?}", token.surface, token.byte_start, token.byte_end, token.details ); } Ok(()) }
Segmenter
Segmenter は形態素解析を実行するコアコンポーネントです。辞書とコストモデルに基づいて、入力テキストの最適な分割を Viterbi アルゴリズムで探索します。
Segmenter の作成
Segmenter には以下の3つのコンポーネントが必要です:
- Mode - トークナイズ戦略(
NormalまたはDecompose) - Dictionary - 形態素解析用のシステム辞書
- UserDictionary(オプション) - カスタム単語用の補助辞書
#![allow(unused)] fn main() { use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); }
トークナイズモード
Mode::Normal
辞書に登録されたエントリに基づく標準的なトークナイズです。辞書に登録された単語に忠実に分割します。
#![allow(unused)] fn main() { use lindera::mode::Mode; let mode = Mode::Normal; }
Mode::Decompose
複合名詞を構成要素に分解します。このモードでは、長い複合語にペナルティを適用し、Segmenter がより短い構成要素に分割するよう促します。
例えば、Mode::Normal では複合語「関西国際空港」は1つのトークンのままですが、Mode::Decompose では「関西」「国際」「空港」に分割されます。
#![allow(unused)] fn main() { use lindera::mode::Mode; let mode = Mode::Decompose(Default::default()); }
辞書の読み込み
Lindera は様々なソースから辞書を読み込むための load_dictionary 関数を提供しています。
埋め込み辞書
適切な Feature フラグ(例: embed-ipadic)を指定してビルドすると、バイナリから直接辞書を読み込むことができます:
#![allow(unused)] fn main() { use lindera::dictionary::load_dictionary; let dictionary = load_dictionary("embedded://ipadic")?; }
利用可能な埋め込み辞書URI:
embedded://ipadic- IPADIC(日本語)embedded://ipadic-neologd- IPADIC NEologd(日本語)embedded://unidic- UniDic(日本語)embedded://ko-dic- ko-dic(韓国語)embedded://cc-cedict- CC-CEDICT(中国語)embedded://jieba- Jieba(中国語)
外部辞書
ビルド済みの辞書ディレクトリをファイルシステムから読み込むことができます:
#![allow(unused)] fn main() { use lindera::dictionary::load_dictionary; let dictionary = load_dictionary("/path/to/dictionary")?; }
Tokenizer との連携
Segmenter は通常、Character Filter と Token Filter のサポートを追加する Tokenizer を通じて使用されます:
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "日本語の形態素解析を行うことができます。"; let tokens = tokenizer.tokenize(text)?; for token in tokens { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Token Filter
Token Filter はセグメンテーション後のトークンに適用される後処理コンポーネントです。検索インデックス作成、テキスト正規化、言語解析などの用途に合わせて、トークンの変更、削除、変換を行うことができます。
利用可能な Token Filter
日本語
| Filter | 説明 |
|---|---|
japanese_compound_word | 指定した品詞タグに一致する連続トークンを複合語に結合 |
japanese_number | 日本語の数値表現を正規化(例: 漢数字の変換) |
japanese_stop_tags | 指定した品詞タグを持つトークンを除去 |
japanese_katakana_stem | カタカナ語の末尾の長音記号を除去してステミング |
japanese_base_form | トークンを原形(辞書形)に正規化 |
japanese_keep_tags | 指定した品詞タグに一致するトークンのみを保持し、それ以外を除去 |
japanese_reading_form | トークンテキストを読み形式(カタカナ)に変換 |
japanese_kana | ひらがなとカタカナを相互変換 |
韓国語
| Filter | 説明 |
|---|---|
korean_stop_tags | 指定した品詞タグを持つ韓国語トークンを除去 |
korean_keep_tags | 指定した品詞タグに一致する韓国語トークンのみを保持 |
korean_reading_form | 韓国語トークンを読み形式に変換 |
汎用
| Filter | 説明 |
|---|---|
lowercase | トークンテキストを小文字に変換 |
uppercase | トークンテキストを大文字に変換 |
mapping | ユーザー定義のマッピングテーブルに従ってトークンテキストを変換 |
length | テキスト長(最小値および/または最大値)でトークンをフィルタリング |
stop_words | ストップワードリストに一致するトークンを除去 |
keep_words | 指定した単語リストに一致するトークンのみを保持 |
remove_diacritical_mark | トークンテキストからダイアクリティカルマーク(アクセント記号)を除去 |
YAML設定
Token Filter はYAML設定ファイルの token_filters キーで設定できます:
token_filters:
- kind: "japanese_stop_tags"
args:
tags:
- "助詞"
- "助動詞"
- "記号"
- kind: "japanese_katakana_stem"
args:
min: 3
- kind: "lowercase"
- kind: "length"
args:
min: 2
Rust API
Token Filter はプログラムから作成・適用することもできます:
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::token_filter::BoxTokenFilter; use lindera::token_filter::japanese_stop_tags::JapaneseStopTagsTokenFilter; use lindera::token_filter::japanese_katakana_stem::JapaneseKatakanaStemTokenFilter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let mut tokenizer = Tokenizer::new(segmenter); // Token Filter を追加 let stop_tags_filter = JapaneseStopTagsTokenFilter::new( vec![ "助詞".to_string(), "助動詞".to_string(), "記号".to_string(), ] .into_iter() .collect(), ); tokenizer.append_token_filter(BoxTokenFilter::from(stop_tags_filter)); let katakana_stem_filter = JapaneseKatakanaStemTokenFilter::new(3); tokenizer.append_token_filter(BoxTokenFilter::from(katakana_stem_filter)); // フィルタを適用してトークナイズ let tokens = tokenizer.tokenize("Linderaは形態素解析エンジンです。")?; for token in tokens { println!( "token: {:?}, details: {:?}", token.surface, token.details ); } Ok(()) }
append_token_filter メソッドはフィルタを順番に追加します。フィルタはセグメンテーション後のトークンリストに対して順次適用されます。
エラーハンドリング
Lindera はライブラリ全体で使いやすいエラーハンドリングを実現するため、anyhow と thiserror に基づく構造化されたエラーシステムを使用しています。
LinderaResult
LinderaResult<T> 型エイリアスは、Lindera における失敗する可能性のある操作の標準的な戻り値型です:
#![allow(unused)] fn main() { pub type LinderaResult<T> = Result<T, LinderaError>; }
LinderaError
LinderaError はメインのエラー型で、エラー種別と完全なコンテキストを持つソースエラーを含みます:
#![allow(unused)] fn main() { pub struct LinderaError { pub kind: LinderaErrorKind, source: anyhow::Error, } }
add_context メソッドを使用して、エラーに追加のコンテキストを付与できます:
#![allow(unused)] fn main() { let error = error.add_context("failed to load dictionary from /path/to/dict"); }
LinderaErrorKind
LinderaErrorKind はエラーを分類する列挙型です:
| Kind | 説明 |
|---|---|
Io | I/Oエラー(ファイルの読み書き、ネットワーク) |
Parse | パースエラー(無効な入力形式) |
Serialize | シリアライズエラー |
Deserialize | デシリアライズエラー |
Content | 無効なコンテンツまたはデータのエラー |
Args | 無効な引数のエラー |
Decode | デコードエラー |
Compression | 圧縮・解凍エラー |
NotFound | リソースが見つからない(例: 辞書ファイルの欠落) |
Build | 辞書ビルドエラー |
Dictionary | 辞書関連のエラー |
Mode | 無効なトークナイズモードのエラー |
Algorithm | アルゴリズムエラー(例: Viterbi の失敗) |
FeatureDisabled | 有効化されていない機能を使用しようとした |
エラーの作成
LinderaErrorKind::with_error を使用して、種別とソースからエラーを作成します:
#![allow(unused)] fn main() { use lindera::error::LinderaErrorKind; let error = LinderaErrorKind::Io.with_error(anyhow::anyhow!("file not found: config.yml")); }
? 演算子の使用
Lindera の関数は LinderaResult を返すため、? 演算子で自然にエラーを伝播できます:
#![allow(unused)] fn main() { use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn analyze(text: &str) -> LinderaResult<Vec<String>> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let tokens = tokenizer.tokenize(text)?; Ok(tokens.iter().map(|t| t.surface.as_ref().to_string()).collect()) } }
エラーハンドリングパターン
エラー種別によるマッチング
#![allow(unused)] fn main() { use lindera::dictionary::load_dictionary; use lindera::error::LinderaErrorKind; match load_dictionary("/path/to/dictionary") { Ok(dict) => { /* 辞書を使用 */ } Err(e) if e.kind() == LinderaErrorKind::NotFound => { eprintln!("Dictionary not found: {}", e); } Err(e) if e.kind() == LinderaErrorKind::Io => { eprintln!("I/O error loading dictionary: {}", e); } Err(e) => { eprintln!("Unexpected error: {}", e); } } }
外部エラーからの変換
#![allow(unused)] fn main() { use lindera::error::LinderaErrorKind; let content = std::fs::read_to_string("config.yml") .map_err(|err| LinderaErrorKind::Io.with_error(anyhow::anyhow!(err)))?; }
APIリファレンス
APIリファレンスは以下で公開されています:
Lindera CLI
Lindera のための形態素解析コマンドラインインターフェースです。
- インストール - CLIのインストールまたはビルド
- コマンド - tokenize、build、train、export のコマンドリファレンス
- チュートリアル - はじめの一歩のステップバイステップガイド
インストール
cargo経由でインストール
cargo経由でバイナリをインストールできます:
% cargo install lindera-cli
GitHub Releasesからダウンロード
または、以下のリリースページからビルド済みバイナリをダウンロードすることもできます:
辞書の入手
Lindera はバイナリに辞書を同梱していません。GitHub Releases ページからビルド済み辞書を別途ダウンロードする必要があります:
# 例: IPADIC 辞書のダウンロードと展開
% curl -LO https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip
% unzip lindera-ipadic-<version>.zip -d /path/to/ipadic
CLI 使用時に辞書パスを指定します:
% lindera tokenize --dictionary /path/to/ipadic "関西国際空港限定トートバッグ"
ソースからビルド
辞書なしでビルド(デフォルト)
辞書を埋め込まず、トークナイザーとトレーナーのみを含むバイナリをビルドします:
% cargo build --release
全機能を含めてビルド
% cargo build --release --all-features
辞書埋め込みビルド(上級者向け)
辞書をバイナリに直接埋め込みたい上級者向けに、embed-* feature フラグを使用できます。実行時の外部辞書ファイルが不要になりますが、バイナリサイズが増加します。
IPADIC(日本語辞書)
% cargo build --release --features=embed-ipadic
IPADIC NEologd(日本語辞書)
% cargo build --release --features=embed-ipadic-neologd
UniDic(日本語辞書)
% cargo build --release --features=embed-unidic
ko-dic(韓国語辞書)
% cargo build --release --features=embed-ko-dic
CC-CEDICT(中国語辞書)
% cargo build --release --features=embed-cc-cedict
Jieba(中国語辞書)
% cargo build --release --features=embed-jieba
[!TIP]
embed-*feature フラグ付きでビルドした後、embedded://スキームで埋め込み辞書をロードできます:% lindera tokenize --dictionary embedded://ipadic "関西国際空港限定トートバッグ"詳細は Feature フラグ を参照してください。
コマンド
Lindera CLI は4つのメインコマンドを提供します:
- tokenize - テキストに対して形態素解析を実行
- build - ソースCSVファイルから辞書をビルド
- train - 注釈付きコーパスデータからCRFモデルを学習
- export - 学習済みモデルを辞書フォーマットにエクスポート
tokenize
様々な辞書を使用して、日本語、中国語、または韓国語のテキストに対して形態素解析(トークナイズ)を行います。
パラメータ
--dict/-d: 辞書のパスまたはURI(必須)- ファイルパス:
/path/to/dictionary - 埋め込み:
embedded://ipadic,embedded://unidic, etc.
- ファイルパス:
--output/-o: 出力形式 (デフォルト: mecab)mecab: 品詞情報を含むMeCab互換形式wakati: スペース区切りのトークンのみjson: すべてのトークン情報を含む詳細なJSON形式
--user-dict/-u: ユーザー辞書のパス(オプション)--mode/-m: トークナイズモード (デフォルト: normal)normal: 標準的なトークナイズdecompose: 複合語を分解する
--char-filter/-c: 文字フィルタ設定 (JSON)--token-filter/-t: トークンフィルタ設定 (JSON)--nbest/-N: 返す N-best 結果の数(デフォルト: 1)。2以上に設定すると N-best 出力が有効になります。--nbest-unique: 同じ分割を生成するパスの重複を排除します。--nbest-cost-threshold: 最良パスからの最大コスト差。best_cost + threshold以内のコストを持つパスのみが返されます。- 入力ファイル: オプションのファイルパス (デフォルト: 標準入力)
基本的な使用方法
# 辞書ディレクトリを指定してトークナイズ
echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /path/to/dictionary
# 埋め込み辞書を指定してトークナイズ
echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic
# 出力形式を指定してトークナイズ
echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic \
--output json
# ファイルからテキストを読み込んでトークナイズ
lindera tokenize \
--dict /path/to/dictionary \
--output wakati \
input.txt
外部辞書を使用した例
外部IPADIC(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-ipadic-2.7.0-20250920
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素 名詞,一般,*,*,*,*,形態素,ケイタイソ,ケイタイソ
解析 名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
外部IPADIC NEologd(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-ipadic-neologd-0.0.7-20200820
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素解析 名詞,固有名詞,一般,*,*,*,形態素解析,ケイタイソカイセキ,ケイタイソカイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
外部UniDic(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-unidic-2.1.2
日本 名詞,固有名詞,地名,国,*,*,ニッポン,日本,日本,ニッポン,日本,ニッポン,固,*,*,*,*
語 名詞,普通名詞,一般,*,*,*,ゴ,語,語,ゴ,語,ゴ,漢,*,*,*,*
の 助詞,格助詞,*,*,*,*,ノ,の,の,ノ,の,ノ,和,*,*,*,*
形態 名詞,普通名詞,一般,*,*,*,ケイタイ,形態,形態,ケータイ,形態,ケータイ,漢,*,*,*,*
素 接尾辞,名詞的,一般,*,*,*,ソ,素,素,ソ,素,ソ,漢,*,*,*,*
解析 名詞,普通名詞,サ変可能,*,*,*,カイセキ,解析,解析,カイセキ,解析,カイセキ,漢,*,*,*,*
を 助詞,格助詞,*,*,*,*,ヲ,を,を,オ,を,オ,和,*,*,*,*
行う 動詞,一般,*,*,五段-ワア行,連体形-一般,オコナウ,行う,行う,オコナウ,行う,オコナウ,和,*,*,*,*
こと 名詞,普通名詞,一般,*,*,*,コト,事,こと,コト,こと,コト,和,コ濁,基本形,*,*
が 助詞,格助詞,*,*,*,*,ガ,が,が,ガ,が,ガ,和,*,*,*,*
でき 動詞,非自立可能,*,*,上一段-カ行,連用形-一般,デキル,出来る,でき,デキ,できる,デキル,和,*,*,*,*
ます 助動詞,*,*,*,助動詞-マス,終止形-一般,マス,ます,ます,マス,ます,マス,和,*,*,*,*
。 補助記号,句点,*,*,*,*,,。,。,,。,,記号,*,*,*,*
EOS
外部ko-dic(韓国語辞書)を使用したトークナイズ
% echo "한국어의형태해석을실시할수있습니다." | lindera tokenize \
--dict /tmp/lindera-ko-dic-2.1.1-20180720
한국어 NNG,*,F,한국어,Compound,*,*,한국/NNG/*+어/NNG/*
의 JKG,*,F,의,*,*,*,*
형태 NNG,*,F,형태,*,*,*,*
해석 NNG,행위,T,해석,*,*,*,*
을 JKO,*,T,을,*,*,*,*
실시 NNG,행위,F,실시,*,*,*,*
할 XSV+ETM,*,T,할,Inflect,XSV,ETM,하/XSV/*+ᆯ/ETM/*
수 NNB,*,F,수,*,*,*,*
있 VV,*,T,있,*,*,*,*
습니다 EF,*,F,습니다,*,*,*,*
. SF,*,*,*,*,*,*,*
EOS
外部CC-CEDICT(中国語辞書)を使用したトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict /tmp/lindera-cc-cedict-0.1.0-20200409
可以 *,*,*,*,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good/
进行 *,*,*,*,jin4 xing2,進行,进行,to advance/to conduct/underway/in progress/to do/to carry out/to carry on/to execute/
中文 *,*,*,*,Zhong1 wen2,中文,中文,Chinese language/
形态学 *,*,*,*,xing2 tai4 xue2,形態學,形态学,morphology (in biology or linguistics)/
分析 *,*,*,*,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4]/
。 *,*,*,*,*,*,*,*
EOS
外部Jieba(中国語辞書)を使用したトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict /tmp/lindera-jieba-0.1.1
埋め込み辞書を使用した例
Linderaは、特定の機能フラグを指定してビルドすることで、バイナリに辞書を直接含めることができます。これにより、外部辞書ファイルなしでトークナイズが可能になります。
埋め込みIPADIC(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素 名詞,一般,*,*,*,*,形態素,ケイタイソ,ケイタイソ
解析 名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
注意: IPADIC辞書をバイナリに含めるには、--features=embed-ipadic オプションを使用してビルドする必要があります。
埋め込みUniDic(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://unidic
日本 名詞,固有名詞,地名,国,*,*,ニッポン,日本,日本,ニッポン,日本,ニッポン,固,*,*,*,*
語 名詞,普通名詞,一般,*,*,*,ゴ,語,語,ゴ,語,ゴ,漢,*,*,*,*
の 助詞,格助詞,*,*,*,*,ノ,の,の,ノ,の,ノ,和,*,*,*,*
形態 名詞,普通名詞,一般,*,*,*,ケイタイ,形態,形態,ケータイ,形態,ケータイ,漢,*,*,*,*
素 接尾辞,名詞的,一般,*,*,*,ソ,素,素,ソ,素,ソ,漢,*,*,*,*
解析 名詞,普通名詞,サ変可能,*,*,*,カイセキ,解析,解析,カイセキ,解析,カイセキ,漢,*,*,*,*
を 助詞,格助詞,*,*,*,*,ヲ,を,を,オ,を,オ,和,*,*,*,*
行う 動詞,一般,*,*,五段-ワア行,連体形-一般,オコナウ,行う,行う,オコナウ,行う,オコナウ,和,*,*,*,*
こと 名詞,普通名詞,一般,*,*,*,コト,事,こと,コト,こと,コト,和,コ濁,基本形,*,*
が 助詞,格助詞,*,*,*,*,ガ,が,が,ガ,が,ガ,和,*,*,*,*
でき 動詞,非自立可能,*,*,上一段-カ行,連用形-一般,デキル,出来る,でき,デキ,できる,デキル,和,*,*,*,*
ます 助動詞,*,*,*,助動詞-マス,終止形-一般,マス,ます,ます,マス,ます,マス,和,*,*,*,*
。 補助記号,句点,*,*,*,*,,。,。,,。,,記号,*,*,*,*
EOS
注意: UniDic辞書をバイナリに含めるには、--features=embed-unidic オプションを使用してビルドする必要があります。
埋め込みIPADIC NEologd(日本語辞書)を使用したトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic-neologd
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素解析 名詞,固有名詞,一般,*,*,*,形態素解析,ケイタイソカイセキ,ケイタイソカイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
注意: IPADIC NEologd辞書をバイナリに含めるには、--features=embed-ipadic-neologd オプションを使用してビルドする必要があります。
埋め込みko-dic(韓国語辞書)を使用したトークナイズ
% echo "한국어의형태해석을실시할수있습니다." | lindera tokenize \
--dict embedded://ko-dic
한국어 NNG,*,F,한국어,Compound,*,*,한국/NNG/*+어/NNG/*
의 JKG,*,F,의,*,*,*,*
형태 NNG,*,F,형태,*,*,*,*
해석 NNG,행위,T,해석,*,*,*,*
을 JKO,*,T,을,*,*,*,*
실시 NNG,행위,F,실시,*,*,*,*
할 XSV+ETM,*,T,할,Inflect,XSV,ETM,하/XSV/*+ᆯ/ETM/*
수 NNB,*,F,수,*,*,*,*
있 VV,*,T,있,*,*,*,*
습니다 EF,*,F,습니다,*,*,*,*
. SF,*,*,*,*,*,*,*
EOS
注意: ko-dic辞書をバイナリに含めるには、--features=embed-ko-dic オプションを使用してビルドする必要があります。
埋め込みCC-CEDICT(中国語辞書)を使用したトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict embedded://cc-cedict
可以 *,*,*,*,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good/
进行 *,*,*,*,jin4 xing2,進行,进行,to advance/to conduct/underway/in progress/to do/to carry out/to carry on/to execute/
中文 *,*,*,*,Zhong1 wen2,中文,中文,Chinese language/
形态学 *,*,*,*,xing2 tai4 xue2,形態學,形态学,morphology (in biology or linguistics)/
分析 *,*,*,*,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4]/
。 *,*,*,*,*,*,*,*
EOS
注意: CC-CEDICT辞書をバイナリに含めるには、--features=embed-cc-cedict オプションを使用してビルドする必要があります。
埋め込みJieba(中国語辞書)を使用したトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict embedded://jieba
注意: Jieba辞書をバイナリに含めるには、--features=embed-jieba オプションを使用してビルドする必要があります。
ユーザー辞書の例
Linderaは、システム辞書と一緒にカスタム単語を追加するためのユーザー辞書をサポートしています。ユーザー辞書はCSVまたはバイナリ形式にすることができます。
ユーザー辞書の使用(CSV形式)
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict embedded://ipadic \
--user-dict ./resources/user_dict/ipadic_simple_userdic.csv
東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
の 助詞,連体化,*,*,*,*,の,ノ,ノ
最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
ユーザー辞書の使用(バイナリ形式)
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict /tmp/lindera-ipadic-2.7.0-20250920 \
--user-dict ./resources/user_dict/ipadic_simple_userdic.bin
東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
の 助詞,連体化,*,*,*,*,の,ノ,ノ
最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
トークナイズモード
Linderaは2つのトークナイズモードを提供します:normal と decompose です。
Normal モード(デフォルト)
辞書に登録された単語に基づいて忠実にトークナイズします:
% echo "関西国際空港限定トートバッグ" | lindera tokenize \
--dict embedded://ipadic \
--mode normal
関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ 名詞,一般,*,*,*,*,*,*,*
EOS
Decompose モード
複合語をさらに分解してトークナイズします:
% echo "関西国際空港限定トートバッグ" | lindera tokenize \
--dict embedded://ipadic \
--mode decompose
関西 名詞,固有名詞,地域,一般,*,*,関西,カンサイ,カンサイ
国際 名詞,一般,*,*,*,*,国際,コクサイ,コクサイ
空港 名詞,一般,*,*,*,*,空港,クウコウ,クーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ 名詞,一般,*,*,*,*,*,*,*
EOS
出力形式
Linderaは3つの出力形式を提供します:mecab, wakati, json。
MeCab 形式(デフォルト)
品詞情報を含むMeCab互換形式で結果を出力します:
% echo "お待ちしております。" | lindera tokenize \
--dict embedded://ipadic \
--output mecab
お待ち 名詞,サ変接続,*,*,*,*,お待ち,オマチ,オマチ
し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
おり 動詞,非自立,*,*,五段・ラ行,連用形,おる,オリ,オリ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
Wakati 形式
トークンテキストのみをスペース区切りで出力します:
% echo "お待ちしております。" | lindera tokenize \
--dict embedded://ipadic \
--output wakati
お待ち し て おり ます 。
JSON 形式
すべてのトークン情報を含む詳細なJSON形式で出力します:
% echo "お待ちしております。" | lindera tokenize \
--dict embedded://ipadic \
--output json
[
{
"base_form": "お待ち",
"byte_end": 9,
"byte_start": 0,
"conjugation_form": "*",
"conjugation_type": "*",
"part_of_speech": "名詞",
"part_of_speech_subcategory_1": "サ変接続",
"part_of_speech_subcategory_2": "*",
"part_of_speech_subcategory_3": "*",
"pronunciation": "オマチ",
"reading": "オマチ",
"surface": "お待ち",
"word_id": 14698
},
...
]
N-Best トークナイズ
Linderaは N-Best トークナイズをサポートしており、コスト順(低コスト=高精度)に上位 N 件のトークナイズ候補を返します。これは MeCab の N-Best 実装と互換性のある Forward-DP Backward-A* アルゴリズムに基づいています。
基本的な N-Best の例
% echo "すもももももももものうち" | lindera tokenize \
--dict embedded://ipadic \
-N 3
NBEST 1 (cost=7546)
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
NBEST 2 (cost=7914)
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
NBEST 3 (cost=10060)
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
も 助詞,係助詞,*,*,*,*,も,モ,モ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
ユニーク結果を使用した N-Best
同じ分割が複数のパスに現れる場合(内部的な Viterbi 状態のみが異なる場合)、--nbest-unique を使用して重複を排除します:
% echo "営業部長谷川です" | lindera tokenize \
--dict embedded://ipadic \
-N 5 --nbest-unique -o wakati
NBEST 1 (cost=15760)
営業 部長 谷川 です
NBEST 2 (cost=17758)
営業 部長 谷 川 です
NBEST 3 (cost=18816)
営業 部 長谷川 です
NBEST 4 (cost=19320)
営業 部長 谷川 で す
NBEST 5 (cost=20814)
営業 部 長谷 川 です
コスト閾値を使用した N-Best
--nbest-cost-threshold を使用して、最良パスから一定のコスト範囲内の結果に制限します:
% echo "営業部長谷川です" | lindera tokenize \
--dict embedded://ipadic \
-N 10 --nbest-unique --nbest-cost-threshold 5000 -o wakati
NBEST 1 (cost=15760)
営業 部長 谷川 です
NBEST 2 (cost=17758)
営業 部長 谷 川 です
NBEST 3 (cost=18816)
営業 部 長谷川 です
残りの候補は 15760 + 5000 = 20760 を超えるため、3件の結果のみが返されます。
フィルタを使用した高度なトークナイズ
Linderaは、文字フィルタ、トークナイザー、トークンフィルタを組み合わせた分析フレームワークを提供します。フィルタはJSONを使用して構成します。
% echo "すもももももももものうち" | lindera tokenize \
--dict embedded://ipadic \
--char-filter 'unicode_normalize:{"kind":"nfkc"}' \
--token-filter 'japanese_keep_tags:{"tags":["名詞,一般"]}'
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
EOS
build
Linderaで使用するための形態素解析辞書をCSVソースファイルからビルド(コンパイル)します。
ビルドパラメータ
--src/-s: 辞書CSVファイルを含むソースディレクトリ(ユーザー辞書の場合は単一CSVファイル)--dest/-d: コンパイルされた辞書の出力先ディレクトリ--metadata/-m: 辞書構造を定義するメタデータ設定ファイル (metadata.json)--user/-u: システム辞書の代わりにユーザー辞書をビルドする(オプションフラグ)
辞書の種類
システム辞書 (System dictionary)
以下を含む完全な形態素解析辞書です:
- 語彙エントリ(単語定義)
- 接続コスト行列
- 未知語処理ルール
- 文字種定義
ユーザー辞書 (User dictionary)
システム辞書と一緒に動作する、カスタム単語のための補助辞書です。
例
IPADIC(日本語辞書)のビルド
# IPADICソースファイルのダウンロードと展開
% curl -L -o /tmp/mecab-ipadic-2.7.0-20250920.tar.gz "https://Lindera.dev/mecab-ipadic-2.7.0-20250920.tar.gz"
% tar zxvf /tmp/mecab-ipadic-2.7.0-20250920.tar.gz -C /tmp
# 辞書のビルド
% lindera build \
--src /tmp/mecab-ipadic-2.7.0-20250920 \
--dest /tmp/lindera-ipadic-2.7.0-20250920 \
--metadata ./lindera-ipadic/metadata.json
IPADIC NEologd(日本語辞書)のビルド
% curl -L -o /tmp/mecab-ipadic-neologd-0.0.7-20200820.tar.gz "https://lindera.dev/mecab-ipadic-neologd-0.0.7-20200820.tar.gz"
% tar zxvf /tmp/mecab-ipadic-neologd-0.0.7-20200820.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-ipadic-neologd-0.0.7-20200820 \
--dest /tmp/lindera-ipadic-neologd-0.0.7-20200820 \
--metadata ./lindera-ipadic-neologd/metadata.json
UniDic(日本語辞書)のビルド
% curl -L -o /tmp/unidic-mecab-2.1.2.tar.gz "https://Lindera.dev/unidic-mecab-2.1.2.tar.gz"
% tar zxvf /tmp/unidic-mecab-2.1.2.tar.gz -C /tmp
% lindera build \
--src /tmp/unidic-mecab-2.1.2 \
--dest /tmp/lindera-unidic-2.1.2 \
--metadata ./lindera-unidic/metadata.json
CC-CEDICT(中国語辞書)のビルド
% curl -L -o /tmp/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz "https://lindera.dev/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz"
% tar zxvf /tmp/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz -C /tmp
% lindera build \
--src /tmp/CC-CEDICT-MeCab-0.1.0-20200409 \
--dest /tmp/lindera-cc-cedict-0.1.0-20200409 \
--metadata ./lindera-cc-cedict/metadata.json
Jieba(中国語辞書)のビルド
% curl -L -o /tmp/mecab-jieba-0.1.1.tar.gz "https://lindera.dev/mecab-jieba-0.1.1.tar.gz"
% tar zxvf /tmp/mecab-jieba-0.1.1.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-jieba-0.1.1/dict-src \
--dest /tmp/lindera-jieba-0.1.1 \
--metadata ./lindera-jieba/metadata.json
ko-dic(韓国語辞書)のビルド
% curl -L -o /tmp/mecab-ko-dic-2.1.1-20180720.tar.gz "https://Lindera.dev/mecab-ko-dic-2.1.1-20180720.tar.gz"
% tar zxvf /tmp/mecab-ko-dic-2.1.1-20180720.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-ko-dic-2.1.1-20180720 \
--dest /tmp/lindera-ko-dic-2.1.1-20180720 \
--metadata ./lindera-ko-dic/metadata.json
ユーザー辞書のビルド
IPADICユーザー辞書(日本語)のビルド
ユーザー辞書フォーマットの詳細については、以下のURLを参照してください:
% lindera build \
--src ./resources/user_dict/ipadic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-ipadic/metadata.json \
--user
UniDicユーザー辞書(日本語)のビルド
ユーザー辞書フォーマットの詳細については、以下のURLを参照してください:
% lindera build \
--src ./resources/user_dict/unidic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-unidic/metadata.json \
--user
CC-CEDICTユーザー辞書(中国語)のビルド
ユーザー辞書フォーマットの詳細については、以下のURLを参照してください:
% lindera build \
--src ./resources/user_dict/cc-cedict_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-cc-cedict/metadata.json \
--user
Jiebaユーザー辞書(中国語)のビルド
ユーザー辞書フォーマットの詳細については、以下のURLを参照してください:
% lindera build \
--src ./resources/user_dict/jieba_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-jieba/metadata.json \
--user
ko-dicユーザー辞書(韓国語)のビルド
ユーザー辞書フォーマットの詳細については、以下のURLを参照してください:
% lindera build \
--src ./resources/user_dict/ko-dic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-ko-dic/metadata.json \
--user
train
注釈付きコーパスデータから新しい形態素解析モデルを学習します。この機能を使用するには、train 機能フラグを有効にしてビルドする必要があります。(train 機能フラグはデフォルトで有効になっています。)
学習パラメータ
--seed/-s: 重み付けを行うシード語彙ファイル(CSV形式)--corpus/-c: 学習用コーパス(注釈付きテキスト)--char-def/-C: 文字定義ファイル (char.def)--unk-def/-u: 未知語定義ファイル (unk.def) - 重み付けの対象--feature-def/-f: 素性定義ファイル (feature.def)--rewrite-def/-r: 書換えルール定義ファイル (rewrite.def)--output/-o: 出力モデルファイル--lambda/-l: L1正則化 (0.0-1.0) (デフォルト: 0.01)--max-iterations/-i: 学習の最大反復回数 (デフォルト: 100)--max-threads/-t: 最大スレッド数 (デフォルトはCPUコア数、データセットサイズに基づいて自動調整)
基本的なワークフロー
1. 学習用ファイルの準備
シード語彙ファイル (seed.csv):
シード語彙ファイルは、CRFモデルの学習に使用される初期辞書エントリを含みます。各行はカンマ区切りのフィールドを持つ単語エントリを表します:
- 表層形
- 左文脈ID
- 右文脈ID
- 単語コスト
- 品詞タグ(複数のフィールド)
- 原形
- 読み(カタカナ)
- 発音
注意: 正確なフィールド定義は辞書フォーマット(IPADIC, UniDic, ko-dic, CC-CEDICT)によって異なります。詳細は各辞書のフォーマット仕様を参照してください。
外国,0,0,0,名詞,一般,*,*,*,*,外国,ガイコク,ガイコク
人,0,0,0,名詞,接尾,一般,*,*,*,人,ジン,ジン
学習用コーパス (corpus.txt):
学習用コーパスファイルは、CRFモデルの学習に使用される注釈付きテキストデータを含みます。各行は以下で構成されます:
- 表層形(単語)とそれに続くタブ文字
- カンマ区切りの形態素素性(品詞タグ、原形、読み、発音)
- 文は "EOS" (End Of Sentence) マーカーで区切られます
外国 名詞,一般,*,*,*,*,外国,ガイコク,ガイコク
人 名詞,接尾,一般,*,*,*,人,ジン,ジン
参政 名詞,サ変接続,*,*,*,*,参政,サンセイ,サンセイ
権 名詞,接尾,一般,*,*,*,権,ケン,ケン
EOS
ファイルフォーマットや高度な機能の詳細については、TRAINER_README.md を参照してください。
2. モデルの学習
lindera train \
--seed ./resources/training/seed.csv \
--corpus ./resources/training/corpus.txt \
--unk-def ./resources/training/unk.def \
--char-def ./resources/training/char.def \
--feature-def ./resources/training/feature.def \
--rewrite-def ./resources/training/rewrite.def \
--output /tmp/lindera/training/model.dat \
--lambda 0.01 \
--max-iterations 100
3. 学習結果
学習済みモデルには以下が含まれます:
- 既存単語: 新しく学習された重みを持つすべてのシード辞書レコード
- 新語: シード辞書にはないがコーパスに含まれる単語(適切な重み付きで追加)
export
学習済みモデルファイルをLindera辞書フォーマットのファイルにエクスポートします。この機能を使用するには、train 機能フラグを有効にしてビルドする必要があります。
エクスポートパラメータ
--model/-m: 学習済みモデルファイル(.dat形式)のパス--output/-o: 辞書ファイルの出力先ディレクトリ--metadata: オプションの metadata.json ファイル(学習済みモデル情報で更新されます)--cost-factor: 重みからコストへの変換係数を上書き(デフォルト: 学習済みモデルの値、通常は700)
出力ファイル
エクスポートコマンドは出力ディレクトリに以下の辞書ファイルを作成します:
lex.csv: 学習された重みを持つ語彙ファイル(MeCab互換のtocost()によるコスト変換)matrix.def: 全 (right_id, left_id) ペアを網羅する密な接続コスト行列unk.def: 未知語定義char.def: 文字種定義feature.def: 素性テンプレート定義(学習済みモデルからコピー)rewrite.def: 素性リライトルール(学習済みモデルからコピー)left-id.def: 左文脈IDから素性文字列へのマッピングright-id.def: 右文脈IDから素性文字列へのマッピングmetadata.json: 更新されたメタデータファイル(--metadataオプションが指定された場合)
完全なワークフロー例
1. モデルの学習
lindera train \
--seed ./resources/training/seed.csv \
--corpus ./resources/training/corpus.txt \
--unk-def ./resources/training/unk.def \
--char-def ./resources/training/char.def \
--feature-def ./resources/training/feature.def \
--rewrite-def ./resources/training/rewrite.def \
--output /tmp/lindera/training/model.dat \
--lambda 0.01 \
--max-iterations 100
2. 辞書フォーマットへのエクスポート
lindera export \
--model /tmp/lindera/training/model.dat \
--metadata ./resources/training/metadata.json \
--output /tmp/lindera/training/dictionary
3. 辞書のビルド
lindera build \
--src /tmp/lindera/training/dictionary \
--dest /tmp/lindera/training/compiled_dictionary \
--metadata /tmp/lindera/training/dictionary/metadata.json
4. 学習済み辞書の使用
echo "これは外国人参政権です。" | lindera tokenize \
-d /tmp/lindera/training/compiled_dictionary
メタデータ更新機能
--metadata オプションが指定されると、エクスポートコマンドは以下の処理を行います:
- ベースとなる metadata.json ファイルを読み込み、既存の設定を保持します
- 特定のフィールドを学習済みモデルの値で更新します:
default_left_context_id: 学習済みモデルからの最大左文脈IDdefault_right_context_id: 学習済みモデルからの最大右文脈IDdefault_word_cost: 素性重みの中央値から計算された値model_info: 素性数、ラベル数、行列サイズ、反復回数、正則化、バージョン、タイムスタンプを含む学習統計情報
- 既存の設定を保持します(辞書名、文字エンコード設定、スキーマ定義、その他のユーザー定義設定など)
チュートリアル
このチュートリアルでは、Lindera CLIの基本的な使い方を、インストールから高度なテキスト処理まで順を追って説明します。
1. CLIのインストール
埋め込みIPADIC辞書付きでLindera CLIをインストールします:
% cargo install lindera-cli --features=embed-ipadic
インストールの確認:
% lindera --help
2. 埋め込み辞書を使用した基本的なトークナイズ
埋め込みIPADIC辞書を使用して日本語テキストをトークナイズします:
% echo "東京は日本の首都です。" | lindera tokenize \
--dict embedded://ipadic
期待される出力:
東京 名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
日本 名詞,固有名詞,地域,国,*,*,日本,ニホン,ニホン
の 助詞,連体化,*,*,*,*,の,ノ,ノ
首都 名詞,一般,*,*,*,*,首都,シュト,シュト
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。 記号,句点,*,*,*,*,。,。,。
EOS
3. 異なる出力形式を試す
Wakati 形式(分かち書きのみ)
% echo "東京は日本の首都です。" | lindera tokenize \
--dict embedded://ipadic \
--output wakati
期待される出力:
東京 は 日本 の 首都 です 。
JSON 形式(詳細情報)
% echo "東京は日本の首都です。" | lindera tokenize \
--dict embedded://ipadic \
--output json
バイトオフセット、品詞タグ、読みなどの詳細なトークン情報を含むJSON配列が出力されます。
4. Decompose モードの使用
Decompose モードは複合名詞を構成要素に分解します:
% echo "関西国際空港限定トートバッグ" | lindera tokenize \
--dict embedded://ipadic \
--mode decompose
期待される出力:
関西 名詞,固有名詞,地域,一般,*,*,関西,カンサイ,カンサイ
国際 名詞,一般,*,*,*,*,国際,コクサイ,コクサイ
空港 名詞,一般,*,*,*,*,空港,クウコウ,クーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ 名詞,一般,*,*,*,*,*,*,*
EOS
Normal モードと比較すると、「関西国際空港」が1つのトークンのままになる点が異なります。
5. 文字フィルタとトークンフィルタの適用
Unicode正規化を行い、一般名詞のみを保持します:
% echo "Linderaは形態素解析エンジンです。" | lindera tokenize \
--dict embedded://ipadic \
--char-filter 'unicode_normalize:{"kind":"nfkc"}' \
--token-filter 'japanese_keep_tags:{"tags":["名詞,一般","名詞,固有名詞,組織"]}'
期待される出力:
Lindera 名詞,固有名詞,組織,*,*,*,*,*,*
形態素 名詞,一般,*,*,*,*,形態素,ケイタイソ,ケイタイソ
解析 名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
エンジン 名詞,一般,*,*,*,*,エンジン,エンジン,エンジン
EOS
Unicode正規化により全角文字が半角に変換され、Token Filter により指定した品詞タグに一致するトークンのみが保持されます。
複数のフィルタを組み合わせることもできます:
% echo "すもももももももものうち" | lindera tokenize \
--dict embedded://ipadic \
--token-filter 'japanese_stop_tags:{"tags":["助詞","助詞,係助詞","助詞,連体化"]}'
6. ユーザー辞書の使用
カスタム単語エントリを含むCSVファイル(例: my_dict.csv)を作成します:
東京スカイツリー,カスタム名詞,トウキョウスカイツリー
ユーザー辞書を使用してトークナイズします:
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict embedded://ipadic \
--user-dict ./my_dict.csv
ユーザー辞書がない場合、「東京スカイツリー」は複数のトークンに分割されます。ユーザー辞書を使用すると、1つのトークンとして認識されます。
ビルド済みのユーザー辞書の例については、以下を参照してください:
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict embedded://ipadic \
--user-dict ./resources/user_dict/ipadic_simple_userdic.csv
期待される出力:
東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
の 助詞,連体化,*,*,*,*,の,ノ,ノ
最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
Lindera Python
Lindera Python は、PyO3 を使用して構築された Lindera 形態素解析エンジンの Python バインディングです。Python 3.10 以降をサポートし、Lindera の高性能なトークナイズ機能を Python エコシステムに提供します。
特徴
- 多言語対応: 日本語(IPADIC、IPADIC NEologd、UniDic)、韓国語(ko-dic)、中国語(CC-CEDICT、Jieba)のテキストをトークナイズ
- テキスト処理パイプライン: 文字フィルタとトークンフィルタを組み合わせて、柔軟な前処理・後処理が可能
- CRF ベースの辞書学習: アノテーション付きコーパスからカスタム形態素解析モデルを学習(
trainfeature が必要) - 複数のトークナイズモード: 解析粒度に応じた Normal モードと Decompose モード
- N-best トークナイズ: コスト順にランク付けされた複数のトークナイズ候補を取得
- ユーザー辞書: システム辞書をカスタム語彙で拡張
ドキュメント
- インストール -- 前提条件、ビルド手順、feature フラグ
- クイックスタート -- 最小限の使用例
- Tokenizer API --
TokenizerBuilder、Tokenizer、Tokenクラスリファレンス - 辞書管理 -- 辞書の読み込み、ビルド、管理
- テキスト処理パイプライン -- 文字フィルタとトークンフィルタ
- 学習 -- カスタム CRF モデルの学習と辞書のエクスポート
インストール
PyPI からのインストール
ビルド済みホイールが PyPI で公開されています:
pip install lindera-python
[!NOTE] PyPI パッケージには辞書が含まれていません。下記の辞書の入手を参照してください。
辞書の入手
Lindera はパッケージに辞書を同梱していません。ビルド済み辞書を別途入手する必要があります。
GitHub Releases からのダウンロード
ビルド済み辞書は GitHub Releases ページから入手できます。辞書アーカイブをダウンロードしてローカルディレクトリに展開してください:
# 例: IPADIC 辞書のダウンロードと展開
curl -LO https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip
unzip lindera-ipadic-<version>.zip -d /path/to/ipadic
ソースからのビルド
特定の feature フラグを有効にする必要がある場合など、ソースからビルドするには以下の前提条件が必要です:
- Python 3.10 以降(3.14 まで)
- Rust ツールチェーン -- rustup 経由でインストール
- maturin -- Rust ベースの Python 拡張をビルドするための Python パッケージ
maturin を pip でインストールします:
pip install maturin
開発ビルド
lindera-python を開発モードでビルドしてインストールします:
cd lindera-python
maturin develop
または、プロジェクトの Makefile を使用します:
make python-develop
学習機能付きビルド
train feature を有効にすると、CRF ベースの辞書学習機能が利用可能になります。デフォルトで有効になっています:
maturin develop --features train
Feature フラグ
| Feature | 説明 | デフォルト |
|---|---|---|
train | CRF 学習機能 | 有効 |
embed-ipadic | 日本語辞書(IPADIC)をバイナリに埋め込み | 無効 |
embed-unidic | 日本語辞書(UniDic)をバイナリに埋め込み | 無効 |
embed-ipadic-neologd | 日本語辞書(IPADIC NEologd)をバイナリに埋め込み | 無効 |
embed-ko-dic | 韓国語辞書(ko-dic)をバイナリに埋め込み | 無効 |
embed-cc-cedict | 中国語辞書(CC-CEDICT)をバイナリに埋め込み | 無効 |
embed-jieba | 中国語辞書(Jieba)をバイナリに埋め込み | 無効 |
embed-cjk | 全 CJK 辞書をバイナリに埋め込み(IPADIC、ko-dic、Jieba) | 無効 |
複数の feature を組み合わせることができます:
maturin develop --features "train,embed-ipadic,embed-ko-dic"
[!TIP] 辞書をバイナリに直接埋め込みたい場合(上級者向け)は、対応する
embed-*feature フラグを有効にしてビルドし、embedded://スキームでロードしてください:dictionary = load_dictionary("embedded://ipadic")詳細は Feature フラグ を参照してください。
インストールの確認
インストール後、Python で lindera が利用可能であることを確認します:
import lindera
print(lindera.version())
クイックスタート
このガイドでは、lindera-python を使用してテキストをトークナイズする方法を紹介します。
基本的なトークナイズ
トークナイザーの作成には TokenizerBuilder の使用を推奨します:
from lindera import TokenizerBuilder
builder = TokenizerBuilder()
builder.set_mode("normal")
builder.set_dictionary("/path/to/ipadic")
tokenizer = builder.build()
tokens = tokenizer.tokenize("関西国際空港限定トートバッグ")
for token in tokens:
print(f"{token.surface}\t{','.join(token.details)}")
注意: ビルド済み辞書を GitHub Releases からダウンロードし、展開したディレクトリのパスを指定してください。
期待される出力:
関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ UNK
メソッドチェーン
TokenizerBuilder は簡潔な設定のためにメソッドチェーンをサポートしています:
from lindera import TokenizerBuilder
tokenizer = (
TokenizerBuilder()
.set_mode("normal")
.set_dictionary("/path/to/ipadic")
.build()
)
tokens = tokenizer.tokenize("すもももももももものうち")
for token in tokens:
print(f"{token.surface}\t{token.get_detail(0)}")
トークンプロパティへのアクセス
各トークンは以下のプロパティを公開しています:
from lindera import TokenizerBuilder
tokenizer = TokenizerBuilder().set_dictionary("/path/to/ipadic").build()
tokens = tokenizer.tokenize("東京タワー")
for token in tokens:
print(f"Surface: {token.surface}")
print(f"Byte range: {token.byte_start}..{token.byte_end}")
print(f"Position: {token.position}")
print(f"Word ID: {token.word_id}")
print(f"Unknown: {token.is_unknown}")
print(f"Details: {token.details}")
print()
N-best トークナイズ
コスト順にランク付けされた複数のトークナイズ候補を取得します:
from lindera import TokenizerBuilder
tokenizer = TokenizerBuilder().set_dictionary("/path/to/ipadic").build()
results = tokenizer.tokenize_nbest("すもももももももものうち", n=3)
for tokens, cost in results:
surfaces = [t.surface for t in tokens]
print(f"Cost {cost}: {' / '.join(surfaces)}")
Tokenizer API
TokenizerBuilder
TokenizerBuilder はビルダーパターンを使用して Tokenizer インスタンスを設定・構築します。
コンストラクタ
TokenizerBuilder()
デフォルト設定で新しいビルダーを作成します。
from lindera import TokenizerBuilder
builder = TokenizerBuilder()
TokenizerBuilder().from_file(file_path)
JSON ファイルから設定を読み込み、新しいビルダーを返します。
builder = TokenizerBuilder().from_file("config.json")
設定メソッド
すべてのセッターメソッドはメソッドチェーンのために self を返します。
set_mode(mode)
トークナイズモードを設定します。
"normal"-- 標準的なトークナイズ(デフォルト)"decompose"-- 複合語をより小さな単位に分解
builder.set_mode("normal")
set_dictionary(path)
システム辞書のパスまたは URI を設定します。
# 埋め込み辞書を使用
builder.set_dictionary("embedded://ipadic")
# 外部辞書を使用
builder.set_dictionary("/path/to/dictionary")
set_user_dictionary(uri)
ユーザー辞書の URI を設定します。
builder.set_user_dictionary("/path/to/user_dictionary")
set_keep_whitespace(keep)
出力に空白トークンを含めるかどうかを制御します。
builder.set_keep_whitespace(True)
append_character_filter(kind, args=None)
前処理パイプラインに文字フィルタを追加します。
builder.append_character_filter("unicode_normalize", {"kind": "nfkc"})
append_token_filter(kind, args=None)
後処理パイプラインにトークンフィルタを追加します。
builder.append_token_filter("lowercase", {})
ビルド
build()
設定された内容で Tokenizer をビルドして返します。
tokenizer = builder.build()
Tokenizer
Tokenizer はテキストに対して形態素解析を行います。
Tokenizer の作成
Tokenizer(dictionary, mode="normal", user_dictionary=None)
読み込み済みの辞書から直接トークナイザーを作成します。
from lindera import Tokenizer, load_dictionary
dictionary = load_dictionary("embedded://ipadic")
tokenizer = Tokenizer(dictionary, mode="normal")
Tokenizer メソッド
tokenize(text)
入力テキストをトークナイズし、Token オブジェクトのリストを返します。
tokens = tokenizer.tokenize("形態素解析")
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | str | トークナイズするテキスト |
戻り値: list[Token]
tokenize_nbest(text, n, unique=False, cost_threshold=None)
N-best トークナイズ結果を返します。各結果はトータルパスコストとペアになっています。
results = tokenizer.tokenize_nbest("すもももももももものうち", n=3)
for tokens, cost in results:
print(cost, [t.surface for t in tokens])
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | str | トークナイズするテキスト |
n | int | 返す結果の数 |
unique | bool | 結果の重複を排除(デフォルト: False) |
cost_threshold | int または None | 最良パスからの最大コスト差(デフォルト: None) |
戻り値: list[tuple[list[Token], int]]
Token
Token は単一の形態素トークンを表します。
プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
surface | str | トークンの表層形 |
byte_start | int | 元テキストでの開始バイト位置 |
byte_end | int | 元テキストでの終了バイト位置 |
position | int | トークンの位置インデックス |
word_id | int | 辞書の単語 ID |
is_unknown | bool | 辞書に登録されていない単語の場合 True |
details | list[str] または None | 形態素の詳細情報(品詞、読みなど) |
Token メソッド
get_detail(index)
指定されたインデックスの詳細文字列を返します。インデックスが範囲外の場合は None を返します。
token = tokenizer.tokenize("東京")[0]
pos = token.get_detail(0) # 例: "名詞"
subpos = token.get_detail(1) # 例: "固有名詞"
reading = token.get_detail(7) # 例: "トウキョウ"
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
index | int | details リストへのゼロベースインデックス |
戻り値: str または None
details の構造は辞書によって異なります:
- IPADIC:
[品詞, 品詞細分類1, 品詞細分類2, 品詞細分類3, 活用型, 活用形, 原形, 読み, 発音] - UniDic: UniDic 仕様に準拠した詳細な形態素情報
- ko-dic / CC-CEDICT / Jieba: 各辞書固有の詳細フォーマット
辞書管理
Lindera Python は、形態素解析で使用する辞書の読み込み、ビルド、管理のための関数を提供します。
辞書の読み込み
システム辞書
load_dictionary(uri) を使用してシステム辞書を読み込みます。GitHub Releases からビルド済み辞書をダウンロードし、展開したディレクトリのパスを指定してください:
from lindera import load_dictionary
dictionary = load_dictionary("/path/to/ipadic")
埋め込み辞書(上級者向け) -- embed-* feature フラグ付きでビルドした場合、埋め込み辞書を使用できます:
dictionary = load_dictionary("embedded://ipadic")
ユーザー辞書
ユーザー辞書はシステム辞書にカスタム語彙を追加します。
from lindera import load_user_dictionary, Metadata
metadata = Metadata()
user_dict = load_user_dictionary("/path/to/user_dictionary", metadata)
トークナイザーのビルド時にユーザー辞書を渡します:
from lindera import Tokenizer, load_dictionary, load_user_dictionary, Metadata
dictionary = load_dictionary("/path/to/ipadic")
metadata = Metadata()
user_dict = load_user_dictionary("/path/to/user_dictionary", metadata)
tokenizer = Tokenizer(dictionary, mode="normal", user_dictionary=user_dict)
または、ビルダー経由で設定します:
from lindera import TokenizerBuilder
tokenizer = (
TokenizerBuilder()
.set_dictionary("/path/to/ipadic")
.set_user_dictionary("/path/to/user_dictionary")
.build()
)
辞書のビルド
システム辞書のビルド
ソースファイルからシステム辞書をビルドします:
from lindera import build_dictionary, Metadata
metadata = Metadata(name="custom", encoding="UTF-8")
build_dictionary("/path/to/input_dir", "/path/to/output_dir", metadata)
入力ディレクトリには辞書のソースファイル(CSV レキシコン、matrix.def など)が含まれている必要があります。
ユーザー辞書のビルド
CSV ファイルからユーザー辞書をビルドします:
from lindera import build_user_dictionary, Metadata
metadata = Metadata()
build_user_dictionary("ipadic", "user_words.csv", "/path/to/output_dir", metadata)
metadata パラメータは省略可能です。省略した場合はデフォルトのメタデータ値が使用されます:
build_user_dictionary("ipadic", "user_words.csv", "/path/to/output_dir")
Metadata
Metadata クラスは辞書のパラメータを設定します。
Metadata の作成
from lindera import Metadata
# デフォルトのメタデータ
metadata = Metadata()
# カスタムメタデータ
metadata = Metadata(
name="my_dictionary",
encoding="UTF-8",
default_word_cost=-10000,
)
JSON からの読み込み
metadata = Metadata.from_json_file("metadata.json")
プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | str | "default" | 辞書名 |
encoding | str | "UTF-8" | 文字エンコーディング |
default_word_cost | int | -10000 | 未知語のデフォルトコスト |
default_left_context_id | int | 1288 | デフォルトの左文脈 ID |
default_right_context_id | int | 1288 | デフォルトの右文脈 ID |
default_field_value | str | "*" | 欠損フィールドのデフォルト値 |
flexible_csv | bool | False | 柔軟な CSV パースを許可 |
skip_invalid_cost_or_id | bool | False | 無効なコストまたは ID のエントリーをスキップ |
normalize_details | bool | False | 形態素の詳細情報を正規化 |
dictionary_schema | Schema | IPADIC スキーマ | メイン辞書のスキーマ |
user_dictionary_schema | Schema | 最小スキーマ | ユーザー辞書のスキーマ |
すべてのプロパティは取得と設定の両方をサポートしています:
metadata = Metadata()
metadata.name = "custom_dict"
metadata.encoding = "EUC-JP"
print(metadata.name) # "custom_dict"
to_dict()
メタデータの辞書表現を返します:
metadata = Metadata(name="test")
print(metadata.to_dict())
テキスト処理パイプライン
Lindera Python は、トークナイズ前に文字フィルタを適用し、トークナイズ後にトークンフィルタを適用する、組み合わせ可能なテキスト処理パイプラインをサポートしています。フィルタは TokenizerBuilder に追加され、追加された順序で実行されます。
Input Text
--> Character Filters (preprocessing)
--> Tokenization
--> Token Filters (postprocessing)
--> Output Tokens
文字フィルタ
文字フィルタはトークナイズ前に入力テキストを変換します。
unicode_normalize
入力テキストに Unicode 正規化を適用します。
from lindera import TokenizerBuilder
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_character_filter("unicode_normalize", {"kind": "nfkc"})
.build()
)
サポートされる正規化形式: "nfc"、"nfkc"、"nfd"、"nfkd"。
mapping
マッピングテーブルに従って文字や文字列を置換します。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_character_filter("mapping", {
"mapping": {
"\u30fc": "-",
"\uff5e": "~",
}
})
.build()
)
japanese_iteration_mark
日本語の踊り字(繰り返し記号)を完全な形に展開します。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_character_filter("japanese_iteration_mark", {
"normalize_kanji": True,
"normalize_kana": True,
})
.build()
)
トークンフィルタ
トークンフィルタはトークナイズ後にトークンを変換または除去します。
lowercase
トークンの表層形を小文字に変換します。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_token_filter("lowercase", {})
.build()
)
japanese_base_form
辞書の形態素情報を使用して、活用形を基本形(辞書形)に置換します。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_token_filter("japanese_base_form", {})
.build()
)
japanese_stop_tags
指定されたタグに一致する品詞のトークンを除去します。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_token_filter("japanese_stop_tags", {
"tags": ["助詞", "助動詞"],
})
.build()
)
japanese_keep_tags
指定されたタグに一致する品詞のトークンのみを保持します。その他のトークンはすべて除去されます。
tokenizer = (
TokenizerBuilder()
.set_dictionary("embedded://ipadic")
.append_token_filter("japanese_keep_tags", {
"tags": ["名詞"],
})
.build()
)
パイプラインの完全な例
以下の例では、複数の文字フィルタとトークンフィルタを1つのパイプラインに組み合わせています:
from lindera import TokenizerBuilder
tokenizer = (
TokenizerBuilder()
.set_mode("normal")
.set_dictionary("embedded://ipadic")
# Preprocessing
.append_character_filter("unicode_normalize", {"kind": "nfkc"})
.append_character_filter("japanese_iteration_mark", {
"normalize_kanji": True,
"normalize_kana": True,
})
# Postprocessing
.append_token_filter("japanese_base_form", {})
.append_token_filter("japanese_stop_tags", {
"tags": ["助詞", "助動詞", "記号"],
})
.append_token_filter("lowercase", {})
.build()
)
tokens = tokenizer.tokenize("Linderaは形態素解析を行うライブラリです。")
for token in tokens:
print(f"{token.surface}\t{','.join(token.details)}")
このパイプラインでは:
unicode_normalizeが全角文字を半角に変換(NFKC 正規化)japanese_iteration_markが踊り字を展開japanese_base_formが活用形のトークンを基本形に変換japanese_stop_tagsが助詞、助動詞、記号を除去lowercaseがアルファベットを小文字に正規化
学習
Lindera Python は、アノテーション付きコーパスからカスタム CRF ベースの形態素解析モデルを学習する機能をサポートしています。この機能には train feature が必要です。
前提条件
train feature を有効にして lindera-python をビルドします(デフォルトで有効):
maturin develop --features train
モデルの学習
lindera.train() を使用して、種辞書とアノテーション付きコーパスから CRF モデルを学習します:
import lindera
lindera.train(
seed="resources/training/seed.csv",
corpus="resources/training/corpus.txt",
char_def="resources/training/char.def",
unk_def="resources/training/unk.def",
feature_def="resources/training/feature.def",
rewrite_def="resources/training/rewrite.def",
output="/tmp/model.dat",
lambda_=0.01,
max_iter=100,
max_threads=4,
)
学習パラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
seed | str | 必須 | 種辞書ファイルのパス(CSV 形式) |
corpus | str | 必須 | アノテーション付き学習コーパスのパス |
char_def | str | 必須 | 文字定義ファイルのパス(char.def) |
unk_def | str | 必須 | 未知語定義ファイルのパス(unk.def) |
feature_def | str | 必須 | 素性定義ファイルのパス(feature.def) |
rewrite_def | str | 必須 | 書き換えルール定義ファイルのパス(rewrite.def) |
output | str | 必須 | 学習済みモデルファイルの出力パス |
lambda_ | float | 0.01 | L1 正則化コスト(0.0--1.0) |
max_iter | int | 100 | 最大学習イテレーション数 |
max_threads | int または None | None | スレッド数(None = CPU コア数を自動検出) |
学習済みモデルのエクスポート
学習後、lindera.export() を使用してモデルを辞書ソースファイルにエクスポートします:
import lindera
lindera.export(
model="/tmp/model.dat",
output="/tmp/dictionary_source",
metadata="resources/training/metadata.json",
)
エクスポートパラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
model | str | 必須 | 学習済みモデルファイルのパス(.dat) |
output | str | 必須 | 辞書ソースファイルの出力ディレクトリ |
metadata | str または None | None | ベースとなる metadata.json ファイルのパス |
エクスポートにより、出力ディレクトリに以下のファイルが作成されます:
lex.csv-- 学習済みコスト付きのレキシコンエントリーmatrix.def-- 連接コスト行列unk.def-- 未知語定義char.def-- 文字カテゴリ定義metadata.json-- 更新されたメタデータ(metadataパラメータ指定時)
完全なワークフロー
カスタム辞書の学習と使用の完全なワークフロー:
import lindera
# Step 1: Train the CRF model
lindera.train(
seed="resources/training/seed.csv",
corpus="resources/training/corpus.txt",
char_def="resources/training/char.def",
unk_def="resources/training/unk.def",
feature_def="resources/training/feature.def",
rewrite_def="resources/training/rewrite.def",
output="/tmp/model.dat",
lambda_=0.01,
max_iter=100,
)
# Step 2: Export to dictionary source files
lindera.export(
model="/tmp/model.dat",
output="/tmp/dictionary_source",
metadata="resources/training/metadata.json",
)
# Step 3: Build the dictionary from exported source files
metadata = lindera.Metadata.from_json_file("/tmp/dictionary_source/metadata.json")
lindera.build_dictionary("/tmp/dictionary_source", "/tmp/dictionary", metadata)
# Step 4: Use the trained dictionary
tokenizer = (
lindera.TokenizerBuilder()
.set_dictionary("/tmp/dictionary")
.set_mode("normal")
.build()
)
tokens = tokenizer.tokenize("形態素解析のテスト")
for token in tokens:
print(f"{token.surface}\t{','.join(token.details)}")
Lindera Node.js
Lindera Node.js は、NAPI-RS を使用して構築された Lindera 形態素解析エンジンの Node.js バインディングです。Node.js 18 以降をサポートし、Lindera の高性能なトークナイズ機能を Node.js エコシステムに提供します。
特徴
- 多言語対応: 日本語(IPADIC、IPADIC NEologd、UniDic)、韓国語(ko-dic)、中国語(CC-CEDICT、Jieba)のテキストをトークナイズ
- テキスト処理パイプライン: 文字フィルタとトークンフィルタを組み合わせて、柔軟な前処理・後処理が可能
- CRF ベースの辞書学習: アノテーション付きコーパスからカスタム形態素解析モデルを学習(
trainfeature が必要) - 複数のトークナイズモード: 解析粒度に応じた Normal モードと Decompose モード
- N-best トークナイズ: コスト順にランク付けされた複数のトークナイズ候補を取得
- ユーザー辞書: システム辞書をカスタム語彙で拡張
- TypeScript サポート: 完全な型定義を同梱
ドキュメント
- インストール -- 前提条件、ビルド手順、feature フラグ
- クイックスタート -- 最小限の使用例
- Tokenizer API --
TokenizerBuilder、Tokenizer、Tokenクラスリファレンス - 辞書管理 -- 辞書の読み込み、ビルド、管理
- テキスト処理パイプライン -- 文字フィルタとトークンフィルタ
- 学習 -- カスタム CRF モデルの学習と辞書のエクスポート
インストール
npm からのインストール
ビルド済みパッケージが npm で公開予定です:
npm install lindera-nodejs
[!NOTE] npm パッケージには辞書が含まれていません。下記の辞書の入手を参照してください。 ブラウザ/WASM での利用には lindera-wasm を参照してください。
ソースからのビルド
前提条件
- Node.js 18 以降(LTS バージョン推奨)
- Rust ツールチェーン -- rustup 経由でインストール
- NAPI-RS CLI -- Rust で Node.js ネイティブアドオンをビルドするための CLI ツール
NAPI-RS CLI をグローバルにインストールします:
npm install -g @napi-rs/cli
辞書の入手
Lindera はパッケージに辞書を同梱していません。ビルド済み辞書を別途入手する必要があります。
GitHub Releases からのダウンロード
ビルド済み辞書は GitHub Releases ページから入手できます。辞書アーカイブをダウンロードしてローカルディレクトリに展開してください:
# 例: IPADIC 辞書のダウンロードと展開
curl -LO https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip
unzip lindera-ipadic-<version>.zip -d /path/to/ipadic
開発ビルド
lindera-nodejs を開発モードでビルドします:
cd lindera-nodejs
npm install
npm run build
または、プロジェクトの Makefile を使用します:
make nodejs-develop
学習機能付きビルド
train feature を有効にすると、CRF ベースの辞書学習機能が利用可能になります。デフォルトで有効になっています:
npm run build -- --features train
Feature フラグ
| Feature | 説明 | デフォルト |
|---|---|---|
train | CRF 学習機能 | 有効 |
embed-ipadic | 日本語辞書(IPADIC)をバイナリに埋め込み | 無効 |
embed-unidic | 日本語辞書(UniDic)をバイナリに埋め込み | 無効 |
embed-ipadic-neologd | 日本語辞書(IPADIC NEologd)をバイナリに埋め込み | 無効 |
embed-ko-dic | 韓国語辞書(ko-dic)をバイナリに埋め込み | 無効 |
embed-cc-cedict | 中国語辞書(CC-CEDICT)をバイナリに埋め込み | 無効 |
embed-jieba | 中国語辞書(Jieba)をバイナリに埋め込み | 無効 |
embed-cjk | 全 CJK 辞書をバイナリに埋め込み(IPADIC、ko-dic、Jieba) | 無効 |
複数の feature を組み合わせることができます:
npm run build -- --features "train,embed-ipadic,embed-ko-dic"
[!TIP] 辞書をバイナリに直接埋め込みたい場合(上級者向け)は、対応する
embed-*feature フラグを有効にしてビルドし、embedded://スキームでロードしてください:const dictionary = loadDictionary("embedded://ipadic");詳細は Feature フラグ を参照してください。
インストールの確認
インストール後、Node.js で lindera が利用可能であることを確認します:
const lindera = require("lindera-nodejs");
console.log(lindera.version());
または ES modules を使用する場合:
import { version } from "lindera-nodejs";
console.log(version());
クイックスタート
このガイドでは、lindera-nodejs を使用してテキストをトークナイズする方法を紹介します。
基本的なトークナイズ
トークナイザーの作成には TokenizerBuilder の使用を推奨します:
const { TokenizerBuilder } = require("lindera-nodejs");
const builder = new TokenizerBuilder();
builder.setMode("normal");
builder.setDictionary("/path/to/ipadic");
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("関西国際空港限定トートバッグ");
for (const token of tokens) {
console.log(`${token.surface}\t${token.details.join(",")}`);
}
注意: ビルド済み辞書を GitHub Releases からダウンロードし、展開したディレクトリのパスを指定してください。
期待される出力:
関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ UNK
メソッドチェーン
TokenizerBuilder は簡潔な設定のためにメソッドチェーンをサポートしています:
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setMode("normal")
.setDictionary("/path/to/ipadic")
.build();
const tokens = tokenizer.tokenize("すもももももももものうち");
for (const token of tokens) {
console.log(`${token.surface}\t${token.getDetail(0)}`);
}
トークンプロパティへのアクセス
各トークンは以下のプロパティを公開しています:
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setDictionary("/path/to/ipadic")
.build();
const tokens = tokenizer.tokenize("東京タワー");
for (const token of tokens) {
console.log(`Surface: ${token.surface}`);
console.log(`Byte range: ${token.byteStart}..${token.byteEnd}`);
console.log(`Position: ${token.position}`);
console.log(`Word ID: ${token.wordId}`);
console.log(`Unknown: ${token.isUnknown}`);
console.log(`Details: ${token.details}`);
console.log();
}
N-best トークナイズ
コスト順にランク付けされた複数のトークナイズ候補を取得します:
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setDictionary("/path/to/ipadic")
.build();
const results = tokenizer.tokenizeNbest("すもももももももものうち", 3);
for (const { tokens, cost } of results) {
const surfaces = tokens.map((t) => t.surface);
console.log(`Cost ${cost}: ${surfaces.join(" / ")}`);
}
TypeScript
Lindera Node.js には TypeScript の型定義が含まれています。すべてのクラスと関数に完全な型が付いています:
import { TokenizerBuilder, Token } from "lindera-nodejs";
const tokenizer = new TokenizerBuilder()
.setMode("normal")
.setDictionary("/path/to/ipadic")
.build();
const tokens: Token[] = tokenizer.tokenize("形態素解析");
for (const token of tokens) {
console.log(`${token.surface}: ${token.details?.join(",")}`);
}
Tokenizer API
TokenizerBuilder
TokenizerBuilder はビルダーパターンを使用して Tokenizer インスタンスを設定・構築します。
コンストラクタ
new TokenizerBuilder()
デフォルト設定で新しいビルダーを作成します。
const { TokenizerBuilder } = require("lindera-nodejs");
const builder = new TokenizerBuilder();
new TokenizerBuilder().fromFile(filePath)
JSON ファイルから設定を読み込み、新しいビルダーを返します。
const builder = new TokenizerBuilder().fromFile("config.json");
設定メソッド
すべてのセッターメソッドはメソッドチェーンのために this を返します。
setMode(mode)
トークナイズモードを設定します。
"normal"-- 標準的なトークナイズ(デフォルト)"decompose"-- 複合語をより小さな単位に分解
builder.setMode("normal");
setDictionary(path)
システム辞書のパスまたは URI を設定します。
// 埋め込み辞書を使用
builder.setDictionary("embedded://ipadic");
// 外部辞書を使用
builder.setDictionary("/path/to/dictionary");
setUserDictionary(uri)
ユーザー辞書の URI を設定します。
builder.setUserDictionary("/path/to/user_dictionary");
setKeepWhitespace(keep)
出力に空白トークンを含めるかどうかを制御します。
builder.setKeepWhitespace(true);
appendCharacterFilter(kind, args?)
前処理パイプラインに文字フィルタを追加します。
builder.appendCharacterFilter("unicode_normalize", { kind: "nfkc" });
appendTokenFilter(kind, args?)
後処理パイプラインにトークンフィルタを追加します。
builder.appendTokenFilter("lowercase", {});
ビルド
build()
設定された内容で Tokenizer をビルドして返します。
const tokenizer = builder.build();
Tokenizer
Tokenizer はテキストに対して形態素解析を行います。
Tokenizer の作成
new Tokenizer(dictionary, mode?, userDictionary?)
読み込み済みの辞書から直接トークナイザーを作成します。
const { Tokenizer, loadDictionary } = require("lindera-nodejs");
const dictionary = loadDictionary("embedded://ipadic");
const tokenizer = new Tokenizer(dictionary, "normal");
Tokenizer メソッド
tokenize(text)
入力テキストをトークナイズし、Token オブジェクトの配列を返します。
const tokens = tokenizer.tokenize("形態素解析");
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | string | トークナイズするテキスト |
戻り値: Token[]
tokenizeNbest(text, n, unique?, costThreshold?)
N-best トークナイズ結果を返します。各結果はトークン配列とトータルパスコストを含みます。
const results = tokenizer.tokenizeNbest("すもももももももものうち", 3);
for (const { tokens, cost } of results) {
console.log(cost, tokens.map((t) => t.surface));
}
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | string | トークナイズするテキスト |
n | number | 返す結果の数 |
unique | boolean | 結果の重複を排除(デフォルト: false) |
costThreshold | number | undefined | 最良パスからの最大コスト差(デフォルト: undefined) |
戻り値: Array<{ tokens: Token[], cost: number }>
Token
Token は単一の形態素トークンを表します。
プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
surface | string | トークンの表層形 |
byteStart | number | 元テキストでの開始バイト位置 |
byteEnd | number | 元テキストでの終了バイト位置 |
position | number | トークンの位置インデックス |
wordId | number | 辞書の単語 ID |
isUnknown | boolean | 辞書に登録されていない単語の場合 true |
details | string[] | null | 形態素の詳細情報(品詞、読みなど) |
Token メソッド
getDetail(index)
指定されたインデックスの詳細文字列を返します。インデックスが範囲外の場合は null を返します。
const token = tokenizer.tokenize("東京")[0];
const pos = token.getDetail(0); // 例: "名詞"
const subpos = token.getDetail(1); // 例: "固有名詞"
const reading = token.getDetail(7); // 例: "トウキョウ"
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
index | number | details 配列へのゼロベースインデックス |
戻り値: string | null
details の構造は辞書によって異なります:
- IPADIC:
[品詞, 品詞細分類1, 品詞細分類2, 品詞細分類3, 活用型, 活用形, 原形, 読み, 発音] - UniDic: UniDic 仕様に準拠した詳細な形態素情報
- ko-dic / CC-CEDICT / Jieba: 各辞書固有の詳細フォーマット
辞書管理
Lindera Node.js は、形態素解析で使用する辞書の読み込み、ビルド、管理のための関数を提供します。
辞書の読み込み
システム辞書
loadDictionary(uri) を使用してシステム辞書を読み込みます。GitHub Releases からビルド済み辞書をダウンロードし、展開したディレクトリのパスを指定してください:
const { loadDictionary } = require("lindera-nodejs");
const dictionary = loadDictionary("/path/to/ipadic");
埋め込み辞書(上級者向け) -- embed-* feature フラグ付きでビルドした場合、埋め込み辞書を使用できます:
const dictionary = loadDictionary("embedded://ipadic");
ユーザー辞書
ユーザー辞書はシステム辞書にカスタム語彙を追加します。
const { loadUserDictionary, Metadata } = require("lindera-nodejs");
const metadata = new Metadata();
const userDict = loadUserDictionary("/path/to/user_dictionary", metadata);
トークナイザーのビルド時にユーザー辞書を渡します:
const { Tokenizer, loadDictionary, loadUserDictionary, Metadata } = require("lindera-nodejs");
const dictionary = loadDictionary("/path/to/ipadic");
const metadata = new Metadata();
const userDict = loadUserDictionary("/path/to/user_dictionary", metadata);
const tokenizer = new Tokenizer(dictionary, "normal", userDict);
または、ビルダー経由で設定します:
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setDictionary("/path/to/ipadic")
.setUserDictionary("/path/to/user_dictionary")
.build();
辞書のビルド
システム辞書のビルド
ソースファイルからシステム辞書をビルドします:
const { buildDictionary, Metadata } = require("lindera-nodejs");
const metadata = new Metadata({ name: "custom", encoding: "UTF-8" });
buildDictionary("/path/to/input_dir", "/path/to/output_dir", metadata);
入力ディレクトリには辞書のソースファイル(CSV レキシコン、matrix.def など)が含まれている必要があります。
ユーザー辞書のビルド
CSV ファイルからユーザー辞書をビルドします:
const { buildUserDictionary, Metadata } = require("lindera-nodejs");
const metadata = new Metadata();
buildUserDictionary("ipadic", "user_words.csv", "/path/to/output_dir", metadata);
metadata パラメータは省略可能です。省略した場合はデフォルトのメタデータ値が使用されます:
buildUserDictionary("ipadic", "user_words.csv", "/path/to/output_dir");
Metadata
Metadata クラスは辞書のパラメータを設定します。
Metadata の作成
const { Metadata } = require("lindera-nodejs");
// デフォルトのメタデータ
const metadata = new Metadata();
// カスタムメタデータ
const metadata = new Metadata({
name: "my_dictionary",
encoding: "UTF-8",
defaultWordCost: -10000,
});
JSON からの読み込み
const metadata = Metadata.fromJsonFile("metadata.json");
プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "default" | 辞書名 |
encoding | string | "UTF-8" | 文字エンコーディング |
defaultWordCost | number | -10000 | 未知語のデフォルトコスト |
defaultLeftContextId | number | 1288 | デフォルトの左文脈 ID |
defaultRightContextId | number | 1288 | デフォルトの右文脈 ID |
defaultFieldValue | string | "*" | 欠損フィールドのデフォルト値 |
flexibleCsv | boolean | false | 柔軟な CSV パースを許可 |
skipInvalidCostOrId | boolean | false | 無効なコストまたは ID のエントリーをスキップ |
normalizeDetails | boolean | false | 形態素の詳細情報を正規化 |
dictionarySchema | Schema | IPADIC スキーマ | メイン辞書のスキーマ |
userDictionarySchema | Schema | 最小スキーマ | ユーザー辞書のスキーマ |
すべてのプロパティは取得と設定の両方をサポートしています:
const metadata = new Metadata();
metadata.name = "custom_dict";
metadata.encoding = "EUC-JP";
console.log(metadata.name); // "custom_dict"
toObject()
メタデータのオブジェクト表現を返します:
const metadata = new Metadata({ name: "test" });
console.log(metadata.toObject());
Schema
Schema クラスは辞書エントリーのフィールド構造を定義します。
Schema の作成
const { Schema } = require("lindera-nodejs");
// デフォルトの IPADIC 互換スキーマ
const schema = Schema.createDefault();
// カスタムスキーマ
const custom = new Schema(["surface", "left_id", "right_id", "cost", "pos", "reading"]);
Schema メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
getFieldIndex(name) | number | null | フィールド名からインデックスを取得 |
fieldCount() | number | フィールドの総数 |
getFieldName(index) | string | null | インデックスからフィールド名を取得 |
getCustomFields() | string[] | インデックス 4 以降のフィールド(形態素素性) |
getAllFields() | string[] | すべてのフィールド名 |
getFieldByName(name) | FieldDefinition | null | フィールド定義の完全な情報を取得 |
validateRecord(record) | void | CSV レコードをスキーマに対して検証 |
const schema = Schema.createDefault();
console.log(schema.fieldCount()); // 13(IPADIC フォーマット)
console.log(schema.getFieldIndex("pos1")); // 例: 4
console.log(schema.getAllFields()); // ["surface", "left_id", ...]
console.log(schema.getCustomFields()); // インデックス 4 以降のフィールド
FieldDefinition
| プロパティ | 型 | 説明 |
|---|---|---|
index | number | フィールドの位置インデックス |
name | string | フィールド名 |
fieldType | FieldType | フィールド型の列挙値 |
description | string | undefined | 任意の説明 |
FieldType
| 値 | 説明 |
|---|---|
FieldType.Surface | 単語の表層形 |
FieldType.LeftContextId | 左文脈 ID |
FieldType.RightContextId | 右文脈 ID |
FieldType.Cost | 単語コスト |
FieldType.Custom | 形態素素性フィールド |
テキスト処理パイプライン
Lindera Node.js は、トークナイズ前に文字フィルタを適用し、トークナイズ後にトークンフィルタを適用する、組み合わせ可能なテキスト処理パイプラインをサポートしています。フィルタは TokenizerBuilder に追加され、追加された順序で実行されます。
Input Text
--> Character Filters (preprocessing)
--> Tokenization
--> Token Filters (postprocessing)
--> Output Tokens
文字フィルタ
文字フィルタはトークナイズ前に入力テキストを変換します。
unicode_normalize
入力テキストに Unicode 正規化を適用します。
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendCharacterFilter("unicode_normalize", { kind: "nfkc" })
.build();
サポートされる正規化形式: "nfc"、"nfkc"、"nfd"、"nfkd"。
mapping
マッピングテーブルに従って文字や文字列を置換します。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendCharacterFilter("mapping", {
mapping: {
"\u30fc": "-",
"\uff5e": "~",
},
})
.build();
japanese_iteration_mark
日本語の踊り字(繰り返し記号)を完全な形に展開します。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendCharacterFilter("japanese_iteration_mark", {
normalize_kanji: true,
normalize_kana: true,
})
.build();
トークンフィルタ
トークンフィルタはトークナイズ後にトークンを変換または除去します。
lowercase
トークンの表層形を小文字に変換します。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendTokenFilter("lowercase", {})
.build();
japanese_base_form
辞書の形態素情報を使用して、活用形を基本形(辞書形)に置換します。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendTokenFilter("japanese_base_form", {})
.build();
japanese_stop_tags
指定されたタグに一致する品詞のトークンを除去します。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendTokenFilter("japanese_stop_tags", {
tags: ["助詞", "助動詞"],
})
.build();
japanese_keep_tags
指定されたタグに一致する品詞のトークンのみを保持します。その他のトークンはすべて除去されます。
const tokenizer = new TokenizerBuilder()
.setDictionary("embedded://ipadic")
.appendTokenFilter("japanese_keep_tags", {
tags: ["名詞"],
})
.build();
パイプラインの完全な例
以下の例では、複数の文字フィルタとトークンフィルタを1つのパイプラインに組み合わせています:
const { TokenizerBuilder } = require("lindera-nodejs");
const tokenizer = new TokenizerBuilder()
.setMode("normal")
.setDictionary("embedded://ipadic")
// Preprocessing
.appendCharacterFilter("unicode_normalize", { kind: "nfkc" })
.appendCharacterFilter("japanese_iteration_mark", {
normalize_kanji: true,
normalize_kana: true,
})
// Postprocessing
.appendTokenFilter("japanese_base_form", {})
.appendTokenFilter("japanese_stop_tags", {
tags: ["助詞", "助動詞", "記号"],
})
.appendTokenFilter("lowercase", {})
.build();
const tokens = tokenizer.tokenize("Linderaは形態素解析を行うライブラリです。");
for (const token of tokens) {
console.log(`${token.surface}\t${token.details.join(",")}`);
}
このパイプラインでは:
unicode_normalizeが全角文字を半角に変換(NFKC 正規化)japanese_iteration_markが踊り字を展開japanese_base_formが活用形のトークンを基本形に変換japanese_stop_tagsが助詞、助動詞、記号を除去lowercaseがアルファベットを小文字に正規化
学習
Lindera Node.js は、アノテーション付きコーパスからカスタム CRF ベースの形態素解析モデルを学習する機能をサポートしています。この機能には train feature が必要です。
前提条件
train feature を有効にして lindera-nodejs をビルドします(デフォルトで有効):
npm run build -- --features train
モデルの学習
train() を使用して、種辞書とアノテーション付きコーパスから CRF モデルを学習します:
const { train } = require("lindera-nodejs");
train({
seed: "resources/training/seed.csv",
corpus: "resources/training/corpus.txt",
charDef: "resources/training/char.def",
unkDef: "resources/training/unk.def",
featureDef: "resources/training/feature.def",
rewriteDef: "resources/training/rewrite.def",
output: "/tmp/model.dat",
lambda: 0.01,
maxIter: 100,
maxThreads: 4,
});
学習パラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
seed | string | 必須 | 種辞書ファイルのパス(CSV 形式) |
corpus | string | 必須 | アノテーション付き学習コーパスのパス |
charDef | string | 必須 | 文字定義ファイルのパス(char.def) |
unkDef | string | 必須 | 未知語定義ファイルのパス(unk.def) |
featureDef | string | 必須 | 素性定義ファイルのパス(feature.def) |
rewriteDef | string | 必須 | 書き換えルール定義ファイルのパス(rewrite.def) |
output | string | 必須 | 学習済みモデルファイルの出力パス |
lambda | number | 0.01 | L1 正則化コスト(0.0--1.0) |
maxIter | number | 100 | 最大学習イテレーション数 |
maxThreads | number | undefined | undefined | スレッド数(undefined = CPU コア数を自動検出) |
学習済みモデルのエクスポート
学習後、exportModel() を使用してモデルを辞書ソースファイルにエクスポートします:
const { exportModel } = require("lindera-nodejs");
exportModel({
model: "/tmp/model.dat",
output: "/tmp/dictionary_source",
metadata: "resources/training/metadata.json",
});
エクスポートパラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
model | string | 必須 | 学習済みモデルファイルのパス(.dat) |
output | string | 必須 | 辞書ソースファイルの出力ディレクトリ |
metadata | string | undefined | undefined | ベースとなる metadata.json ファイルのパス |
エクスポートにより、出力ディレクトリに以下のファイルが作成されます:
lex.csv-- 学習済みコスト付きのレキシコンエントリーmatrix.def-- 連接コスト行列unk.def-- 未知語定義char.def-- 文字カテゴリ定義metadata.json-- 更新されたメタデータ(metadataパラメータ指定時)
完全なワークフロー
カスタム辞書の学習と使用の完全なワークフロー:
const {
train,
exportModel,
buildDictionary,
Metadata,
TokenizerBuilder,
} = require("lindera-nodejs");
// Step 1: Train the CRF model
train({
seed: "resources/training/seed.csv",
corpus: "resources/training/corpus.txt",
charDef: "resources/training/char.def",
unkDef: "resources/training/unk.def",
featureDef: "resources/training/feature.def",
rewriteDef: "resources/training/rewrite.def",
output: "/tmp/model.dat",
lambda: 0.01,
maxIter: 100,
});
// Step 2: Export to dictionary source files
exportModel({
model: "/tmp/model.dat",
output: "/tmp/dictionary_source",
metadata: "resources/training/metadata.json",
});
// Step 3: Build the dictionary from exported source files
const metadata = Metadata.fromJsonFile("/tmp/dictionary_source/metadata.json");
buildDictionary("/tmp/dictionary_source", "/tmp/dictionary", metadata);
// Step 4: Use the trained dictionary
const tokenizer = new TokenizerBuilder()
.setDictionary("/tmp/dictionary")
.setMode("normal")
.build();
const tokens = tokenizer.tokenize("形態素解析のテスト");
for (const token of tokens) {
console.log(`${token.surface}\t${token.details.join(",")}`);
}
Lindera Ruby
Lindera Ruby は、Magnus と rb-sys を使用して構築された Lindera 形態素解析エンジンの Ruby バインディングです。Ruby 3.1 以降をサポートし、Lindera の高性能なトークナイズ機能を Ruby エコシステムに提供します。
特徴
- 多言語対応: 日本語(IPADIC、IPADIC NEologd、UniDic)、韓国語(ko-dic)、中国語(CC-CEDICT、Jieba)のテキストをトークナイズ
- テキスト処理パイプライン: 文字フィルタとトークンフィルタを組み合わせて、柔軟な前処理・後処理が可能
- CRF ベースの辞書学習: アノテーション付きコーパスからカスタム形態素解析モデルを学習(
trainfeature が必要) - 複数のトークナイズモード: 解析粒度に応じた Normal モードと Decompose モード
- N-best トークナイズ: コスト順にランク付けされた複数のトークナイズ候補を取得
- ユーザー辞書: システム辞書をカスタム語彙で拡張
ドキュメント
- インストール -- 前提条件、ビルド手順、feature フラグ
- クイックスタート -- 最小限の使用例
- Tokenizer API --
TokenizerBuilder、Tokenizer、Tokenクラスリファレンス - 辞書管理 -- 辞書の読み込み、ビルド、管理
- テキスト処理パイプライン -- 文字フィルタとトークンフィルタ
- 学習 -- カスタム CRF モデルの学習と辞書のエクスポート
インストール
[!NOTE] lindera-ruby はまだ RubyGems に公開されていません。ソースからビルドする必要があります。
前提条件
- Ruby 3.1 以降
- Rust ツールチェーン -- rustup 経由でインストール
- Bundler -- Ruby の依存関係管理ツール(
gem install bundler)
辞書の入手
Lindera はパッケージに辞書を同梱していません。ビルド済み辞書を別途入手する必要があります。
GitHub Releases からのダウンロード
ビルド済み辞書は GitHub Releases ページから入手できます。辞書アーカイブをダウンロードしてローカルディレクトリに展開してください:
# 例: IPADIC 辞書のダウンロードと展開
curl -LO https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip
unzip lindera-ipadic-<version>.zip -d /path/to/ipadic
開発ビルド
lindera-ruby を開発モードでビルドしてインストールします:
cd lindera-ruby
bundle install
bundle exec rake compile
または、プロジェクトの Makefile を使用します:
make ruby-develop
学習機能付きビルド
train feature を有効にすると、CRF ベースの辞書学習機能が利用可能になります:
LINDERA_FEATURES="train" bundle exec rake compile
Feature フラグ
Feature は環境変数 LINDERA_FEATURES にカンマ区切りリストで指定します。
| Feature | 説明 | デフォルト |
|---|---|---|
train | CRF 学習機能 | 無効 |
embed-ipadic | 日本語辞書(IPADIC)をバイナリに埋め込み | 無効 |
embed-unidic | 日本語辞書(UniDic)をバイナリに埋め込み | 無効 |
embed-ipadic-neologd | 日本語辞書(IPADIC NEologd)をバイナリに埋め込み | 無効 |
embed-ko-dic | 韓国語辞書(ko-dic)をバイナリに埋め込み | 無効 |
embed-cc-cedict | 中国語辞書(CC-CEDICT)をバイナリに埋め込み | 無効 |
embed-jieba | 中国語辞書(Jieba)をバイナリに埋め込み | 無効 |
embed-cjk | 全 CJK 辞書をバイナリに埋め込み(IPADIC、ko-dic、Jieba) | 無効 |
複数の feature を組み合わせることができます:
LINDERA_FEATURES="train,embed-ipadic,embed-ko-dic" bundle exec rake compile
[!TIP] 辞書をバイナリに直接埋め込みたい場合(上級者向け)は、対応する
embed-*feature フラグを有効にしてビルドし、embedded://スキームでロードしてください:dictionary = Lindera.load_dictionary("embedded://ipadic")詳細は Feature フラグ を参照してください。
インストールの確認
インストール後、Ruby で lindera が利用可能であることを確認します:
require 'lindera'
puts Lindera.version
クイックスタート
このガイドでは、lindera-ruby を使用してテキストをトークナイズする方法を紹介します。
基本的なトークナイズ
トークナイザーの作成には Lindera::TokenizerBuilder の使用を推奨します:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_mode('normal')
builder.set_dictionary('/path/to/ipadic')
tokenizer = builder.build
tokens = tokenizer.tokenize('関西国際空港限定トートバッグ')
tokens.each do |token|
puts "#{token.surface}\t#{token.details.join(',')}"
end
注意: ビルド済み辞書を GitHub Releases からダウンロードし、展開したディレクトリのパスを指定してください。
期待される出力:
関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ UNK
逐次的な設定
TokenizerBuilder は逐次的なメソッド呼び出しで設定します:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_mode('normal')
builder.set_dictionary('/path/to/ipadic')
tokenizer = builder.build
tokens = tokenizer.tokenize('すもももももももものうち')
tokens.each do |token|
puts "#{token.surface}\t#{token.get_detail(0)}"
end
トークンプロパティへのアクセス
各トークンは以下のプロパティを公開しています:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('/path/to/ipadic')
tokenizer = builder.build
tokens = tokenizer.tokenize('東京タワー')
tokens.each do |token|
puts "Surface: #{token.surface}"
puts "Byte range: #{token.byte_start}..#{token.byte_end}"
puts "Position: #{token.position}"
puts "Word ID: #{token.word_id}"
puts "Unknown: #{token.is_unknown}"
puts "Details: #{token.details}"
puts
end
N-best トークナイズ
コスト順にランク付けされた複数のトークナイズ候補を取得します:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('/path/to/ipadic')
tokenizer = builder.build
results = tokenizer.tokenize_nbest('すもももももももものうち', 3, false, nil)
results.each do |tokens, cost|
surfaces = tokens.map(&:surface)
puts "Cost #{cost}: #{surfaces.join(' / ')}"
end
Tokenizer API
TokenizerBuilder
Lindera::TokenizerBuilder はビルダーパターンを使用して Tokenizer インスタンスを設定・構築します。
コンストラクタ
Lindera::TokenizerBuilder.new
デフォルト設定で新しいビルダーを作成します。
require 'lindera'
builder = Lindera::TokenizerBuilder.new
設定メソッド
set_mode(mode)
トークナイズモードを設定します。
"normal"-- 標準的なトークナイズ(デフォルト)"decompose"-- 複合語をより小さな単位に分解
builder.set_mode('normal')
set_dictionary(path)
システム辞書のパスまたは URI を設定します。
# 埋め込み辞書を使用
builder.set_dictionary('embedded://ipadic')
# 外部辞書を使用
builder.set_dictionary('/path/to/dictionary')
set_user_dictionary(uri)
ユーザー辞書の URI を設定します。
builder.set_user_dictionary('/path/to/user_dictionary')
set_keep_whitespace(keep)
出力に空白トークンを含めるかどうかを制御します。
builder.set_keep_whitespace(true)
append_character_filter(kind, args)
前処理パイプラインに文字フィルタを追加します。
builder.append_character_filter('unicode_normalize', { 'kind' => 'nfkc' })
append_token_filter(kind, args)
後処理パイプラインにトークンフィルタを追加します。args が不要な場合は nil を渡します。
builder.append_token_filter('lowercase', nil)
ビルド
build
設定された内容で Tokenizer をビルドして返します。
tokenizer = builder.build
Tokenizer
Lindera::Tokenizer はテキストに対して形態素解析を行います。
Tokenizer の作成
Lindera::Tokenizer.new(dictionary, mode, user_dictionary)
読み込み済みの辞書から直接トークナイザーを作成します。user_dictionary が不要な場合は nil を渡します。
require 'lindera'
dictionary = Lindera.load_dictionary('embedded://ipadic')
tokenizer = Lindera::Tokenizer.new(dictionary, 'normal', nil)
ユーザー辞書を使用する場合:
dictionary = Lindera.load_dictionary('embedded://ipadic')
metadata = dictionary.metadata
user_dict = Lindera.load_user_dictionary('/path/to/user_dictionary', metadata)
tokenizer = Lindera::Tokenizer.new(dictionary, 'normal', user_dict)
Tokenizer メソッド
tokenize(text)
入力テキストをトークナイズし、Token オブジェクトの配列を返します。
tokens = tokenizer.tokenize('形態素解析')
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | String | トークナイズするテキスト |
戻り値: Array<Token>
tokenize_nbest(text, n, unique, cost_threshold)
N-best トークナイズ結果を返します。各結果はトータルパスコストとペアになっています。
results = tokenizer.tokenize_nbest('すもももももももものうち', 3, false, nil)
results.each do |tokens, cost|
puts "#{cost}: #{tokens.map(&:surface).join(' / ')}"
end
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
text | String | トークナイズするテキスト |
n | Integer | 返す結果の数 |
unique | Boolean | 結果の重複を排除(false で無効) |
cost_threshold | Integer または nil | 最良パスからの最大コスト差(nil で無制限) |
戻り値: Array<[Array<Token>, Integer]>
Token
Token は単一の形態素トークンを表します。
プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
surface | String | トークンの表層形 |
byte_start | Integer | 元テキストでの開始バイト位置 |
byte_end | Integer | 元テキストでの終了バイト位置 |
position | Integer | トークンの位置インデックス |
word_id | Integer | 辞書の単語 ID |
is_unknown | Boolean | 辞書に登録されていない単語の場合 true |
details | Array<String> または nil | 形態素の詳細情報(品詞、読みなど) |
Token メソッド
get_detail(index)
指定されたインデックスの詳細文字列を返します。インデックスが範囲外の場合は nil を返します。
token = tokenizer.tokenize('東京')[0]
pos = token.get_detail(0) # 例: "名詞"
subpos = token.get_detail(1) # 例: "固有名詞"
reading = token.get_detail(7) # 例: "トウキョウ"
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
index | Integer | details 配列へのゼロベースインデックス |
戻り値: String または nil
details の構造は辞書によって異なります:
- IPADIC:
[品詞, 品詞細分類1, 品詞細分類2, 品詞細分類3, 活用型, 活用形, 原形, 読み, 発音] - UniDic: UniDic 仕様に準拠した詳細な形態素情報
- ko-dic / CC-CEDICT / Jieba: 各辞書固有の詳細フォーマット
辞書管理
Lindera Ruby は、形態素解析で使用する辞書の読み込み、ビルド、管理のためのメソッドを提供します。
辞書の読み込み
システム辞書
Lindera.load_dictionary(uri) を使用してシステム辞書を読み込みます。GitHub Releases からビルド済み辞書をダウンロードし、展開したディレクトリのパスを指定してください:
require 'lindera'
dictionary = Lindera.load_dictionary('/path/to/ipadic')
埋め込み辞書(上級者向け) -- embed-* feature フラグ付きでビルドした場合、埋め込み辞書を使用できます:
dictionary = Lindera.load_dictionary('embedded://ipadic')
ユーザー辞書
ユーザー辞書はシステム辞書にカスタム語彙を追加します。
require 'lindera'
dictionary = Lindera.load_dictionary('/path/to/ipadic')
metadata = dictionary.metadata
user_dict = Lindera.load_user_dictionary('/path/to/user_dictionary', metadata)
トークナイザーの作成時にユーザー辞書を渡します:
require 'lindera'
dictionary = Lindera.load_dictionary('/path/to/ipadic')
metadata = dictionary.metadata
user_dict = Lindera.load_user_dictionary('/path/to/user_dictionary', metadata)
tokenizer = Lindera::Tokenizer.new(dictionary, 'normal', user_dict)
または、ビルダー経由で設定します:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('/path/to/ipadic')
builder.set_user_dictionary('/path/to/user_dictionary')
tokenizer = builder.build
辞書のビルド
システム辞書のビルド
ソースファイルからシステム辞書をビルドします:
require 'lindera'
metadata = Lindera::Metadata.from_json_file('metadata.json')
Lindera.build_dictionary('/path/to/input_dir', '/path/to/output_dir', metadata)
入力ディレクトリには辞書のソースファイル(CSV レキシコン、matrix.def など)が含まれている必要があります。
ユーザー辞書のビルド
CSV ファイルからユーザー辞書をビルドします:
require 'lindera'
metadata = Lindera::Metadata.new
Lindera.build_user_dictionary('ipadic', 'user_words.csv', '/path/to/output_dir', metadata)
Metadata
Lindera::Metadata クラスは辞書のパラメータを設定します。
Metadata の作成
require 'lindera'
# デフォルトのメタデータ
metadata = Lindera::Metadata.new
# JSON ファイルからの読み込み
metadata = Lindera::Metadata.from_json_file('metadata.json')
辞書からのメタデータ取得
読み込み済みの辞書からメタデータを取得できます:
dictionary = Lindera.load_dictionary('/path/to/ipadic')
metadata = dictionary.metadata
プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | String | "default" | 辞書名 |
encoding | String | "UTF-8" | 文字エンコーディング |
default_word_cost | Integer | -10000 | 未知語のデフォルトコスト |
default_left_context_id | Integer | 1288 | デフォルトの左文脈 ID |
default_right_context_id | Integer | 1288 | デフォルトの右文脈 ID |
default_field_value | String | "*" | 欠損フィールドのデフォルト値 |
flexible_csv | Boolean | false | 柔軟な CSV パースを許可 |
skip_invalid_cost_or_id | Boolean | false | 無効なコストまたは ID のエントリーをスキップ |
normalize_details | Boolean | false | 形態素の詳細情報を正規化 |
テキスト処理パイプライン
Lindera Ruby は、トークナイズ前に文字フィルタを適用し、トークナイズ後にトークンフィルタを適用する、組み合わせ可能なテキスト処理パイプラインをサポートしています。フィルタは Lindera::TokenizerBuilder に追加され、追加された順序で実行されます。
Input Text
--> Character Filters (preprocessing)
--> Tokenization
--> Token Filters (postprocessing)
--> Output Tokens
文字フィルタ
文字フィルタはトークナイズ前に入力テキストを変換します。
unicode_normalize
入力テキストに Unicode 正規化を適用します。
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_character_filter('unicode_normalize', { 'kind' => 'nfkc' })
tokenizer = builder.build
サポートされる正規化形式: "nfc"、"nfkc"、"nfd"、"nfkd"。
mapping
マッピングテーブルに従って文字や文字列を置換します。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_character_filter('mapping', {
'mapping' => {
"\u30fc" => '-',
"\uff5e" => '~'
}
})
tokenizer = builder.build
japanese_iteration_mark
日本語の踊り字(繰り返し記号)を完全な形に展開します。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_character_filter('japanese_iteration_mark', {
'normalize_kanji' => 'true',
'normalize_kana' => 'true'
})
tokenizer = builder.build
トークンフィルタ
トークンフィルタはトークナイズ後にトークンを変換または除去します。
lowercase
トークンの表層形を小文字に変換します。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_token_filter('lowercase', nil)
tokenizer = builder.build
japanese_base_form
辞書の形態素情報を使用して、活用形を基本形(辞書形)に置換します。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_token_filter('japanese_base_form', nil)
tokenizer = builder.build
japanese_stop_tags
指定されたタグに一致する品詞のトークンを除去します。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_token_filter('japanese_stop_tags', {
'tags' => ['助詞', '助動詞']
})
tokenizer = builder.build
japanese_keep_tags
指定されたタグに一致する品詞のトークンのみを保持します。その他のトークンはすべて除去されます。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_token_filter('japanese_keep_tags', {
'tags' => ['名詞']
})
tokenizer = builder.build
japanese_katakana_stem
カタカナ語の末尾にある長音記号を除去します。最小文字数を指定できます。
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('embedded://ipadic')
builder.append_token_filter('japanese_katakana_stem', { 'min' => 3 })
tokenizer = builder.build
パイプラインの完全な例
以下の例では、複数の文字フィルタとトークンフィルタを1つのパイプラインに組み合わせています:
require 'lindera'
builder = Lindera::TokenizerBuilder.new
builder.set_mode('normal')
builder.set_dictionary('embedded://ipadic')
# Preprocessing
builder.append_character_filter('unicode_normalize', { 'kind' => 'nfkc' })
builder.append_character_filter('japanese_iteration_mark', {
'normalize_kanji' => 'true',
'normalize_kana' => 'true'
})
# Postprocessing
builder.append_token_filter('japanese_base_form', nil)
builder.append_token_filter('japanese_stop_tags', {
'tags' => ['助詞', '助動詞', '記号']
})
builder.append_token_filter('lowercase', nil)
tokenizer = builder.build
tokens = tokenizer.tokenize('Linderaは形態素解析を行うライブラリです。')
tokens.each do |token|
puts "#{token.surface}\t#{token.details.join(',')}"
end
このパイプラインでは:
unicode_normalizeが全角文字を半角に変換(NFKC 正規化)japanese_iteration_markが踊り字を展開japanese_base_formが活用形のトークンを基本形に変換japanese_stop_tagsが助詞、助動詞、記号を除去lowercaseがアルファベットを小文字に正規化
学習
Lindera Ruby は、アノテーション付きコーパスからカスタム CRF ベースの形態素解析モデルを学習する機能をサポートしています。この機能には train feature が必要です。
前提条件
train feature を有効にして lindera-ruby をビルドします:
LINDERA_FEATURES="embed-ipadic,train" bundle exec rake compile
モデルの学習
Lindera.train を使用して、種辞書とアノテーション付きコーパスから CRF モデルを学習します:
require 'lindera'
Lindera.train(
'resources/training/seed.csv',
'resources/training/corpus.txt',
'resources/training/char.def',
'resources/training/unk.def',
'resources/training/feature.def',
'resources/training/rewrite.def',
'/tmp/model.dat',
0.01, # lambda (L1 regularization)
100, # max_iter
nil # max_threads (nil = auto-detect)
)
学習パラメータ
Lindera.train の引数は位置引数として順番に渡します:
| 順番 | パラメータ | 型 | 説明 |
|---|---|---|---|
| 1 | seed | String | 種辞書ファイルのパス(CSV 形式) |
| 2 | corpus | String | アノテーション付き学習コーパスのパス |
| 3 | char_def | String | 文字定義ファイルのパス(char.def) |
| 4 | unk_def | String | 未知語定義ファイルのパス(unk.def) |
| 5 | feature_def | String | 素性定義ファイルのパス(feature.def) |
| 6 | rewrite_def | String | 書き換えルール定義ファイルのパス(rewrite.def) |
| 7 | output | String | 学習済みモデルファイルの出力パス |
| 8 | lambda | Float | L1 正則化コスト(0.0--1.0) |
| 9 | max_iter | Integer | 最大学習イテレーション数 |
| 10 | max_threads | Integer または nil | スレッド数(nil = CPU コア数を自動検出) |
学習済みモデルのエクスポート
学習後、Lindera.export を使用してモデルを辞書ソースファイルにエクスポートします:
require 'lindera'
Lindera.export('/tmp/model.dat', '/tmp/dictionary_source', 'resources/training/metadata.json')
エクスポートパラメータ
| 順番 | パラメータ | 型 | 説明 |
|---|---|---|---|
| 1 | model | String | 学習済みモデルファイルのパス(.dat) |
| 2 | output | String | 辞書ソースファイルの出力ディレクトリ |
| 3 | metadata | String または nil | ベースとなる metadata.json ファイルのパス |
エクスポートにより、出力ディレクトリに以下のファイルが作成されます:
lex.csv-- 学習済みコスト付きのレキシコンエントリーmatrix.def-- 連接コスト行列unk.def-- 未知語定義char.def-- 文字カテゴリ定義metadata.json-- 更新されたメタデータ(metadataパラメータ指定時)
完全なワークフロー
カスタム辞書の学習と使用の完全なワークフロー:
require 'lindera'
# Step 1: Train the CRF model
Lindera.train(
'resources/training/seed.csv',
'resources/training/corpus.txt',
'resources/training/char.def',
'resources/training/unk.def',
'resources/training/feature.def',
'resources/training/rewrite.def',
'/tmp/model.dat',
0.01, # lambda
100, # max_iter
nil # max_threads
)
# Step 2: Export to dictionary source files
Lindera.export('/tmp/model.dat', '/tmp/dictionary_source', 'resources/training/metadata.json')
# Step 3: Build the dictionary from exported source files
metadata = Lindera::Metadata.from_json_file('/tmp/dictionary_source/metadata.json')
Lindera.build_dictionary('/tmp/dictionary_source', '/tmp/dictionary', metadata)
# Step 4: Use the trained dictionary
builder = Lindera::TokenizerBuilder.new
builder.set_dictionary('/tmp/dictionary')
builder.set_mode('normal')
tokenizer = builder.build
tokens = tokenizer.tokenize('形態素解析のテスト')
tokens.each do |token|
puts "#{token.surface}\t#{token.details.join(',')}"
end
Lindera PHP
Lindera PHP は、ext-php-rs を使用して構築された Lindera 形態素解析エンジンの PHP バインディングです。PHP 8.1 以降をサポートし、Lindera の高性能なトークナイズ機能を PHP エコシステムに提供します。
特徴
- 多言語対応: 日本語(IPADIC、IPADIC NEologd、UniDic)、韓国語(ko-dic)、中国語(CC-CEDICT、Jieba)のテキストをトークナイズ
- テキスト処理パイプライン: 文字フィルタとトークンフィルタを組み合わせて、柔軟な前処理・後処理が可能
- CRF ベースの辞書学習: アノテーション付きコーパスからカスタム形態素解析モデルを学習(
trainfeature が必要) - 複数のトークナイズモード: 解析粒度に応じた Normal モードと Decompose モード
- N-best トークナイズ: コスト順にランク付けされた複数のトークナイズ候補を取得
- ユーザー辞書: システム辞書をカスタム語彙で拡張
ドキュメント
- インストール -- 前提条件、ビルド手順、feature フラグ
- クイックスタート -- 最小限の使用例
- トークナイザー API --
TokenizerBuilder、Tokenizer、Tokenクラスリファレンス - 辞書管理 -- 辞書の読み込み、ビルド、管理
- テキスト処理パイプライン -- 文字フィルタとトークンフィルタ
- 学習 -- カスタム CRF モデルの学習と辞書のエクスポート
インストール
[!NOTE] lindera-php はまだ Packagist に公開されていません。ソースからビルドする必要があります。
前提条件
- PHP 8.1 以降
- Rust ツールチェーン -- rustup 経由でインストール
- Composer -- PHP の依存関係管理(テスト実行時に必要)
辞書の入手
Lindera はパッケージに辞書を同梱していません。ビルド済み辞書を別途入手する必要があります。
GitHub Releases からのダウンロード
ビルド済み辞書は GitHub Releases ページから入手で���ます。辞書アーカイブをダウンロードしてローカルディレクトリに展開してください:
# 例: IPADIC 辞書のダウンロードと展開
curl -LO https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip
unzip lindera-ipadic-<version>.zip -d /path/to/ipadic
ビルド
lindera-php をビルドします:
cargo build -p lindera-php
または、プロジェクトの Makefile を使用します:
make php-build
学習機能付きビルド
train feature を有効にすると、CRF ベースの辞書学習機能が利用可能になります。デフォルトで有効になっています:
cargo build -p lindera-php --features train
PHP 拡張の読み込み
ビルド後、-d extension= オプションでビルドされた共有ライブラリを指定して PHP を実行します:
php -d extension=target/debug/liblindera_php.so script.php
リリースビルドの場合:
cargo build -p lindera-php --release
php -d extension=target/release/liblindera_php.so script.php
Feature フラグ
| Feature | 説明 | デフォルト |
|---|---|---|
train | CRF 学習機能 | 有効 |
embed-ipadic | 日本語辞書(IPADIC)をバイナリに埋め込み | 無効 |
embed-unidic | 日本語辞書(UniDic)をバイナリに埋め込み | 無効 |
embed-ipadic-neologd | 日本語辞書(IPADIC NEologd)をバイナリに埋め込み | 無効 |
embed-ko-dic | 韓国語辞書(ko-dic)をバイナリに埋め込み | 無効 |
embed-cc-cedict | 中国語辞書(CC-CEDICT)をバイナリに埋め込み | 無効 |
embed-jieba | 中国語辞書(Jieba)をバイナリに埋め込み | 無効 |
embed-cjk | 全 CJK 辞書をバイナリに埋め込み(IPADIC、ko-dic、Jieba) | 無効 |
複数の feature を組み合わせることができます:
cargo build -p lindera-php --features "train,embed-ipadic,embed-ko-dic"
[!TIP] 辞書をバイナリに直接埋め込みたい場合(上級者向け)は、対応する
embed-*feature フラグを有効にしてビルドし、embedded://スキームでロードしてください:$dictionary = Lindera\Dictionary::load('embedded://ipadic');詳細は Feature フラグ を参照してください。
インストールの確認
インストール後、PHP で lindera が利用可能であることを確認します:
<?php
$version = Lindera\Dictionary::version();
echo "Lindera version: {$version}\n";
実行方法:
php -d extension=target/debug/liblindera_php.so script.php
クイックスタート
このガイドでは、lindera-php を使用してテキストをトークナイズする方法を紹介します。
基本的なトークナイズ
辞書を読み込み、トークナイザーを作成してテキストをトークナイズします:
<?php
// Load the dictionary
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
// Create a tokenizer
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal');
// Tokenize the text
$tokens = $tokenizer->tokenize('関西国際空港限定トートバッグ');
foreach ($tokens as $token) {
echo $token->surface . "\t" . implode(',', $token->details) . "\n";
}
注意: ビルド済み辞書を GitHub Releases からダウンロードし、展開したディレクトリのパスを指定してください。
期待される出力:
関西国際空港 名詞,固有名詞,組織,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ UNK
TokenizerBuilder の使用
TokenizerBuilder を使用すると、より柔軟にトークナイザーを設定できます:
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setMode('normal');
$builder->setDictionary('/path/to/ipadic');
$tokenizer = $builder->build();
$tokens = $tokenizer->tokenize('すもももももももものうち');
foreach ($tokens as $token) {
echo $token->surface . "\t" . $token->getDetail(0) . "\n";
}
トークンプロパティへのアクセス
各トークンは以下のプロパティを公開しています:
<?php
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal');
$tokens = $tokenizer->tokenize('東京タワー');
foreach ($tokens as $token) {
echo "Surface: {$token->surface}\n";
echo "Byte range: {$token->byte_start}..{$token->byte_end}\n";
echo "Position: {$token->position}\n";
echo "Word ID: {$token->word_id}\n";
echo "Unknown: " . ($token->is_unknown ? 'true' : 'false') . "\n";
echo "Details: " . implode(',', $token->details) . "\n";
echo "\n";
}
N-best トークナイズ
コスト順にランク付けされた複数のトークナイズ候補を取得します:
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('/path/to/ipadic');
$tokenizer = $builder->build();
$results = $tokenizer->tokenizeNbest('東京都', 3);
foreach ($results as $result) {
$surfaces = array_map(fn($t) => $t->surface, $result->tokens);
echo "Cost {$result->cost}: " . implode(' / ', $surfaces) . "\n";
}
Decompose モード
Decompose モードでは、複合語をより小さな単位に分解します:
<?php
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
$tokenizer = new Lindera\Tokenizer($dictionary, 'decompose');
$tokens = $tokenizer->tokenize('関西国際空港限定トートバッグ');
foreach ($tokens as $token) {
echo $token->surface . "\n";
}
トークナイザー API
TokenizerBuilder
TokenizerBuilder はビルダーパターンを使用して Tokenizer インスタンスを設定・構築します。
コンストラクタ
new Lindera\TokenizerBuilder()
デフォルト設定で新しいビルダーを作成します。
<?php
$builder = new Lindera\TokenizerBuilder();
設定メソッド
すべてのセッターメソッドはメソッドチェーンのために $this を返します。
setMode($mode)
トークナイズモードを設定します。
"normal"-- 標準的なトークナイズ(デフォルト)"decompose"-- 複合語をより小さな単位に分解
$builder->setMode('normal');
setDictionary($uri)
システム辞書のパスまたは URI を設定します。
// 埋め込み辞書を使用
$builder->setDictionary('embedded://ipadic');
// 外部辞書を使用
$builder->setDictionary('/path/to/dictionary');
setUserDictionary($uri)
ユーザー辞書の URI を設定します。
$builder->setUserDictionary('/path/to/user_dictionary');
setKeepWhitespace($keep)
出力に空白トークンを含めるかどうかを制御します。
$builder->setKeepWhitespace(true);
appendCharacterFilter($kind, $args)
前処理パイプラインに文字フィルタを追加します。
$builder->appendCharacterFilter('unicode_normalize', ['kind' => 'nfkc']);
appendTokenFilter($kind, $args)
後処理パイプラインにトークンフィルタを追加します。
$builder->appendTokenFilter('lowercase');
$builder->appendTokenFilter('japanese_stop_tags', ['tags' => ['助詞', '助動詞']]);
ビルド
build()
設定された内容で Tokenizer をビルドして返します。
$tokenizer = $builder->build();
Tokenizer
Tokenizer はテキストに対して形態素解析を行います。
Tokenizer の作成
new Lindera\Tokenizer($dictionary, $mode, $userDictionary)
読み込み済みの辞書から直接トークナイザーを作成します。
<?php
$dictionary = Lindera\Dictionary::load('embedded://ipadic');
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal');
ユーザー辞書を指定する場合:
<?php
$dictionary = Lindera\Dictionary::load('embedded://ipadic');
$metadata = $dictionary->metadata();
$userDictionary = Lindera\Dictionary::loadUser('/path/to/user_dictionary', $metadata);
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal', $userDictionary);
Tokenizer メソッド
tokenize($text)
入力テキストをトークナイズし、Token オブジェクトの配列を返します。
$tokens = $tokenizer->tokenize('形態素解析');
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
$text | string | トークナイズするテキスト |
戻り値: array<Token>
tokenizeNbest($text, $n)
N-best トークナイズ結果を返します。各結果は NbestResult オブジェクトで、トークン配列とトータルパスコストを含みます。
$results = $tokenizer->tokenizeNbest('すもももももももものうち', 3);
foreach ($results as $result) {
echo "Cost: {$result->cost}\n";
foreach ($result->tokens as $token) {
echo " {$token->surface}\n";
}
}
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
$text | string | トークナイズするテキスト |
$n | int | 返す結果の数 |
戻り値: array<NbestResult>
NbestResult
NbestResult は N-best トークナイズの個別の結果を表します。
NbestResult プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
tokens | array<Token> | トークンの配列 |
cost | int | トータルパスコスト |
Token
Token は単一の形態素トークンを表します。
Token プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
surface | string | トークンの表層形 |
byte_start | int | 元テキストでの開始バイト位置 |
byte_end | int | 元テキストでの終了バイト位置 |
position | int | トークンの位置インデックス |
word_id | int | 辞書の単語 ID |
is_unknown | bool | 辞書に登録されていない単語の場合 true |
details | array<string> | 形態素の詳細情報(品詞、読みなど) |
Token メソッド
getDetail($index)
指定されたインデックスの詳細文字列を返します。インデックスが範囲外の場合は null を返します。
$token = $tokenizer->tokenize('東京')[0];
$pos = $token->getDetail(0); // 例: "名詞"
$subpos = $token->getDetail(1); // 例: "固有名詞"
$reading = $token->getDetail(7); // 例: "トウキョウ"
パラメータ:
| 名前 | 型 | 説明 |
|---|---|---|
$index | int | details 配列へのゼロベースインデックス |
戻り値: string または null
details の構造は辞書によって異なります:
- IPADIC:
[品詞, 品詞細分類1, 品詞細分類2, 品詞細分類3, 活用型, 活用形, 原形, 読み, 発音] - UniDic: UniDic 仕様に準拠した詳細な形態素情報
- ko-dic / CC-CEDICT / Jieba: 各辞書固有の詳細フォーマット
Mode
Mode はトークナイズの動作モードを表します。
Mode の作成
new Lindera\Mode($name)
$mode = new Lindera\Mode('normal');
$mode = new Lindera\Mode('decompose');
$mode = new Lindera\Mode(); // デフォルト: 'normal'
Mode プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
name | string | モード名("normal" または "decompose") |
Mode メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
isNormal() | bool | Normal モードの場合 true |
isDecompose() | bool | Decompose モードの場合 true |
辞書管理
Lindera PHP は、形態素解析で使用する辞書の読み込み、ビルド、管理のためのクラスを提供します。
辞書の読み込み
システム辞書
Lindera\Dictionary::load($uri) を使用してシステム辞書を読み込みます。GitHub Releases からビルド済み辞書をダウンロードし、展開したディレクトリのパスを指定してください:
<?php
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
埋め込み辞書(上級者向け) -- embed-* feature フラグ付きでビルドした場合、埋め込み辞書を使用できます:
<?php
$dictionary = Lindera\Dictionary::load('embedded://ipadic');
ユーザー辞書
ユーザー辞書はシステム辞書にカスタム語彙を追加します。Lindera\Dictionary::loadUser() を使用して読み込みます。
<?php
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
$metadata = $dictionary->metadata();
$userDictionary = Lindera\Dictionary::loadUser('/path/to/user_dictionary.csv', $metadata);
トークナイザーの作成時にユーザー辞書を渡します:
<?php
$dictionary = Lindera\Dictionary::load('/path/to/ipadic');
$metadata = $dictionary->metadata();
$userDictionary = Lindera\Dictionary::loadUser('/path/to/user_dictionary.csv', $metadata);
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal', $userDictionary);
または、ビルダー経由で設定します:
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('/path/to/ipadic');
$builder->setUserDictionary('/path/to/user_dictionary');
$tokenizer = $builder->build();
Dictionary メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
Dictionary::load($uri) | Dictionary | システム辞書を読み込む |
Dictionary::loadUser($path, $metadata) | UserDictionary | ユーザー辞書を読み込む |
Dictionary::version() | string | Lindera のバージョン文字列を返す |
Dictionary::build($source, $dest, $metadata) | void | 辞書をビルドする |
$dictionary->metadata() | Metadata | 辞書のメタデータを返す |
$dictionary->metadataName() | string | 辞書名を返す |
$dictionary->metadataEncoding() | string | 辞書のエンコーディングを返す |
辞書のビルド
システム辞書のビルド
ソースファイルからシステム辞書をビルドします:
<?php
$metadata = Lindera\Metadata::fromJsonFile('/path/to/metadata.json');
Lindera\Dictionary::build('/path/to/input_dir', '/path/to/output_dir', $metadata);
入力ディレクトリには辞書のソースファイル(CSV レキシコン、matrix.def など)が含まれている必要があります。
以下は IPADIC 辞書をダウンロードしてビルドする例です:
<?php
$url = 'https://lindera.dev/mecab-ipadic-2.7.0-20070801.tar.gz';
$filename = '/tmp/mecab-ipadic-2.7.0-20070801.tar.gz';
// Download and extract dictionary source
file_put_contents($filename, file_get_contents($url));
$phar = new PharData($filename);
$phar->extractTo('/tmp/', null, true);
// Load metadata and build
$metadata = Lindera\Metadata::fromJsonFile('resources/ipadic_metadata.json');
Lindera\Dictionary::build(
'/tmp/mecab-ipadic-2.7.0-20070801',
'/tmp/lindera-ipadic',
$metadata
);
Metadata
Metadata クラスは辞書のパラメータを設定します。
Metadata の作成
<?php
// デフォルトのメタデータ
$metadata = Lindera\Metadata::createDefault();
// カスタムメタデータ
$metadata = new Lindera\Metadata('my_dictionary', 'UTF-8', -10000);
JSON からの読み込み
$metadata = Lindera\Metadata::fromJsonFile('metadata.json');
プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "default" | 辞書名 |
encoding | string | "UTF-8" | 文字エンコーディング |
default_word_cost | int | -10000 | 未知語のデフォルトコスト |
Schema
Schema クラスは辞書のフィールド構造を定義します。
Schema の作成
<?php
// デフォルトスキーマ(IPADIC 互換)
$schema = Lindera\Schema::createDefault();
// カスタムスキーマ
$schema = new Lindera\Schema(['surface', 'pos']);
メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
fieldCount() | int | フィールド数を返す |
getFieldIndex($name) | int | フィールドのインデックスを返す(見つからない場合は -1) |
getFieldByName($name) | Field または null | フィールド情報を返す |
getCustomFields() | array<string> | カスタムフィールド名の配列を返す |
validateRecord($record) | void | レコードがスキーマに適合するか検証する |
Schema プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
fields | array<string> | フィールド名の配列 |
テキスト処理パイプライン
Lindera PHP は、トークナイズ前に文字フィルタを適用し、トークナイズ後にトークンフィルタを適用する、組み合わせ可能なテキスト処理パイプラインをサポートしています。フィルタは TokenizerBuilder に追加され、追加された順序で実行されます。
Input Text
--> Character Filters (preprocessing)
--> Tokenization
--> Token Filters (postprocessing)
--> Output Tokens
文字フィルタ
文字フィルタはトークナイズ前に入力テキストを変換します。
unicode_normalize
入力テキストに Unicode 正規化を適用します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendCharacterFilter('unicode_normalize', ['kind' => 'nfkc']);
$tokenizer = $builder->build();
サポートされる正規化形式: "nfc"、"nfkc"、"nfd"、"nfkd"。
mapping
マッピングテーブルに従って文字や文字列を置換します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendCharacterFilter('mapping', [
'mapping' => [
'リンデラ' => 'lindera',
],
]);
$tokenizer = $builder->build();
japanese_iteration_mark
日本語の踊り字(繰り返し記号)を完全な形に展開します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendCharacterFilter('japanese_iteration_mark', [
'normalize_kanji' => 'true',
'normalize_kana' => 'true',
]);
$tokenizer = $builder->build();
トークンフィルタ
トークンフィルタはトークナイズ後にトークンを変換または除去します。
lowercase
トークンの表層形を小文字に変換します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendTokenFilter('lowercase');
$tokenizer = $builder->build();
japanese_base_form
辞書の形態素情報を使用して、活用形を基本形(辞書形)に置換します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendTokenFilter('japanese_base_form', []);
$tokenizer = $builder->build();
japanese_katakana_stem
カタカナ語の語尾の長音記号を除去してステミングを行います。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendTokenFilter('japanese_katakana_stem', ['min' => 3]);
$tokenizer = $builder->build();
japanese_stop_tags
指定されたタグに一致する品詞のトークンを除去します。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendTokenFilter('japanese_stop_tags', [
'tags' => ['助詞', '助動詞', '記号'],
]);
$tokenizer = $builder->build();
japanese_keep_tags
指定されたタグに一致する品詞のトークンのみを保持します。その他のトークンはすべて除去されます。
<?php
$builder = new Lindera\TokenizerBuilder();
$builder->setDictionary('embedded://ipadic');
$builder->appendTokenFilter('japanese_keep_tags', [
'tags' => ['名詞'],
]);
$tokenizer = $builder->build();
パイプラインの完全な例
以下の例では、複数の文字フィルタとトークンフィルタを1つのパイプラインに組み合わせています:
<?php
$builder = new Lindera\TokenizerBuilder();
// Set mode and dictionary
$builder->setMode('normal');
$builder->setDictionary('embedded://ipadic');
// Preprocessing
$builder->appendCharacterFilter('unicode_normalize', ['kind' => 'nfkc']);
$builder->appendCharacterFilter(
'japanese_iteration_mark',
['normalize_kanji' => 'true', 'normalize_kana' => 'true']
);
$builder->appendCharacterFilter('mapping', ['mapping' => ['リンデラ' => 'lindera']]);
// Postprocessing
$builder->appendTokenFilter('japanese_katakana_stem', ['min' => 3]);
$builder->appendTokenFilter('japanese_stop_tags', [
'tags' => [
'接続詞',
'助詞',
'助詞,格助詞',
'助詞,格助詞,一般',
'助詞,係助詞',
'助詞,副助詞',
'助詞,終助詞',
'助詞,連体化',
'助動詞',
'記号',
'記号,一般',
'記号,読点',
'記号,句点',
'記号,空白',
],
]);
$builder->appendTokenFilter('lowercase');
// Build the tokenizer
$tokenizer = $builder->build();
// Tokenize
$text = 'Linderaは形態素解析エンジンです。';
$tokens = $tokenizer->tokenize($text);
foreach ($tokens as $token) {
echo $token->surface . "\t" . implode(',', $token->details) . "\n";
}
このパイプラインでは:
unicode_normalizeが全角文字を半角に変換(NFKC 正規化)japanese_iteration_markが踊り字を展開mappingが指定された文字列を置換japanese_katakana_stemがカタカナ語をステミングjapanese_stop_tagsが助詞、助動詞、記号を除去lowercaseがアルファベットを小文字に正規化
学習
Lindera PHP は、アノテーション付きコーパスからカスタム CRF ベースの形態素解析モデルを学習する機能をサポートしています。この機能には train feature が必要です。
前提条件
train feature を有効にして lindera-php をビルドします(デフォルトで有効):
cargo build -p lindera-php --features train
モデルの学習
Lindera\Trainer::train() を使用して、種辞書とアノテーション付きコーパスから CRF モデルを学習します:
<?php
Lindera\Trainer::train(
'/path/to/seed.csv', // seed: 種辞書ファイル
'/path/to/corpus.txt', // corpus: アノテーション付きコーパス
'/path/to/char.def', // char_def: 文字定義ファイル
'/path/to/unk.def', // unk_def: 未知語定義ファイル
'/path/to/feature.def', // feature_def: 素性定義ファイル
'/path/to/rewrite.def', // rewrite_def: 書き換えルール定義ファイル
'/tmp/model.dat', // output: 学習済みモデルの出力パス
0.01, // lambda: L1 正則化コスト
100, // max_iter: 最大イテレーション数
null // max_threads: スレッド数(null = 自動検出)
);
学習パラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
$seed | string | 必須 | 種辞書ファイルのパス(CSV 形式) |
$corpus | string | 必須 | アノテーション付き学習コーパスのパス |
$charDef | string | 必須 | 文字定義ファイルのパス(char.def) |
$unkDef | string | 必須 | 未知語定義ファイルのパス(unk.def) |
$featureDef | string | 必須 | 素性定義ファイルのパス(feature.def) |
$rewriteDef | string | 必須 | 書き換えルール定義ファイルのパス(rewrite.def) |
$output | string | 必須 | 学習済みモデルファイルの出力パス |
$lambda | float | 0.01 | L1 正則化コスト(0.0--1.0) |
$maxIter | int | 100 | 最大学習イテレーション数 |
$maxThreads | int または null | null | スレッド数(null = CPU コア数を自動検出) |
学習済みモデルのエクスポート
学習後、Lindera\Trainer::export() を使用してモデルを辞書ソースファイルにエクスポートします:
<?php
Lindera\Trainer::export(
'/tmp/model.dat', // model: 学習済みモデルファイル
'/tmp/dictionary_source', // output: 出力ディレクトリ
'/path/to/metadata.json' // metadata: メタデータファイル(省略可)
);
エクスポートパラメータ
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
$model | string | 必須 | 学習済みモデルファイルのパス(.dat) |
$output | string | 必須 | 辞書ソースファイルの出力ディレクトリ |
$metadata | string または null | null | ベースとなる metadata.json ファイルのパス |
エクスポートにより、出力ディレクトリに以下のファイルが作成されます:
lex.csv-- 学習済みコスト付きのレキシコンエントリーmatrix.def-- 連接コスト行列unk.def-- 未知語定義char.def-- 文字カテゴリ定義metadata.json-- 更新されたメタデータ($metadataパラメータ指定時)
完全なワークフロー
カスタム辞書の学習と使用の完全なワークフロー:
<?php
// Step 1: Train the CRF model
Lindera\Trainer::train(
'resources/training/seed.csv',
'resources/training/corpus.txt',
'resources/training/char.def',
'resources/training/unk.def',
'resources/training/feature.def',
'resources/training/rewrite.def',
'/tmp/model.dat',
0.01, // lambda
100, // max_iter
null // max_threads
);
// Step 2: Export to dictionary source files
Lindera\Trainer::export(
'/tmp/model.dat',
'/tmp/dictionary_source',
'resources/training/metadata.json'
);
// Step 3: Build the dictionary from exported source files
$metadata = Lindera\Metadata::fromJsonFile('/tmp/dictionary_source/metadata.json');
Lindera\Dictionary::build('/tmp/dictionary_source', '/tmp/dictionary', $metadata);
// Step 4: Use the trained dictionary
$dictionary = Lindera\Dictionary::load('/tmp/dictionary');
$tokenizer = new Lindera\Tokenizer($dictionary, 'normal');
$tokens = $tokenizer->tokenize('形態素解析のテスト');
foreach ($tokens as $token) {
echo $token->surface . "\t" . implode(',', $token->details) . "\n";
}
Lindera WASM
Lindera WASM は、wasm-bindgen を使用して構築された Lindera 形態素解析エンジンの WebAssembly バインディングです。Web ブラウザ、Node.js、バンドラー環境で日本語、韓国語、中国語のテキストトークナイズを直接実行できます。
配布フォーマット
Lindera WASM は wasm-pack を通じて複数の配布フォーマットをサポートしています:
| ターゲット | 用途 | モジュールシステム |
|---|---|---|
web | ブラウザ ESM | ES Modules |
bundler | Webpack、Vite、Rollup | ES Modules(バンドラー解決) |
辞書パッケージ
各パッケージはオフライン使用のために特定の辞書を埋め込みます:
| Feature フラグ | 辞書 | 言語 |
|---|---|---|
| (なし) | 埋め込み辞書なし | -- |
embed-ipadic | IPADIC | 日本語 |
embed-unidic | UniDic | 日本語 |
embed-ko-dic | ko-dic | 韓国語 |
embed-cc-cedict | CC-CEDICT | 中国語 |
embed-jieba | Jieba | 中国語 |
embed-cjk | IPADIC + ko-dic + Jieba | CJK |
セクション
- インストール -- lindera-wasm パッケージのビルドとインストール
- クイックスタート -- 最小限の動作例
- Tokenizer API -- JavaScript/TypeScript の完全な API リファレンス
- 辞書管理 -- 辞書の読み込みとビルド
- ブラウザでの使用 -- Web アプリケーションとの統合
- OPFS 辞書ストレージ -- OPFS による辞書の永続キャッシュ
インストール
前提条件
辞書の入手
Lindera WASM はデフォルトで辞書を同梱しません。ブラウザ環境では、OPFS(Origin Private File System)API を使用して辞書を実行時にダウンロードする方法を推奨します。
GitHub Releases からのダウンロード
ビルド済み辞書は GitHub Releases ページから入手できます。ブラウザ環境では、OPFS ヘルパーを使用して辞書をダウンロードしてキャッシュします:
import { downloadDictionary, hasDictionary } from 'lindera-wasm-web/opfs';
if (!await hasDictionary("ipadic")) {
await downloadDictionary(
"https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip",
"ipadic",
);
}
詳細は OPFS 辞書ストレージ を参照してください。
wasm-pack によるビルド
ターゲット環境に合わせて WASM パッケージをビルドします:
Web(ブラウザ向け ES Modules)
wasm-pack build --target web
バンドラー(Webpack、Vite、Rollup)
wasm-pack build --target bundler
出力は lindera-wasm クレート内の pkg/ ディレクトリに書き込まれます。
利用可能な Feature フラグ(上級者向け)
辞書を WASM バイナリに直接埋め込みたい上級者向けに、以下の feature フラグが利用できます。バイナリサイズが大幅に増加しますが、実行時の辞書ダウンロードが不要になります。
| Feature | 辞書 | 言語 |
|---|---|---|
embed-ipadic | IPADIC | 日本語 |
embed-unidic | UniDic | 日本語 |
embed-ko-dic | ko-dic | 韓国語 |
embed-cc-cedict | CC-CEDICT | 中国語 |
embed-jieba | Jieba | 中国語 |
embed-cjk | IPADIC + ko-dic + Jieba | CJK(全言語) |
複数の feature フラグを有効にして複数の辞書を組み合わせることができます:
wasm-pack build --target web --features embed-ipadic,embed-ko-dic
npm パッケージの命名規則
npm に公開する際の推奨命名規則は以下の通りです:
lindera-wasm-{target}
lindera-wasm-{target}-{dict}
例:
lindera-wasm-weblindera-wasm-web-ipadiclindera-wasm-bundler-unidiclindera-wasm-web-cjk
公開前にパッケージ名を設定するには、生成された pkg/package.json の name フィールドを編集します。
npm からのインストール
ビルド済みパッケージが npm で公開されています:
npm install lindera-wasm-web
または yarn で:
yarn add lindera-wasm-web
[!NOTE] npm パッケージには辞書が含まれていません。OPFS ヘルパーを使用して辞書を実行時にダウンロードしてください。詳細は OPFS 辞書ストレージ を参照してください。
クイックスタート
Web(ブラウザ) -- OPFS 辞書ロード
推奨される方法は、OPFS ヘルパーを使用して辞書を実行時にダウンロードすることです:
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from 'lindera-wasm-web';
import { downloadDictionary, loadDictionaryFiles, hasDictionary } from 'lindera-wasm-web/opfs';
async function main() {
await __wbg_init();
// キャッシュされていない場合は辞書をダウンロード
if (!await hasDictionary("ipadic")) {
await downloadDictionary(
"https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip",
"ipadic",
);
}
// OPFS から辞書を読み込み
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
// トークナイザーを構築
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("関西国際空港限定トートバッグ");
tokens.forEach(token => {
console.log(`${token.surface}\t${token.details.join(',')}`);
});
}
main();
注意: ビルド済み辞書を GitHub Releases からダウンロードしてください。完全なワークフローは OPFS 辞書ストレージ を参照してください。
期待される出力:
関西国際空港 名詞,固有名詞,一般,*,*,*,関西国際空港,カンサイコクサイクウコウ,カンサイコクサイクーコー
限定 名詞,サ変接続,*,*,*,*,限定,ゲンテイ,ゲンテイ
トートバッグ 名詞,一般,*,*,*,*,*,*,*
埋め込み辞書の使用(上級者向け)
embed-* feature フラグ付きでビルドした場合、埋め込み辞書を使用できます:
import __wbg_init, { TokenizerBuilder } from 'lindera-wasm-web-ipadic';
async function main() {
await __wbg_init();
const builder = new TokenizerBuilder();
builder.setDictionary("embedded://ipadic");
builder.setMode("normal");
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("関西国際空港限定トートバッグ");
tokens.forEach(token => {
console.log(`${token.surface}\t${token.details.join(',')}`);
});
}
main();
フィルタの使用
トークナイズパイプラインに文字フィルタやトークンフィルタを追加できます:
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from 'lindera-wasm-web';
import { loadDictionaryFiles } from 'lindera-wasm-web/opfs';
async function main() {
await __wbg_init();
// OPFS にキャッシュ済みの辞書を読み込み
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
// Add Unicode NFKC normalization
builder.appendCharacterFilter("unicode_normalize", { kind: "nfkc" });
// Add a stop-tags filter to remove particles and auxiliary verbs
builder.appendTokenFilter("japanese_stop_tags", {
tags: ["助詞", "助動詞"]
});
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("Linderaは形態素解析エンジンです");
tokens.forEach(token => {
console.log(`${token.surface}\t${token.details.join(',')}`);
});
}
main();
N-Best トークナイズ
コスト順にランク付けされた複数のトークナイズ候補を取得します:
const results = tokenizer.tokenizeNbest("すもももももももものうち", 3);
results.forEach((result, rank) => {
console.log(`--- NBEST ${rank + 1} (cost=${result.cost}) ---`);
result.tokens.forEach(token => {
console.log(`${token.surface}\t${token.details.join(',')}`);
});
});
Tokenizer API
このページでは、lindera-wasm が公開する JavaScript/TypeScript API について説明します。
TokenizerBuilder
設定済みの Tokenizer インスタンスを作成するためのビルダークラスです。
コンストラクタ
const builder = new TokenizerBuilder();
デフォルト設定で新しいビルダーを作成します。
メソッド
setMode(mode)
トークナイズモードを設定します。
- パラメータ:
mode(string) --"normal"または"decompose" - 戻り値: void
builder.setMode("normal");
setDictionary(uri)
トークナイズに使用する辞書を設定します。
- パラメータ:
uri(string) -- 辞書の URI(例:"embedded://ipadic") - 戻り値: void
builder.setDictionary("embedded://ipadic");
setDictionaryInstance(dictionary)
読み込み済みの辞書インスタンスをトークナイズに設定します。
URI の代わりにバイトデータから読み込んだ辞書(例: loadDictionaryFromBytes() 経由)を使用する場合に使います。
- パラメータ:
dictionary(Dictionary) -- 読み込み済みの辞書オブジェクト - 戻り値: void
import { loadDictionaryFromBytes } from 'lindera-wasm-web';
import { loadDictionaryFiles } from 'lindera-wasm-web/opfs';
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
builder.setDictionaryInstance(dictionary);
setUserDictionary(uri)
ユーザー定義辞書を設定します。
- パラメータ:
uri(string) -- ユーザー辞書のパスまたは URI - 戻り値: void
builder.setUserDictionary("file:///path/to/user_dict.csv");
setUserDictionaryInstance(userDictionary)
読み込み済みのユーザー辞書インスタンスを設定します。URI の代わりにバイトデータから読み込んだユーザー辞書を使用する場合に使います。
- パラメータ:
userDictionary(UserDictionary) -- 読み込み済みのユーザー辞書オブジェクト - 戻り値: void
setKeepWhitespace(keep)
出力に空白トークンを保持するかどうかを設定します。
- パラメータ:
keep(boolean) --trueで空白トークンを保持 - 戻り値: void
builder.setKeepWhitespace(true);
appendCharacterFilter(name, args)
前処理パイプラインに文字フィルタを追加します。
- パラメータ:
name(string) -- フィルタ名(例:"unicode_normalize"、"japanese_iteration_mark")args(object, 省略可) -- フィルタの設定
- 戻り値: void
builder.appendCharacterFilter("unicode_normalize", { kind: "nfkc" });
appendTokenFilter(name, args)
後処理パイプラインにトークンフィルタを追加します。
- パラメータ:
name(string) -- フィルタ名(例:"japanese_stop_tags"、"lowercase")args(object, 省略可) -- フィルタの設定
- 戻り値: void
builder.appendTokenFilter("japanese_stop_tags", {
tags: ["助詞", "助動詞", "記号"]
});
build()
設定済みの Tokenizer インスタンスをビルドして返します。ビルダーは消費されます。
- 戻り値:
Tokenizer
const tokenizer = builder.build();
Tokenizer
メインのトークナイザークラスです。TokenizerBuilder.build() またはコンストラクタ経由で作成できます。
Tokenizer コンストラクタ
const tokenizer = new Tokenizer(dictionary, mode, userDictionary);
- パラメータ:
dictionary(Dictionary) -- 読み込み済みの辞書オブジェクトmode(string, 省略可) -- トークナイズモード("normal"または"decompose"、デフォルト:"normal")userDictionary(UserDictionary, 省略可) -- 読み込み済みのユーザー辞書
Tokenizer メソッド
tokenize(text)
入力テキストをトークナイズします。
- パラメータ:
text(string) -- トークナイズするテキスト - 戻り値:
Token[]-- トークンオブジェクトの配列
const tokens = tokenizer.tokenize("関西国際空港");
tokenizeNbest(text, n, unique?, costThreshold?)
トータルパスコスト順に N-best トークナイズ結果を返します。
- パラメータ:
text(string) -- トークナイズするテキストn(number) -- 返す結果の数unique(boolean, 省略可) -- 同一のセグメンテーション結果を重複排除(デフォルト:false)costThreshold(number, 省略可) --bestCost + threshold以内のパスのみ返す
- 戻り値:
{ tokens: object[], cost: number }の配列
const results = tokenizer.tokenizeNbest("すもももももももものうち", 3);
Token
トークナイザーが生成する単一のトークンを表します。
プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
surface | string | トークンの表層形 |
byteStart | number | 元テキストでの開始バイトオフセット |
byteEnd | number | 元テキストでの終了バイトオフセット |
position | number | トークンの位置インデックス |
wordId | number | 辞書内の単語 ID |
isUnknown | boolean | 未知語かどうか |
details | string[] | 形態素の詳細フィールド |
Token メソッド
getDetail(index)
指定されたインデックスの詳細文字列を返します。
- パラメータ:
index(number) -- details 配列へのゼロベースインデックス - 戻り値:
string | undefined
const pos = token.getDetail(0); // 例: "名詞"
const reading = token.getDetail(7); // 例: "トウキョウ"
toJSON()
トークンのプレーンな JavaScript オブジェクト表現を返します。
- 戻り値:
surface、byteStart、byteEnd、position、wordId、isUnknown、detailsをキーに持つobject
console.log(JSON.stringify(token.toJSON(), null, 2));
ヘルパー関数
loadDictionary(uri)
指定された URI から辞書を読み込みます。
- パラメータ:
uri(string) -- 辞書の URI(例:"embedded://ipadic") - 戻り値:
Dictionary
import { loadDictionary } from 'lindera-wasm-web-ipadic';
const dict = loadDictionary("embedded://ipadic");
loadUserDictionary(uri, metadata)
指定された URI からユーザー辞書を読み込みます。
- パラメータ:
uri(string) -- ユーザー辞書ファイルのパスまたは URImetadata(Metadata) -- 辞書のメタデータオブジェクト
- 戻り値:
UserDictionary
buildDictionary(inputDir, outputDir, metadata)
ソースファイルからコンパイル済み辞書をビルドします。
- パラメータ:
inputDir(string) -- 辞書ソースファイルを含むディレクトリのパスoutputDir(string) -- 出力ディレクトリのパスmetadata(Metadata) -- 辞書のメタデータオブジェクト
- 戻り値: void
buildUserDictionary(inputFile, outputDir, metadata?)
CSV ファイルからコンパイル済みユーザー辞書をビルドします。
- パラメータ:
inputFile(string) -- ユーザー辞書 CSV ファイルのパスoutputDir(string) -- 出力ディレクトリのパスmetadata(Metadata, 省略可) -- 辞書のメタデータオブジェクト
- 戻り値: void
version() / getVersion()
lindera-wasm パッケージのバージョン文字列を返します。
- 戻り値:
string
import { version } from 'lindera-wasm-web-ipadic';
console.log(version()); // 例: "2.1.1"
列挙型とユーティリティクラス
Mode
トークナイズモードの列挙型です。
| 値 | 説明 |
|---|---|
Mode.Normal | 辞書コストに基づく標準的なトークナイズ |
Mode.Decompose | ペナルティベースのセグメンテーションによる複合語分解 |
Penalty
decompose モードの設定です。複合語をどの程度積極的に分解するかを制御します。
const penalty = new Penalty(
kanjiThreshold?, // 漢字の長さ閾値(デフォルト: 2)
kanjiPenalty?, // 漢字の長さペナルティ(デフォルト: 3000)
otherThreshold?, // その他の文字の長さ閾値(デフォルト: 7)
otherPenalty?, // その他の文字の長さペナルティ(デフォルト: 1700)
);
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
kanji_penalty_length_threshold | number | 2 | 漢字複合語分割の長さ閾値 |
kanji_penalty_length_penalty | number | 3000 | 閾値を超える漢字複合語のペナルティコスト |
other_penalty_length_threshold | number | 7 | 非漢字複合語分割の長さ閾値 |
other_penalty_length_penalty | number | 1700 | 閾値を超える非漢字複合語のペナルティコスト |
LinderaError
Lindera 操作のエラー型です。
const error = new LinderaError("message");
console.log(error.message); // "message"
console.log(error.toString()); // "message"
| プロパティ / メソッド | 型 | 説明 |
|---|---|---|
message | string | エラーメッセージ |
toString() | string | エラーメッセージを返す |
snake_case エイリアス
Python API との一貫性のため、すべてのメソッドは snake_case 形式でも利用可能です:
| camelCase | snake_case |
|---|---|
setMode() | set_mode() |
setDictionary() | set_dictionary() |
setDictionaryInstance() | set_dictionary_instance() |
setUserDictionary() | set_user_dictionary() |
setUserDictionaryInstance() | set_user_dictionary_instance() |
setKeepWhitespace() | set_keep_whitespace() |
appendCharacterFilter() | append_character_filter() |
appendTokenFilter() | append_token_filter() |
tokenizeNbest() | tokenize_nbest() |
loadDictionary() | load_dictionary() |
loadDictionaryFromBytes() | load_dictionary_from_bytes() |
loadUserDictionary() | load_user_dictionary() |
buildDictionary() | build_dictionary() |
buildUserDictionary() | build_user_dictionary() |
辞書管理
OPFS からの辞書読み込み
WASM で辞書を使用する推奨方法は、GitHub Releases からダウンロードし、OPFS 経由で読み込むことです。これにより、WASM バイナリに大きな辞書を埋め込む必要がなくなります。
バイトデータからの読み込み
OPFS やその他のブラウザストレージに保存された辞書を loadDictionaryFromBytes() で読み込みます。
loadDictionaryFromBytes(metadata, dictDa, dictVals, dictWordsIdx, dictWords, matrixMtx, charDef, unk)
- パラメータ:
metadata(Uint8Array) --metadata.jsonの内容dictDa(Uint8Array) --dict.daの内容(Double-Array Trie)dictVals(Uint8Array) --dict.valsの内容(単語値データ)dictWordsIdx(Uint8Array) --dict.wordsidxの内容(単語詳細インデックス)dictWords(Uint8Array) --dict.wordsの内容(単語詳細)matrixMtx(Uint8Array) --matrix.mtxの内容(連接コスト行列)charDef(Uint8Array) --char_def.binの内容(文字定義)unk(Uint8Array) --unk.binの内容(未知語辞書)
- 戻り値:
Dictionary
import { loadDictionaryFromBytes, TokenizerBuilder } from 'lindera-wasm-web';
import { loadDictionaryFiles } from 'lindera-wasm-web/opfs';
// OPFS から辞書ファイルを読み込む
const files = await loadDictionaryFiles("ipadic");
// バイトデータから Dictionary を作成
const dictionary = loadDictionaryFromBytes(
files.metadata,
files.dictDa,
files.dictVals,
files.dictWordsIdx,
files.dictWords,
files.matrixMtx,
files.charDef,
files.unk,
);
// TokenizerBuilder で使用
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
const tokenizer = builder.build();
ダウンロードとキャッシュを含む完全なワークフローは OPFS 辞書ストレージ を参照してください。
埋め込み辞書(上級者向け)
embed-* feature フラグ付きでビルドした場合、embedded:// URI スキームで埋め込み辞書を読み込めます。WASM バイナリのサイズが大幅に増加します。
埋め込み辞書の読み込み
import { loadDictionary } from 'lindera-wasm-web-ipadic';
const dictionary = loadDictionary("embedded://ipadic");
利用可能な埋め込み辞書の URI(ビルド時に有効にした feature に依存):
| URI | Feature フラグ |
|---|---|
embedded://ipadic | embed-ipadic |
embedded://unidic | embed-unidic |
embedded://ko-dic | embed-ko-dic |
embedded://cc-cedict | embed-cc-cedict |
embedded://jieba | embed-jieba |
TokenizerBuilder での使用
const builder = new TokenizerBuilder();
builder.setDictionary("embedded://ipadic");
builder.setMode("normal");
const tokenizer = builder.build();
Tokenizer コンストラクタでの使用
import { loadDictionary, Tokenizer } from 'lindera-wasm-web-ipadic';
const dictionary = loadDictionary("embedded://ipadic");
const tokenizer = new Tokenizer(dictionary, "normal");
Dictionary クラス
Dictionary クラスは、読み込み済みの形態素解析辞書を表します。
プロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
name | string | 辞書名(例: "ipadic") |
encoding | string | 辞書の文字エンコーディング |
metadata | Metadata | 完全なメタデータオブジェクト |
console.log(dictionary.name); // "ipadic"
console.log(dictionary.encoding); // "utf-8"
ユーザー辞書
ユーザー辞書を使用すると、システム辞書にないカスタム語彙を追加できます。
ユーザー辞書の読み込み
import { loadUserDictionary } from 'lindera-wasm-web';
const metadata = dictionary.metadata;
const userDict = loadUserDictionary("/path/to/user_dict.csv", metadata);
Tokenizer でのユーザー辞書の使用
import { loadDictionaryFromBytes, loadUserDictionary, Tokenizer } from 'lindera-wasm-web';
import { loadDictionaryFiles } from 'lindera-wasm-web/opfs';
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
const userDict = loadUserDictionary("/path/to/user_dict.csv", dictionary.metadata);
const tokenizer = new Tokenizer(dictionary, "normal", userDict);
ユーザー辞書の CSV フォーマット
ユーザー辞書の CSV は Lindera ユーザー辞書と同じフォーマットに準拠します:
東京スカイツリー,カスタム名詞,トウキョウスカイツリー
東武スカイツリーライン,カスタム名詞,トウブスカイツリーライン
各行の構成: surface,part_of_speech,reading
辞書のビルド
JavaScript API を使用してソースファイルからコンパイル済み辞書をビルドできます。
システム辞書のビルド
import { buildDictionary } from 'lindera-wasm-web';
const metadata = {
name: "custom-dict",
encoding: "utf-8",
// ... other metadata fields
};
buildDictionary("/path/to/source/dir", "/path/to/output/dir", metadata);
ユーザー辞書のビルド
import { buildUserDictionary } from 'lindera-wasm-web';
buildUserDictionary("/path/to/user_dict.csv", "/path/to/output/dir");
buildUserDictionary の metadata パラメータは省略可能です。省略した場合はデフォルトのメタデータが使用されます。
Metadata
Metadata クラスは辞書のパラメータを設定します。
コンストラクタ
const metadata = new Metadata(name?, encoding?);
- パラメータ:
name(string, 省略可) -- 辞書名(デフォルト:"default")encoding(string, 省略可) -- 文字エンコーディング(デフォルト:"UTF-8")
静的メソッド
Metadata.createDefault()
デフォルト値で Metadata インスタンスを作成します。
const metadata = Metadata.createDefault();
Metadata プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | "default" | 辞書名 |
encoding | string | "UTF-8" | 文字エンコーディング |
dictionary_schema | Schema | IPADIC スキーマ | メイン辞書のスキーマ |
user_dictionary_schema | Schema | 最小スキーマ | ユーザー辞書のスキーマ |
すべてのプロパティは取得と設定の両方に対応しています:
const metadata = Metadata.createDefault();
metadata.name = "custom_dict";
metadata.encoding = "EUC-JP";
console.log(metadata.name); // "custom_dict"
読み込み済み辞書のメタデータには dictionary.metadata からアクセスできます。
Schema
Schema クラスは辞書エントリのフィールド構造を定義します。
Schema コンストラクタ
const schema = new Schema(["surface", "left_id", "right_id", "cost", "pos", "reading"]);
Schema 静的メソッド
Schema.create_default()-- デフォルトの IPADIC 互換スキーマを作成
Schema メソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
get_field_index(name) | number | undefined | フィールド名からインデックスを取得 |
field_count() | number | フィールドの総数 |
get_field_name(index) | string | undefined | インデックスからフィールド名を取得 |
get_custom_fields() | string[] | インデックス 3 以降のフィールド(形態素素性) |
get_all_fields() | string[] | すべてのフィールド名 |
get_field_by_name(name) | FieldDefinition | undefined | フィールド定義の完全な情報を取得 |
FieldDefinition
| プロパティ | 型 | 説明 |
|---|---|---|
index | number | フィールドの位置インデックス |
name | string | フィールド名 |
field_type | FieldType | フィールド型の列挙値 |
description | string | undefined | 説明(省略可) |
FieldType
| 値 | 説明 |
|---|---|
FieldType.Surface | 単語の表層形テキスト |
FieldType.LeftContextId | 左文脈 ID |
FieldType.RightContextId | 右文脈 ID |
FieldType.Cost | 単語コスト |
FieldType.Custom | 形態素素性フィールド |
ブラウザでの使用
ES Module インポート
ブラウザ環境では、Lindera の関数を使用する前に WASM モジュールを初期化する必要があります。デフォルトエクスポートの __wbg_init がこの初期化を処理します。
推奨される方法は、辞書を WASM バイナリに埋め込むのではなく、OPFS から読み込むことです:
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from 'lindera-wasm-web';
import { downloadDictionary, loadDictionaryFiles, hasDictionary } from 'lindera-wasm-web/opfs';
async function main() {
// Initialize the WASM module (must be called once before using any API)
await __wbg_init();
// キャッシュされていない場合は辞書をダウンロード
if (!await hasDictionary("ipadic")) {
await downloadDictionary(
"https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip",
"ipadic",
);
}
// OPFS から辞書を読み込み
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("形態素解析を行います");
tokens.forEach(token => {
console.log(`${token.surface}: ${token.details.join(',')}`);
});
}
main();
埋め込み辞書の使用(上級者向け)
embed-* feature フラグ付きでビルドした場合、OPFS の代わりに埋め込み辞書を使用できます:
import __wbg_init, { TokenizerBuilder } from 'lindera-wasm-web-ipadic';
async function main() {
await __wbg_init();
const builder = new TokenizerBuilder();
builder.setDictionary("embedded://ipadic");
builder.setMode("normal");
const tokenizer = builder.build();
const tokens = tokenizer.tokenize("形態素解析を行います");
tokens.forEach(token => {
console.log(`${token.surface}: ${token.details.join(',')}`);
});
}
main();
HTML の例
OPFS 辞書ロードを使用した lindera-wasm の最小限の HTML ページ:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lindera WASM Demo</title>
</head>
<body>
<textarea id="input" rows="4" cols="50">関西国際空港限定トートバッグ</textarea>
<br>
<button id="tokenize" disabled>Tokenize</button>
<pre id="output">Loading dictionary...</pre>
<script type="module">
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from './pkg/lindera_wasm.js';
import { downloadDictionary, loadDictionaryFiles, hasDictionary } from './pkg/opfs.js';
let tokenizer;
async function init() {
await __wbg_init();
// キャッシュされていない場合は辞書をダウンロード
if (!await hasDictionary("ipadic")) {
document.getElementById('output').textContent = 'Downloading dictionary...';
await downloadDictionary(
"https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip",
"ipadic",
);
}
// OPFS から辞書を読み込み
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
tokenizer = builder.build();
document.getElementById('tokenize').disabled = false;
document.getElementById('output').textContent = 'Ready!';
}
document.getElementById('tokenize').addEventListener('click', () => {
const text = document.getElementById('input').value;
const tokens = tokenizer.tokenize(text);
const output = tokens.map(t =>
`${t.surface}\t${t.details.join(',')}`
).join('\n');
document.getElementById('output').textContent = output;
});
init();
</script>
</body>
</html>
Webpack の設定
Webpack 5 を使用する場合は、asyncWebAssembly experiment を有効にします:
// webpack.config.js
module.exports = {
experiments: {
asyncWebAssembly: true,
},
module: {
rules: [
{
test: /\.wasm$/,
type: "webassembly/async",
},
],
},
};
次に、bundler ターゲットビルドを使用してインポートします:
import { TokenizerBuilder, loadDictionaryFromBytes } from 'lindera-wasm-bundler';
import { loadDictionaryFiles } from 'lindera-wasm-bundler/opfs';
// OPFS から辞書を読み込み(セットアップは OPFS 辞書ストレージを参照)
const files = await loadDictionaryFiles("ipadic");
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
const tokenizer = builder.build();
bundler ターゲットでは、__wbg_init() はバンドラーによって自動的に呼び出されます。
Vite / Rollup のセットアップ
Vite は web ターゲットでの WASM をそのままサポートしています。ビルド済みの pkg/ ディレクトリをプロジェクトに配置し、直接インポートします:
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from './pkg/lindera_wasm.js';
import { loadDictionaryFiles } from './pkg/opfs.js';
await __wbg_init();
// OPFS から辞書を読み込み、上記のように TokenizerBuilder を使用
bundler ターゲットで Vite を使用する場合は、vite-plugin-wasm プラグインが必要になることがあります:
// vite.config.js
import wasm from 'vite-plugin-wasm';
export default {
plugins: [wasm()],
};
Chrome 拡張機能に関する注意事項
Manifest V3 を使用する Chrome 拡張機能では、デフォルトで WebAssembly.compile と WebAssembly.instantiate が制限されています。拡張機能で lindera-wasm を使用するには、Content Security Policy に wasm-unsafe-eval を追加する必要があります:
{
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
}
}
wasm-unsafe-eval は WebAssembly の実行のみを許可し、任意の JavaScript eval() は許可しません。
パフォーマンスのヒント
- 初期化は一度だけ:
__wbg_init()はアプリケーション起動時に一度だけ呼び出し、トークナイズリクエストごとには呼び出さないでください。 - トークナイザーの再利用:
Tokenizerインスタンスは一度作成し、複数のtokenize()呼び出しで再利用してください。 - Web Workers: 大量のトークナイズ処理を行う場合は、メインスレッドのブロックを避けるため、Web Worker での Lindera の実行を検討してください。
OPFS 辞書ストレージ
Lindera WASM は、Web ブラウザでの辞書の永続キャッシュのために OPFS(Origin Private File System)ヘルパーユーティリティを提供します。辞書を一度ダウンロードすれば、WASM バイナリに埋め込むことなく、セッションをまたいで再利用できます。
概要
OPFS ヘルパーは、WASM パッケージとともに別の JavaScript モジュール(opfs.js)として配布されます。ブラウザの Origin Private File System を使用して、辞書のダウンロード、保存、読み込み、管理を行う関数を提供します。
辞書は OPFS パス lindera/dictionaries/<name>/ に保存されます。
インポート
import { downloadDictionary, loadDictionaryFiles, removeDictionary,
listDictionaries, hasDictionary } from 'lindera-wasm-web/opfs';
関数
downloadDictionary(url, name, options?)
辞書の zip アーカイブをダウンロードし、展開して、ファイルを OPFS に保存します。
アーカイブは、必要な 8 つの辞書ファイルを含む zip ファイルである必要があります。サブディレクトリにネストされていても構いません。
- 引数:
url(string) -- 辞書 zip アーカイブの URLname(string) -- 辞書の保存名(例:"ipadic")options(object, 省略可):onProgress(function) -- 進捗コールバック
- 戻り値:
Promise<void>
await downloadDictionary(
"https://example.com/ipadic.zip",
"ipadic",
{
onProgress: (progress) => {
switch (progress.phase) {
case "downloading":
console.log(`Downloading: ${progress.loaded}/${progress.total} bytes`);
break;
case "extracting":
console.log("Extracting archive...");
break;
case "storing":
console.log("Storing in OPFS...");
break;
case "complete":
console.log("Done!");
break;
}
},
},
);
進捗コールバック
onProgress コールバックは以下の形式のオブジェクトを受け取ります:
| プロパティ | 型 | 説明 |
|---|---|---|
phase | string | "downloading"、"extracting"、"storing"、または "complete" |
loaded | number | undefined | ダウンロード済みバイト数("downloading" フェーズのみ) |
total | number | undefined | 合計バイト数(判明している場合、"downloading" フェーズのみ) |
loadDictionaryFiles(name)
OPFS から辞書ファイルを Uint8Array 値のオブジェクトとして読み込みます。
返されたオブジェクトは loadDictionaryFromBytes() にそのまま渡すことができます。
- 引数:
name(string) -- 辞書名(例:"ipadic") - 戻り値:
Promise<DictionaryFiles>
const files = await loadDictionaryFiles("ipadic");
DictionaryFiles
| プロパティ | 型 | ソースファイル |
|---|---|---|
metadata | Uint8Array | metadata.json |
dictDa | Uint8Array | dict.da(Double-Array Trie) |
dictVals | Uint8Array | dict.vals(単語値データ) |
dictWordsIdx | Uint8Array | dict.wordsidx(単語詳細インデックス) |
dictWords | Uint8Array | dict.words(単語詳細) |
matrixMtx | Uint8Array | matrix.mtx(連接コスト行列) |
charDef | Uint8Array | char_def.bin(文字定義) |
unk | Uint8Array | unk.bin(未知語辞書) |
removeDictionary(name)
OPFS から辞書を削除します。
- 引数:
name(string) -- 削除する辞書名 - 戻り値:
Promise<void>
await removeDictionary("ipadic");
listDictionaries()
OPFS に保存されているすべての辞書を一覧表示します。
- 戻り値:
Promise<string[]>-- 辞書名の配列
const names = await listDictionaries();
console.log(names); // 例: ["ipadic", "unidic"]
hasDictionary(name)
OPFS に辞書が存在するかどうかを確認します。
- 引数:
name(string) -- 確認する辞書名 - 戻り値:
Promise<boolean>
if (await hasDictionary("ipadic")) {
console.log("Dictionary is cached");
}
完全なワークフロー
OPFS ベースの辞書を使用する一般的なワークフロー:
import __wbg_init, { TokenizerBuilder, loadDictionaryFromBytes } from 'lindera-wasm-web';
import { downloadDictionary, loadDictionaryFiles, hasDictionary } from 'lindera-wasm-web/opfs';
async function main() {
await __wbg_init();
const DICT_NAME = "ipadic";
const DICT_URL = "https://github.com/lindera/lindera/releases/download/<version>/lindera-ipadic-<version>.zip";
// キャッシュされていない場合は辞書をダウンロード
if (!await hasDictionary(DICT_NAME)) {
await downloadDictionary(DICT_URL, DICT_NAME, {
onProgress: ({ phase, loaded, total }) => {
if (phase === "downloading" && total) {
console.log(`${(loaded / total * 100).toFixed(1)}%`);
}
},
});
}
// OPFS から辞書を読み込み
const files = await loadDictionaryFiles(DICT_NAME);
const dictionary = loadDictionaryFromBytes(
files.metadata, files.dictDa, files.dictVals, files.dictWordsIdx,
files.dictWords, files.matrixMtx, files.charDef, files.unk,
);
// トークナイザーを構築
const builder = new TokenizerBuilder();
builder.setDictionaryInstance(dictionary);
builder.setMode("normal");
const tokenizer = builder.build();
// トークナイズ
const tokens = tokenizer.tokenize("形態素解析を行います");
tokens.forEach(token => {
console.log(`${token.surface}\t${token.details.join(',')}`);
});
}
main();
必要な辞書ファイル
有効な辞書アーカイブには以下の 8 ファイルが含まれている必要があります:
| ファイル | 説明 |
|---|---|
metadata.json | 辞書メタデータ(名前、エンコーディング、スキーマなど) |
dict.da | Double-Array Trie 構造 |
dict.vals | 単語値データ |
dict.wordsidx | 単語詳細インデックス |
dict.words | 単語詳細(形態素素性) |
matrix.mtx | 連接コスト行列 |
char_def.bin | 文字カテゴリ定義 |
unk.bin | 未知語辞書 |
ブラウザ互換性
OPFS は安全なコンテキスト(HTTPS または localhost)が必要で、以下のブラウザでサポートされています:
- Chrome 86+
- Edge 86+
- Firefox 111+
- Safari 15.2+
zip の展開には DecompressionStream API を使用しており、以下が必要です:
- Chrome 80+
- Edge 80+
- Firefox 113+
- Safari 16.4+
Lindera IPADIC
Lindera IPADIC は、IPADIC に基づく日本語辞書クレートです。IPADIC は、日本語の形態素解析で最も広く使われている辞書です。
目次
API リファレンス
Lindera IPADIC
辞書バージョン
このリポジトリには mecab-ipadic が含まれています。
辞書フォーマット
IPADIC の辞書フォーマットおよび品詞タグの詳細については、マニュアルを参照してください。
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞 | Part-of-speech | |
| 5 | 品詞細分類1 | Part-of-speech subcategory 1 | |
| 6 | 品詞細分類2 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類3 | Part-of-speech subcategory 3 | |
| 8 | 活用形 | Conjugation form | |
| 9 | 活用型 | Conjugation type | |
| 10 | 原形 | Base form | |
| 11 | 読み | Reading | |
| 12 | 発音 | Pronunciation |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 品詞 | Part-of-speech | |
| 2 | 読み | Reading |
詳細版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞 | Part-of-speech | |
| 5 | 品詞細分類1 | Part-of-speech subcategory 1 | |
| 6 | 品詞細分類2 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類3 | Part-of-speech subcategory 3 | |
| 8 | 活用形 | Conjugation form | |
| 9 | 活用型 | Conjugation type | |
| 10 | 原形 | Base form | |
| 11 | 読み | Reading | |
| 12 | 発音 | Pronunciation | |
| 13 | - | - | 13 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
このページでは、ソースファイルから IPADIC 辞書をビルドする方法を説明します。
システム辞書のビルド
IPADIC のソースファイルをダウンロードし、辞書をビルドします:
# IPADIC ソースファイルのダウンロードと展開
% curl -L -o /tmp/mecab-ipadic-2.7.0-20250920.tar.gz "https://Lindera.dev/mecab-ipadic-2.7.0-20250920.tar.gz"
% tar zxvf /tmp/mecab-ipadic-2.7.0-20250920.tar.gz -C /tmp
# 辞書のビルド
% lindera build \
--src /tmp/mecab-ipadic-2.7.0-20250920 \
--dest /tmp/lindera-ipadic-2.7.0-20250920 \
--metadata ./lindera-ipadic/metadata.json
ユーザー辞書のビルド
CSV ファイルからユーザー辞書をビルドします:
% lindera build \
--src ./resources/user_dict/ipadic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-ipadic/metadata.json \
--user
ユーザー辞書フォーマットの詳細については、辞書フォーマットを参照してください。
バイナリへの埋め込み
IPADIC 辞書をバイナリに直接埋め込むには、以下のようにビルドします:
cargo build --features=embed-ipadic
これにより、外部辞書ファイルなしで embedded://ipadic を辞書パスとして使用できるようになります。
使用例
このページでは、IPADIC 辞書を使用したトークナイズの例を示します。
外部 IPADIC でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-ipadic-2.7.0-20250920
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素 名詞,一般,*,*,*,*,形態素,ケイタイソ,ケイタイソ
解析 名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
埋め込み IPADIC でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素 名詞,一般,*,*,*,*,形態素,ケイタイソ,ケイタイソ
解析 名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
注意: IPADIC 辞書をバイナリに含めるには、--features=embed-ipadic オプションを付けてビルドする必要があります。
ユーザー辞書を使用したトークナイズ (CSV フォーマット)
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict embedded://ipadic \
--user-dict ./resources/user_dict/ipadic_simple_userdic.csv
東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
の 助詞,連体化,*,*,*,*,の,ノ,ノ
最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
ユーザー辞書を使用したトークナイズ (バイナリフォーマット)
% echo "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です" | lindera tokenize \
--dict /tmp/lindera-ipadic-2.7.0-20250920 \
--user-dict ./resources/user_dict/ipadic_simple_userdic.bin
東京スカイツリー カスタム名詞,*,*,*,*,*,東京スカイツリー,トウキョウスカイツリー,*
の 助詞,連体化,*,*,*,*,の,ノ,ノ
最寄り駅 名詞,一般,*,*,*,*,最寄り駅,モヨリエキ,モヨリエキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
とうきょうスカイツリー駅 カスタム名詞,*,*,*,*,*,とうきょうスカイツリー駅,トウキョウスカイツリーエキ,*
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "日本語の形態素解析を行うことができます。"; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Lindera IPADIC NEologd
Lindera IPADIC NEologd は、新語を含む IPADIC NEologd に基づく日本語辞書クレートです。標準の IPADIC 辞書を拡張し、最新の用語や固有名詞を追加した語彙を提供します。
目次
API リファレンス
Lindera IPADIC NEologd
辞書バージョン
このリポジトリには mecab-ipadic-neologd が含まれています。
辞書フォーマット
IPADIC の辞書フォーマットおよび品詞タグの詳細については、マニュアルを参照してください。
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞 | Part-of-speech | |
| 5 | 品詞細分類1 | Part-of-speech subcategory 1 | |
| 6 | 品詞細分類2 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類3 | Part-of-speech subcategory 3 | |
| 8 | 活用形 | Conjugation form | |
| 9 | 活用型 | Conjugation type | |
| 10 | 原形 | Base form | |
| 11 | 読み | Reading | |
| 12 | 発音 | Pronunciation |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 品詞 | Part-of-speech | |
| 2 | 読み | Reading |
詳細版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞 | Part-of-speech | |
| 5 | 品詞細分類1 | Part-of-speech subcategory 1 | |
| 6 | 品詞細分類2 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類3 | Part-of-speech subcategory 3 | |
| 8 | 活用形 | Conjugation form | |
| 9 | 活用型 | Conjugation type | |
| 10 | 原形 | Base form | |
| 11 | 読み | Reading | |
| 12 | 発音 | Pronunciation | |
| 13 | - | - | 13 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
このページでは、ソースファイルから IPADIC NEologd 辞書をビルドする方法を説明します。
システム辞書のビルド
IPADIC NEologd のソースファイルをダウンロードし、辞書をビルドします:
% curl -L -o /tmp/mecab-ipadic-neologd-0.0.7-20200820.tar.gz "https://lindera.dev/mecab-ipadic-neologd-0.0.7-20200820.tar.gz"
% tar zxvf /tmp/mecab-ipadic-neologd-0.0.7-20200820.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-ipadic-neologd-0.0.7-20200820 \
--dest /tmp/lindera-ipadic-neologd-0.0.7-20200820 \
--metadata ./lindera-ipadic-neologd/metadata.json
バイナリへの埋め込み
IPADIC NEologd 辞書をバイナリに直接埋め込むには、以下のようにビルドします:
cargo build --features=embed-ipadic-neologd
これにより、外部辞書ファイルなしで embedded://ipadic-neologd を辞書パスとして使用できるようになります。
使用例
このページでは、IPADIC NEologd 辞書を使用したトークナイズの例を示します。
外部 IPADIC NEologd でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-ipadic-neologd-0.0.7-20200820
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素解析 名詞,固有名詞,一般,*,*,*,形態素解析,ケイタイソカイセキ,ケイタイソカイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
NEologd では「形態素解析」が単一の複合名詞として扱われますが、標準の IPADIC では「形態素」と「解析」に分割されます。
埋め込み IPADIC NEologd でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://ipadic-neologd
日本語 名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
形態素解析 名詞,固有名詞,一般,*,*,*,形態素解析,ケイタイソカイセキ,ケイタイソカイセキ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
行う 動詞,自立,*,*,五段・ワ行促音便,基本形,行う,オコナウ,オコナウ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
でき 動詞,自立,*,*,一段,連用形,できる,デキ,デキ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
EOS
注意: IPADIC NEologd 辞書をバイナリに含めるには、--features=embed-ipadic-neologd オプションを付けてビルドする必要があります。
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ipadic-neologd")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "日本語の形態素解析を行うことができます。"; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Lindera UniDic
Lindera UniDic は、統一的な単語単位の定義を使用する UniDic に基づく日本語辞書クレートです。UniDic は IPADIC よりも詳細な形態素情報を提供し、1エントリあたり 21 フィールドを持ちます。
目次
API リファレンス
Lindera UniDic
辞書バージョン
このリポジトリには unidic-mecab が含まれています。
辞書フォーマット
unidic-mecab の辞書フォーマットおよび品詞タグの詳細については、マニュアルを参照してください。
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞大分類 | Part-of-speech | |
| 5 | 品詞中分類 | Part-of-speech subcategory 1 | |
| 6 | 品詞小分類 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類 | Part-of-speech subcategory 3 | |
| 8 | 活用型 | Conjugation type | |
| 9 | 活用形 | Conjugation form | |
| 10 | 語彙素読み | Reading | |
| 11 | 語彙素(語彙素表記 + 語彙素細分類) | Lexeme | |
| 12 | 書字形出現形 | Orthographic surface form | |
| 13 | 発音形出現形 | Phonological surface form | |
| 14 | 書字形基本形 | Orthographic base form | |
| 15 | 発音形基本形 | Phonological base form | |
| 16 | 語種 | Word type | |
| 17 | 語頭変化型 | Initial mutation type | |
| 18 | 語頭変化形 | Initial mutation form | |
| 19 | 語末変化型 | Final mutation type | |
| 20 | 語末変化形 | Final mutation form |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 品詞大分類 | Part-of-speech | |
| 2 | 語彙素読み | Reading |
詳細版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表層形 | Surface | |
| 1 | 左文脈ID | Left context ID | |
| 2 | 右文脈ID | Right context ID | |
| 3 | コスト | Cost | |
| 4 | 品詞大分類 | Part-of-speech | |
| 5 | 品詞中分類 | Part-of-speech subcategory 1 | |
| 6 | 品詞小分類 | Part-of-speech subcategory 2 | |
| 7 | 品詞細分類 | Part-of-speech subcategory 3 | |
| 8 | 活用型 | Conjugation type | |
| 9 | 活用形 | Conjugation form | |
| 10 | 語彙素読み | Reading | |
| 11 | 語彙素(語彙素表記 + 語彙素細分類) | Lexeme | |
| 12 | 書字形出現形 | Orthographic surface form | |
| 13 | 発音形出現形 | Phonological surface form | |
| 14 | 書字形基本形 | Orthographic base form | |
| 15 | 発音形基本形 | Phonological base form | |
| 16 | 語種 | Word type | |
| 17 | 語頭変化型 | Initial mutation type | |
| 18 | 語頭変化形 | Initial mutation form | |
| 19 | 語末変化型 | Final mutation type | |
| 20 | 語末変化形 | Final mutation form | |
| 21 | - | - | 21 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
このページでは、ソースファイルから UniDic 辞書をビルドする方法を説明します。
システム辞書のビルド
UniDic のソースファイルをダウンロードし、辞書をビルドします:
% curl -L -o /tmp/unidic-mecab-2.1.2.tar.gz "https://Lindera.dev/unidic-mecab-2.1.2.tar.gz"
% tar zxvf /tmp/unidic-mecab-2.1.2.tar.gz -C /tmp
% lindera build \
--src /tmp/unidic-mecab-2.1.2 \
--dest /tmp/lindera-unidic-2.1.2 \
--metadata ./lindera-unidic/metadata.json
ユーザー辞書のビルド
CSV ファイルからユーザー辞書をビルドします:
% lindera build \
--src ./resources/user_dict/unidic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-unidic/metadata.json \
--user
ユーザー辞書フォーマットの詳細については、辞書フォーマットを参照してください。
バイナリへの埋め込み
UniDic 辞書をバイナリに直接埋め込むには、以下のようにビルドします:
cargo build --features=embed-unidic
これにより、外部辞書ファイルなしで embedded://unidic を辞書パスとして使用できるようになります。
使用例
このページでは、UniDic 辞書を使用したトークナイズの例を示します。
外部 UniDic でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict /tmp/lindera-unidic-2.1.2
日本 名詞,固有名詞,地名,国,*,*,ニッポン,日本,日本,ニッポン,日本,ニッポン,固,*,*,*,*
語 名詞,普通名詞,一般,*,*,*,ゴ,語,語,ゴ,語,ゴ,漢,*,*,*,*
の 助詞,格助詞,*,*,*,*,ノ,の,の,ノ,の,ノ,和,*,*,*,*
形態 名詞,普通名詞,一般,*,*,*,ケイタイ,形態,形態,ケータイ,形態,ケータイ,漢,*,*,*,*
素 接尾辞,名詞的,一般,*,*,*,ソ,素,素,ソ,素,ソ,漢,*,*,*,*
解析 名詞,普通名詞,サ変可能,*,*,*,カイセキ,解析,解析,カイセキ,解析,カイセキ,漢,*,*,*,*
を 助詞,格助詞,*,*,*,*,ヲ,を,を,オ,を,オ,和,*,*,*,*
行う 動詞,一般,*,*,五段-ワア行,連体形-一般,オコナウ,行う,行う,オコナウ,行う,オコナウ,和,*,*,*,*
こと 名詞,普通名詞,一般,*,*,*,コト,事,こと,コト,こと,コト,和,コ濁,基本形,*,*
が 助詞,格助詞,*,*,*,*,ガ,が,が,ガ,が,ガ,和,*,*,*,*
でき 動詞,非自立可能,*,*,上一段-カ行,連用形-一般,デキル,出来る,でき,デキ,できる,デキル,和,*,*,*,*
ます 助動詞,*,*,*,助動詞-マス,終止形-一般,マス,ます,ます,マス,ます,マス,和,*,*,*,*
。 補助記号,句点,*,*,*,*,,。,。,,。,,記号,*,*,*,*
EOS
UniDic では「日本語」が「日本」と「語」に、「形態素」が「形態」と「素」に分割されます。これは UniDic の統一的な単語単位の定義を反映しています。
埋め込み UniDic でトークナイズ
% echo "日本語の形態素解析を行うことができます。" | lindera tokenize \
--dict embedded://unidic
日本 名詞,固有名詞,地名,国,*,*,ニッポン,日本,日本,ニッポン,日本,ニッポン,固,*,*,*,*
語 名詞,普通名詞,一般,*,*,*,ゴ,語,語,ゴ,語,ゴ,漢,*,*,*,*
の 助詞,格助詞,*,*,*,*,ノ,の,の,ノ,の,ノ,和,*,*,*,*
形態 名詞,普通名詞,一般,*,*,*,ケイタイ,形態,形態,ケータイ,形態,ケータイ,漢,*,*,*,*
素 接尾辞,名詞的,一般,*,*,*,ソ,素,素,ソ,素,ソ,漢,*,*,*,*
解析 名詞,普通名詞,サ変可能,*,*,*,カイセキ,解析,解析,カイセキ,解析,カイセキ,漢,*,*,*,*
を 助詞,格助詞,*,*,*,*,ヲ,を,を,オ,を,オ,和,*,*,*,*
行う 動詞,一般,*,*,五段-ワア行,連体形-一般,オコナウ,行う,行う,オコナウ,行う,オコナウ,和,*,*,*,*
こと 名詞,普通名詞,一般,*,*,*,コト,事,こと,コト,こと,コト,和,コ濁,基本形,*,*
が 助詞,格助詞,*,*,*,*,ガ,が,が,ガ,が,ガ,和,*,*,*,*
でき 動詞,非自立可能,*,*,上一段-カ行,連用形-一般,デキル,出来る,でき,デキ,できる,デキル,和,*,*,*,*
ます 助動詞,*,*,*,助動詞-マス,終止形-一般,マス,ます,ます,マス,ます,マス,和,*,*,*,*
。 補助記号,句点,*,*,*,*,,。,。,,。,,記号,*,*,*,*
EOS
注意: UniDic 辞書をバイナリに含めるには、--features=embed-unidic オプションを付けてビルドする必要があります。
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://unidic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "日本語の形態素解析を行うことができます。"; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Lindera ko-dic
Lindera ko-dic は、mecab-ko-dic に基づく韓国語辞書クレートです。
目次
API リファレンス
Lindera ko-dic
辞書バージョン
このリポジトリには mecab-ko-dic が含まれています。
辞書フォーマット
mecab-ko-dic で使用される辞書フォーマットおよび品詞タグの情報は、mecab-ko-dic のリポジトリ README からリンクされているこの Google スプレッドシートに記載されています。
ko-dic は NAIST JDIC よりもフィールド列が 1 つ少なく、全体的に異なる情報セットを持っています(例: 単語の「原形」を提供しません)。
タグは世宗(Sejong)で規定されたものを若干修正したものです。世宗から mecab-ko-dic のタグ名へのマッピングは、上記スプレッドシートの 태그 v2.0 タブに記載されています。
辞書フォーマットの完全な仕様は(韓国語で)スプレッドシートの 사전 형식 v2.0 タブに記載されています。空の値はデフォルトで * になります。
| Index | Name (Korean) | Name (English) | Notes |
|---|---|---|---|
| 0 | 표면 | Surface | |
| 1 | 왼쪽 문맥 ID | Left context ID | |
| 2 | 오른쪽 문맥 ID | Right context ID | |
| 3 | 비용 | Cost | |
| 4 | 품사 태그 | Part-of-speech tag | スプレッドシートの 태그 v2.0 タブを参照 |
| 5 | 의미 부류 | Meaning | (確信するには例が少なすぎます) |
| 6 | 종성 유무 | Presence or absence | T は true、F は false、それ以外は * |
| 7 | 읽기 | Reading | 通常は表層形と一致しますが、外来語(例: 漢字語)では異なる場合があります |
| 8 | 타입 | Type | Inflect(活用)、Compound(複合名詞)、Preanalysis(基分析)のいずれか |
| 9 | 첫번째 품사 | First part-of-speech | 例: 品詞タグが "VV+EM+VX+EP" の場合、VV を返します |
| 10 | 마지막 품사 | Last part-of-speech | 例: 品詞タグが "VV+EM+VX+EP" の場合、EP を返します |
| 11 | 표현 | Expression | 활용, 복합명사, 기분석이 어떻게 구성되는지 알려주는 필드 -- 活用、複合名詞、基分析がどのように構成されるかを示すフィールド |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 표면 | Surface | |
| 1 | 품사 태그 | part-of-speech tag | スプレッドシートの 태그 v2.0 タブを参照 |
| 2 | 읽기 | reading | 通常は表層形と一致しますが、外来語(例: 漢字語)では異なる場合があります |
詳細版
| Index | Name (Korean) | Name (English) | Notes |
|---|---|---|---|
| 0 | 표면 | Surface | |
| 1 | 왼쪽 문맥 ID | Left context ID | |
| 2 | 오른쪽 문맥 ID | Right context ID | |
| 3 | 비용 | Cost | |
| 4 | 품사 태그 | part-of-speech tag | スプレッドシートの 태그 v2.0 タブを参照 |
| 5 | 의미 부류 | meaning | (確信するには例が少なすぎます) |
| 6 | 종성 유무 | presence or absence | T は true、F は false、それ以外は * |
| 7 | 읽기 | reading | 通常は表層形と一致しますが、外来語(例: 漢字語)では異なる場合があります |
| 8 | 타입 | type | Inflect(活用)、Compound(複合名詞)、Preanalysis(基分析)のいずれか |
| 9 | 첫번째 품사 | first part-of-speech | 例: 品詞タグが "VV+EM+VX+EP" の場合、VV を返します |
| 10 | 마지막 품사 | last part-of-speech | 例: 品詞タグが "VV+EM+VX+EP" の場合、EP を返します |
| 11 | 표현 | expression | 활용, 복합명사, 기분석이 어떻게 구성되는지 알려주는 필드 -- 活用、複合名詞、基分析がどのように構成されるかを示すフィールド |
| 12 | - | - | 12 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
システム辞書のビルド
mecab-ko-dic のソースファイルをダウンロード・展開し、辞書をビルドします:
% curl -L -o /tmp/mecab-ko-dic-2.1.1-20180720.tar.gz "https://Lindera.dev/mecab-ko-dic-2.1.1-20180720.tar.gz"
% tar zxvf /tmp/mecab-ko-dic-2.1.1-20180720.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-ko-dic-2.1.1-20180720 \
--dest /tmp/lindera-ko-dic-2.1.1-20180720 \
--metadata ./lindera-ko-dic/metadata.json
ユーザー辞書のビルド
% lindera build \
--src ./resources/user_dict/ko-dic_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-ko-dic/metadata.json \
--user
辞書の埋め込み
ko-dic 辞書をバイナリに直接埋め込むには、以下の feature フラグを付けてビルドします:
% cargo build --features=embed-ko-dic
使用例
外部 ko-dic でトークナイズ
% echo "한국어의형태해석을실시할수있습니다." | lindera tokenize \
--dict /tmp/lindera-ko-dic-2.1.1-20180720
한국어 NNG,*,F,한국어,Compound,*,*,한국/NNG/*+어/NNG/*
의 JKG,*,F,의,*,*,*,*
형태 NNG,*,F,형태,*,*,*,*
해석 NNG,행위,T,해석,*,*,*,*
을 JKO,*,T,을,*,*,*,*
실시 NNG,행위,F,실시,*,*,*,*
할 XSV+ETM,*,T,할,Inflect,XSV,ETM,하/XSV/*+ᆯ/ETM/*
수 NNB,*,F,수,*,*,*,*
있 VV,*,T,있,*,*,*,*
습니다 EF,*,F,습니다,*,*,*,*
. SF,*,*,*,*,*,*,*
EOS
埋め込み ko-dic でトークナイズ
% echo "한국어의형태해석을실시할수있습니다." | lindera tokenize \
--dict embedded://ko-dic
한국어 NNG,*,F,한국어,Compound,*,*,한국/NNG/*+어/NNG/*
의 JKG,*,F,의,*,*,*,*
형태 NNG,*,F,형태,*,*,*,*
해석 NNG,행위,T,해석,*,*,*,*
을 JKO,*,T,을,*,*,*,*
실시 NNG,행위,F,실시,*,*,*,*
할 XSV+ETM,*,T,할,Inflect,XSV,ETM,하/XSV/*+ᆯ/ETM/*
수 NNB,*,F,수,*,*,*,*
있 VV,*,T,있,*,*,*,*
습니다 EF,*,F,습니다,*,*,*,*
. SF,*,*,*,*,*,*,*
EOS
注意: ko-dic 辞書をバイナリに含めるには、--features=embed-ko-dic オプションを付けてビルドする必要があります。
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://ko-dic")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "한국어의형태해석을실시할수있습니다."; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Lindera CC-CEDICT
Lindera CC-CEDICT は、CC-CEDICT-MeCab に基づく中国語辞書クレートです。
目次
API リファレンス
Lindera CC-CE-DICT
辞書バージョン
このリポジトリには CC-CEDICT-MeCab が含まれています。
辞書フォーマット
unidic-mecab の辞書フォーマットおよび品詞タグの詳細については、マニュアルを参照してください。
| Index | Name (Chinese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 左语境ID | Left context ID | |
| 2 | 右语境ID | Right context ID | |
| 3 | 成本 | Cost | |
| 4 | 词类 | Part-of-speech | |
| 5 | 词类1 | Part-of-speech subcategory 1 | |
| 6 | 词类2 | Part-of-speech subcategory 2 | |
| 7 | 词类3 | Part-of-speech subcategory 3 | |
| 8 | 併音 | Pinyin | |
| 9 | 繁体字 | Traditional | |
| 10 | 簡体字 | Simplified | |
| 11 | 定义 | Definition |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 词类 | Part-of-speech | |
| 2 | 併音 | Pinyin |
詳細版
| Index | Name (Japanese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 左语境ID | Left context ID | |
| 2 | 右语境ID | Right context ID | |
| 3 | 成本 | Cost | |
| 4 | 词类 | Part-of-speech | |
| 5 | 词类1 | Part-of-speech subcategory 1 | |
| 6 | 词类2 | Part-of-speech subcategory 2 | |
| 7 | 词类3 | Part-of-speech subcategory 3 | |
| 8 | 併音 | Pinyin | |
| 9 | 繁体字 | Traditional | |
| 10 | 簡体字 | Simplified | |
| 11 | 定义 | Definition | |
| 12 | - | - | 12 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
システム辞書のビルド
CC-CEDICT-MeCab のソースファイルをダウンロード・展開し、辞書をビルドします:
% curl -L -o /tmp/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz "https://lindera.dev/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz"
% tar zxvf /tmp/CC-CEDICT-MeCab-0.1.0-20200409.tar.gz -C /tmp
% lindera build \
--src /tmp/CC-CEDICT-MeCab-0.1.0-20200409 \
--dest /tmp/lindera-cc-cedict-0.1.0-20200409 \
--metadata ./lindera-cc-cedict/metadata.json
ユーザー辞書のビルド
% lindera build \
--src ./resources/user_dict/cc-cedict_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-cc-cedict/metadata.json \
--user
辞書の埋め込み
CC-CEDICT 辞書をバイナリに直接埋め込むには、以下の feature フラグを付けてビルドします:
% cargo build --features=embed-cc-cedict
使用例
外部 CC-CEDICT でトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict /tmp/lindera-cc-cedict-0.1.0-20200409
可以 *,*,*,*,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good/
进行 *,*,*,*,jin4 xing2,進行,进行,to advance/to conduct/underway/in progress/to do/to carry out/to carry on/to execute/
中文 *,*,*,*,Zhong1 wen2,中文,中文,Chinese language/
形态学 *,*,*,*,xing2 tai4 xue2,形態學,形态学,morphology (in biology or linguistics)/
分析 *,*,*,*,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4]/
。 *,*,*,*,*,*,*,*
EOS
埋め込み CC-CEDICT でトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict embedded://cc-cedict
可以 *,*,*,*,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good/
进行 *,*,*,*,jin4 xing2,進行,进行,to advance/to conduct/underway/in progress/to do/to carry out/to carry on/to execute/
中文 *,*,*,*,Zhong1 wen2,中文,中文,Chinese language/
形态学 *,*,*,*,xing2 tai4 xue2,形態學,形态学,morphology (in biology or linguistics)/
分析 *,*,*,*,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4]/
。 *,*,*,*,*,*,*,*
EOS
注意: CC-CEDICT 辞書をバイナリに含めるには、--features=embed-cc-cedict オプションを付けてビルドする必要があります。
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://cc-cedict")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "可以进行中文形态学分析。"; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
Lindera Jieba
Lindera Jieba は、mecab-jieba に基づく中国語辞書クレートです。
目次
API リファレンス
Lindera Jieba
辞書バージョン
このリポジトリには mecab-jieba が含まれています。
辞書フォーマット
| Index | Name (Chinese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 左语境ID | Left context ID | |
| 2 | 右语境ID | Right context ID | |
| 3 | 成本 | Cost | |
| 4 | 词类 | Part-of-speech | |
| 5 | 併音 | Pinyin | |
| 6 | 繁体字 | Traditional | |
| 7 | 簡体字 | Simplified | |
| 8 | 定义 | Definition |
ユーザー辞書フォーマット (CSV)
簡易版
| Index | Name (Chinese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 词类 | Part-of-speech | |
| 2 | 併音 | Pinyin |
詳細版
| Index | Name (Chinese) | Name (English) | Notes |
|---|---|---|---|
| 0 | 表面形式 | Surface | |
| 1 | 左语境ID | Left context ID | |
| 2 | 右语境ID | Right context ID | |
| 3 | 成本 | Cost | |
| 4 | 词类 | Part-of-speech | |
| 5 | 併音 | Pinyin | |
| 6 | 繁体字 | Traditional | |
| 7 | 簡体字 | Simplified | |
| 8 | 定义 | Definition | |
| 9 | - | - | 9 以降は自由に拡張可能です。 |
API リファレンス
API リファレンスは以下の URL から参照できます:
ビルド
システム辞書のビルド
mecab-jieba のソースファイルをダウンロード・展開し、辞書をビルドします:
% curl -L -o /tmp/mecab-jieba-0.1.1.tar.gz "https://lindera.dev/mecab-jieba-0.1.1.tar.gz"
% tar zxvf /tmp/mecab-jieba-0.1.1.tar.gz -C /tmp
% lindera build \
--src /tmp/mecab-jieba-0.1.1/dict-src \
--dest /tmp/lindera-jieba-0.1.1 \
--metadata ./lindera-jieba/metadata.json
ユーザー辞書のビルド
% lindera build \
--src ./resources/user_dict/jieba_simple_userdic.csv \
--dest ./resources/user_dict \
--metadata ./lindera-jieba/metadata.json \
--user
辞書の埋め込み
Jieba 辞書をバイナリに直接埋め込むには、以下の feature フラグを付けてビルドします:
% cargo build --features=embed-jieba
使用例
外部 Jieba でトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict /tmp/lindera-jieba-0.1.1
可以 c,CHINESE,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good,2,可,以,high
进行 v,CHINESE,jin4 xing2,進行,进行,(of a process etc) to proceed; to be in progress; to be underway/(of people) to carry out; to conduct (an investigation or discussion etc)/(of an army etc) to be on the march; to advance,2,进,行,high
中文 nz,CHINESE,Zhong1 wen2,中文,中文,Chinese language,2,中,文,high
形态 n,CHINESE,xing2 tai4,形態,形态,shape/form/pattern/morphology,2,形,态,high
学 n,CHINESE,xue2,學,学,to learn/to study/to imitate/science/-ology,1,学,学,high
分析 vn,CHINESE,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4],2,分,析,high
。 w,*,*,*,*,*,*,*,*,*
EOS
埋め込み Jieba でトークナイズ
% echo "可以进行中文形态学分析。" | lindera tokenize \
--dict embedded://jieba
可以 c,CHINESE,ke3 yi3,可以,可以,can/may/possible/able to/not bad/pretty good,2,可,以,high
进行 v,CHINESE,jin4 xing2,進行,进行,(of a process etc) to proceed; to be in progress; to be underway/(of people) to carry out; to conduct (an investigation or discussion etc)/(of an army etc) to be on the march; to advance,2,进,行,high
中文 nz,CHINESE,Zhong1 wen2,中文,中文,Chinese language,2,中,文,high
形态 n,CHINESE,xing2 tai4,形態,形态,shape/form/pattern/morphology,2,形,态,high
学 n,CHINESE,xue2,學,学,to learn/to study/to imitate/science/-ology,1,学,学,high
分析 vn,CHINESE,fen1 xi1,分析,分析,to analyze/analysis/CL:個|个[ge4],2,分,析,high
。 w,*,*,*,*,*,*,*,*,*
EOS
注意: Jieba 辞書をバイナリに含めるには、--features=embed-jieba オプションを付けてビルドする必要があります。
Rust API の使用例
use lindera::dictionary::load_dictionary; use lindera::mode::Mode; use lindera::segmenter::Segmenter; use lindera::tokenizer::Tokenizer; use lindera::LinderaResult; fn main() -> LinderaResult<()> { let dictionary = load_dictionary("embedded://jieba")?; let segmenter = Segmenter::new(Mode::Normal, dictionary, None); let tokenizer = Tokenizer::new(segmenter); let text = "可以进行中文形态学分析。"; let mut tokens = tokenizer.tokenize(text)?; for token in tokens.iter_mut() { let details = token.details().join(","); println!("{}\t{}", token.surface.as_ref(), details); } Ok(()) }
開発ガイド
このセクションでは、Lindera のビルド、テスト、貢献に関する情報を提供します。
- ビルドとテスト -- ビルドコマンド、テスト実行、品質チェック
- Feature フラグ -- 利用可能な feature フラグとその効果
- プロジェクト構成 -- クレートの配置とモジュール構成
- 学習パイプライン -- CRF ベースの辞書学習ワークフロー
- 貢献ガイド -- コントリビューター向けガイドライン
ビルドとテスト
ビルド
デフォルトビルド
デフォルトの feature(mmap)でワークスペースをビルドします:
cargo build
学習機能付きビルド
CRF ベースの辞書学習機能を含めてビルドします:
cargo build --features train
CLI のみビルド
cargo build -p lindera-cli
CLI ではデフォルトで train feature が有効になっています。
テスト
単一テスト
クレート内の特定のテストを実行します(開発時はこちらを推奨):
cargo test -p <crate> <test_name>
学習機能のテスト
cargo test -p lindera-dictionary --features train
クレート単位の全機能テスト
単一クレートの全テストスイートを実行します(CI と同等):
cargo test -p <crate> --all-features
ワークスペース全体のテスト
cargo test
品質チェック
フォーマットチェック
コードのフォーマットがプロジェクトのスタイルに一致しているか確認します:
cargo fmt --all -- --check
フォーマットを自動修正するには:
cargo fmt --all
リント
Clippy を警告をエラーとして扱うモードで実行します:
cargo clippy -- -D warnings
ドキュメント
API ドキュメント
Rust の API ドキュメントを生成して開きます:
cargo doc --no-deps --open
mdBook ドキュメント
ユーザー向けドキュメントをビルドします:
mdbook build docs
http://localhost:3000 でローカルプレビュー:
mdbook serve docs
Markdown リント
ドキュメントの Markdown スタイルの問題をチェックします:
markdownlint-cli2 "docs/src/**/*.md"
ルールはリポジトリルートの .markdownlint.json で設定されています。
Feature フラグ
Lindera は Cargo の feature フラグを使用して、オプション機能と辞書の埋め込みを制御します。
コア Feature
| Feature | 説明 | デフォルト |
|---|---|---|
mmap | メモリマップドファイルサポート | 有効 |
train | CRF ベースの辞書学習(lindera-crf に依存) | CLI のみ |
mmapはメインのlinderaクレートでデフォルトで有効です。trainはデフォルトではlindera-cliでのみ有効です。ライブラリとして使用する場合は--features trainで明示的に有効にしてください。
外部辞書の使用(推奨)
推奨される方法は、ビルド済み辞書を外部ファイルとして使用することです。GitHub Releases から辞書をダウンロードし、実行時にそのパスを指定してください:
#![allow(unused)] fn main() { let dictionary = load_dictionary("/path/to/ipadic")?; }
この使用方法では、追加の feature フラグは不要です。
辞書埋め込み Feature(上級者向け)
これらの feature はビルド済み辞書をバイナリに直接埋め込み、実行時に外部辞書ファイルを不要にします。自己完結型バイナリが必要な上級者向けの機能です。
| Feature | 辞書 | 言語 |
|---|---|---|
embed-ipadic | IPADIC | 日本語 |
embed-ipadic-neologd | IPADIC NEologd | 日本語 |
embed-unidic | UniDic | 日本語 |
embed-ko-dic | ko-dic | 韓国語 |
embed-cc-cedict | CC-CEDICT | 中国語 |
embed-jieba | Jieba | 中国語 |
いずれもデフォルトでは無効です。必要に応じて有効にしてください:
[dependencies]
lindera = { version = "2.3.2", features = ["embed-ipadic"] }
埋め込みを有効にした場合、以下のように辞書を読み込めます:
#![allow(unused)] fn main() { let dictionary = load_dictionary("embedded://ipadic")?; }
組み合わせ Feature
多言語アプリケーション向けに、複数の辞書を一度に有効にするメタ Feature です。
| Feature | 含まれる辞書 |
|---|---|
embed-cjk | IPADIC + ko-dic + Jieba |
embed-cjk2 | UniDic + ko-dic + Jieba |
embed-cjk3 | IPADIC NEologd + ko-dic + Jieba |
Feature フラグの組み合わせ
複数の feature フラグを組み合わせることができます。例えば、日本語と韓国語の辞書を両方埋め込む場合:
[dependencies]
lindera = { version = "2.3.2", features = ["embed-ipadic", "embed-ko-dic"] }
またはコマンドラインから:
cargo build --features embed-ipadic,embed-ko-dic
注意事項
- 辞書の埋め込みはバイナリサイズを大幅に増加させます。実際に必要な辞書のみを埋め込んでください。
trainfeature はlindera-crfへの依存を追加し、コンパイル時間が増加します。トークナイズのみのユースケースでは不要です。mmapfeature はメモリマップドによる辞書読み込みを有効にし、ディスクから読み込む大規模辞書のメモリ使用量を削減します。埋め込み辞書には影響しません。
プロジェクト構成
Lindera は複数のクレートで構成される Cargo ワークスペースとして組織されています。
ディレクトリ構成
lindera/
├── lindera-crf/ # CRF engine (pure Rust, no_std)
├── lindera-dictionary/ # Dictionary base library
├── lindera/ # Core morphological analysis library
├── lindera-cli/ # CLI tool
├── lindera-ipadic/ # IPADIC dictionary (Japanese)
├── lindera-ipadic-neologd/ # IPADIC NEologd dictionary (Japanese)
├── lindera-unidic/ # UniDic dictionary (Japanese)
├── lindera-ko-dic/ # ko-dic dictionary (Korean)
├── lindera-cc-cedict/ # CC-CEDICT dictionary (Chinese)
├── lindera-jieba/ # Jieba dictionary (Chinese)
├── lindera-python/ # Python bindings (PyO3)
├── lindera-wasm/ # WebAssembly bindings (wasm-bindgen)
├── resources/ # Test resources and sample data
├── docs/ # Documentation (mdBook)
└── examples/ # Example code
クレートの説明
コアクレート
lindera-crf
条件付き確率場(CRF)の pure Rust 実装です。no_std 環境をサポートします。高速なゼロコピーシリアライゼーションに rkyv を使用します。辞書学習で使用される統計学習エンジンを提供します。
lindera-dictionary
辞書のベースライブラリです。辞書の読み込み、ビルド、クエリ機能を提供します。train feature を有効にすると、カスタム辞書作成のための CRF 学習パイプラインも提供します。
src/trainer/ 配下の主要モジュール:
| モジュール | 役割 |
|---|---|
config.rs | 設定管理(種辞書、char.def、feature.def、rewrite.def) |
corpus.rs | 学習コーパスの処理 |
feature_extractor.rs | 素性テンプレートの解析と素性 ID 管理 |
feature_rewriter.rs | MeCab 互換の素性書き換え(3セクション形式) |
model.rs | 学習済みモデルの保存、シリアライゼーション、辞書出力 |
lindera
メインの形態素解析ライブラリです。辞書クレートを統合し、Tokenizer、Segmenter、文字フィルタ、トークンフィルタを提供します。
lindera-cli
トークナイズ、辞書学習、エクスポート、ビルドのためのコマンドラインインターフェースです。デフォルトで train feature が有効です。
辞書クレート
各辞書クレートには、特定の言語と辞書ソースのビルド済み辞書データが含まれます。
| クレート | 言語 | 辞書ソース |
|---|---|---|
lindera-ipadic | 日本語 | IPADIC |
lindera-ipadic-neologd | 日本語 | IPADIC NEologd(拡張語彙) |
lindera-unidic | 日本語 | UniDic |
lindera-ko-dic | 韓国語 | ko-dic |
lindera-cc-cedict | 中国語 | CC-CEDICT |
lindera-jieba | 中国語 | Jieba |
バインディング
lindera-python
PyO3 で構築された Python バインディングです。Lindera のトークナイザー API を Python アプリケーションに公開します。
lindera-wasm
wasm-bindgen で構築された WebAssembly バインディングです。ブラウザと Node.js でのトークナイズを可能にします。
その他のディレクトリ
resources/
テストスイートで使用されるサンプル辞書、ユーザー辞書、テストコーパスなどのテストリソースです。
docs/
mdBook で構築されたユーザー向けドキュメントです。目次は docs/src/SUMMARY.md で定義されています。日本語翻訳は docs/ja/ 配下にあります。
examples/
一般的な使用パターンを示す実行可能なサンプルプログラムです。以下のコマンドで実行できます:
cargo run --features=embed-ipadic --example=<example_name>
学習パイプライン
Lindera は、カスタム形態素解析モデルを作成するための CRF ベースの辞書学習機能を提供します。この機能には train feature フラグが必要です。
概要
学習パイプラインは3つのステージで構成されます:
lindera train --> model.dat --> lindera export --> dictionary files --> lindera build --> compiled dictionary
- Train: アノテーション付きコーパスと種辞書から CRF の重みを学習し、バイナリモデルファイルを生成します。
- Export: 学習済みモデルを Lindera 辞書ソースファイルに変換します。
- Build: ソースファイルを Lindera が実行時に読み込めるバイナリ辞書にコンパイルします。
必要な入力ファイル
1. 種辞書 (seed.csv)
MeCab CSV 形式のベース語彙辞書です。
外国,0,0,0,名詞,一般,*,*,*,*,外国,ガイコク,ガイコク
人,0,0,0,名詞,接尾,一般,*,*,*,人,ジン,ジン
参政,0,0,0,名詞,サ変接続,*,*,*,*,参政,サンセイ,サンセイ
各行の構成: surface,left_id,right_id,cost,pos,pos_detail1,pos_detail2,pos_detail3,inflection_type,inflection_form,base_form,reading,pronunciation
種辞書では left_id、right_id、cost フィールドは 0 に設定されます。学習器が CRF モデルから適切な値を計算します。
2. 学習コーパス (corpus.txt)
タブ区切り形式のアノテーション付きテキストデータです。各行は surface<TAB>pos_info で、文は EOS で区切られます。
外国 名詞,一般,*,*,*,*,外国,ガイコク,ガイコク
人 名詞,接尾,一般,*,*,*,人,ジン,ジン
参政 名詞,サ変接続,*,*,*,*,参政,サンセイ,サンセイ
権 名詞,接尾,一般,*,*,*,権,ケン,ケン
EOS
これ 連体詞,*,*,*,*,*,これ,コレ,コレ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
テスト 名詞,サ変接続,*,*,*,*,テスト,テスト,テスト
EOS
学習の品質はこのコーパスの量と質に大きく依存します。
3. 文字定義 (char.def)
文字タイプのカテゴリと Unicode コードポイント範囲を定義します。
# Category definition: category_name compatibility_flag continuity_flag length
DEFAULT 0 1 0
HIRAGANA 1 1 0
KATAKANA 1 1 0
KANJI 0 0 2
ALPHA 1 1 0
NUMERIC 1 1 0
# Character range mapping
0x3041..0x3096 HIRAGANA # Hiragana
0x30A1..0x30F6 KATAKANA # Katakana
0x4E00..0x9FAF KANJI # Kanji
0x0030..0x0039 NUMERIC # Numbers
0x0041..0x005A ALPHA # Uppercase letters
0x0061..0x007A ALPHA # Lowercase letters
パラメータは各文字タイプの未知語がどのように分割されるかを制御します。隣接文字との互換性、同一タイプの連続が1つのトークンとして続くかどうか、デフォルトのトークン長を指定します。
4. 未知語定義 (unk.def)
文字タイプごとに未知語の処理方法を定義します。
DEFAULT,0,0,0,名詞,一般,*,*,*,*,*,*,*
HIRAGANA,0,0,0,名詞,一般,*,*,*,*,*,*,*
KATAKANA,0,0,0,名詞,一般,*,*,*,*,*,*,*
KANJI,0,0,0,名詞,一般,*,*,*,*,*,*,*
ALPHA,0,0,0,名詞,固有名詞,一般,*,*,*,*,*,*
NUMERIC,0,0,0,名詞,数,*,*,*,*,*,*,*
5. 素性テンプレート (feature.def)
CRF モデルが学習に使用する情報を定義する MeCab 互換の素性抽出パターンです。
# Unigram features (word-level)
UNIGRAM U00:%F[0] # POS
UNIGRAM U01:%F[0],%F?[1] # POS + POS detail (%F?[n] = optional, skipped if *)
UNIGRAM U02:%F[6] # Base form
UNIGRAM U03:%w # Surface form
# Bigram features (context combination)
BIGRAM B00:%L[0]/%R[0] # Left POS / Right POS
BIGRAM B01:%L[0],%L[1]/%R[0],%R[1] # Left POS detail / Right POS detail
テンプレート変数:
| 変数 | 説明 |
|---|---|
%F[n] / %F?[n] | インデックス n の素性フィールド(? = オプション、値が * の場合はスキップ) |
%L[n] | 左文脈の素性フィールド(rewrite.def の左セクションから) |
%R[n] | 右文脈の素性フィールド(rewrite.def の右セクションから) |
%w | 単語の表層形 |
%u | ユニグラム書き換え後の素性文字列 |
%l | 左書き換え後の素性文字列 |
%r | 右書き換え後の素性文字列 |
6. 素性書き換えルール (rewrite.def)
MeCab 互換の3セクション形式による素性正規化ルールです。セクションは空行で区切られます。
# Section 1: Unigram rewrite rules
名詞,固有名詞,* 名詞,固有名詞
助動詞,*,*,*,特殊・デス 助動詞
* *
# Section 2: Left context rewrite rules
名詞,固有名詞,* 名詞,固有名詞
助詞,* 助詞
* *
# Section 3: Right context rewrite rules
名詞,固有名詞,* 名詞,固有名詞
助詞,* 助詞
* *
各行は pattern<TAB>replacement です。パターンはワイルドカードとして * を使用し、前方一致で照合されます。各セクションで最初に一致したルールが適用されます。ユニグラム、左文脈、右文脈に対して異なるルールを独立して適用できるため、スパース性を低減するきめ細かい素性正規化が可能です。
学習パラメータ
| パラメータ | 説明 | デフォルト |
|---|---|---|
lambda | L1 正則化係数(過学習の制御) | 0.01 |
max-iterations | 最大学習イテレーション数 | 100 |
max-threads | 並列処理スレッド数 | 1 |
CLI の使用
Train
lindera train \
--seed seed.csv \
--corpus corpus.txt \
--char-def char.def \
--unk-def unk.def \
--feature-def feature.def \
--rewrite-def rewrite.def \
--lambda 0.01 \
--max-iter 100 \
--max-threads 4 \
--output model.dat
Export
学習済みモデルを辞書ソースファイルに変換します:
lindera export --model model.dat --output-dir ./dict-source
以下のファイルが生成されます:
| ファイル | 説明 |
|---|---|
lex.csv | 学習済みコスト付きレキシコン |
matrix.def | 連接コスト行列 |
unk.def | 未知語定義 |
char.def | 文字定義 |
feature.def | 素性テンプレート |
rewrite.def | 素性書き換えルール |
left-id.def | 左文脈 ID マッピング |
right-id.def | 右文脈 ID マッピング |
metadata.json | 辞書メタデータ |
Build
エクスポートされたソースファイルをバイナリ辞書にコンパイルします:
lindera build --input-dir ./dict-source --output-dir ./dict-compiled
出力モデルの形式
学習済みモデルは高速読み込みのために rkyv バイナリ形式でシリアライズされます。以下を含みます:
- CRF で学習された素性の重み
- ラベルセット(語彙エントリー)
- 品詞情報
- 素性テンプレート
- 学習メタデータ(正則化、イテレーション数、素性・ラベル数)
API の使用
#![allow(unused)] fn main() { use std::fs::File; use lindera_dictionary::trainer::{Corpus, Trainer, TrainerConfig}; // Load configuration from files let seed_file = File::open("resources/training/seed.csv")?; let char_file = File::open("resources/training/char.def")?; let unk_file = File::open("resources/training/unk.def")?; let feature_file = File::open("resources/training/feature.def")?; let rewrite_file = File::open("resources/training/rewrite.def")?; let config = TrainerConfig::from_readers( seed_file, char_file, unk_file, feature_file, rewrite_file )?; // Initialize and configure trainer let trainer = Trainer::new(config)? .regularization_cost(0.01) .max_iter(100) .num_threads(4); // Load corpus let corpus_file = File::open("resources/training/corpus.txt")?; let corpus = Corpus::from_reader(corpus_file)?; // Execute training let model = trainer.train(corpus)?; // Save model (binary format) let mut output = File::create("trained_model.dat")?; model.write_model(&mut output)?; // Output in Lindera dictionary format let mut lex_out = File::create("output_lex.csv")?; let mut conn_out = File::create("output_conn.dat")?; let mut unk_out = File::create("output_unk.def")?; let mut user_out = File::create("output_user.csv")?; model.write_dictionary(&mut lex_out, &mut conn_out, &mut unk_out, &mut user_out)?; Ok::<(), Box<dyn std::error::Error>>(()) }
推奨コーパス仕様
実用的なアプリケーション向けの辞書を生成するための推奨事項:
コーパスサイズ
| レベル | 文数 | 用途 |
|---|---|---|
| 最小 | 100以上 | 基本的な動作確認 |
| 推奨 | 1,000以上 | 実用的なアプリケーション |
| 理想 | 10,000以上 | 商用品質 |
品質ガイドライン
- 語彙の多様性: さまざまな品詞のバランスの取れた分布、活用形・接尾語のカバー、専門用語・固有名詞の適切な含有。
- 一貫性: コーパス全体で分析基準を一貫して適用すること。
- 検証: 形態素解析結果を手動で検証すること。エラー率を5%以下に維持すること。
貢献ガイド
Lindera への貢献に興味をお持ちいただきありがとうございます。このページでは、貢献を始めるためのガイドラインを紹介します。
はじめに
-
GitHub でリポジトリをフォークします。
-
フォークをローカルにクローンします:
git clone https://github.com/<your-username>/lindera.git cd lindera -
feature ブランチを作成します:
git checkout -b feature/my-feature -
変更を行い、すべてのチェックに通ることを確認します:
cargo fmt --all -- --check cargo clippy -- -D warnings cargo test -
変更をコミットしてプッシュし、プルリクエストを開きます。
コードスタイル
- リポジトリの既存のコードスタイルに従ってください。
- コミット前に
cargo fmtを実行してください。 - すべての public および private アイテム(型、関数、モジュール、フィールド、定数、型エイリアス)にドキュメントコメント(
///)を記述してください。 - trait 実装メソッドにも、実装固有の振る舞いを説明するドキュメントコメントを記述してください。
- 関数・メソッドのドキュメントには、該当する場合
# Argumentsと# Returnsセクションを含めてください。 - コードコメント、ドキュメントコメント、コミットメッセージ、ログメッセージ、エラーメッセージは英語で記述してください。
- 本番コードでは
unwrap()やexpect()を避けてください(テストコードでは使用可)。 unsafeブロックは必要な場合にのみ使用し、必ず// SAFETY: ...コメントを付けてください。- モジュールは
mod.rsスタイルではなく、ファイルベースのスタイル(src/tokenizer.rs)を使用してください。
テスト
-
すべての新機能にユニットテストを作成してください。
-
開発中は迅速なフィードバックのために関連するテストのみを実行してください:
cargo test -p <crate> <test_name> -
trainfeature に関連する作業では、feature フラグを含めてください:cargo test -p lindera-dictionary --features train
コミットメッセージ
Conventional Commits の仕様に従ってください。コミットメッセージは英語で記述してください。
例:
feat: add Korean dictionary supportfix: correct character category ID in trainerdocs: update installation instructionsrefactor: split large training method into smaller functions
ドキュメント
-
変更がユーザー向けドキュメントに影響する場合は、
docs/src/配下の関連ファイルを更新してください。 -
Markdown ファイルの編集後は、リントエラーがないことを確認してください:
markdownlint-cli2 "docs/src/**/*.md" -
ルールはリポジトリルートの
.markdownlint.jsonで設定されています。
依存関係
新しい依存関係を追加する際は、ライセンスの互換性を確認してください。Lindera は MIT / Apache-2.0 デュアルライセンスを使用しています。
Feature フラグ
学習関連コードの条件コンパイルには #[cfg(feature = "train")] を使用してください。完全なリストは Feature フラグ を参照してください。
問題の報告
バグを報告する際は、以下の情報を含めてください:
- Lindera のバージョン(
lindera --versionまたはCargo.tomlを確認) - Rust のバージョン(
rustc --version) - オペレーティングシステム
- 問題の再現手順
- 期待される動作と実際の動作