GYOM15
Deploy the RAG comparison app
45d0949
Raw
History Blame Contribute Delete
2.23 kB
"""Embedding provider based on sentence-transformers."""
import numpy as np
from sentence_transformers import SentenceTransformer
def _infer_prefixes(model_name: str) -> tuple[str, str]:
"""Prefixes (query, document) expected by certain model families.
e5 requires "query: " / "passage: "; bge recommends an instruction on the
query side. The others (MiniLM, gte...) do not use any.
"""
name = model_name.lower()
if "e5" in name:
return "query: ", "passage: "
if "bge" in name:
return "Represent this sentence for searching relevant passages: ", ""
return "", ""
class EmbeddingModel:
"""Wrap sentence-transformers and handle the query/document prefixes.
The model is selected by `model_name` (all-MiniLM-L6-v2 by default); the
prefixes are inferred from the name but remain overridable.
"""
def __init__(
self,
model_name: str = "all-MiniLM-L6-v2",
query_prefix: str | None = None,
doc_prefix: str | None = None,
):
self.model = SentenceTransformer(model_name)
inferred_q, inferred_d = _infer_prefixes(model_name)
self.query_prefix = inferred_q if query_prefix is None else query_prefix
self.doc_prefix = inferred_d if doc_prefix is None else doc_prefix
# `get_sentence_embedding_dimension` was recently renamed `get_embedding_dimension`.
if hasattr(self.model, "get_embedding_dimension"):
self.dimension = self.model.get_embedding_dimension()
else:
self.dimension = self.model.get_sentence_embedding_dimension()
def encode(self, texts: list[str], batch_size: int = 32) -> np.ndarray:
"""Encode documents into vectors, shape (len(texts), dimension)."""
if self.doc_prefix:
texts = [self.doc_prefix + t for t in texts]
return self.model.encode(
texts,
show_progress_bar=True,
convert_to_numpy=True,
batch_size=batch_size,
)
def encode_query(self, query: str) -> np.ndarray:
"""Encode a query into a 1-D vector of shape (dimension,)."""
return self.model.encode([self.query_prefix + query], convert_to_numpy=True)[0]