Text Ranking
sentence-transformers
Safetensors
Transformers
multilingual
t5gemma2
text2text-generation
reranker
encoder-decoder
FBNL
matryoshka
retrieval
RAG
Instructions to use KaLM-Embedding/KaLM-Reranker-V1-Large-R2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- sentence-transformers
How to use KaLM-Embedding/KaLM-Reranker-V1-Large-R2 with sentence-transformers:
from sentence_transformers import CrossEncoder model = CrossEncoder("KaLM-Embedding/KaLM-Reranker-V1-Large-R2") query = "Which planet is known as the Red Planet?" passages = [ "Venus is often called Earth's twin because of its similar size and proximity.", "Mars, known for its reddish appearance, is often referred to as the Red Planet.", "Jupiter, the largest planet in our solar system, has a prominent red spot.", "Saturn, famous for its rings, is sometimes mistaken for the Red Planet." ] scores = model.predict([(query, passage) for passage in passages]) print(scores) - Transformers
How to use KaLM-Embedding/KaLM-Reranker-V1-Large-R2 with Transformers:
# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("KaLM-Embedding/KaLM-Reranker-V1-Large-R2") model = AutoModelForMultimodalLM.from_pretrained("KaLM-Embedding/KaLM-Reranker-V1-Large-R2", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Update README.md
Browse files
README.md
CHANGED
|
@@ -157,6 +157,188 @@ On LMEB-Dialogue, a compact embedding model paired with our Nano reranker, which
|
|
| 157 |

|
| 158 |

|
| 159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
#### Ablation on multi-stage training
|
| 161 |
|
| 162 |
Across all three model sizes and all seven compression ratios, performance on BEIR and MIRACL improves consistently from Stage 1 to Stage 3, demonstrating the effectiveness of our multi-stage training pipeline. Concretely, Stage 1 establishes a robust foundation for document reranking, distillation in Stage 2 substantially improves performance, and Stage 3 yields further modest gains. More importantly, robustness to compression generally improves across the three training stages. For example, from Stage 1 to Stage 3, the performance retention of KaLM-Reranker-V1-Nano at r = 128 relative to r = 2 increases from 92.88% to 93.80% on BEIR and from 90.93% to 92.15% on MIRACL.
|
|
|
|
| 157 |

|
| 158 |

|
| 159 |
|
| 160 |
+
### Using Sentence Transformers
|
| 161 |
+
|
| 162 |
+
KaLM-Reranker-V1-Large-R2 can be loaded as a modular Sentence Transformers
|
| 163 |
+
`CrossEncoder`. This integration requires `sentence-transformers>=5.6,<6`,
|
| 164 |
+
`transformers>=5.3,<6`, and the PyTorch backend. The repository contains custom
|
| 165 |
+
modeling code, so load only trusted revisions and pass `trust_remote_code=True`.
|
| 166 |
+
|
| 167 |
+
```bash
|
| 168 |
+
pip install "sentence-transformers>=5.6,<6" "transformers>=5.3,<6"
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
```python
|
| 172 |
+
import torch
|
| 173 |
+
from sentence_transformers import CrossEncoder
|
| 174 |
+
|
| 175 |
+
model = CrossEncoder(
|
| 176 |
+
"KaLM-Embedding/KaLM-Reranker-V1-Large-R2",
|
| 177 |
+
trust_remote_code=True,
|
| 178 |
+
device="cuda",
|
| 179 |
+
model_kwargs={"dtype": torch.bfloat16, "chunk_size": 4},
|
| 180 |
+
)
|
| 181 |
+
|
| 182 |
+
query = "What is the capital of China?"
|
| 183 |
+
documents = [
|
| 184 |
+
"The capital of China is Beijing.",
|
| 185 |
+
"Gravity attracts bodies toward one another.",
|
| 186 |
+
]
|
| 187 |
+
pairs = [(query, document) for document in documents]
|
| 188 |
+
|
| 189 |
+
# The default output is P(yes).
|
| 190 |
+
scores = model.predict(pairs)
|
| 191 |
+
rankings = model.rank(query, documents, return_documents=True)
|
| 192 |
+
|
| 193 |
+
# CrossEncoder prompts are interpreted as KaLM task instructions.
|
| 194 |
+
instruction = "Given a web search query, retrieve passages that answer the query."
|
| 195 |
+
custom_scores = model.predict(pairs, prompt=instruction)
|
| 196 |
+
custom_rankings = model.rank(query, documents, prompt=instruction)
|
| 197 |
+
|
| 198 |
+
# Use Identity to return yes_logit - no_logit instead of P(yes).
|
| 199 |
+
margins = model.predict(pairs, activation_fn=torch.nn.Identity())
|
| 200 |
+
|
| 201 |
+
print(f"scores: {scores}")
|
| 202 |
+
print(f"rankings: {rankings}")
|
| 203 |
+
print(f"custom_scores: {custom_scores}")
|
| 204 |
+
print(f"custom_rankings: {custom_rankings}")
|
| 205 |
+
print(f"margins: {margins}")
|
| 206 |
+
|
| 207 |
+
'''
|
| 208 |
+
scores: [9.8677725e-01 9.0574264e-05]
|
| 209 |
+
rankings: [{'corpus_id': 0, 'score': 0.98677725, 'text': 'The capital of China is Beijing.'}, {'corpus_id': 1, 'score': 9.057426e-05, 'text': 'Gravity attracts bodies toward one another.'}]
|
| 210 |
+
custom_scores: [9.7241479e-01 3.2129523e-05]
|
| 211 |
+
custom_rankings: [{'corpus_id': 0, 'score': 0.9724148}, {'corpus_id': 1, 'score': 3.2129523e-05}]
|
| 212 |
+
margins: [ 4.3125 -9.30925]
|
| 213 |
+
'''
|
| 214 |
+
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
Inputs must be ordered as `(query, document)`. By default, queries are
|
| 218 |
+
truncated to 512 tokens and documents to 1024 tokens. `chunk_size=4` performs a
|
| 219 |
+
mask-aware mean over each consecutive group of four encoder token states before
|
| 220 |
+
passing the compressed encoder output to the decoder. Set `chunk_size=None` to
|
| 221 |
+
disable compression, or change `model[0].chunk_size` after loading.
|
| 222 |
+
|
| 223 |
+
For CPU inference, use `device="cpu"` and
|
| 224 |
+
`model_kwargs={"dtype": torch.float32, "chunk_size": 4}`. Only the PyTorch
|
| 225 |
+
inference backend is currently supported; training, ONNX, and OpenVINO are not
|
| 226 |
+
included in this release.
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
### Using transformers
|
| 230 |
+
```python
|
| 231 |
+
import argparse
|
| 232 |
+
from typing import Optional
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def optional_positive_int(value: str) -> Optional[int]:
|
| 236 |
+
if value.lower() == "none":
|
| 237 |
+
return None
|
| 238 |
+
try:
|
| 239 |
+
parsed = int(value)
|
| 240 |
+
except ValueError as error:
|
| 241 |
+
raise argparse.ArgumentTypeError(
|
| 242 |
+
"must be a positive integer or 'none'"
|
| 243 |
+
) from error
|
| 244 |
+
if parsed <= 0:
|
| 245 |
+
raise argparse.ArgumentTypeError("must be a positive integer or 'none'")
|
| 246 |
+
return parsed
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def build_parser() -> argparse.ArgumentParser:
|
| 250 |
+
parser = argparse.ArgumentParser(
|
| 251 |
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
| 252 |
+
)
|
| 253 |
+
parser.add_argument(
|
| 254 |
+
"--model",
|
| 255 |
+
default="KaLM-Embedding/KaLM-Reranker-V1-Large-R2",
|
| 256 |
+
help="Hugging Face model ID or local checkpoint path.",
|
| 257 |
+
)
|
| 258 |
+
parser.add_argument(
|
| 259 |
+
"--device",
|
| 260 |
+
default=None,
|
| 261 |
+
help="Inference device, such as 'cuda', 'cuda:0', or 'cpu'.",
|
| 262 |
+
)
|
| 263 |
+
parser.add_argument(
|
| 264 |
+
"--dtype",
|
| 265 |
+
default=None,
|
| 266 |
+
choices=("bfloat16", "bf16", "float16", "fp16", "float32", "fp32"),
|
| 267 |
+
help="Model parameter dtype. By default, use BF16 on CUDA and FP32 on CPU.",
|
| 268 |
+
)
|
| 269 |
+
parser.add_argument(
|
| 270 |
+
"--batch-size",
|
| 271 |
+
type=int,
|
| 272 |
+
default=32,
|
| 273 |
+
help="Number of query-document pairs scored per inference batch.",
|
| 274 |
+
)
|
| 275 |
+
parser.add_argument(
|
| 276 |
+
"--query-max-length",
|
| 277 |
+
type=int,
|
| 278 |
+
default=512,
|
| 279 |
+
help=(
|
| 280 |
+
"Maximum tokens in the raw query before it is inserted into the "
|
| 281 |
+
"decoder prompt; prompt tokens are not included in this limit."
|
| 282 |
+
),
|
| 283 |
+
)
|
| 284 |
+
parser.add_argument(
|
| 285 |
+
"--reranker-max-length",
|
| 286 |
+
type=int,
|
| 287 |
+
default=1024,
|
| 288 |
+
help=(
|
| 289 |
+
"Maximum encoder tokens for '<Document>: {passage}'. This is not a "
|
| 290 |
+
"combined query-document context limit."
|
| 291 |
+
),
|
| 292 |
+
)
|
| 293 |
+
parser.add_argument(
|
| 294 |
+
"--chunk-size",
|
| 295 |
+
type=optional_positive_int,
|
| 296 |
+
default=4,
|
| 297 |
+
metavar="N|none",
|
| 298 |
+
help=(
|
| 299 |
+
"Number of encoder token hidden states per mean-pooled chunk; use "
|
| 300 |
+
"'none' to disable encoder chunk pooling."
|
| 301 |
+
),
|
| 302 |
+
)
|
| 303 |
+
return parser
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
def main() -> None:
|
| 307 |
+
args = build_parser().parse_args()
|
| 308 |
+
|
| 309 |
+
from kalm_reranker import KaLMReranker
|
| 310 |
+
|
| 311 |
+
reranker = KaLMReranker(
|
| 312 |
+
args.model,
|
| 313 |
+
device=args.device,
|
| 314 |
+
dtype=args.dtype,
|
| 315 |
+
batch_size=args.batch_size,
|
| 316 |
+
query_max_length=args.query_max_length,
|
| 317 |
+
max_length=args.reranker_max_length,
|
| 318 |
+
chunk_size=args.chunk_size,
|
| 319 |
+
)
|
| 320 |
+
query = "What is the capital of China?"
|
| 321 |
+
documents = [
|
| 322 |
+
"The capital of China is Beijing.",
|
| 323 |
+
"Gravity attracts bodies toward one another.",
|
| 324 |
+
]
|
| 325 |
+
instruction = "Given a query, retrieve documents that answer the query."
|
| 326 |
+
|
| 327 |
+
pairs = [(query, document) for document in documents]
|
| 328 |
+
print("scores:", reranker.predict(pairs, instruction=instruction))
|
| 329 |
+
print("rankings:", reranker.rank(query, documents, instruction=instruction))
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
if __name__ == "__main__":
|
| 333 |
+
main()
|
| 334 |
+
|
| 335 |
+
'''
|
| 336 |
+
scores: [0.9867772459983826, 9.0574256319087e-05]
|
| 337 |
+
rankings: [{'corpus_id': 0, 'score': 0.9867772459983826}, {'corpus_id': 1, 'score': 9.0574256319087e-05}]
|
| 338 |
+
'''
|
| 339 |
+
|
| 340 |
+
```
|
| 341 |
+
|
| 342 |
#### Ablation on multi-stage training
|
| 343 |
|
| 344 |
Across all three model sizes and all seven compression ratios, performance on BEIR and MIRACL improves consistently from Stage 1 to Stage 3, demonstrating the effectiveness of our multi-stage training pipeline. Concretely, Stage 1 establishes a robust foundation for document reranking, distillation in Stage 2 substantially improves performance, and Stage 3 yields further modest gains. More importantly, robustness to compression generally improves across the three training stages. For example, from Stage 1 to Stage 3, the performance retention of KaLM-Reranker-V1-Nano at r = 128 relative to r = 2 increases from 92.88% to 93.80% on BEIR and from 90.93% to 92.15% on MIRACL.
|