MeCab 用のコンパイル済み辞書を読み取り、解析・再構成し、最終的に Vibrato や Lindera のような Mecab互換 tokenizer が使える辞書へ変換するための Rust crate です。
現時点では、UTF-8 の compiled MeCab 0.996 系辞書を対象にしています。
本リポジトリの検討と実装にあたっては、アドバイザーとして支援していただいた帝京大学 文学部 日本文化学科 講師 梅田径 先生に感謝します。
- 梅田 径 (Kei UMEDA) - マイポータル - researchmap: https://researchmap.jp/KEIUMEDA
- このリポジトリには、手元検証で使っている
mecab-dicts/,mecab-0.996/,samples/などのローカル作業用ディレクトリは含まれていません - README や examples に出てくるそれらのパスは、開発時の既定値または検証用パスです。公開版を clone した環境では、利用者が自分で辞書や比較用データを用意する前提です
- 辞書データやその再配布条件は upstream ごとに異なります。この crate 自体とは別に、入力辞書・生成物・比較用データのライセンスを確認してください
- 特に
unidic系辞書は系統ごとに条件が異なります。Ver.2.x以降の現代書き言葉 UniDic など triple-license のものもありますが、歴史系・小説系を含む他の UniDic には商用利用前の事前相談や成果公表時の明記が求められるものがあります
sys.dic/unk.dic/matrix.bin/char.bin/dicrcのパース- compiled 辞書から
lex.csv/unk.def/char.def/matrix.def相当の再構成 - 辞書全体 CSV や lookup 結果 CSV のデバッグ出力
vibrato-rkyv形式のsystem.dic.zst生成- MeCab と Vibrato の形態素解析結果比較
- 対象は UTF-8 の compiled MeCab 0.996 辞書に限定しています
decoder -> resolver -> encoderの分離を前提に実装しています- フル辞書の
system.dic.zst生成は動作します - UniDic 全件での MeCab / Vibrato 完全一致はまだ調整中です
- Rust / Cargo
- Linux などの POSIX 環境を推奨
- Windows でも CLI の build は可能です。release CLI は GitHub Actions の
windows-latestでも build しています - Windows で source build する場合は Git と Visual Studio C++ Build Tools (MSVC) が必要です
- MeCab CLI 比較 example を使う場合は
mecabコマンドが必要
比較 example 以外も、実行には compiled MeCab 辞書一式を別途用意する前提です。
依存解決と基本テストは次で確認できます。
cargo testvibrato-rkyv への変換機能を使う場合は vibrato-export feature を有効にします。
cargo test --features vibrato-export別の Windows マシンで source から build する場合は、少なくとも次を用意してください。
- Git
- Visual Studio 2022 Build Tools
- Rustup と stable の
x86_64-pc-windows-msvctoolchain - GitHub / crates.io にアクセスできるネットワーク
vibrato-rkyv は git pin した fork に依存しているため、fresh な環境では依存取得のためにネットワークが必要です。
Visual Studio Build Tools は Desktop development with C++ を有効にし、少なくとも MSVC toolchain と Windows SDK を入れてください。
セットアップ後の確認手順は次です。
rustup default stable-x86_64-pc-windows-msvc
cargo test
cargo test --features vibrato-exportlindera-export を含めた release CLI の build は次で確認できます。
cargo build --release --features "vibrato-export lindera-export" --bin mecab-dic-converter通常の PowerShell で link.exe を見失う場合は、Developer PowerShell for VS 2022 から同じコマンドを実行してください。
MeCab との比較 example を Windows でも使いたい場合は、別途 mecab.exe をインストールして PATH に通す必要があります。比較以外の parser / resolver / encoder 系コマンドは、repo 内の辞書ファイルだけで実行できます。
source build ではなく CLI を実行するだけなら、GitHub Releases か workflow artifact の Windows 向け mecab-dic-converter.exe を使う方法もあります。
library に加えて、1 本の CLI バイナリとしても使えるようにしました。ローカル build は次です。
cargo build --release --features "vibrato-export lindera-export" --bin mecab-dic-converter生成物は Linux なら target/release/mecab-dic-converter、Windows なら
target\release\mecab-dic-converter.exe です。
GitHub Actions には release-cli.yml を追加してあり、
workflow_dispatch か v* tag push で Linux / Windows の release artifact を生成します。
CLI は compiled MeCab 辞書ルートを明示的に渡す前提です。help は次で確認できます。
cargo run --release --features "vibrato-export lindera-export" -- --help以下の例で使っている mecab-dicts/unidic-novel-v202512 はローカル検証用のパス名です。公開リポジトリには含まれないため、手元の辞書配置に置き換えてください。
例えば lookup は次です。
cargo run --release --features "vibrato-export lindera-export" -- \
lookup \
--dictionary-root mecab-dicts/unidic-novel-v202512 \
京都東京都Vibrato 用辞書の生成は次です。
cargo run --release --features "vibrato-export lindera-export" -- \
build-vibrato \
--dictionary-root mecab-dicts/unidic-novel-v202512 \
--output target/system-full.dic.zstLindera 用 compiled directory の生成は次です。
cargo run --release --features "vibrato-export lindera-export" -- \
build-lindera \
--dictionary-root mecab-dicts/unidic-novel-v202512 \
--output target/lindera-system-dicこのリポジトリ内のコードは MIT OR Apache-2.0 で提供します。詳細は LICENSE-MIT と LICENSE-APACHE を参照してください。
ただし、次はこのリポジトリのコードライセンスとは別に扱ってください。
- 外部辞書データ
- 外部辞書から生成した成果物
patches/git-deps/に含まれる upstream 差分
これらの扱いは THIRD_PARTY.md に整理しています。
入力文字列に対して、辞書引き結果を MeCab 風の CSV で表示します。
cargo run --example dump_lookup_csv -- 京都東京都辞書ルートを明示する場合:
cargo run --example dump_lookup_csv -- mecab-dicts/unidic-novel-v202512 京都東京都system / unknown / both を指定できます。省略時は both です。
cargo run --example dump_dictionary_csv -- both > target/dictionary.csvcargo run --example dump_dictionary_csv -- mecab-dicts/unidic-novel-v202512 system > target/system.csvcargo run --example dump_char_def > target/char.defcargo run --example dump_matrix_def -- nonzero > target/matrix.defdump_matrix_def の第 2 引数は all または nonzero です。省略時は nonzero です。
フル辞書の system.dic.zst を生成します。大きい辞書では debug build がかなり遅いので、release build を推奨します。
cargo run --release --example build_system_dic_zst --features vibrato-export -- \
mecab-dicts/unidic-novel-v202512 \
target/system-full.dic.zst引数を省略すると、辞書ルートは mecab-dicts/unidic-novel-v202512、出力先は system.dic.zst になります。
現在の検証環境では、checked-in UniDic のフル変換はおおむね次の規模です。
- 所要時間: 約 9 分
- 出力サイズ: 約 968 MB
- 最大 RSS: 約 7.8 GB
値は実行環境に依存します。
zstd 圧縮 worker 数は既定で利用可能 CPU 数と 8 の小さい方を使います。必要なら MECAB_DIC_CONVERTER_ZSTD_WORKERS で上書きできます。
MECAB_DIC_CONVERTER_ZSTD_WORKERS=16 \
cargo run --release --example build_system_dic_zst --features vibrato-export -- \
mecab-dicts/unidic-novel-v202512 \
target/system-full.dic.zstLindera がそのまま読める compiled dictionary directory を生成します。内部では一時ディレクトリに
lex.csv / char.def / unk.def / matrix.def を再構成し、lindera-dictionary の
DictionaryBuilder で metadata.json と各 .bin / .mtx / .da を生成します。
cargo run --release --example build_lindera_system_dic --features lindera-export -- \
mecab-dicts/unidic-novel-v202512 \
target/lindera-system-dic第 1 引数の辞書ルートは必須です。出力先を省略した場合は target/lindera-system-dic を使います。
出力先には少なくとも次の Lindera runtime files が並びます。
metadata.jsondict.dadict.valsdict.wordsidxdict.wordsmatrix.mtxchar_def.binunk.bin
checked-in の compiled UniDic は Lindera 既定の UniDic schema より feature 列が多いため、
この exporter は辞書内の実列数に合わせた custom metadata.json を自動生成します。
ただし Lindera 3.0.5 の matrix.mtx format は context size を signed 16-bit で保持するため、
matrix.bin の right/left context size が 32767 を超える辞書は compiled Lindera directory に
変換できません。checked-in の mecab-dicts/unidic-novel-v202512 は
right=39687, left=35597 なので、この辞書をそのまま Lindera 向けに export することはできません。
入力テキストに必要な語だけを拾って小さな辞書を in-memory で組み、MeCab と比較します。
cargo run --release --example compare_mecab_vibrato --features vibrato-export -- 京都東京都フル辞書 artifact があればそれを使い、なければ in-memory build にフォールバックして比較します。
cargo run --release --example compare_mecab_vibrato_full --features vibrato-export -- \
mecab-dicts/unidic-novel-v202512 \
target/system-full.dic.zst \
samples/takekurabe.txt \
50出力は target/*.mecab.tsv と target/*.vibrato.tsv に保存されます。
この crate は大きく 3 層に分かれています。
decoder: compiled バイナリをそのまま読む層resolver:lex.csvやmatrix.def相当を再構成する層encoder: Vibrato 向け辞書へ変換する層
最小の利用例は次のようになります。
use std::{fs::File, path::Path};
use mecab_dic_converter::{CharDefResolver, CompileInputResolver, MatrixDefResolver};
#[cfg(feature = "vibrato-export")]
use mecab_dic_converter::VibratoRkyvEncoder;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let root = Path::new("mecab-dicts/unidic-novel-v202512");
let compile_inputs = CompileInputResolver::open(root)?;
let mut lex_csv = Vec::new();
compile_inputs.write_lex_csv(&mut lex_csv)?;
let char_def = CharDefResolver::open(root)?;
let matrix_def = MatrixDefResolver::open(root)?;
let _ = (char_def, matrix_def);
#[cfg(feature = "vibrato-export")]
{
let encoder = VibratoRkyvEncoder::open(root)?;
let file = File::create("system.dic.zst")?;
encoder.write_dictionary_zstd(file)?;
}
Ok(())
}公開 API は src/lib.rs から re-export しています。
変換進捗を UI に流したい場合は、write_dictionary_zstd_with_progress(...) を使うと callback で stage ごとの進捗を受け取れます。
checked-in の build_system_dic_zst.rs example もこの progress API を使うようにしてあり、実行すると stderr に現在の stage と進捗率が表示されます。
use std::{fs::File, path::Path};
use mecab_dic_converter::{
VibratoRkyvEncodeStage, VibratoRkyvEncodeProgress, VibratoRkyvEncoder,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let root = Path::new("mecab-dicts/unidic-novel-v202512");
let encoder = VibratoRkyvEncoder::open(root)?;
let file = File::create("system.dic.zst")?;
encoder.write_dictionary_zstd_with_progress(file, |progress: VibratoRkyvEncodeProgress| {
let stage = match progress.stage() {
VibratoRkyvEncodeStage::ReconstructLexCsv => "lex.csv",
VibratoRkyvEncodeStage::ReconstructCharDef => "char.def",
VibratoRkyvEncodeStage::ReconstructUnkDef => "unk.def",
VibratoRkyvEncodeStage::BuildDictionary => "dictionary build",
VibratoRkyvEncodeStage::BuildMatrixConnector => "matrix connector",
VibratoRkyvEncodeStage::SerializeDictionary => "serialize",
VibratoRkyvEncodeStage::CompressDictionary => "zstd",
VibratoRkyvEncodeStage::Finished => "finished",
};
if let Some(fraction) = progress.fraction() {
eprintln!("{stage}: {:.1}%", fraction * 100.0);
} else {
eprintln!("{stage}: in progress");
}
})?;
Ok(())
}desktop app 側で closure を避けたい場合は、標準の std::sync::mpsc::Sender をそのまま渡せる sender wrapper も使えます。receiver が先に閉じても変換処理自体は継続します。
use std::{fs::File, path::Path, sync::mpsc};
use mecab_dic_converter::{VibratoRkyvEncodeStage, VibratoRkyvEncoder};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let root = Path::new("mecab-dicts/unidic-novel-v202512");
let encoder = VibratoRkyvEncoder::open(root)?;
let file = File::create("system.dic.zst")?;
let (sender, receiver) = mpsc::channel();
std::thread::spawn(move || {
while let Ok(progress) = receiver.recv() {
if progress.stage() == VibratoRkyvEncodeStage::Finished {
break;
}
eprintln!(
"{:?}: {} / {:?}",
progress.stage(),
progress.completed(),
progress.total(),
);
}
});
encoder.write_dictionary_zstd_with_progress_sender(file, &sender)?;
Ok(())
}ReconstructLexCsv / ReconstructUnkDef / BuildMatrixConnector / CompressDictionary は determinate progress を返します。BuildMatrixConnector は matrix.bin から dense な connector data を直接組み立てる段階です。BuildDictionary も以前の開始・完了だけではなく、lex.csv parse、lexicon index 構築、検証などの途中経過を返すようになりました。なお BuildDictionary の unit と total は sub-phase ごとに切り替わるため、UI 側では stage だけでなく unit も見て扱う前提です。
build_system_dic_zst.rs: フル辞書をsystem.dic.zstに変換し、stderr に進捗を表示compare_mecab_vibrato.rs: 部分辞書で MeCab / Vibrato を比較compare_mecab_vibrato_full.rs: フル辞書で MeCab / Vibrato を比較dump_char_def.rs:char.defを再構成して標準出力へ出すdump_dictionary_csv.rs: 辞書全体 CSV を出力dump_lookup_csv.rs: 入力文字列に対する候補 CSV を出力dump_matrix_def.rs:matrix.defを再構成して標準出力へ出すprofile_build_stages.rs: 再構成 / builder / zstd 圧縮の段階別時間を計測
- 対象外のエンコーディングや MeCab バージョンには未対応です
vibrato-rkyv/crawdad-rkyvは git pin した fork に依存しており、matrix.binから dense な matrix costs を直接 builder に渡しています- フル辞書変換はメモリ使用量が大きめです
- checked-in UniDic での full comparison には未解決の差分が残っています
cargo test
cargo test --features vibrato-export
cargo run --example dump_lookup_csv -- 京都東京都
cargo run --example dump_dictionary_csv -- both > target/dictionary.csv
cargo run --example dump_char_def > target/char.def
cargo run --example dump_matrix_def -- nonzero > target/matrix.def
cargo run --release --example build_system_dic_zst --features vibrato-export -- mecab-dicts/unidic-novel-v202512 target/system-full.dic.zst
cargo run --release --example compare_mecab_vibrato_full --features vibrato-export -- mecab-dicts/unidic-novel-v202512 target/system-full.dic.zst samples/takekurabe.txt 50