Newer
Older
TelosDB / src-tauri / src / utils / tokenizer.rs
use lindera::tokenizer::Tokenizer;
use lindera::mode::Mode;
use lindera_core::viterbi::{PenaltyType};
use anyhow::Result;

pub struct JapaneseTokenizer {
    tokenizer: Tokenizer,
}

impl JapaneseTokenizer {
    pub fn new() -> Result<Self> {
        // IPADIC 辞書を使用したトークナイザーの初期化
        // 辞書は埋め込みバイナリとして扱われる
        let tokenizer = Tokenizer::new_with_config(lindera::tokenizer::TokenizerConfig {
            dictionary: lindera::tokenizer::DictionaryConfig {
                kind: Some(lindera_core::lexicon::DictionaryKind::IPADIC),
                path: None,
            },
            user_dictionary: None,
            mode: Mode::Decompose(Mode::Normal), // 検索向けに分解モード
        })?;
        
        Ok(JapaneseTokenizer { tokenizer })
    }

    /// テキストを形態素解析し、わかち書き(スペース区切り)の文字列として返す
    pub fn tokenize_to_string(&self, text: &str) -> Result<String> {
        let tokens = self.tokenizer.tokenize(text)?;
        let result: Vec<&str> = tokens
            .iter()
            .map(|token| token.text)
            .collect();
        
        Ok(result.join(" "))
    }

    /// 単語のリスト(ベクタ)として返す
    pub fn tokenize_to_vec(&self, text: &str) -> Result<Vec<String>> {
        let tokens = self.tokenizer.tokenize(text)?;
        Ok(tokens.iter().map(|t| t.text.to_string()).collect())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_japanese_tokenization() {
        let tokenizer = JapaneseTokenizer::new().unwrap();
        let text = "すもももももももものうち";
        let tokenized = tokenizer.tokenize_to_string(text).unwrap();
        assert!(tokenized.contains("すもも"));
        assert!(tokenized.contains("もも"));
    }
}