lbourdois commited on
Commit
be82fe6
·
verified ·
1 Parent(s): 5dc0914

Trimmed pplx-embed-v1 French 32768 tokens

Browse files
1_Pooling/config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "word_embedding_dimension": 1024,
3
+ "pooling_mode_cls_token": false,
4
+ "pooling_mode_mean_tokens": true,
5
+ "pooling_mode_max_tokens": false,
6
+ "pooling_mode_mean_sqrt_len_tokens": false,
7
+ "pooling_mode_weightedmean_tokens": false,
8
+ "pooling_mode_lasttoken": false,
9
+ "include_prompt": true
10
+ }
README.md ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ pipeline_tag: sentence-similarity
3
+ language: fra
4
+ license: mit
5
+ tags:
6
+ - trimmed
7
+ - sentence-transformers
8
+ - feature-extraction
9
+ - bidirectional_pplx_qwen3
10
+ library_name: sentence-transformers
11
+ base_model: perplexity-ai/pplx-embed-v1-0.6b
12
+ base_model_relation: quantized
13
+ datasets:
14
+ - Lumberjackk/fineweb-2-trimming
15
+ ---
16
+
17
+ # pplx-embed-v1-fra-32768
18
+
19
+ This model is a **20.47% smaller** version of [perplexity-ai/pplx-embed-v1-0.6b](https://huggingface.co/perplexity-ai/pplx-embed-v1-0.6b) optimized for French language via vocabulary size reduction using the [trimming](https://huggingface.co/blog/introduction-to-trimming) method.
20
+
21
+ This trimmed model should perform similarly to the original model with only **32,768 tokens** and a much smaller memory footprint. However, it may not perform well for other languages as tokens not commonly used in French were removed from the vocabulary.
22
+
23
+ ## Model Statistics
24
+
25
+ | Metric | Original | Trimmed | Reduction |
26
+ |--------|----------|---------|-----------|
27
+ | **Vocabulary size** | 151,643 tokens | 32,768 tokens | **78.39%** |
28
+ | **Model size** | 596,049,920 params | 474,021,888 params | **20.47%** |
29
+
30
+ ## Mining Dataset Statistics
31
+
32
+ - **Number of texts used for mining**: 200,000 texts
33
+ - **Dataset**: [Lumberjackk/fineweb-2-trimming](https://huggingface.co/datasets/Lumberjackk/fineweb-2-trimming)
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from sentence_transformers import SentenceTransformer
39
+
40
+ model = SentenceTransformer("alphaedge-ai/pplx-embed-v1-fra-32768", trust_remote_code=True)
41
+ texts = [
42
+ "Chunk 1",
43
+ "Chunk 2",
44
+ "Chunk 3",
45
+ ]
46
+ embeddings = model.encode(texts)
47
+ print(embeddings.shape)
48
+ ```
49
+
50
+ ## Citation
51
+
52
+ #### pplx-embed
53
+
54
+ ```bibtex
55
+ @article{pplxembed2025,
56
+ title={pplx-embed: State-of-the-Art Embedding Models for Web-Scale Retrieval},
57
+ author={Perplexity AI},
58
+ year={2025}
59
+ }
60
+ ```
added_tokens.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "</think>": 32767,
3
+ "<think>": 32766,
4
+ "<|box_end|>": 32758,
5
+ "<|box_start|>": 32757,
6
+ "<|endoftext|>": 32752,
7
+ "<|im_end|>": 32754,
8
+ "<|im_start|>": 32753,
9
+ "<|image_pad|>": 32764,
10
+ "<|object_ref_end|>": 32756,
11
+ "<|object_ref_start|>": 32755,
12
+ "<|quad_end|>": 32760,
13
+ "<|quad_start|>": 32759,
14
+ "<|video_pad|>": 32765,
15
+ "<|vision_end|>": 32762,
16
+ "<|vision_pad|>": 32763,
17
+ "<|vision_start|>": 32761
18
+ }
config.json ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "PPLXQwen3Model"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "auto_map": {
8
+ "AutoConfig": "configuration.PPLXQwen3Config",
9
+ "AutoModel": "modeling.PPLXQwen3Model"
10
+ },
11
+ "eos_token_id": 32752,
12
+ "head_dim": 128,
13
+ "hidden_act": "silu",
14
+ "hidden_size": 1024,
15
+ "initializer_range": 0.02,
16
+ "intermediate_size": 3072,
17
+ "layer_types": [
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention",
44
+ "full_attention",
45
+ "full_attention"
46
+ ],
47
+ "max_position_embeddings": 32768,
48
+ "max_window_layers": 28,
49
+ "model_type": "bidirectional_pplx_qwen3",
50
+ "num_attention_heads": 16,
51
+ "num_hidden_layers": 28,
52
+ "num_key_value_heads": 8,
53
+ "pad_token_id": 32752,
54
+ "rms_norm_eps": 1e-06,
55
+ "sliding_window": null,
56
+ "tie_word_embeddings": true,
57
+ "transformers.js_config": {
58
+ "use_external_data_format": {
59
+ "model.onnx": 2,
60
+ "model_q4.onnx": 1,
61
+ "model_quantized.onnx": 1
62
+ }
63
+ },
64
+ "transformers_version": "5.3.0.dev0",
65
+ "use_bidirectional_attention": true,
66
+ "use_cache": false,
67
+ "use_sliding_window": false,
68
+ "vocab_size": 32768,
69
+ "rope_theta": 1000000,
70
+ "torch_dtype": "bfloat16"
71
+ }
configuration.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from transformers.models.qwen3.configuration_qwen3 import Qwen3Config
2
+
3
+
4
+ class PPLXQwen3Config(Qwen3Config):
5
+ model_type = "bidirectional_pplx_qwen3"
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2b7270a0976ab069f91fc737480d5b358b75bff817e501c77ffe7eabaf6fbea8
3
+ size 948077008
modeling.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Callable
2
+ import torch
3
+ from transformers import Qwen3Model
4
+ from transformers.cache_utils import Cache
5
+ from transformers.masking_utils import create_causal_mask
6
+ from transformers.modeling_outputs import BaseModelOutputWithPooling
7
+ from transformers.processing_utils import Unpack
8
+ from transformers.utils import TransformersKwargs
9
+ from .configuration import PPLXQwen3Config
10
+
11
+
12
+ # From modeling_t5gemma.py
13
+ def bidirectional_mask_function(attention_mask: torch.Tensor | None) -> Callable:
14
+ """
15
+ This creates bidirectional attention mask.
16
+ """
17
+
18
+ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
19
+ if attention_mask is None:
20
+ return torch.ones((), dtype=torch.bool)
21
+ return attention_mask[batch_idx, kv_idx].to(torch.bool)
22
+
23
+ return inner_mask
24
+
25
+
26
+ class PPLXQwen3Model(Qwen3Model):
27
+ _supports_flash_attn = True
28
+ _supports_sdpa = True
29
+
30
+ config_class = PPLXQwen3Config
31
+
32
+ def __init__(self, config):
33
+ super().__init__(config)
34
+ self.post_init()
35
+
36
+ def post_init(self):
37
+ super().post_init()
38
+ # Override to set all layers to non-causal attention. This'll work with attn_implementation="flash_attention_2" or "sdpa"
39
+ for layer in self.layers:
40
+ layer.self_attn.is_causal = False
41
+
42
+ def forward(
43
+ self,
44
+ input_ids: torch.LongTensor | None = None,
45
+ attention_mask: torch.Tensor | None = None,
46
+ position_ids: torch.LongTensor | None = None,
47
+ past_key_values: Cache | None = None,
48
+ inputs_embeds: torch.FloatTensor | None = None,
49
+ use_cache: bool | None = None,
50
+ cache_position: torch.LongTensor | None = None,
51
+ **kwargs: Unpack[TransformersKwargs],
52
+ ) -> BaseModelOutputWithPooling:
53
+ if inputs_embeds is None:
54
+ inputs_embeds = self.embed_tokens(input_ids)
55
+ input_ids = None
56
+
57
+ # We construct a dummy tensor imitating initial positions
58
+ dummy_cache_position = torch.arange(
59
+ inputs_embeds.shape[1], device=inputs_embeds.device, dtype=torch.long
60
+ )
61
+ attention_mask = {
62
+ "full_attention": create_causal_mask(
63
+ config=self.config,
64
+ input_embeds=inputs_embeds,
65
+ attention_mask=attention_mask,
66
+ cache_position=dummy_cache_position,
67
+ past_key_values=None,
68
+ position_ids=position_ids,
69
+ or_mask_function=bidirectional_mask_function(attention_mask),
70
+ )
71
+ }
72
+
73
+ outputs = super().forward(
74
+ input_ids=input_ids,
75
+ attention_mask=attention_mask,
76
+ position_ids=position_ids,
77
+ past_key_values=past_key_values,
78
+ inputs_embeds=inputs_embeds,
79
+ use_cache=use_cache,
80
+ cache_position=cache_position,
81
+ **kwargs,
82
+ )
83
+ return outputs
modules.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": "",
6
+ "type": "sentence_transformers.models.Transformer"
7
+ },
8
+ {
9
+ "idx": 1,
10
+ "name": "1",
11
+ "path": "1_Pooling",
12
+ "type": "sentence_transformers.models.Pooling"
13
+ },
14
+ {
15
+ "idx": 2,
16
+ "name": "2",
17
+ "path": "",
18
+ "type": "st_quantize.FlexibleQuantizer",
19
+ "kwargs": ["quantization"]
20
+ }
21
+ ]
st_quantize.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import numpy as np
3
+ from typing import Literal
4
+ from sentence_transformers.models import Module
5
+
6
+
7
+ class Quantizer(torch.nn.Module):
8
+ def __init__(self, hard: bool = True):
9
+ """
10
+ Args:
11
+ hard: Whether to use hard or soft quantization. Defaults to True.
12
+ """
13
+ super().__init__()
14
+ self._hard = hard
15
+
16
+ def _hard_quantize(self, x, *args, **kwargs) -> torch.Tensor:
17
+ raise NotImplementedError
18
+
19
+ def _soft_quantize(self, x, *args, **kwargs) -> torch.Tensor:
20
+ raise NotImplementedError
21
+
22
+ def forward(self, x, *args, **kwargs) -> torch.Tensor:
23
+ soft = self._soft_quantize(x, *args, **kwargs)
24
+
25
+ if not self._hard:
26
+ result = soft
27
+ else:
28
+ result = (
29
+ self._hard_quantize(x, *args, **kwargs).detach() + soft - soft.detach()
30
+ )
31
+
32
+ return result
33
+
34
+
35
+ class Int8TanhQuantizer(Quantizer):
36
+ def __init__(
37
+ self,
38
+ hard: bool = True,
39
+ ):
40
+ super().__init__(hard=hard)
41
+ self.qmin = -128
42
+ self.qmax = 127
43
+
44
+ def _soft_quantize(self, x, *args, **kwargs):
45
+ return torch.tanh(x)
46
+
47
+ def _hard_quantize(self, x, *args, **kwargs):
48
+ soft = self._soft_quantize(x)
49
+ int_x = torch.round(soft * self.qmax)
50
+ int_x = torch.clamp(int_x, self.qmin, self.qmax)
51
+ return int_x
52
+
53
+
54
+ class BinaryTanhQuantizer(Quantizer):
55
+ def __init__(
56
+ self,
57
+ hard: bool = True,
58
+ scale: float = 1.0,
59
+ ):
60
+ super().__init__(hard)
61
+ self._scale = scale
62
+
63
+ def _soft_quantize(self, x, *args, **kwargs):
64
+ return torch.tanh(self._scale * x)
65
+
66
+ def _hard_quantize(self, x, *args, **kwargs):
67
+ return torch.where(x >= 0, 1.0, -1.0)
68
+
69
+
70
+ class PackedBinaryQuantizer:
71
+ def __call__(self, x: torch.Tensor) -> torch.Tensor:
72
+ bits = np.where(x.cpu().numpy() >= 0, True, False)
73
+ packed = np.packbits(bits, axis=-1)
74
+ return torch.from_numpy(packed).to(x.device)
75
+
76
+
77
+ class FlexibleQuantizer(Module):
78
+ def __init__(self):
79
+ super().__init__()
80
+ self._int8_quantizer = Int8TanhQuantizer()
81
+ self._binary_quantizer = BinaryTanhQuantizer()
82
+ self._packed_binary_quantizer = PackedBinaryQuantizer()
83
+
84
+ def forward(
85
+ self,
86
+ features: dict[str, torch.Tensor],
87
+ quantization: Literal["int8", "binary", "ubinary"] = "int8",
88
+ **kwargs
89
+ ) -> dict[str, torch.Tensor]:
90
+ if quantization == "int8":
91
+ features["sentence_embedding"] = self._int8_quantizer(
92
+ features["sentence_embedding"]
93
+ )
94
+ elif quantization == "binary":
95
+ features["sentence_embedding"] = self._binary_quantizer(
96
+ features["sentence_embedding"]
97
+ )
98
+ elif quantization == "ubinary":
99
+ features["sentence_embedding"] = self._packed_binary_quantizer(
100
+ features["sentence_embedding"]
101
+ )
102
+ else:
103
+ raise ValueError(
104
+ f"Invalid quantization type: {quantization}. Must be 'binary', 'ubinary', or 'int8'."
105
+ )
106
+ return features
107
+
108
+ @classmethod
109
+ def load(
110
+ cls,
111
+ model_name_or_path: str,
112
+ subfolder: str = "",
113
+ token: bool | str | None = None,
114
+ cache_folder: str | None = None,
115
+ revision: str | None = None,
116
+ local_files_only: bool = False,
117
+ **kwargs,
118
+ ):
119
+ return cls()
120
+
121
+ def save(self, output_path: str, *args, **kwargs) -> None:
122
+ return
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "tokenizer_class": "Qwen2Tokenizer",
3
+ "model_max_length": 131072,
4
+ "clean_up_tokenization_spaces": false,
5
+ "errors": "replace",
6
+ "split_special_tokens": false,
7
+ "add_bos_token": false,
8
+ "add_prefix_space": false,
9
+ "eos_token": "<|endoftext|>",
10
+ "eos_token_id": 32752,
11
+ "pad_token": "<|endoftext|>",
12
+ "pad_token_id": 32752,
13
+ "bos_token": null,
14
+ "unk_token": null,
15
+ "additional_special_tokens": [
16
+ "<|endoftext|>",
17
+ "<|im_start|>",
18
+ "<|im_end|>",
19
+ "<|object_ref_start|>",
20
+ "<|object_ref_end|>",
21
+ "<|box_start|>",
22
+ "<|box_end|>",
23
+ "<|quad_start|>",
24
+ "<|quad_end|>",
25
+ "<|vision_start|>",
26
+ "<|vision_end|>",
27
+ "<|vision_pad|>",
28
+ "<|image_pad|>",
29
+ "<|video_pad|>",
30
+ "<think>",
31
+ "</think>"
32
+ ],
33
+ "added_tokens_decoder": {
34
+ "32752": {
35
+ "content": "<|endoftext|>",
36
+ "lstrip": false,
37
+ "normalized": false,
38
+ "rstrip": false,
39
+ "single_word": false,
40
+ "special": true
41
+ },
42
+ "32753": {
43
+ "content": "<|im_start|>",
44
+ "lstrip": false,
45
+ "normalized": false,
46
+ "rstrip": false,
47
+ "single_word": false,
48
+ "special": true
49
+ },
50
+ "32754": {
51
+ "content": "<|im_end|>",
52
+ "lstrip": false,
53
+ "normalized": false,
54
+ "rstrip": false,
55
+ "single_word": false,
56
+ "special": true
57
+ },
58
+ "32755": {
59
+ "content": "<|object_ref_start|>",
60
+ "lstrip": false,
61
+ "normalized": false,
62
+ "rstrip": false,
63
+ "single_word": false,
64
+ "special": true
65
+ },
66
+ "32756": {
67
+ "content": "<|object_ref_end|>",
68
+ "lstrip": false,
69
+ "normalized": false,
70
+ "rstrip": false,
71
+ "single_word": false,
72
+ "special": true
73
+ },
74
+ "32757": {
75
+ "content": "<|box_start|>",
76
+ "lstrip": false,
77
+ "normalized": false,
78
+ "rstrip": false,
79
+ "single_word": false,
80
+ "special": true
81
+ },
82
+ "32758": {
83
+ "content": "<|box_end|>",
84
+ "lstrip": false,
85
+ "normalized": false,
86
+ "rstrip": false,
87
+ "single_word": false,
88
+ "special": true
89
+ },
90
+ "32759": {
91
+ "content": "<|quad_start|>",
92
+ "lstrip": false,
93
+ "normalized": false,
94
+ "rstrip": false,
95
+ "single_word": false,
96
+ "special": true
97
+ },
98
+ "32760": {
99
+ "content": "<|quad_end|>",
100
+ "lstrip": false,
101
+ "normalized": false,
102
+ "rstrip": false,
103
+ "single_word": false,
104
+ "special": true
105
+ },
106
+ "32761": {
107
+ "content": "<|vision_start|>",
108
+ "lstrip": false,
109
+ "normalized": false,
110
+ "rstrip": false,
111
+ "single_word": false,
112
+ "special": true
113
+ },
114
+ "32762": {
115
+ "content": "<|vision_end|>",
116
+ "lstrip": false,
117
+ "normalized": false,
118
+ "rstrip": false,
119
+ "single_word": false,
120
+ "special": true
121
+ },
122
+ "32763": {
123
+ "content": "<|vision_pad|>",
124
+ "lstrip": false,
125
+ "normalized": false,
126
+ "rstrip": false,
127
+ "single_word": false,
128
+ "special": true
129
+ },
130
+ "32764": {
131
+ "content": "<|image_pad|>",
132
+ "lstrip": false,
133
+ "normalized": false,
134
+ "rstrip": false,
135
+ "single_word": false,
136
+ "special": true
137
+ },
138
+ "32765": {
139
+ "content": "<|video_pad|>",
140
+ "lstrip": false,
141
+ "normalized": false,
142
+ "rstrip": false,
143
+ "single_word": false,
144
+ "special": true
145
+ },
146
+ "32766": {
147
+ "content": "<think>",
148
+ "lstrip": false,
149
+ "normalized": false,
150
+ "rstrip": false,
151
+ "single_word": false,
152
+ "special": true
153
+ },
154
+ "32767": {
155
+ "content": "</think>",
156
+ "lstrip": false,
157
+ "normalized": false,
158
+ "rstrip": false,
159
+ "single_word": false,
160
+ "special": true
161
+ }
162
+ }
163
+ }
vocab.json ADDED
The diff for this file is too large to render. See raw diff