SonicEmbed / eval /mteb_tasks.py
jaisawhney's picture
Upload folder using huggingface_hub
413610a verified
Raw History Blame Contribute Delete
3.89 kB
"""General text quality on the full MTEB(eng, v2) benchmark (41 tasks).
Give each model its own --output-dir, or local models will reuse each other's cached scores.
uv run mteb_tasks.py jaisawhney/SonicEmbed --output-dir mteb-results/sonicembed
"""
import argparse
import csv
import json
from pathlib import Path
from typing import cast
import mteb
import torch
from mteb import BenchmarkResults
from sentence_transformers import SentenceTransformer
from sentence_transformers.base.modules.transformer import Transformer
BENCHMARK = "MTEB(eng, v2)"
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("model")
parser.add_argument("--batch-size", type=int, default=16)
parser.add_argument("--output-dir", default="mteb-results")
parser.add_argument("--device", default="cuda", help="cuda, mps or cpu")
args = parser.parse_args()
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
# Only the text side is needed.
model =SentenceTransformer(
args.model,
device=args.device,
model_kwargs={
"torch_dtype": torch.bfloat16 if args.device == "cuda" else torch.float32,
},
config_kwargs={
"vision_config": None,
"audio_config": None,
},
)
# Otherwise a text that's just a link gets fetched as a video, image or audio file.
transformer = cast(Transformer, model[0])
for modality in transformer.modalities:
if modality != "text":
del transformer.modality_config[modality]
transformer.input_formatter.supported_modalities = transformer.modalities
# MTEB calls this task type STS.
if "SentenceSimilarity" in model.prompts:
model.prompts.setdefault(
"STS",
model.prompts["SentenceSimilarity"],
)
benchmark = mteb.get_benchmark(BENCHMARK)
cache =mteb.ResultCache(str(output_dir / "cache"))
print(f"Evaluating {args.model} on {BENCHMARK}")
print(f"Tasks: {len(benchmark.tasks)}")
results = mteb.evaluate(
model,
tasks=benchmark,
encode_kwargs={
"batch_size": args.batch_size,
},
cache=cache,
overwrite_strategy="only-missing",
)
scores ={
result.task_name: 100 * result.get_score()
for result in results.task_results
}
summary =benchmark.get_score(
BenchmarkResults(model_results=[results]),
raise_error=True,
)[results.model_name]
rows = []
for task in benchmark.tasks:
name = task.metadata.name
score = scores.get(name)
rows.append({
"Task": name,
"Score": round(score, 2) if score is not None else None,
})
with open(output_dir / "task_scores.csv", "w", newline="") as file:
writer = csv.DictWriter(
file,
fieldnames=["Task", "Score"],
)
writer.writeheader()
writer.writerows(rows)
with open(output_dir / "summary.json", "w") as file:
json.dump(
{
"model": results.model_name,
"benchmark": BENCHMARK,
"summary": summary,
},
file,
indent=2,
)
print(f"\n{args.model} ({BENCHMARK})")
print("| Task | Score |")
print("|---|---:|")
for row in rows:
score = row["Score"]
value = f"{score:.2f}" if score is not None else "N/A"
print(f"| {row['Task']} | {value} |")
print("\nAggregate scores:")
for name, score in summary.items():
if name == "Rank":
continue
value = f"{score * 100:.2f}" if score is not None else "N/A"
print(f"| {name} | {value} |")
print(f"\nResults saved to: {output_dir.resolve()}")
if __name__ == "__main__":
main()