プログラミング

日本語を含むRAGでのEmbeddingモデルの探し方

Embeddingは意味検索やRAGの土台となりますが、英語で学習されたembeddingモデルを日本語の文章に対して適用すると精度が出ないことがあります。

この記事では、日本語を含むRAGでembeddingモデルを選ぶときの注意点を整理し、最後にモデルを使う手順をハンズオンで確認します。

動作確認

Python 3.12/sentence-transformers 5.6.0/transformers 5.14.1/torch 2.13.0/numpy 2.5.1で確認しています。

本文の記述は2026年7月時点のものです。

目次

はじめに

ライブラリとして以下を使用します。

pip install sentence-transformers

# uvの場合
uv add sentence-transformers

英語中心モデルで日本語を扱った場合の問題点

英語を中心に学習したモデルは、日本語の文をほとんど見ていないため、日本語の意味の関係(在宅勤務とリモートワークが近い等)をベクトルに反映することができません。

また、モデルは文をそのまま扱うのではなく、トークナイザを用いて「トークン」という小さい単位に分割してから処理をしますが、英語中心のモデルのトークナイザは日本語の語彙を持たないことが多く、日本語の文を意味の単位ごとに切り出すことができません。どのように問題が現れるかはトークナイザの方式によって違います。

例えばe5-small-v2はWordPieceという方式を使っており、語彙にない文字のまとまりは未知語([UNK])に置き換えられます。未知語になった部分は中身の情報が失われます。以下は、e5-small-v2モデルを使って日本語の文章をトークンに分割しています。

from transformers import AutoTokenizer

# 英語中心のモデルe5-small-v2のトークナイザを読み込む
tok = AutoTokenizer.from_pretrained("intfloat/e5-small-v2")
# 分割対象の日本語の文
text = "在宅勤務は週3日まで認められています。"
# トークンに分割する
toks = tok.tokenize(text)
# 分割結果を表示する
print(toks)

トークンへの分割結果は以下のようになります。

['[UNK]', '[UNK]', '[UNK]', '[UNK]', 'は', '[UNK]', '3', '日', 'ま', '##て', '[UNK]', 'め', '##ら', '##れ', '##て', '##い', '##ま', '##す', '。']

「在宅勤務」や「認められています」といった語句が[UNK]によって潰れてしまっています。

これらが、英語中心モデルを日本語文に適用すると精度が落ちる主な原因になります。

日本語で使えるモデルの選択肢

日本語で使えるembeddingモデルは大きく、「日本語特化」と「多言語」の2つの系統に分かれます。

モデル概要
日本語特化モデル日本語のデータを中心に学習・調整がされているモデルです。日本語専用の語彙を持つことが多く、日本語のみを扱う用途で候補になります。たとえば、名古屋大学の研究グループ(cl-nagoya)が公開しているRuri v3があります。
多言語モデル複数の言語のデータを一緒に学習させ、日本語も英語も同じベクトル空間に載せられるモデルです。日英が混在するデータに使いやすい選択肢になります。たとえば、intfloatが公開している多言語モデルmultilingual-e5や北京の研究機関BAAIが公開しているbge-m3などがあります。

なお、日本語の質問文で英語の文書を引くような、言語をまたぐ検索(クロスリンガル検索)をする場合は、日本語と英語の両方を学習している多言語モデルを使います。

どのようなモデルがあるかを調べるには、Hugging Faceで公開ベンチマークを見るのが手っ取り早い方法です。

補足:モデルの入れ替わりは速い

この分野はモデルの入れ替わりが速く、モデルの数も増えています。モデルを選ぶ前に次節で述べているJMTEBなどのベンチマークで最新の状況を確認するのがよいです。

日本語のベンチマークと評価用データセット

英語と多言語のベンチマークはそれぞれMTEB(Massive Text Embedding Benchmark)とMMTEB(Massive Multilingual Text Embedding Benchmark)が代表的です。これらは、Hugging Faceのリーダーボードで公開されています。

https://huggingface.co/spaces/mteb/leaderboard

多言語に対するベンチマークを見たい場合は「Multilingual」をクリックし、英語に対するベンチマークを見たい場合は「English」をクリックします。

クリックすると、モデル一覧とスコアが表示されます。

しかし、これらのスコアが高いことは日本語での性能を必ずしも保証しないため、日本語には次のような専用の評価用データセットとベンチマークも公開されています。

名称(リンク)内容
JMTEB日本語の埋め込みモデルを、検索・分類・意味的類似度など多くのタスクで総合評価するベンチマーク。
JQaRA
RAGを想定した日本語のQ&A検索評価データセット。検索でどれだけ回答に役立つ文書を引けるかを測ります。
JaCWIR日本語Webの記事タイトルや概要を使った情報検索の評価データセット。

Hugging FaceのLeaderboardでは、JMTEBの評価結果も公開されています。Hugging FaceのLeaderboardの「Language」を開き、「Japanese」をクリックします。

https://huggingface.co/spaces/mteb/leaderboard

すると、同様にモデル一覧とスコアを見ることができます。

スコア表に使われている代表的な列名とその意味を以下にまとめます(MTEBJMTEBで含まれる列名が異なりますが、どちらも入れています)。

なお、Leaderboardの表を読むには、「タスク」と「タスクの種類」の関係を知っておくとわかりやすくなります。

  • タスクとは、個々の評価用データセットのことです。たとえば「JSTS」というタスクは、日本語の文のペアに人間が付けた類似度が入ったデータセットです。JMTEB v2.0にはこうしたタスクが28個あります。
  • タスクの種類とは、タスクの分類のことです。たとえば、「JSTS」は「STS」(意味的類似度を測るタスク群)に属し、「JaqketRetrieval」は「Retrieval」(検索の精度を測るタスク群)に属します。

モデルの特性と総合評価、ベンチマークの公正さを示すものとして、次のパラメータがあります。

列名意味
Rankボルダ得点により評価したモデルの総合順位
Modelモデルの名前
Total Paramsモデルのパラメータ数
Zero-shot評価に用いた全タスクの内、そのモデルの学習データに含まれていなかったタスクの割合。高いほど評価は公正

また、モデルの性能を測るスコアとして、全タスクのスコア平均やタスクの種類に属する各タスクのスコア平均が公開されています。

列名何の平均化何を測っているか
Mean (Task)全タスクのスコア平均モデル全体としての総合的な強さ
Mean (TaskType)タスクの種類ごとにスコア平均を計算し、それをさらに種類間で平均したものタスクの種類ごとのタスク数の偏りを均一にした総合的な強さ(タスクの種類ごとに一旦平均することで、タスクの種類ごとの重みが均一になる)
Class.Classification(分類)というタスク種類に属する、各タスクのスコアの平均文章を決まったカテゴリに正しく振り分けられるか(例:レビューが好意的か否定的か)
Clust.Clustering(クラスタリング)というタスク種類に属する、各タスクのスコアの平均似た文章どうしを、正解のグループに近い形でまとめられるか
Rerank / Instr RerankReranking(並べ替え)というタスク種類に属する、各タスクのスコアの平均検索結果の候補を、関連度が高い順に正しく並べ替えられるか(Instr Rerankはクエリに「〜について」といった指示が付く形式)
Retr.Retrieval(検索)というタスク種類に属する、各タスクのスコアの平均クエリに対して、正解の文書を上位に検索できるか
STSSemantic Textual Similarity(意味的類似度)というタスク種類に属する、各タスクのスコアの平均2つの文が意味的にどれくらい似ているかを、人間の判定にどれだけ近く言い当てられるか
BitextBitext Mining(対訳マイニング)というタスク種類に属する、各タスクのスコアの平均2つの言語の文の集まりから、対応する翻訳ペアを正しく見つけられるか
MultiClass.Multilabel Classification(マルチラベル分類)というタスク種類に属する、各タスクのスコアの平均1つの文章に複数のラベルが付く場合に、それらを正しく当てられるか
PairClass.Pair Classification(ペア分類)というタスク種類に属する、各タスクのスコアの平均2つの文が同じ意味かどうかを、Yes/Noで正しく判定できるか

日本語のEmbeddingモデルを使ってみる

Hugging faceのJMTEBのスコア表の中からCPUでも動く軽めのモデルruri-v3-30mを使用してみます。スコア表からモデル名をクリックすると、次のページが現れます。

この中の「Reference」にあるURLをクリックすると、Hugging Face内のそのモデルに関するページに飛びます。そのページの「Usage」に使い方が載っています。

「他のモデルの使い方」を調べる場合も大体同じ流れです。

あとは、サンプルを参考にして、コードを書くだけです。コードの意味については、別記事「Embeddingモデルを用いて文をベクトルに変換する」を参照します。

import torch
import numpy as np
from sentence_transformers import SentenceTransformer

# モデルカードのUsageに従う
device = "cuda" if torch.cuda.is_available() else "cpu"
model = SentenceTransformer("cl-nagoya/ruri-v3-30m", device=device)

# プレフィックス
QUERY_PREFIX = "検索クエリ: "
DOC_PREFIX = "検索文書: "

# 検索対象の文書
docs = [
    "リモートワークは週に3回まで認められています。",
    "経費の精算は毎月20日が締め切りです。",
    "健康診断は毎年11月に実施します。",
    "有給休暇は入社から半年後に付与されます。",
]

# 文書側にプレフィックスを付けてベクトル化
doc_embeddings = model.encode(
    [DOC_PREFIX + d for d in docs],
    normalize_embeddings=True,
)

# クエリ(文書側にはない言い換え)
query = "在宅勤務は何日できますか?"

# クエリ側にプレフィックスを付けてベクトル化
query_embedding = model.encode(
    QUERY_PREFIX + query,
    normalize_embeddings=True,
)

# コサイン類似度(正規化しているので内積と同じ。@は行列積)
similarities = doc_embeddings @ query_embedding

# 類似度が高い順に並べて表示
ranking = sorted(enumerate(similarities), key=lambda x: x[1], reverse=True)
print(f"クエリ: {query}")
print("類似度が高い順:")
for rank, (idx, sim) in enumerate(ranking, 1):
    print(f"  {rank}. 類似度 {sim:.3f}  {docs[idx]}")

実行すると、次の結果が得られました。

クエリ: 在宅勤務は何日できますか?
類似度が高い順:
  1. 類似度 0.901  リモートワークは週に3回まで認められています。
  2. 類似度 0.830  経費の精算は毎月20日が締め切りです。
  3. 類似度 0.808  有給休暇は入社から半年後に付与されます。
  4. 類似度 0.794  健康診断は毎年11月に実施します。

このクエリに対しては、もっとも意味をくみ取った回答が得られましたが、クエリを変えると、次のように人間の判断とは異なる回答が得られる場合もあります。

クエリ: 休暇を取得したいのですが決まりはありますか?
類似度が高い順:
  1. 類似度 0.840  経費の精算は毎月20日が締め切りです。
  2. 類似度 0.835  有給休暇は入社から半年後に付与されます。
  3. 類似度 0.807  リモートワークは週に3回まで認められています。
  4. 類似度 0.789  健康診断は毎年11月に実施します。

このように実際にクエリを色々と変換してみて、自分の目的に合った精度が得られるかを確認しておくことが大事です。

その他、全角・半角の違いや表記ゆれを揃えるように前処理しておくと、embeddingの精度が改善することがあります。

まとめ

日本語を含むRAGでembeddingモデルを選ぶときの注意点を整理しました。要点は次のとおりです。

  • 英語中心のモデルは、日本語を学習していないうえに、トークナイザの方式によっては重要な語が未知語に置き換えられ、意味を捉えられなくなります。
  • 日本語で使えるモデルには、日本語特化と多言語があります。日英が混在するならば多言語が扱いやすいです。
  • 日本語でのRAGを行う場合には、英語のベンチマーク(MTEB)だけを見ず、日本語専用のベンチマーク(JMTEBなど)も確認することが重要です。
  • モデルは入れ替わりが速いので、特定モデルの使い方を覚えるのではなく、モデルカードのUsageから使い方を読み取ります。

参考資料

-プログラミング
-, ,