使用 Cohere 和 BGE 进行交叉编码器重排
集成 Cohere 的重排端点和 BGE-reranker 模型,为查询-文档对评分,并依据真实相关性重新排列前 k 个分块。
使用 Cohere 和 BGE 进行交叉编码器重排 是 CoddyKit 上的免费 AI Engineering Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Engineering Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Engineering Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
What Is a Cross-Encoder?
A cross-encoder is a neural model that takes a query and a document as a single concatenated input and outputs a relevance score. Unlike a bi-encoder that embeds query and document separately, the cross-encoder's attention layers see both texts simultaneously, enabling it to model fine-grained relevance signals that a bi-encoder misses. This joint processing is what makes cross-encoders significantly more accurate at ranking.
# Bi-encoder: separate encoding
query_vec = encoder.encode(query) # [768] vector
doc_vec = encoder.encode(document) # [768] vector
score = cosine_similarity(query_vec, doc_vec) # compare independently
# Cross-encoder: joint encoding
combined_input = '[CLS] ' + query + ' [SEP] ' + document + ' [SEP]'
logits = cross_encoder.forward(combined_input) # score from joint attention
# The model attends from every query token to every document tokenThe Cohere Rerank API
Cohere Rerank is a cloud-hosted cross-encoder re-ranking API that accepts a query and a list of up to 1000 document texts and returns relevance scores. It uses large cross-encoder models trained on high-quality ranking datasets and consistently outperforms self-hosted small cross-encoders on most benchmarks. The API is priced per thousand documents re-ranked.
import cohere
co = cohere.Client('YOUR_COHERE_API_KEY')
candidates = [
'How to configure pgvector in PostgreSQL for vector search',
'BM25 scoring formula and hyperparameters explained',
'Installing and using the pgvector extension for embeddings',
'Hybrid search combining BM25 and dense retrieval',
]
result = co.rerank(
model='rerank-english-v3.0',
query='pgvector setup guide',
documents=candidates,
top_n=3,
return_documents=True,
)
for item in result.results:
print(f'Score {item.relevance_score:.4f}: {item.document.text[:60]}')Cohere Rerank in a RAG Pipeline
Integrating Cohere Rerank into a RAG pipeline follows a simple pattern: retrieve 20-50 candidates from your vector store, extract their text, call the Cohere Rerank API, and take the top-K results to pass to the LLM. The latency overhead is typically 100-300ms, which is acceptable when the improved precision leads to better final answers.
import cohere
from openai import OpenAI
co = cohere.Client('COHERE_KEY')
client = OpenAI()
def rag_with_rerank(question: str, retriever, top_k: int = 5) -> str:
# Stage 1: coarse retrieval
candidates = retriever.invoke(question) # returns 30 docs
texts = [doc.page_content for doc in candidates]
# Stage 2: Cohere re-ranking
rerank_result = co.rerank(
model='rerank-english-v3.0',
query=question,
documents=texts,
top_n=top_k,
)
top_texts = [texts[r.index] for r in rerank_result.results]
context = '\n\n'.join(top_texts)
# Stage 3: generation
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[
{'role': 'system', 'content': 'Answer using only the provided context.'},
{'role': 'user', 'content': f'Context:\n{context}\n\nQuestion: {question}'},
],
)
return response.choices[0].message.contentBGE Reranker: Open-Source Alternative
BGE Reranker (BAAI General Embedding) is an open-source family of cross-encoder models from the Beijing Academy of AI. The BAAI/bge-reranker-v2-m3 model supports multilingual re-ranking and achieves scores close to Cohere Rerank on English benchmarks while running locally. Use it with the sentence-transformers library for fully self-hosted re-ranking without API costs.
from sentence_transformers import CrossEncoder
# Load BGE reranker model
reranker = CrossEncoder(
'BAAI/bge-reranker-v2-m3',
max_length=512,
device='cpu', # use 'cuda' if GPU is available
)
def bge_rerank(query: str, documents: list[str], top_k: int = 5) -> list[dict]:
pairs = [[query, doc] for doc in documents]
scores = reranker.predict(pairs, show_progress_bar=False)
ranked = sorted(
zip(documents, scores.tolist()),
key=lambda x: x[1],
reverse=True,
)
return [{'text': doc, 'score': score} for doc, score in ranked[:top_k]]BGE Reranker Model Variants
The BGE reranker family offers size-quality trade-offs. bge-reranker-base (278M parameters) is the fastest and smallest. bge-reranker-large (560M parameters) is more accurate. bge-reranker-v2-m3 supports multiple languages and is the recommended default for production. For maximum accuracy, bge-reranker-v2-gemma uses a Gemma backbone and leads most English benchmarks among open-source options.
# Model size vs accuracy trade-offs
models = [
('BAAI/bge-reranker-base', '278M params', 'fast, English-focused'),
('BAAI/bge-reranker-large', '560M params', 'better, English-focused'),
('BAAI/bge-reranker-v2-m3', '570M params', 'best for multilingual use'),
('BAAI/bge-reranker-v2-gemma', '2B params', 'SOTA open-source accuracy'),
]
# For most RAG applications, bge-reranker-v2-m3 offers the best
# balance of accuracy, multilingual support, and inference speed on CPUBatching Cross-Encoder Predictions
Cross-encoders process (query, document) pairs one by one by default, but batch prediction dramatically improves throughput by running multiple pairs through the model simultaneously. The batch_size parameter controls how many pairs are processed together. On GPU, batch sizes of 32-128 are typical. On CPU, smaller batches of 4-16 reduce memory pressure while still improving throughput over sequential processing.
def batch_rerank(reranker, query: str, documents: list[str],
top_k: int = 5, batch_size: int = 32) -> list[dict]:
pairs = [[query, doc] for doc in documents]
# Batch prediction
all_scores = reranker.predict(
pairs,
batch_size=batch_size,
show_progress_bar=len(pairs) > 100,
)
ranked = sorted(
zip(documents, all_scores.tolist()),
key=lambda x: x[1],
reverse=True,
)
return [{'text': doc, 'score': score} for doc, score in ranked[:top_k]]LangChain CrossEncoderReranker Integration
LangChain provides CrossEncoderReranker as a document compressor that integrates cross-encoder re-ranking into the ContextualCompressionRetriever pattern. This lets you wrap any existing retriever with a re-ranking stage using just a few lines of code, and plug it into any LCEL chain that accepts a retriever interface.
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
# Base retriever (coarse stage)
base_retriever = FAISS.from_documents(
documents, OpenAIEmbeddings()
).as_retriever(search_kwargs={'k': 30})
# Re-ranker (fine stage)
model = HuggingFaceCrossEncoder(model_name='BAAI/bge-reranker-v2-m3')
compressor = CrossEncoderReranker(model=model, top_n=5)
# Combined two-stage retriever
two_stage_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=base_retriever,
)
docs = two_stage_retriever.invoke('how does hybrid search work?')Scoring Interpretation and Thresholding
Cross-encoder scores do not have a universal scale. BGE reranker outputs raw logits (often in the range -10 to +10) while Cohere returns a normalized relevance score between 0 and 1. You can apply a minimum score threshold to exclude very low-relevance documents from the context sent to the LLM, reducing noise even further. Start with a threshold at the 25th percentile of scores and tune from there.
def rerank_with_threshold(reranker, query, documents, top_k=5, min_score=-2.0):
pairs = [[query, doc] for doc in documents]
scores = reranker.predict(pairs)
scored_docs = [
{'text': doc, 'score': float(score)}
for doc, score in zip(documents, scores)
if float(score) >= min_score # filter low-relevance docs
]
scored_docs.sort(key=lambda x: x['score'], reverse=True)
if not scored_docs:
return [] # nothing passed the threshold
return scored_docs[:top_k]Cohere vs BGE: Which to Choose
Use Cohere Rerank when you want a managed API, need the highest accuracy on English enterprise data, and want to avoid GPU infrastructure. Use BGE Reranker when you need to self-host for data privacy, want zero per-query API cost, need multilingual support, or want to run offline. Both achieve similar NDCG scores on most benchmarks — the choice is primarily about infrastructure preferences and cost model.
Re-ranking Multilingual Content
If your corpus or users span multiple languages, choose a multilingual cross-encoder. bge-reranker-v2-m3 handles over 100 languages, and Cohere Rerank has a multilingual model variant. Cross-lingual re-ranking — scoring an English query against documents in French or Spanish — is also supported, which is useful in global enterprise deployments where knowledge bases exist in multiple languages.
from sentence_transformers import CrossEncoder
# Multilingual BGE reranker
ml_reranker = CrossEncoder('BAAI/bge-reranker-v2-m3')
# Cross-lingual example: English query, French document
query_en = 'How to configure vector search?'
doc_fr = 'La configuration de la recherche vectorielle dans PostgreSQL'
score = ml_reranker.predict([[query_en, doc_fr]])
print(f'Cross-lingual relevance score: {float(score):.3f}')
# Positive score indicates the document is relevant to the query
# despite being in a different languageCaching Re-ranking Results
Cross-encoder inference is the slowest part of a two-stage pipeline. For applications where the same (query, document) pairs recur frequently, caching re-ranking results can eliminate redundant inference. Hash the (query, document_id) pair as a cache key and store the score in Redis with a TTL. Cache hit rates of 30-50 percent are common in customer support applications where users frequently ask similar questions.
import redis
import hashlib
import json
r = redis.Redis(host='localhost', port=6379)
def cached_rerank_score(reranker, query: str, doc_text: str, doc_id: str) -> float:
cache_key = 'rerank:' + hashlib.md5((query + doc_id).encode()).hexdigest()
cached = r.get(cache_key)
if cached:
return float(cached)
score = float(reranker.predict([[query, doc_text]]))
r.setex(cache_key, 3600, str(score)) # cache 1 hour
return scoreQuick Check
Test your understanding of cross-encoder re-ranking from this lesson.
Lesson Recap
In this lesson you learned: Cohere Rerank provides a cloud-hosted cross-encoder API with state-of-the-art accuracy, BGE Reranker is an open-source alternative for self-hosted deployment including multilingual content, and batching dramatically improves throughput when scoring many (query, document) pairs. LangChain's CrossEncoderReranker integrates both into the ContextualCompressionRetriever pattern. Next up we implement contextual compression to reduce noise in retrieved chunks.
常见问题解答
「使用 Cohere 和 BGE 进行交叉编码器重排」课时是免费的吗?
是的 — 「使用 Cohere 和 BGE 进行交叉编码器重排」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Engineering Academy 课程的其余内容,请升级到 CoddyKit PRO。 AI Engineering Academy 课程共包含 4 节课。
「使用 Cohere 和 BGE 进行交叉编码器重排」这节课中我会学到什么?
集成 Cohere 的重排端点和 BGE-reranker 模型,为查询-文档对评分,并依据真实相关性重新排列前 k 个分块。 你通过在浏览器中直接运行的动手代码来练习 AI Engineering Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Engineering Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Engineering Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 Cohere 和 BGE 进行交叉编码器重排」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Engineering Academy 课中编写并运行代码吗?
能。每节 AI Engineering Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 两阶段检索为何有效
- 使用 Cohere 和 BGE 进行交叉编码器重排
- 上下文压缩与相关性过滤
- 衡量重排的影响