Lightweight offline Japanese input completion library
Project description
ja-complete
LLMやデータベースを使わない、軽量なオフライン日本語入力補完ライブラリ
概要
ja-completeは日本語テキスト補完・予測のための純粋なPython OSSライブラリです。異なるユースケースに対応する複数の独立した補完メソッドを提供します:
- フレーズベース補完: 自動プレフィックス生成を伴うカスタムフレーズリスト
- N-gramモデル: 日本語テキストコーパスに基づく統計的予測
- 単純辞書: プレフィックスから候補への直接マッピング
- カスタムJSONL: 柔軟なカスタムデータフォーマットサポート
主な特徴:
- LLMやデータベース不要: 完全オフラインで軽量
- 複数の独立した補完API
- Janomeによる形態素解析
- CLIツール、エディタ、Webアプリケーションへの簡単な統合
インストール
pip install ja-complete
# または uv を使用
uv add ja-complete
クイックスタート
フレーズベース補完
from ja_complete import JaCompleter
completer = JaCompleter()
# カスタムフレーズを追加
phrases = [
"スマホの買い換えと合わせて一式揃えたい",
"新生活に備えた準備を始めたい",
"夏を爽やかに過ごしたい",
]
completer.add_phrases(phrases)
# 補完を取得(フレーズマッチがない場合、自動的にN-gramにフォールバック)
results = completer.suggest_from_phrases("ス", top_k=5)
print(results) # [{'text': 'スマホの買い換えと合わせて一式揃えたい', 'score': 0.82}, ...]
# 厳密なフレーズマッチングのためN-gramフォールバックを無効化
results = completer.suggest_from_phrases("未登録の入力", fallback_to_ngram=False)
print(results) # [] (フレーズマッチがない場合は空)
N-gram補完
from ja_complete import JaCompleter
completer = JaCompleter()
# デフォルトのN-gramモデルを使用
results = completer.suggest_from_ngram("今日は", top_k=5)
print(results) # [{'text': '今日はいい天気', 'score': 0.85}, ...]
# 助詞拡張を無効化
results = completer.suggest_from_ngram("今日は", top_k=5, extend_particles=False)
print(results) # 助詞で終わる候補のみ
単純辞書補完
from ja_complete import JaCompleter
completer = JaCompleter()
# 単純なプレフィックスマッピングを追加
suggestions = {
"お": ["おはよう", "おやすみ", "お疲れ様"],
"あり": ["ありがとう", "ありがとうございます"],
}
completer.add_simple_suggestions(suggestions)
# 補完を取得(マッチがない場合、自動的にN-gramにフォールバック)
results = completer.suggest_from_simple("あり", top_k=3)
print(results) # [{'text': 'ありがとう', 'score': 1.0}, ...]
# フォールバックを無効化
results = completer.suggest_from_simple("未登録", fallback_to_ngram=False)
print(results) # [] (マッチがない場合は空)
フレーズから補完データを生成
文字ベースのプレフィックス生成
from ja_complete import JaCompleter
# フレーズから文字ベースのプレフィックスマッピングを生成
phrases = ["今日はいい天気", "今日は雨", "明日は晴れ"]
suggestions = JaCompleter.phrases_to_simple_suggestions(phrases)
# SimpleSuggestions型で返される
print(suggestions.data["今"])
# ['今日はいい天気', '今日は雨']
# 補完器に直接追加可能
completer = JaCompleter()
completer.add_simple_suggestions(suggestions)
results = completer.suggest_from_simple("今", fallback_to_ngram=False)
print(results) # 2件の候補が返される
N-gramデータの抽出とモデルへの追加
from ja_complete import JaCompleter
# フレーズからN-gramデータを抽出(形態素情報含む)
phrases = [
"今日はいい天気ですね",
"明日は雨が降りそうです",
"週末は晴れるといいな",
]
ngram_data = JaCompleter.phrases_to_ngram_data(phrases)
# NgramData型で返される
print(ngram_data.unigrams["今日"]) # カウント数
print(ngram_data.morphology["今日"].pos) # 品詞情報
# デフォルトモデルに追加してカスタマイズ
completer = JaCompleter()
completer._ngram_model.add_ngram_data(ngram_data)
# カスタマイズしたモデルで補完
results = completer.suggest_from_ngram("今日は", top_k=5)
print(results)
CLI使用方法
# フレーズベース補完
ja-complete phrase "新生活" --phrases phrases.txt
# N-gram補完
ja-complete ngram "今日は"
# 単純辞書補完
ja-complete simple "あり" --dict suggestions.json
APIリファレンス
JaCompleter
複数の補完メソッドを提供するメインクラス。
コンストラクタ
JaCompleter(enable_ngram_fallback: bool = True)- オプションのN-gramフォールバック付きで補完器を初期化
enable_ngram_fallback=Trueの場合、フレーズおよび単純辞書メソッドはマッチが見つからない場合に自動的にN-gram補完を使用
メソッド
フレーズベース補完:
-
add_phrases(phrases: List[str]) -> None- フレーズベース補完用のフレーズを追加
- 形態素解析を使用して自動的にプレフィックスを生成
-
suggest_from_phrases(input_text: str, top_k: int = 10, fallback_to_ngram: bool | None = None, extend_particles: bool = True) -> List[Dict[str, Any]]- 追加されたフレーズから補完を取得
- マッチがなく
fallback_to_ngram=True(またはインスタンスデフォルト)の場合、N-gram補完を返す - スコア付きのランク付けされた結果を返す
N-gram補完:
-
suggest_from_ngram(input_text: str, top_k: int = 10, extend_particles: bool = True) -> List[Dict[str, Any]]- N-gramモデルを使用して補完を取得
- デフォルトモデルまたはロードされたカスタムモデルを使用
extend_particles=Trueの場合、助詞で終わる候補に次の語を自動追加
-
load_ngram_model(model_path: str) -> None- ファイルからカスタムN-gramモデルを読み込む
単純辞書補完:
-
add_simple_suggestions(suggestions: Dict[str, List[str]] | SimpleSuggestions) -> None- プレフィックスから候補へのマッピングを追加
- 辞書形式またはSimpleSuggestions値オブジェクトを受け入れ
-
suggest_from_simple(input_text: str, top_k: int = 10, fallback_to_ngram: bool | None = None, extend_particles: bool = True) -> List[Dict[str, Any]]- 単純辞書から補完を取得
- マッチがなく
fallback_to_ngram=True(またはインスタンスデフォルト)の場合、N-gram補完を返す - 直接プレフィックスマッチング
データ変換メソッド:
-
phrases_to_simple_suggestions(phrases: List[str], min_prefix_length: int = 1, max_prefix_length: int = 10) -> SimpleSuggestions(静的メソッド)- フレーズから文字ベースのプレフィックスマッピングを生成
- 各フレーズから1文字〜max_prefix_length文字までのプレフィックスを抽出
- SimpleSuggestions値オブジェクトを返す
-
phrases_to_ngram_data(phrases: List[str]) -> NgramData(静的メソッド)- フレーズをN-gramデータに変換(形態素情報含む)
- unigram/bigram/trigramのカウントと形態素情報を抽出
- NgramData値オブジェクトを返す
値オブジェクト型
SimpleSuggestions
- プレフィックス -> 補完候補リストのマッピングを保持する値クラス
data: Dict[str, List[str]]- プレフィックスから候補へのマッピングto_dict() -> Dict[str, List[str]]- 通常の辞書に変換- イミュータブル(frozen)
- バリデーション付き(空文字列キー禁止、空リスト禁止)
MorphToken
- 形態素トークン情報を保持する値クラス
surface: str- 表層形pos: str- 品詞base_form: str- 基本形- イミュータブル(frozen)
NgramData
- N-gramカウントと形態素情報を保持する値クラス
unigrams: Dict[str, int]- unigramカウントbigrams: Dict[str, Dict[str, int]]- bigramカウントtrigrams: Dict[Tuple[str, str], Dict[str, int]]- trigramカウントmorphology: Dict[str, MorphToken]- 形態素情報- バリデーション付き(正の整数カウントのみ)
NgramModel
メソッド:
add_ngram_data(data: NgramData) -> None- N-gramデータをモデルにマージ(破壊的更新)
- 既存のカウントに新しいカウントを加算
- 形態素情報を追加(既存のトークンは上書きしない)
- vocabulary_sizeを自動更新
スコアリングの仕組み
フレーズベース補完のスコアリング
フレーズベース補完は、プレフィックスマッチングと意味的類似性の両方を考慮したハイブリッドスコアリングアルゴリズムを使用します:
スコア構成要素:
- プレフィックスマッチ品質(60%): 入力がフレーズの先頭とどれだけよくマッチするか
- 形態素オーバーラップ(40%): 入力からの形態素(単語単位)がフレーズにいくつ現れるか
例:
# 完全な形態素オーバーラップを持つ長い入力
入力: "スマホの買い換え"
フレーズ: "スマホの買い換えと合わせて一式揃えたい"
スコア: 0.82 (高 - 良好なプレフィックスマッチ + すべての形態素が存在)
# 短い入力
入力: "スマホ"
フレーズ: "スマホの買い換えと合わせて一式揃えたい"
スコア: 0.75 (良好 - 短いプレフィックスだが形態素は存在)
# 完全一致
入力: "夏を爽やかに過ごしたい"
フレーズ: "夏を爽やかに過ごしたい"
スコア: 1.0 (完全一致)
このハイブリッドアプローチにより:
- 入力と正確に始まる補完が優先される
- 意味的に関連するフレーズ(キーワードを含む)がより高くランク付けされる
- より短く関連性の高い補完が不当にペナルティを受けない
N-gram補完の助詞拡張機能
N-gram補完は助詞で終わる候補を自動的に拡張する機能を持っています:
動作:
- 「今日は」のような助詞で終わる入力に対し、次に来る可能性の高い1〜3語を予測
- 元のスコアと次のトークンの確率を掛け合わせて総合スコアを算出
- 元の助詞終わりの候補と拡張された候補の両方を返す
例:
入力: "今日は"
結果(extend_particles=True):
- "今日は " (元の候補)
- "今日は晴れ" (拡張された候補)
- "今日は雨" (拡張された候補)
- "今日は良い天気" (拡張された候補)
結果(extend_particles=False):
- "今日は " (元の候補のみ)
セキュリティに関する考慮事項
重要: Pickleセキュリティ警告
N-gramモデルはPythonのpickleモジュールを使用してシリアライズされています。Pickleファイルは読み込み時に任意のコードを実行できます。
- ⚠️ 信頼できるソースからのモデルファイルのみを読み込んでください
- ⚠️ 不明または信頼できない出所の
.pklファイルを読み込まないでください - ⚠️ カスタムモデルを読み込むとセキュリティ警告が表示されます
# 安全: デフォルトモデルの使用(パッケージに含まれる)
completer = JaCompleter()
# 警告: カスタムモデルの読み込み(信頼できるファイルのみ使用!)
completer.load_ngram_model("custom_model.pkl") # セキュリティ警告が表示されます
詳細については、DEVELOPING.mdを参照してください。
カスタムN-gramモデルの構築
独自のN-gramモデルを構築したい上級ユーザー向け:
# Wikipedia抽出用にgensimをインストール
pip install gensim
# 日本語Wikipediaダンプをダウンロード
wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2
# gensimを使用してテキストを抽出(Python 3.13+推奨)
python extract_wiki_text.py
# またはWikiExtractorを使用(Python 3.12以前)
# python -m wikiextractor.WikiExtractor jawiki-latest-pages-articles.xml.bz2 -o wiki_text/
# N-gramモデルを構築
python scripts/build_ngram_model.py --input training_data/ --output my_model.pkl --verbose
Git LFS(Large File Storage)
このプロジェクトでは、モデルファイル(*.pkl)をGit LFSで管理しています。
開発者向け
リポジトリをクローンまたはプルする際に、Git LFSがインストールされていることを確認してください:
# Git LFSのインストール確認
git lfs version
# インストールされていない場合
# macOS:
brew install git-lfs
# Ubuntu/Debian:
sudo apt-get install git-lfs
# リポジトリでGit LFSを有効化
git lfs install
詳細なセットアップ手順については、docs/GIT_LFS_SETUP.mdを参照してください。
ユーザー向け
通常のpip install ja-completeまたはuv add ja-completeでは、PyPIから自動的にパッケージがインストールされます。Git LFSは不要です。
コントリビューション
コントリビューションを歓迎します!開発セットアップとガイドラインについては、DEVELOPING.mdを参照してください。
ライセンス
このプロジェクトはデュアルライセンス方式を採用しています:
ソースコード - MITライセンス
ソースコードはMITライセンスの下でライセンスされています。
Copyright (c) 2025 Taketo Yoda
N-gramモデルデータ - CC BY-SA 3.0
N-gramモデルファイル(*.pkl)はCC BY-SA 3.0の下でライセンスされています。
デフォルトモデルは日本語Wikipediaデータでトレーニングされています:
- ソース: 日本語Wikipedia
- ライセンス: CC BY-SA 3.0
- 著作権: © Wikipediaコントリビューター
- データセット: 約10万記事のサブセット
重要: N-gramモデルを配布または修正する場合、以下を行う必要があります:
- Wikipediaへの帰属表示を提供
- 行われた変更を示す
- CC BY-SA 3.0または互換性のあるライセンスの下で配布
詳細については、LICENSE-CC-BY-SA.txtを参照してください。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ja_complete-0.1.0.tar.gz.
File metadata
- Download URL: ja_complete-0.1.0.tar.gz
- Upload date:
- Size: 4.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5b3294671957017f8ccf32283bb4dd6bcf5884307d20771282ece2b289ffbfc
|
|
| MD5 |
93d240e0d4cba393a081a69a090d332f
|
|
| BLAKE2b-256 |
f3ed027ad7f5d6095cf0218713527da53142c70cd605d8df9f8a653a5cfb7eba
|
File details
Details for the file ja_complete-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ja_complete-0.1.0-py3-none-any.whl
- Upload date:
- Size: 4.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79093da6df0648c3bd49877396160dc99b14d576277fbe40a8c207d090430bc9
|
|
| MD5 |
e2872462376347b31bae4f2437acc077
|
|
| BLAKE2b-256 |
84683f6b45c3706be1caa9516bfedaff3e4fdc23ce7e5705d688b4b938af1990
|