[CI] Deflake MTEB score tests with per-model mteb_tol and reruns (#57364)
Signed-off-by: khluu <khluu000@gmail.com>
Kevin H. Luu committed
Sep 18, 2026 at 20:29 UTC
2fd6268e6d75f16f05c048cfb26d300ac49f548e
17 files changed
+75
-4
tests/models/language/pooling_mteb_test/mteb_embed_utils.py
+10
-2
@@ -161,10 +161,14 @@ def mteb_test_embed_models(
161
model_info: EmbedModelInfo,
162
vllm_extra_kwargs=None,
163
hf_model_callback=None,
164
- atol=MTEB_EMBED_TOL,
164
+ atol: float | None = None,
165
prompt_prefix: str | None = None,
166
vllm_model_callback=None,
167
):
168
+ if atol is None:
169
+ atol = (
170
+ model_info.mteb_tol if model_info.mteb_tol is not None else MTEB_EMBED_TOL
171
+ )
172
vllm_extra_kwargs = get_vllm_extra_kwargs(model_info, vllm_extra_kwargs)
173
174
# Test embed_dims, isnan and whether to use normalize
@@ -268,4 +272,8 @@ def mteb_test_embed_models(
272
273
# We are not concerned that the vllm mteb results are better
274
# than SentenceTransformers, so we only perform one-sided testing.
271
- assert st_main_score - vllm_main_score < atol
275
+ diff = st_main_score - vllm_main_score
276
+ assert diff < atol, (
277
+ f"diff={diff:.6g} tol={atol} model={model_info.name} "
278
+ f"(st={st_main_score}, vllm={vllm_main_score})"
279
+ )
tests/models/language/pooling_mteb_test/mteb_score_utils.py
+10
-2
@@ -230,8 +230,12 @@ def mteb_test_rerank_models(
230
hf_runner=HFMtebCrossEncoder,
231
vllm_extra_kwargs=None,
232
vllm_mteb_encoder=VllmMtebCrossEncoder,
233
- atol=MTEB_RERANK_TOL,
233
+ atol: float | None = None,
234
):
235
+ if atol is None:
236
+ atol = (
237
+ model_info.mteb_tol if model_info.mteb_tol is not None else MTEB_RERANK_TOL
238
+ )
239
vllm_extra_kwargs = get_vllm_extra_kwargs(model_info, vllm_extra_kwargs)
240
241
# Maybe load chat_template.
@@ -308,4 +312,8 @@ def mteb_test_rerank_models(
312
313
# We are not concerned that the vllm mteb results are better
314
# than SentenceTransformers, so we only perform one-sided testing.
311
- assert st_main_score - vllm_main_score < atol
315
+ diff = st_main_score - vllm_main_score
316
+ assert diff < atol, (
317
+ f"diff={diff:.6g} tol={atol} model={model_info.name} "
318
+ f"(st={st_main_score}, vllm={vllm_main_score})"
319
+ )
tests/models/language/pooling_mteb_test/test_baai.py
+5
@@ -17,6 +17,7 @@ MODELS = [
17
"BAAI/bge-base-en",
18
architecture="BertModel",
19
mteb_score=0.779336792,
20
+ mteb_tol=2e-3,
21
seq_pooling_type="CLS",
22
attn_type="encoder_only",
23
is_prefix_caching_supported=False,
@@ -54,6 +55,7 @@ MODELS = [
55
"BAAI/bge-m3",
56
architecture="XLMRobertaModel",
57
mteb_score=0.787343078,
58
+ mteb_tol=2e-3,
59
seq_pooling_type="CLS",
60
attn_type="encoder_only",
61
is_prefix_caching_supported=False,
@@ -82,6 +84,7 @@ RERANK_MODELS = [
84
"BAAI/bge-reranker-base",
85
architecture="XLMRobertaForSequenceClassification",
86
mteb_score=0.32398,
87
+ mteb_tol=1e-2,
88
seq_pooling_type="CLS",
89
attn_type="encoder_only",
90
is_prefix_caching_supported=False,
@@ -101,6 +104,7 @@ RERANK_MODELS = [
104
]
105
106
107
+@pytest.mark.flaky(reruns=2)
108
@pytest.mark.parametrize("model_info", MODELS)
109
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
110
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
@@ -113,6 +117,7 @@ def test_embed_models_correctness(
117
correctness_test_embed_models(hf_runner, vllm_runner, model_info, example_prompts)
118
119
120
+@pytest.mark.flaky(reruns=2)
121
@pytest.mark.parametrize("model_info", RERANK_MODELS)
122
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
123
mteb_test_rerank_models(vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_bge_reranker_v2_gemma.py
+2
@@ -26,6 +26,7 @@ RERANK_MODELS = [
26
"method": "no_post_processing",
27
},
28
mteb_score=0.33757,
29
+ mteb_tol=1e-2,
30
seq_pooling_type="LAST",
31
attn_type="decoder",
32
is_prefix_caching_supported=True,
@@ -127,6 +128,7 @@ class GemmaRerankerHfRunner(MtebCrossEncoderMixin, HfRunner):
128
return torch.Tensor(scores)
129
130
131
+@pytest.mark.flaky(reruns=2)
132
@pytest.mark.parametrize("model_info", RERANK_MODELS)
133
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
134
mteb_test_rerank_models(
tests/models/language/pooling_mteb_test/test_cross_encoder.py
+3
@@ -17,6 +17,7 @@ RERANK_MODELS = [
17
is_prefix_caching_supported=False,
18
is_chunked_prefill_supported=False,
19
mteb_score=0.32898,
20
+ mteb_tol=1e-2,
21
),
22
RerankModelInfo(
23
"tomaarsen/Qwen3-Reranker-0.6B-seq-cls",
@@ -27,10 +28,12 @@ RERANK_MODELS = [
28
is_chunked_prefill_supported=True,
29
chat_template_name="qwen3_reranker.jinja",
30
mteb_score=0.33459,
31
+ mteb_tol=1e-2,
32
),
33
]
34
35
36
+@pytest.mark.flaky(reruns=2)
37
@pytest.mark.parametrize("model_info", RERANK_MODELS)
38
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
39
mteb_test_rerank_models(vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_gte.py
+8
@@ -18,6 +18,7 @@ MODELS = [
18
EmbedModelInfo(
19
"thenlper/gte-large",
20
mteb_score=0.76807651,
21
+ mteb_tol=2e-3,
22
architecture="BertModel",
23
seq_pooling_type="MEAN",
24
attn_type="encoder_only",
@@ -44,6 +45,7 @@ MODELS = [
45
"Alibaba-NLP/gte-multilingual-base",
46
architecture="GteNewModel",
47
mteb_score=0.775074696,
48
+ mteb_tol=2e-3,
49
hf_overrides={"architectures": ["GteNewModel"]},
50
seq_pooling_type="CLS",
51
attn_type="encoder_only",
@@ -79,6 +81,7 @@ MODELS = [
81
EmbedModelInfo(
82
"Alibaba-NLP/gte-modernbert-base",
83
mteb_score=0.748193353,
84
+ mteb_tol=2e-3,
85
architecture="ModernBertModel",
86
seq_pooling_type="CLS",
87
attn_type="encoder_only",
@@ -90,6 +93,7 @@ MODELS = [
93
EmbedModelInfo(
94
"Qwen/Qwen3-Embedding-0.6B",
95
mteb_score=0.771163695,
96
+ mteb_tol=2e-3,
97
architecture="Qwen3ForCausalLM",
98
seq_pooling_type="LAST",
99
attn_type="decoder",
@@ -109,6 +113,7 @@ RERANK_MODELS = [
113
# classifier_pooling: mean
114
"Alibaba-NLP/gte-reranker-modernbert-base",
115
mteb_score=0.33386,
116
+ mteb_tol=1e-2,
117
architecture="ModernBertForSequenceClassification",
118
seq_pooling_type="CLS",
119
attn_type="encoder_only",
@@ -119,6 +124,7 @@ RERANK_MODELS = [
124
RerankModelInfo(
125
"Alibaba-NLP/gte-multilingual-reranker-base",
126
mteb_score=0.33062,
127
+ mteb_tol=1e-2,
128
architecture="GteNewForSequenceClassification",
129
hf_overrides={"architectures": ["GteNewForSequenceClassification"]},
130
seq_pooling_type="CLS",
@@ -130,6 +136,7 @@ RERANK_MODELS = [
136
]
137
138
139
+@pytest.mark.flaky(reruns=2)
140
@pytest.mark.parametrize("model_info", MODELS)
141
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
142
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
@@ -142,6 +149,7 @@ def test_embed_models_correctness(
149
correctness_test_embed_models(hf_runner, vllm_runner, model_info, example_prompts)
150
151
152
+@pytest.mark.flaky(reruns=2)
153
@pytest.mark.parametrize("model_info", RERANK_MODELS)
154
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
155
vllm_extra_kwargs = {}
tests/models/language/pooling_mteb_test/test_intfloat.py
+3
@@ -13,6 +13,7 @@ MODELS = [
13
"intfloat/e5-small",
14
architecture="BertModel",
15
mteb_score=0.742285423,
16
+ mteb_tol=2e-3,
17
seq_pooling_type="MEAN",
18
attn_type="encoder_only",
19
is_prefix_caching_supported=False,
@@ -29,6 +30,7 @@ MODELS = [
30
"intfloat/multilingual-e5-base",
31
architecture="XLMRobertaModel",
32
mteb_score=0.779325955,
33
+ mteb_tol=2e-3,
34
seq_pooling_type="MEAN",
35
attn_type="encoder_only",
36
is_prefix_caching_supported=False,
@@ -48,6 +50,7 @@ MODELS = [
50
]
51
52
53
+@pytest.mark.flaky(reruns=2)
54
@pytest.mark.parametrize("model_info", MODELS)
55
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
56
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_jina.py
+6
@@ -23,6 +23,7 @@ EMBEDDING_MODELS = [
23
EmbedModelInfo(
24
"jinaai/jina-embeddings-v3",
25
mteb_score=0.824413164,
26
+ mteb_tol=2e-3,
27
architecture="XLMRobertaModel",
28
is_matryoshka=True,
29
seq_pooling_type="MEAN",
@@ -33,6 +34,7 @@ EMBEDDING_MODELS = [
34
EmbedModelInfo(
35
"jinaai/jina-embeddings-v5-text-small",
36
mteb_score=0.794535707854956,
37
+ mteb_tol=2e-3,
38
architecture="JinaEmbeddingsV5Model",
39
seq_pooling_type="LAST",
40
attn_type="decoder",
@@ -42,6 +44,7 @@ EMBEDDING_MODELS = [
44
EmbedModelInfo(
45
"jinaai/jina-embeddings-v5-text-nano",
46
architecture="JinaEmbeddingsV5Model",
47
+ mteb_tol=2e-3,
48
dtype="bfloat16" if current_platform.is_rocm() else "auto",
49
seq_pooling_type="LAST",
50
attn_type="encoder_only",
@@ -54,6 +57,7 @@ RERANK_MODELS = [
57
RerankModelInfo(
58
"jinaai/jina-reranker-v2-base-multilingual",
59
mteb_score=0.33643,
60
+ mteb_tol=1e-2,
61
architecture="XLMRobertaForSequenceClassification",
62
seq_pooling_type="CLS",
63
attn_type="encoder_only",
@@ -63,6 +67,7 @@ RERANK_MODELS = [
67
]
68
69
70
+@pytest.mark.flaky(reruns=2)
71
@pytest.mark.parametrize("model_info", EMBEDDING_MODELS)
72
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
73
task = "retrieval" if "v5" in model_info.name else "text-matching"
@@ -98,6 +103,7 @@ def test_embed_models_correctness(
103
)
104
105
106
+@pytest.mark.flaky(reruns=2)
107
@pytest.mark.parametrize("model_info", RERANK_MODELS)
108
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
109
mteb_test_rerank_models(vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_modernbert_fp8.py
+1
@@ -56,6 +56,7 @@ def _assert_modernbert_online_fp8(model) -> None:
56
)
57
58
59
+@pytest.mark.flaky(reruns=2)
60
@pytest.mark.skipif(
61
_fp8_scaled_mm_unsupported(),
62
reason="No FP8 ScaledMM kernel is available on this GPU type.",
tests/models/language/pooling_mteb_test/test_mxbai_rerank.py
+2
@@ -30,6 +30,7 @@ RERANK_MODELS = [
30
is_chunked_prefill_supported=True,
31
chat_template_name="mxbai_rerank_v2.jinja",
32
mteb_score=0.33651,
33
+ mteb_tol=1e-2,
34
enable_test=True,
35
),
36
RerankModelInfo(
@@ -104,6 +105,7 @@ class MxbaiRerankerHfRunner(MtebCrossEncoderMixin, HfRunner):
105
return torch.Tensor(scores)
106
107
108
+@pytest.mark.flaky(reruns=2)
109
@pytest.mark.parametrize("model_info", RERANK_MODELS)
110
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
111
mteb_test_rerank_models(vllm_runner, model_info, hf_runner=MxbaiRerankerHfRunner)
tests/models/language/pooling_mteb_test/test_nemotron.py
+4
@@ -19,6 +19,7 @@ EMBEDDING_MODELS = [
19
"nvidia/llama-nemotron-embed-1b-v2",
20
architecture="LlamaBidirectionalModel",
21
mteb_score=0.689164662128673,
22
+ mteb_tol=2e-3,
23
seq_pooling_type="MEAN",
24
attn_type="encoder_only",
25
is_prefix_caching_supported=False,
@@ -32,6 +33,7 @@ RERANK_MODELS = [
33
architecture="LlamaBidirectionalForSequenceClassification",
34
chat_template_name="nemotron-rerank.jinja",
35
mteb_score=0.33994,
36
+ mteb_tol=1e-2,
37
seq_pooling_type="MEAN",
38
attn_type="encoder_only",
39
is_prefix_caching_supported=False,
@@ -40,11 +42,13 @@ RERANK_MODELS = [
42
]
43
44
45
+@pytest.mark.flaky(reruns=2)
46
@pytest.mark.parametrize("model_info", EMBEDDING_MODELS)
47
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
48
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
49
50
51
+@pytest.mark.flaky(reruns=2)
52
@pytest.mark.parametrize("model_info", RERANK_MODELS)
53
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
54
mteb_test_rerank_models(vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_nomic.py
+3
@@ -17,6 +17,7 @@ MODELS = [
17
# HF version and remove revision set.
18
revision="720244025c1a7e15661a174c63cce63c8218e52b",
19
mteb_score=0.737568559,
20
+ mteb_tol=2e-3,
21
enable_test=True,
22
seq_pooling_type="MEAN",
23
attn_type="encoder_only",
@@ -35,6 +36,7 @@ MODELS = [
36
"nomic-ai/nomic-embed-text-v2-moe",
37
architecture="NomicBertModel",
38
mteb_score=0.715488912,
39
+ mteb_tol=2e-3,
40
enable_test=True,
41
seq_pooling_type="MEAN",
42
attn_type="encoder_only",
@@ -44,6 +46,7 @@ MODELS = [
46
]
47
48
49
+@pytest.mark.flaky(reruns=2)
50
@pytest.mark.parametrize("model_info", MODELS)
51
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
52
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_qwen3_reranker.py
+3
@@ -32,6 +32,7 @@ RERANK_MODELS = [
32
is_prefix_caching_supported=True,
33
is_chunked_prefill_supported=True,
34
mteb_score=0.33459,
35
+ mteb_tol=1e-2,
36
enable_test=True,
37
),
38
RerankModelInfo(
@@ -108,11 +109,13 @@ class Qwen3RerankerHfRunner(MtebCrossEncoderMixin, HfRunner):
109
return torch.Tensor(scores)
110
111
112
+@pytest.mark.flaky(reruns=2)
113
@pytest.mark.parametrize("model_info", RERANK_MODELS)
114
def test_rerank_models_mteb(vllm_runner, model_info: RerankModelInfo) -> None:
115
mteb_test_rerank_models(vllm_runner, model_info, hf_runner=Qwen3RerankerHfRunner)
116
117
118
+@pytest.mark.flaky(reruns=2)
119
@pytest.mark.parametrize("model_info", RERANK_MODELS)
120
@multi_gpu_test(num_gpus=2)
121
def test_rerank_models_mteb_tp(vllm_runner, model_info: RerankModelInfo) -> None:
tests/models/language/pooling_mteb_test/test_snowflake_arctic_embed.py
+6
@@ -14,6 +14,7 @@ MODELS = [
14
is_matryoshka=False,
15
architecture="BertModel",
16
mteb_score=0.714927797,
17
+ mteb_tol=2e-3,
18
seq_pooling_type="CLS",
19
attn_type="encoder_only",
20
is_prefix_caching_supported=False,
@@ -37,6 +38,7 @@ MODELS = [
38
is_matryoshka=False,
39
architecture="NomicBertModel",
40
mteb_score=0.681146831,
41
+ mteb_tol=2e-3,
42
seq_pooling_type="CLS",
43
attn_type="encoder_only",
44
is_prefix_caching_supported=False,
@@ -54,6 +56,7 @@ MODELS = [
56
is_matryoshka=True,
57
architecture="BertModel",
58
mteb_score=0.649088363,
59
+ mteb_tol=2e-3,
60
seq_pooling_type="CLS",
61
attn_type="encoder_only",
62
is_prefix_caching_supported=False,
@@ -65,6 +68,7 @@ MODELS = [
68
is_matryoshka=True,
69
architecture="XLMRobertaModel",
70
mteb_score=0.712258299,
71
+ mteb_tol=2e-3,
72
seq_pooling_type="CLS",
73
attn_type="encoder_only",
74
is_prefix_caching_supported=False,
@@ -76,6 +80,7 @@ MODELS = [
80
is_matryoshka=True,
81
architecture="GteModel",
82
mteb_score=0.706622444,
83
+ mteb_tol=2e-3,
84
seq_pooling_type="CLS",
85
attn_type="encoder_only",
86
is_prefix_caching_supported=False,
@@ -85,6 +90,7 @@ MODELS = [
90
]
91
92
93
+@pytest.mark.flaky(reruns=2)
94
@pytest.mark.parametrize("model_info", MODELS)
95
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
96
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_st_projector.py
+3
@@ -14,6 +14,7 @@ ST_PROJECTOR_MODELS = [
14
"TencentBAC/Conan-embedding-v1",
15
architecture="BertModel",
16
mteb_score=0.688611955,
17
+ mteb_tol=2e-3,
18
seq_pooling_type="MEAN",
19
attn_type="encoder_only",
20
is_prefix_caching_supported=False,
@@ -24,6 +25,7 @@ ST_PROJECTOR_MODELS = [
25
"google/embeddinggemma-300m",
26
architecture="Gemma3TextModel",
27
mteb_score=0.7473819294684156,
28
+ mteb_tol=2e-3,
29
seq_pooling_type="MEAN",
30
attn_type="encoder_only",
31
is_prefix_caching_supported=False,
@@ -33,6 +35,7 @@ ST_PROJECTOR_MODELS = [
35
]
36
37
38
+@pytest.mark.flaky(reruns=2)
39
@pytest.mark.parametrize("model_info", ST_PROJECTOR_MODELS)
40
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
41
mteb_test_embed_models(hf_runner, vllm_runner, model_info)
tests/models/language/pooling_mteb_test/test_voyage.py
+2
@@ -22,6 +22,7 @@ MODELS = [
22
"num_labels": 2048,
23
},
24
mteb_score=0.7054,
25
+ mteb_tol=2e-3,
26
# === MTEB Results ===
27
# STS12: 0.6613
28
# STS13: 0.6906
@@ -34,6 +35,7 @@ MODELS = [
35
]
36
37
38
+@pytest.mark.flaky(reruns=2)
39
@pytest.mark.parametrize("model_info", MODELS)
40
def test_embed_models_mteb(hf_runner, vllm_runner, model_info: EmbedModelInfo) -> None:
41
# Encoder-only attention models need enforce_eager=True to avoid
tests/models/utils.py
+4
@@ -396,6 +396,8 @@ class ModelInfo:
396
@dataclass
397
class EmbedModelInfo(ModelInfo):
398
mteb_score: float | None = None
399
+ # Per-model MTEB score tolerance; falls back to MTEB_EMBED_TOL.
400
+ mteb_tol: float | None = None
401
is_matryoshka: bool = False
402
matryoshka_dimensions: list[int] | None = None
403
@@ -403,6 +405,8 @@ class EmbedModelInfo(ModelInfo):
405
@dataclass
406
class RerankModelInfo(ModelInfo):
407
mteb_score: float | None = None
408
+ # Per-model MTEB score tolerance; falls back to MTEB_RERANK_TOL.
409
+ mteb_tol: float | None = None
410
chat_template_name: str | None = None
411
412