mixedbread-ai/ Alibaba-NLP / OpenAI GPTによるリランキング【実装サンプル付き】

はじめに
RAGをはじめとする現代の情報検索システムでは、「リランカー(Reranker)」と呼ばれる仕組みが使われることがあります。
検索候補を単にキーワードマッチやベクトル検索でピックアップするだけでなく、さらに高精度なモデル(=リランカー)で再スコアリング(再ランキング)することで、ユーザーが本当に求めている情報を上位に表示できます。
本記事では、筆者が実際に業務中の検証作業で利用した次の3つのモデル:
mixedbread-ai/mxbai-rerank-v2
Alibaba-NLP/gte-multilingual
OpenAIのGPT(Chatモデルをリランカーとして活用)
を題材に、特徴や実装例を紹介します。
- mixedbread-ai/ Alibaba-NLP / OpenAI GPTによるリランキング【実装サンプル付き】
- はじめに
- 1. リランカーとは?
- 2. 各リランカーモデルの特徴
- 3. 実装サンプル
- 4. まとめ
- 参考リンク
1. リランカーとは?
リランカーは、情報検索の「第二段階目」を担う仕組みです。
一次検索: BM25などのキーワード検索やベクトル検索で候補文書を多数ピックアップ
リランカーによる再ランキング: 高度な意味理解や言語能力を持つモデルで、一次検索結果を再評価して順位付け
リランカーは、FAQ検索やナレッジベースのチャットボットなど、ユーザー体験の鍵となる部分で利用されています。
2. 各リランカーモデルの特徴
mixedbread-ai/mxbai-rerank-v2
2025年3月に公開された比較的新しめのモデル
Apache 2.0で公開されており、商用利用が可能
軽量モデルもありCPU環境でも使いやすい
専用のライブラリ(mxbai_rerank)から手軽に利用できる
Alibaba-NLP/gte-multilingual
中国の大企業Alibaba製
Hugging Faceでモデルが公開されており、transformersライブラリから簡単に利用できる
Apache 2.0で公開されており、商用利用が可能
70言語以上に対応している(らしい) ※ 日本語と英語に対応していることは確認済
OpenAI GPT(Chatモデルをリランカーとして利用)
専用のライブラリ(opeaai)やlangchainから簡単に利用できる
プロンプトによって挙動を柔軟に調整できる
高性能モデルを使う場合、高い精度が期待できる
API利用のため運用コスト・レイテンシには注意
3. 実装サンプル
上記3つのモデルを実装してみます。
それぞれのモデルの実装の互換性を保つために最初にデータクラスとリランカーの抽象クラスを実装しておきます。
from abc import ABC, abstractmethod from pydantic import BaseModel, Field class RankResult(BaseModel): index: int score: float document: str = "" class BaseReranker(ABC): @abstractmethod def rerank(self): pass
mixedbread-ai/mxbai-rerank-v2 を使ったリランカー
from mxbai_rerank import MxbaiRerankV2 class MxbaiReranker(BaseReranker): def __init__( self, model_name: str = "mixedbread-ai/mxbai-rerank-base-v2", ): self.model = MxbaiRerankV2(model_name, device="cpu") def rerank( self, query: str, documents: list[str], return_documents: bool = True, top_n: int = 3, ) -> list[RankResult]: results = self.model.rank( query, documents, return_documents=return_documents, top_k=top_n, ) return results mxbai_reranker = MxbaiReranker()
Alibaba-NLP/gte-multilingual を使ったリランカー
import torch from transformers import AutoModelForSequenceClassification, AutoTokenizer class AlibabaReranker(BaseReranker): def __init__( self, model_name: str = "Alibaba-NLP/gte-multilingual-reranker-base" ): self.tokenizer = AutoTokenizer.from_pretrained(model_name) self.model = AutoModelForSequenceClassification.from_pretrained( model_name, trust_remote_code=True, torch_dtype=torch.float32, ) self.model = self.model.to("cpu") self.model.eval() def rerank( self, query: str, documents: list[str], return_documents: bool = True, top_n: int = 3, ) -> list[RankResult]: pairs = [[query, doc] for doc in documents] with torch.no_grad(): inputs = self.tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512).to("cpu") scores = self.model(**inputs, return_dict=True).logits.view(-1, ).float() index = 0 rank_results = [] for p, s in zip(pairs, scores): rank_results.append( RankResult( index=index, score=s.item(), document=p[1] if return_documents else "", ) ) index += 1 rank_results.sort(key=lambda x: x.score, reverse=True) return rank_results[:top_n] alibaba_reranker = AlibabaReranker()
OpenAI GPT(gpt-4.1-mini)を使ったリランカー
import os from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI API_KEY = "XXXXX" os.environ["OPENAI_API_KEY"] = API_KEY RERANK_PROMPT = """queryとなるテキストと複数のテキストを含むtext_listが与えられます。 text_listの中のテキストとqueryの内容を比較し、queryの内容と近い順にtext_listのテキストを並べ替えなさい。 ***条件*** 1. queryとの内容が近い順に並べたテキストのインデックスとスコアのリストを返すこと。 2. スコアは0.0から1.0の範囲で、queryとの内容が近いほど高くなるようにすること。 """ class RerankedIndex(BaseModel): index: list[int] = Field( default=[], description="queryとの内容が近い順に並べたテキストのインデックスのリスト。" ) score: list[float] = Field( default=[], description="queryとの内容が近い順に並べたテキストのスコアのリスト。" ) class OpenaiReranker(BaseReranker): def __init__( self, model_name: str = "gpt-4.1-mini", ): self.model = ChatOpenAI( model=model_name, max_tokens=1000, # temperature=0.0, top_p=0.01, seed=42, ) self.prompt = ChatPromptTemplate.from_messages( [ ("system", RERANK_PROMPT), ("human", "query: '{query}'\ntext_list: '{text_list}'"), ]) self.chain = self.prompt | self.model.with_structured_output(RerankedIndex) def _rerank_text( self, query: str, text_list: str, ) -> int: res = self.chain.invoke({"query": query, "text_list": text_list}) return res def rerank( self, query: str, documents: list[str], return_documents: bool = True, top_n: int = 3, ) -> list[RankResult]: text_list = [f"{i}. {doc}" for i, doc in enumerate(documents)] text_list = "\n".join(text_list) res = _rerank_text(query, text_list) index_score_pairs = list(zip(res.index, res.score)) rank_results = [] for idx, score in index_score_pairs: rank_results.append( RankResult( index=idx, score=score, document=documents[idx] if return_documents else "", ) ) rank_results.sort(key=lambda x: x.score, reverse=True) return rank_results[:top_n] openai_reranker = OpenaiReranker()
リランキングの実行
実行例
test_query = "Give me the first document." test_documents = [ "This is the first document.", "This is the second document.", "This is the third document.", "This is the fourth document.", "This is the fifth document.", ] res_mxbai = mxbai_reranker.rerank(test_query, test_documents, return_documents=True, top_n=3) res_gte = alibaba_reranker.rerank(test_query, test_documents, return_documents=True, top_n=3) res_openai = openai_reranker.rerank(test_query, test_documents, return_documents=True, top_n=3)
4. まとめ
筆者の検証においてリランキングの精度は、
openai (gpt-4.1-mini) > mxbai > alibaba
といった結果になりました。
(精度は対象のテキスト群の内容によるところも大きいと思いますが...)、 実行コストが最も高いopenaiを使ったリランカーで最も良い結果が得られるのは妥当なように思います。
リランカーは検索体験の向上に役立ちます。各モデルの特性やプロダクト要件に応じて、最適な選択を検討してみてください!