Pythonで自然言語処理やRAGの実験をしていると、次のようなことを試したくなることがあります。
- 日本語テキストを検索したい
- Elasticsearch / OpenSearch / Solr のような検索エンジンの動きを軽く試したい
- ベクトル検索も試したい
- Google Colab や Jupyter Notebook 上で簡単に検索実験をしたい
- ただし、検索サーバーや Docker は立てたくない
そのような用途向けに、nlp4j-local-search にベクトル検索機能を追加しました。
GitHub:
https://github.com/oyahiroki/nlp4j-local-search
nlp4j-local-search とは
nlp4j-local-search は、Python からローカルで手軽に検索インデックスを作成して検索できるライブラリです。
特徴は次のとおりです。
- Python から利用できる
- 日本語キーワード検索ができる
- ベクトル検索ができる
- Elasticsearch / OpenSearch / Solr のインストールが不要
- Docker も不要
- Jupyter Notebook / Google Colab でも試しやすい
- 内部的には Apache Lucene ベースの検索機能を利用
大規模な本番検索システムを置き換えるものではなく、自然言語処理やRAGの実験で「まず検索を試したい」場合に使うことを想定しています。
インストール
現時点では GitHub から直接インストールします。
!pip install git+https://github.com/oyahiroki/nlp4j-local-search.git
インストール後、次のように確認できます。
!pip list | grep nlp4j
例:
nlp4j-local-search 0.2.0
日本語キーワード検索の例
まずは日本語のキーワード検索を試します。
from nlp4j_local_search import SearchEngine
# 検索エンジンを初期化(日本語モード)
engine = SearchEngine("ja")
ドキュメントを追加します。
engine.add("1", "東京都は日本の都道府県のひとつです")
engine.add("2", "京都は日本の都市です")
engine.add("3", "京都市には任天堂の本社があります")
engine.add_json({"id": "4", "body": "京都府は広いです"}) # JSON形式もOK
engine.add_json({"id": "5", "body": "大阪は関西の大都市です"})
追加したドキュメントをインデックスに反映します。
engine.commit()
print("インデックスのコミットが完了しました")
「京都」で検索します。
results = engine.search("京都", limit=10)
for r in results:
print(f"ID: {r.id}, Score: {r.score:.4f}")
print(f"Body: {r.body}")
print("-" * 50)
出力例:
ID: 2, Score: 0.2729
Body: 京都は日本の都市です
--------------------------------------------------
ID: 4, Score: 0.2729
Body: 京都府は広いです
--------------------------------------------------
ID: 3, Score: 0.2450
Body: 京都市には任天堂の本社があります
--------------------------------------------------
ここで重要なのは、単なる文字列の部分一致検索ではないことです。
たとえば単純な部分一致であれば、東京都 の中にも 京都 という文字列が含まれるため、東京都は日本の都道府県のひとつです もヒットしてしまう可能性があります。
しかし日本語の全文検索では、東京都 と 京都 を単純な文字列包含だけで扱うのではなく、検索用に解析された語として扱います。
そのため、日本語検索の実験に使いやすくなっています。
ベクトル検索の例
次に、今回追加したベクトル検索を試します。
ここでは説明しやすいように、2次元ベクトルを使います。
from nlp4j_local_search import SearchEngine
# 日本語モード + 2次元ベクトル検索
engine = SearchEngine(lang="ja", vector_dimension=2)
東西南北を2次元ベクトルとして登録します。
engine.add("1 East", [1.0, 0.0]) # 東
engine.add("2 North", [1.0, 1.0]) # 北東
engine.add("3 West", [-1.0, 0.0]) # 西
engine.add("4 South", [-1.0, -1.0]) # 南西
engine.commit()
クエリーベクトルを指定して検索します。
query_vector = [0.9, 0.1]
print("クエリベクトル:", query_vector)
for r in engine.search(query_vector, limit=10):
print(f"{r.id}: body={r.body} score={r.score}")
出力例:
クエリベクトル: [0.9, 0.1]
1 East: body=None score=0.9969
2 North: body=None score=0.8904
4 South: body=None score=0.1095
3 West: body=None score=0.0036
[0.9, 0.1] は [1.0, 0.0] に近いので、East が最も高いスコアで返ってきます。
このように、ベクトルを登録しておけば、クエリーベクトルに近いデータを検索できます。
キーワード検索とベクトル検索を同じ感覚で使える
nlp4j-local-search では、キーワード検索もベクトル検索も SearchEngine から利用できます。
キーワード検索:
results = engine.search("京都", limit=10)
ベクトル検索:
results = engine.search([0.9, 0.1], limit=10)
自然言語処理の実験では、キーワード検索とベクトル検索を比較したいことがあります。
たとえば次のような用途です。
- キーワード検索の結果と embedding 検索の結果を比較する
- RAG の検索部分だけをローカルで試す
- 小さなデータセットで検索ロジックを検証する
- 単体テスト用に一時的な検索インデックスを作る
- Google Colab 上で検索の挙動を確認する
Elasticsearch や OpenSearch を立てる前に、まずローカルで検索の感触を確認できます。
Elasticsearch サーバーが不要
検索エンジンを使おうとすると、通常は次のような準備が必要になります。
- Elasticsearch をインストールする
- OpenSearch をインストールする
- Solr をインストールする
- Docker Compose を用意する
- ポート番号やメモリ設定を調整する
- インデックス定義やマッピングを作る
もちろん本格的な検索システムではこれらが必要になります。
しかし、自然言語処理の実験やNotebook上での検証では、そこまでの準備が重く感じることがあります。
nlp4j-local-search では、Pythonコードの中で検索エンジンを初期化して、その場でドキュメントを追加し、検索できます。
from nlp4j_local_search import SearchEngine
with SearchEngine("ja") as engine:
engine.add("1", "京都は日本の都市です")
engine.add("2", "大阪は関西の大都市です")
engine.commit()
for r in engine.search("京都", limit=10):
print(r.id, r.body, r.score)
このように、検索サーバーを起動せずに、Pythonのコードだけで検索実験を始められます。
どのような用途に向いているか
nlp4j-local-search は、特に次のような用途に向いています。
1. NLP実験
Wikipedia由来のテキスト、辞書データ、JSONLデータなどを対象に、検索結果を確認する用途です。
2. RAGのプロトタイピング
本格的なベクトルDBや検索サーバーを用意する前に、検索部分の動きをローカルで確認できます。
3. キーワード検索とベクトル検索の比較
embedding モデルの評価では、キーワード検索の結果とベクトル検索の結果を比較したいことがあります。
小規模な評価データであれば、ローカルで簡単に確認できます。
4. Google Colab / Jupyter Notebook での検索実験
Notebook上で検索用のインデックスを一時的に作り、実験が終わったら破棄するような使い方に向いています。
5. 単体テスト
検索処理を含むアプリケーションのテストで、一時的な検索インデックスを作ることができます。
注意点
現時点では、主に実験・検証用途を想定しています。
本番環境で大規模データを扱う検索システムを作る場合は、Elasticsearch、OpenSearch、Solr、Milvusなどの利用を検討するのがよいと思います。
一方で、次のような段階では nlp4j-local-search が便利です。
- まず検索の挙動を確認したい
- 小さなデータでPoCしたい
- Notebookで検索実験したい
- キーワード検索とベクトル検索を比較したい
- 検索サーバーを立てる前にロジックを検証したい
まとめ
nlp4j-local-search にベクトル検索機能を追加しました。
これにより、Pythonから次の検索を手軽に利用できます。
- 日本語キーワード検索
- 英語キーワード検索
- JSONドキュメントの追加
- ベクトル検索
- インメモリ検索
Elasticsearch / OpenSearch / Solr / Docker を用意しなくても、Pythonだけで検索実験を始められます。
自然言語処理、RAG、embedding評価、検索ロジックの検証などで、軽量なローカル検索エンジンとして活用できます。
関連ページ