Skip to content

Commit 6ae4835

Browse files
authored
docs: Updated readme (#9)
1 parent 10c852e commit 6ae4835

File tree

4 files changed

+58
-20
lines changed

4 files changed

+58
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "model2vec-rs"
33
version = "0.1.0"
44
edition = "2021"
5-
description = "Official Rust Implementation for Model2Vec"
5+
description = "Official Rust Implementation of Model2Vec"
66
readme = "README.md"
77
license-file = "LICENSE"
88
authors = ["Thomas van Dongen <thomas123@live.nl>", "Stéphan Tulkens <stephantul@gmail.com>"]

README.md

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1-
# model2vec-rs
21

3-
This crate provides a lightweight Rust implementation for loading and running inference on [Model2Vec](https://github.com/MinishLab/model2vec) static embedding models from either local folders or the Hugging Face Hub.
2+
<div align="center">
3+
<picture>
4+
<img width="35%" alt="Model2Vec logo" src="assets/images/model2vec_rs_logo.png">
5+
</picture>
6+
</div>
7+
8+
<div align="center">
9+
10+
[Quickstart](#quickstart)
11+
[Models](#models)
12+
[Performance](#performance)
13+
</div>
14+
15+
This crate provides a lightweight Rust implementation for loading and inference of [Model2Vec](https://github.com/MinishLab/model2vec) static embedding models. For distillation and training, the [Python Model2Vec package](https://github.com/MinishLab/model2vec) can be used.
16+
17+
418

519
## Quick Start
620

7-
Install the crate:
21+
Add the crate:
822

923
```bash
10-
git clone https://github.com/minishlab/model2vec-rust.git
11-
cd model2vec-rs
12-
13-
# Build
14-
cargo build --release
24+
cargo add model2vec-rs
1525
```
1626

1727
Make embeddings:
@@ -62,6 +72,34 @@ let embeddings = model.encode_with_args(
6272
);
6373
```
6474

75+
## Models
76+
77+
We provide a number of models that can be used out of the box. These models are available on the [HuggingFace hub](https://huggingface.co/collections/minishlab/model2vec-base-models-66fd9dd9b7c3b3c0f25ca90e) and can be loaded using the `from_pretrained` method. The models are listed below.
78+
79+
80+
81+
| Model | Language | Sentence Transformer | Params | Task |
82+
|-----------------------------------------------------------------------|------------|-----------------------------------------------------------------|---------|-----------|
83+
| [potion-base-32M](https://huggingface.co/minishlab/potion-base-32M) | English | [bge-base-en-v1.5](https://huggingface.co/BAAI/bge-base-en-v1.5) | 32.3M | General |
84+
| [potion-base-8M](https://huggingface.co/minishlab/potion-base-8M) | English | [bge-base-en-v1.5](https://huggingface.co/BAAI/bge-base-en-v1.5) | 7.5M | General |
85+
| [potion-base-4M](https://huggingface.co/minishlab/potion-base-4M) | English | [bge-base-en-v1.5](https://huggingface.co/BAAI/bge-base-en-v1.5) | 3.7M | General |
86+
| [potion-base-2M](https://huggingface.co/minishlab/potion-base-2M) | English | [bge-base-en-v1.5](https://huggingface.co/BAAI/bge-base-en-v1.5) | 1.8M | General |
87+
| [potion-retrieval-32M](https://huggingface.co/minishlab/potion-retrieval-32M) | English | [bge-base-en-v1.5](https://huggingface.co/BAAI/bge-base-en-v1.5) | 32.3M | Retrieval |
88+
| [M2V_multilingual_output](https://huggingface.co/minishlab/M2V_multilingual_output) | Multilingual | [LaBSE](https://huggingface.co/sentence-transformers/LaBSE) | 471M | General |
89+
90+
91+
## Performance
92+
93+
We compared the performance of the Rust implementation with the Python version of Model2Vec. The benchmark was run single-threaded on a CPU.
94+
95+
| Implementation | Throughput |
96+
| -------------- | -------------------------------------------------- |
97+
| **Rust** | 8000 sentences |
98+
| **Python** | 4650 sentences |
99+
100+
The Rust version is roughly **1.7×** faster than the Python version.
101+
102+
65103
## License
66104

67105
MIT
1.69 MB
Loading

tests/test_model.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ use model2vec_rs::model::StaticModel;
66

77
#[test]
88
fn test_encode_matches_python_model2vec() {
9-
// Load your test model once
9+
// Load the test model
1010
let model = load_test_model();
1111

12-
// Define (fixture path, inputs) for both short and long cases
13-
let long_text = vec!["hello"; 1000].join(" "); // 1 000 “hello”s
12+
// Define the short and long text inputs
13+
let long_text = vec!["hello"; 1000].join(" ");
14+
let short_text = "hello world".to_string();
1415
let cases = vec![
1516
(
1617
"tests/fixtures/embeddings_short.json",
17-
vec!["hello world".to_string()],
18+
vec![short_text],
1819
),
1920
(
2021
"tests/fixtures/embeddings_long.json",
@@ -29,7 +30,7 @@ fn test_encode_matches_python_model2vec() {
2930
let expected: Vec<Vec<f32>> = serde_json::from_str(&fixture)
3031
.expect("Failed to parse fixture");
3132

32-
// Encode with your Rust model
33+
// Encode with the Rust model
3334
let output = model.encode(&inputs);
3435

3536
// Sanity checks
@@ -53,16 +54,15 @@ fn test_encode_matches_python_model2vec() {
5354
}
5455
}
5556

56-
57-
/// Test that encoding an empty input slice yields an empty Vec
57+
/// Test that encoding an empty input slice yields an empty output
5858
#[test]
5959
fn test_encode_empty_input() {
6060
let model = load_test_model();
6161
let embs: Vec<Vec<f32>> = model.encode(&[]);
6262
assert!(embs.is_empty(), "Expected no embeddings for empty input");
6363
}
6464

65-
/// Test encoding a single empty sentence produces a zero vector with no NaNs
65+
/// Test that encoding a single empty sentence produces a zero vector
6666
#[test]
6767
fn test_encode_empty_sentence() {
6868
let model = load_test_model();
@@ -75,21 +75,21 @@ fn test_encode_empty_sentence() {
7575
/// Test override of `normalize` flag in from_pretrained
7676
#[test]
7777
fn test_normalization_flag_override() {
78-
// first load with normalize = true (default in config)
78+
// Load with normalize = true (default in config)
7979
let model_norm = StaticModel::from_pretrained(
8080
"tests/fixtures/test-model-float32", None, None, None
8181
).unwrap();
8282
let emb_norm = model_norm.encode(&["test sentence".to_string()])[0].clone();
8383
let norm_norm = emb_norm.iter().map(|&x| x*x).sum::<f32>().sqrt();
8484

85-
// now load with normalize = false override
85+
// Load with normalize = false override
8686
let model_no_norm = StaticModel::from_pretrained(
8787
"tests/fixtures/test-model-float32", None, Some(false), None
8888
).unwrap();
8989
let emb_no = model_no_norm.encode(&["test sentence".to_string()])[0].clone();
9090
let norm_no = emb_no.iter().map(|&x| x*x).sum::<f32>().sqrt();
9191

92-
// normalized version should have unit length, override should give larger norm
92+
// Normalized version should have unit length, override should give larger norm
9393
assert!((norm_norm - 1.0).abs() < 1e-5, "Normalized vector should have unit norm");
9494
assert!(norm_no > norm_norm, "Without normalization override, norm should be larger");
9595
}

0 commit comments

Comments
 (0)