kekekeke commited on
Commit
0d5cf66
·
verified ·
1 Parent(s): 59d8db5

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  *.safetensors filter=lfs diff=lfs merge=lfs -text
2
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
LICENSE ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Tencent is pleased to support the open source community by making WeMM-Embedding-2B available.
2
+
3
+ Copyright (C) 2026 Tencent. All rights reserved.
4
+
5
+ The open-source software and/or models included in this distribution may have been modified by Tencent (“Tencent Modifications”). All Tencent Modifications are Copyright (C) Tencent.
6
+
7
+ WeMM-Embedding-2B is licensed under Apache-2.0, except for the third-party components listed below, which remain licensed under their respective original terms. WeMM-Embedding-2B does not impose any additional restrictions beyond those specified in the original licenses of these third-party components. Users are required to comply with all applicable terms and conditions of the original licenses and to ensure that the use of these third-party components conforms to all relevant laws and regulations.
8
+
9
+ For the avoidance of doubt, WeMM-Embedding-2B refers to code, parameters, and weights made publicly available by Tencent in accordance with Apache-2.0.
10
+
11
+ Terms of Apache-2.0:
12
+ --------------------------------------------------------------------
13
+ Apache License
14
+ Version 2.0, January 2004
15
+ http://www.apache.org/licenses/
16
+
17
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
18
+
19
+ 1. Definitions.
20
+
21
+ "License" shall mean the terms and conditions for use, reproduction,
22
+ and distribution as defined by Sections 1 through 9 of this document.
23
+
24
+ "Licensor" shall mean the copyright owner or entity authorized by
25
+ the copyright owner that is granting the License.
26
+
27
+ "Legal Entity" shall mean the union of the acting entity and all
28
+ other entities that control, are controlled by, or are under common
29
+ control with that entity. For the purposes of this definition,
30
+ "control" means (i) the power, direct or indirect, to cause the
31
+ direction or management of such entity, whether by contract or
32
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
33
+ outstanding shares, or (iii) beneficial ownership of such entity.
34
+
35
+ "You" (or "Your") shall mean an individual or Legal Entity
36
+ exercising permissions granted by this License.
37
+
38
+ "Source" form shall mean the preferred form for making modifications,
39
+ including but not limited to software source code, documentation
40
+ source, and configuration files.
41
+
42
+ "Object" form shall mean any form resulting from mechanical
43
+ transformation or translation of a Source form, including but
44
+ not limited to compiled object code, generated documentation,
45
+ and conversions to other media types.
46
+
47
+ "Work" shall mean the work of authorship, whether in Source or
48
+ Object form, made available under the License, as indicated by a
49
+ copyright notice that is included in or attached to the work
50
+ (an example is provided in the Appendix below).
51
+
52
+ "Derivative Works" shall mean any work, whether in Source or Object
53
+ form, that is based on (or derived from) the Work and for which the
54
+ editorial revisions, annotations, elaborations, or other modifications
55
+ represent, as a whole, an original work of authorship. For the purposes
56
+ of this License, Derivative Works shall not include works that remain
57
+ separable from, or merely link (or bind by name) to the interfaces of,
58
+ the Work and Derivative Works thereof.
59
+
60
+ "Contribution" shall mean any work of authorship, including
61
+ the original version of the Work and any modifications or additions
62
+ to that Work or Derivative Works thereof, that is intentionally
63
+ submitted to Licensor for inclusion in the Work by the copyright owner
64
+ or by an individual or Legal Entity authorized to submit on behalf of
65
+ the copyright owner. For the purposes of this definition, "submitted"
66
+ means any form of electronic, verbal, or written communication sent
67
+ to the Licensor or its representatives, including but not limited to
68
+ communication on electronic mailing lists, source code control systems,
69
+ and issue tracking systems that are managed by, or on behalf of, the
70
+ Licensor for the purpose of discussing and improving the Work, but
71
+ excluding communication that is conspicuously marked or otherwise
72
+ designated in writing by the copyright owner as "Not a Contribution."
73
+
74
+ "Contributor" shall mean Licensor and any individual or Legal Entity
75
+ on behalf of whom a Contribution has been received by Licensor and
76
+ subsequently incorporated within the Work.
77
+
78
+ 2. Grant of Copyright License. Subject to the terms and conditions of
79
+ this License, each Contributor hereby grants to You a perpetual,
80
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81
+ copyright license to reproduce, prepare Derivative Works of,
82
+ publicly display, publicly perform, sublicense, and distribute the
83
+ Work and such Derivative Works in Source or Object form.
84
+
85
+ 3. Grant of Patent License. Subject to the terms and conditions of
86
+ this License, each Contributor hereby grants to You a perpetual,
87
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
88
+ (except as stated in this section) patent license to make, have made,
89
+ use, offer to sell, sell, import, and otherwise transfer the Work,
90
+ where such license applies only to those patent claims licensable
91
+ by such Contributor that are necessarily infringed by their
92
+ Contribution(s) alone or by combination of their Contribution(s)
93
+ with the Work to which such Contribution(s) was submitted. If You
94
+ institute patent litigation against any entity (including a
95
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
96
+ or a Contribution incorporated within the Work constitutes direct
97
+ or contributory patent infringement, then any patent licenses
98
+ granted to You under this License for that Work shall terminate
99
+ as of the date such litigation is filed.
100
+
101
+ 4. Redistribution. You may reproduce and distribute copies of the
102
+ Work or Derivative Works thereof in any medium, with or without
103
+ modifications, and in Source or Object form, provided that You
104
+ meet the following conditions:
105
+
106
+ (a) You must give any other recipients of the Work or
107
+ Derivative Works a copy of this License; and
108
+
109
+ (b) You must cause any modified files to carry prominent notices
110
+ stating that You changed the files; and
111
+
112
+ (c) You must retain, in the Source form of any Derivative Works
113
+ that You distribute, all copyright, patent, trademark, and
114
+ attribution notices from the Source form of the Work,
115
+ excluding those notices that do not pertain to any part of
116
+ the Derivative Works; and
117
+
118
+ (d) If the Work includes a "NOTICE" text file as part of its
119
+ distribution, then any Derivative Works that You distribute must
120
+ include a readable copy of the attribution notices contained
121
+ within such NOTICE file, excluding those notices that do not
122
+ pertain to any part of the Derivative Works, in at least one
123
+ of the following places: within a NOTICE text file distributed
124
+ as part of the Derivative Works; within the Source form or
125
+ documentation, if provided along with the Derivative Works; or,
126
+ within a display generated by the Derivative Works, if and
127
+ wherever such third-party notices normally appear. The contents
128
+ of the NOTICE file are for informational purposes only and
129
+ do not modify the License. You may add Your own attribution
130
+ notices within Derivative Works that You distribute, alongside
131
+ or as an addendum to the NOTICE text from the Work, provided
132
+ that such additional attribution notices cannot be construed
133
+ as modifying the License.
134
+
135
+ You may add Your own copyright statement to Your modifications and
136
+ may provide additional or different license terms and conditions
137
+ for use, reproduction, or distribution of Your modifications, or
138
+ for any such Derivative Works as a whole, provided Your use,
139
+ reproduction, and distribution of the Work otherwise complies with
140
+ the conditions stated in this License.
141
+
142
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
143
+ any Contribution intentionally submitted for inclusion in the Work
144
+ by You to the Licensor shall be under the terms and conditions of
145
+ this License, without any additional terms or conditions.
146
+ Notwithstanding the above, nothing herein shall supersede or modify
147
+ the terms of any separate license agreement you may have executed
148
+ with Licensor regarding such Contributions.
149
+
150
+ 6. Trademarks. This License does not grant permission to use the trade
151
+ names, trademarks, service marks, or product names of the Licensor,
152
+ except as required for reasonable and customary use in describing the
153
+ origin of the Work and reproducing the content of the NOTICE file.
154
+
155
+ 7. Disclaimer of Warranty. Unless required by applicable law or
156
+ agreed to in writing, Licensor provides the Work (and each
157
+ Contributor provides its Contributions) on an "AS IS" BASIS,
158
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
159
+ implied, including, without limitation, any warranties or conditions
160
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
161
+ PARTICULAR PURPOSE. You are solely responsible for determining the
162
+ appropriateness of using or redistributing the Work and assume any
163
+ risks associated with Your exercise of permissions under this License.
164
+
165
+ 8. Limitation of Liability. In no event and under no legal theory,
166
+ whether in tort (including negligence), contract, or otherwise,
167
+ unless required by applicable law (such as deliberate and grossly
168
+ negligent acts) or agreed to in writing, shall any Contributor be
169
+ liable to You for damages, including any direct, indirect, special,
170
+ incidental, or consequential damages of any character arising as a
171
+ result of this License or out of the use or inability to use the
172
+ Work (including but not limited to damages for loss of goodwill,
173
+ work stoppage, computer failure or malfunction, or any and all
174
+ other commercial damages or losses), even if such Contributor
175
+ has been advised of the possibility of such damages.
176
+
177
+ 9. Accepting Warranty or Additional Liability. While redistributing
178
+ the Work or Derivative Works thereof, You may choose to offer,
179
+ and charge a fee for, acceptance of support, warranty, indemnity,
180
+ or other liability obligations and/or rights consistent with this
181
+ License. However, in accepting such obligations, You may act only
182
+ on Your own behalf and on Your sole responsibility, not on behalf
183
+ of any other Contributor, and only if You agree to indemnify,
184
+ defend, and hold each Contributor harmless for any liability
185
+ incurred by, or claims asserted against, such Contributor by reason
186
+ of your accepting any such warranty or additional liability.
187
+
188
+ END OF TERMS AND CONDITIONS
189
+
190
+ APPENDIX: How to apply the Apache License to your work.
191
+
192
+ To apply the Apache License to your work, attach the following
193
+ boilerplate notice, with the fields enclosed by brackets "[]"
194
+ replaced with your own identifying information. (Don't include
195
+ the brackets!) The text should be enclosed in the appropriate
196
+ comment syntax for the file format. We also recommend that a
197
+ file or class name and description of purpose be included on the
198
+ same "printed page" as the copyright notice for easier
199
+ identification within third-party archives.
200
+
201
+ Copyright [yyyy] [name of copyright owner]
202
+
203
+ Licensed under the Apache License, Version 2.0 (the "License");
204
+ you may not use this file except in compliance with the License.
205
+ You may obtain a copy of the License at
206
+
207
+ http://www.apache.org/licenses/LICENSE-2.0
208
+
209
+ Unless required by applicable law or agreed to in writing, software
210
+ distributed under the License is distributed on an "AS IS" BASIS,
211
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
212
+ See the License for the specific language governing permissions and
213
+ limitations under the License.
214
+
215
+
216
+ Dependencies and Licenses:
217
+
218
+ This open-source project, WeMM-Embedding-2B, builds upon the following open-source models and/or software components, each of which remains licensed under its original license. Certain models or software may include modifications made by Tencent (“Tencent Modifications”), which are Copyright (C) Tencent.
219
+
220
+ In case you believe there have been errors in the attribution below, you may submit the concerns to us for review and correction.
221
+
222
+
223
+ Open Source Model Licensed under the Apache-2.0:
224
+ --------------------------------------------------------------------
225
+ 1. Qwen3.5-2B
226
+ Copyright 2026 Alibaba Cloud
227
+ Please note this model has been modified by Tencent in this distribution.
228
+
229
+
230
+
231
+ Terms of the Apache-2.0:
232
+ --------------------------------------------------------------------
233
+ Apache License
234
+ Version 2.0, January 2004
235
+ http://www.apache.org/licenses/
236
+
237
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
238
+
239
+ 1. Definitions.
240
+
241
+ "License" shall mean the terms and conditions for use, reproduction,
242
+ and distribution as defined by Sections 1 through 9 of this document.
243
+
244
+ "Licensor" shall mean the copyright owner or entity authorized by
245
+ the copyright owner that is granting the License.
246
+
247
+ "Legal Entity" shall mean the union of the acting entity and all
248
+ other entities that control, are controlled by, or are under common
249
+ control with that entity. For the purposes of this definition,
250
+ "control" means (i) the power, direct or indirect, to cause the
251
+ direction or management of such entity, whether by contract or
252
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
253
+ outstanding shares, or (iii) beneficial ownership of such entity.
254
+
255
+ "You" (or "Your") shall mean an individual or Legal Entity
256
+ exercising permissions granted by this License.
257
+
258
+ "Source" form shall mean the preferred form for making modifications,
259
+ including but not limited to software source code, documentation
260
+ source, and configuration files.
261
+
262
+ "Object" form shall mean any form resulting from mechanical
263
+ transformation or translation of a Source form, including but
264
+ not limited to compiled object code, generated documentation,
265
+ and conversions to other media types.
266
+
267
+ "Work" shall mean the work of authorship, whether in Source or
268
+ Object form, made available under the License, as indicated by a
269
+ copyright notice that is included in or attached to the work
270
+ (an example is provided in the Appendix below).
271
+
272
+ "Derivative Works" shall mean any work, whether in Source or Object
273
+ form, that is based on (or derived from) the Work and for which the
274
+ editorial revisions, annotations, elaborations, or other modifications
275
+ represent, as a whole, an original work of authorship. For the purposes
276
+ of this License, Derivative Works shall not include works that remain
277
+ separable from, or merely link (or bind by name) to the interfaces of,
278
+ the Work and Derivative Works thereof.
279
+
280
+ "Contribution" shall mean any work of authorship, including
281
+ the original version of the Work and any modifications or additions
282
+ to that Work or Derivative Works thereof, that is intentionally
283
+ submitted to Licensor for inclusion in the Work by the copyright owner
284
+ or by an individual or Legal Entity authorized to submit on behalf of
285
+ the copyright owner. For the purposes of this definition, "submitted"
286
+ means any form of electronic, verbal, or written communication sent
287
+ to the Licensor or its representatives, including but not limited to
288
+ communication on electronic mailing lists, source code control systems,
289
+ and issue tracking systems that are managed by, or on behalf of, the
290
+ Licensor for the purpose of discussing and improving the Work, but
291
+ excluding communication that is conspicuously marked or otherwise
292
+ designated in writing by the copyright owner as "Not a Contribution."
293
+
294
+ "Contributor" shall mean Licensor and any individual or Legal Entity
295
+ on behalf of whom a Contribution has been received by Licensor and
296
+ subsequently incorporated within the Work.
297
+
298
+ 2. Grant of Copyright License. Subject to the terms and conditions of
299
+ this License, each Contributor hereby grants to You a perpetual,
300
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
301
+ copyright license to reproduce, prepare Derivative Works of,
302
+ publicly display, publicly perform, sublicense, and distribute the
303
+ Work and such Derivative Works in Source or Object form.
304
+
305
+ 3. Grant of Patent License. Subject to the terms and conditions of
306
+ this License, each Contributor hereby grants to You a perpetual,
307
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
308
+ (except as stated in this section) patent license to make, have made,
309
+ use, offer to sell, sell, import, and otherwise transfer the Work,
310
+ where such license applies only to those patent claims licensable
311
+ by such Contributor that are necessarily infringed by their
312
+ Contribution(s) alone or by combination of their Contribution(s)
313
+ with the Work to which such Contribution(s) was submitted. If You
314
+ institute patent litigation against any entity (including a
315
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
316
+ or a Contribution incorporated within the Work constitutes direct
317
+ or contributory patent infringement, then any patent licenses
318
+ granted to You under this License for that Work shall terminate
319
+ as of the date such litigation is filed.
320
+
321
+ 4. Redistribution. You may reproduce and distribute copies of the
322
+ Work or Derivative Works thereof in any medium, with or without
323
+ modifications, and in Source or Object form, provided that You
324
+ meet the following conditions:
325
+
326
+ (a) You must give any other recipients of the Work or
327
+ Derivative Works a copy of this License; and
328
+
329
+ (b) You must cause any modified files to carry prominent notices
330
+ stating that You changed the files; and
331
+
332
+ (c) You must retain, in the Source form of any Derivative Works
333
+ that You distribute, all copyright, patent, trademark, and
334
+ attribution notices from the Source form of the Work,
335
+ excluding those notices that do not pertain to any part of
336
+ the Derivative Works; and
337
+
338
+ (d) If the Work includes a "NOTICE" text file as part of its
339
+ distribution, then any Derivative Works that You distribute must
340
+ include a readable copy of the attribution notices contained
341
+ within such NOTICE file, excluding those notices that do not
342
+ pertain to any part of the Derivative Works, in at least one
343
+ of the following places: within a NOTICE text file distributed
344
+ as part of the Derivative Works; within the Source form or
345
+ documentation, if provided along with the Derivative Works; or,
346
+ within a display generated by the Derivative Works, if and
347
+ wherever such third-party notices normally appear. The contents
348
+ of the NOTICE file are for informational purposes only and
349
+ do not modify the License. You may add Your own attribution
350
+ notices within Derivative Works that You distribute, alongside
351
+ or as an addendum to the NOTICE text from the Work, provided
352
+ that such additional attribution notices cannot be construed
353
+ as modifying the License.
354
+
355
+ You may add Your own copyright statement to Your modifications and
356
+ may provide additional or different license terms and conditions
357
+ for use, reproduction, or distribution of Your modifications, or
358
+ for any such Derivative Works as a whole, provided Your use,
359
+ reproduction, and distribution of the Work otherwise complies with
360
+ the conditions stated in this License.
361
+
362
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
363
+ any Contribution intentionally submitted for inclusion in the Work
364
+ by You to the Licensor shall be under the terms and conditions of
365
+ this License, without any additional terms or conditions.
366
+ Notwithstanding the above, nothing herein shall supersede or modify
367
+ the terms of any separate license agreement you may have executed
368
+ with Licensor regarding such Contributions.
369
+
370
+ 6. Trademarks. This License does not grant permission to use the trade
371
+ names, trademarks, service marks, or product names of the Licensor,
372
+ except as required for reasonable and customary use in describing the
373
+ origin of the Work and reproducing the content of the NOTICE file.
374
+
375
+ 7. Disclaimer of Warranty. Unless required by applicable law or
376
+ agreed to in writing, Licensor provides the Work (and each
377
+ Contributor provides its Contributions) on an "AS IS" BASIS,
378
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
379
+ implied, including, without limitation, any warranties or conditions
380
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
381
+ PARTICULAR PURPOSE. You are solely responsible for determining the
382
+ appropriateness of using or redistributing the Work and assume any
383
+ risks associated with Your exercise of permissions under this License.
384
+
385
+ 8. Limitation of Liability. In no event and under no legal theory,
386
+ whether in tort (including negligence), contract, or otherwise,
387
+ unless required by applicable law (such as deliberate and grossly
388
+ negligent acts) or agreed to in writing, shall any Contributor be
389
+ liable to You for damages, including any direct, indirect, special,
390
+ incidental, or consequential damages of any character arising as a
391
+ result of this License or out of the use or inability to use the
392
+ Work (including but not limited to damages for loss of goodwill,
393
+ work stoppage, computer failure or malfunction, or any and all
394
+ other commercial damages or losses), even if such Contributor
395
+ has been advised of the possibility of such damages.
396
+
397
+ 9. Accepting Warranty or Additional Liability. While redistributing
398
+ the Work or Derivative Works thereof, You may choose to offer,
399
+ and charge a fee for, acceptance of support, warranty, indemnity,
400
+ or other liability obligations and/or rights consistent with this
401
+ License. However, in accepting such obligations, You may act only
402
+ on Your own behalf and on Your sole responsibility, not on behalf
403
+ of any other Contributor, and only if You agree to indemnify,
404
+ defend, and hold each Contributor harmless for any liability
405
+ incurred by, or claims asserted against, such Contributor by reason
406
+ of your accepting any such warranty or additional liability.
407
+
408
+ END OF TERMS AND CONDITIONS
409
+
410
+ APPENDIX: How to apply the Apache License to your work.
411
+
412
+ To apply the Apache License to your work, attach the following
413
+ boilerplate notice, with the fields enclosed by brackets "[]"
414
+ replaced with your own identifying information. (Don't include
415
+ the brackets!) The text should be enclosed in the appropriate
416
+ comment syntax for the file format. We also recommend that a
417
+ file or class name and description of purpose be included on the
418
+ same "printed page" as the copyright notice for easier
419
+ identification within third-party archives.
420
+
421
+ Copyright [yyyy] [name of copyright owner]
422
+
423
+ Licensed under the Apache License, Version 2.0 (the "License");
424
+ you may not use this file except in compliance with the License.
425
+ You may obtain a copy of the License at
426
+
427
+ http://www.apache.org/licenses/LICENSE-2.0
428
+
429
+ Unless required by applicable law or agreed to in writing, software
430
+ distributed under the License is distributed on an "AS IS" BASIS,
431
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
432
+ See the License for the specific language governing permissions and
433
+ limitations under the License.
434
+
435
+
README.md ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ license: apache-2.0
4
+ base_model:
5
+ - Qwen/Qwen3.5-2B
6
+ pipeline_tag: feature-extraction
7
+ tags:
8
+ - multimodal-embedding
9
+ - text-embedding
10
+ - image-embedding
11
+ - video-embedding
12
+ - mrl
13
+ ---
14
+
15
+ # WeMM-Embedding-2B
16
+
17
+ WeMM-Embedding-2B is a universal multimodal embedding model built on Qwen3.5. It accepts text, images, videos, visual documents, and interleaved multimodal inputs, and returns a 2,048-dimensional L2-normalized embedding. Audio input is not supported.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install torch transformers==5.2.0 "qwen-vl-utils[decord]==0.0.14" \
23
+ sentence-transformers==5.7.0 "accelerate>=1.1.0"
24
+ ```
25
+
26
+ ## Transformers
27
+
28
+ ```python
29
+ import torch
30
+ from qwen_vl_utils import process_vision_info
31
+ from transformers import AutoModel, AutoProcessor
32
+
33
+ model_id = "tencent/WeMM-Embedding-2B"
34
+ processor = AutoProcessor.from_pretrained(model_id, trust_remote_code=True)
35
+ model = AutoModel.from_pretrained(
36
+ model_id, trust_remote_code=True, dtype=torch.bfloat16
37
+ ).cuda().eval()
38
+
39
+ messages = [{"role": "user", "content": [
40
+ {"type": "image", "image": "/path/to/image.jpg"},
41
+ {"type": "video", "video": "/path/to/video.mp4"},
42
+ {"type": "text", "text": "This can be any text input."},
43
+ ]}]
44
+ text = processor.apply_chat_template(
45
+ messages, tokenize=False, add_generation_prompt=False
46
+ )
47
+ images, videos, video_kwargs = process_vision_info(
48
+ messages,
49
+ image_patch_size=16,
50
+ return_video_kwargs=True,
51
+ return_video_metadata=True,
52
+ )
53
+ if videos is not None:
54
+ videos, video_metadata = zip(*videos)
55
+ videos, video_metadata = list(videos), list(video_metadata)
56
+ else:
57
+ video_metadata = None
58
+ inputs = processor(
59
+ text=text,
60
+ images=images,
61
+ videos=videos,
62
+ video_metadata=video_metadata,
63
+ return_tensors="pt",
64
+ **video_kwargs,
65
+ ).to("cuda")
66
+
67
+ with torch.inference_mode():
68
+ embedding = model.embedding(**inputs)
69
+ ```
70
+
71
+ Use any subset of the content items to encode text, image, or video independently.
72
+
73
+ ## Sentence Transformers
74
+
75
+ ```python
76
+ from wemm_sentence_transformers import load_wemm_sentence_transformer
77
+
78
+ model_id = "tencent/WeMM-Embedding-2B"
79
+ model = load_wemm_sentence_transformer(model_id, device="cuda:0")
80
+ inputs = [
81
+ "A dog is running on a beach.",
82
+ {"image": "/path/to/image.jpg", "text": "Represent this image."},
83
+ {"video": "/path/to/video.mp4", "text": "Represent this video."},
84
+ ]
85
+ embeddings = model.encode(
86
+ inputs,
87
+ batch_size=1,
88
+ truncate_dim=256,
89
+ normalize_embeddings=True,
90
+ )
91
+ ```
92
+
93
+
94
+ ## Matryoshka Embeddings
95
+
96
+ ```python
97
+ embedding_256 = torch.nn.functional.normalize(embedding[..., :256], dim=-1)
98
+ ```
99
+
100
+ Use a dimension listed in `model.config.matryoshka_dimensions`. On MMEB-v2, 256-dimensional embeddings retain 98.7% of the full-dimensional image and video performance.
101
+
102
+ ## Serving
103
+
104
+ vLLM `0.27.0`:
105
+
106
+ ```bash
107
+ MODEL_PATH=/path/to/WeMM-Embedding-2B
108
+ vllm serve "$MODEL_PATH" \
109
+ --runner pooling \
110
+ --chat-template "$MODEL_PATH/embedding_chat_template.jinja"
111
+ ```
112
+
113
+ SGLang `0.5.9`:
114
+
115
+ ```bash
116
+ MODEL_PATH=/path/to/WeMM-Embedding-2B
117
+ python patch_sglang_video.py
118
+ python -m sglang.launch_server \
119
+ --model-path "$MODEL_PATH" \
120
+ --is-embedding \
121
+ --enable-precise-embedding-interpolation
122
+ ```
123
+
124
+ ## Citation
125
+
126
+ ```bibtex
127
+ @techreport{wemm_embedding_2026,
128
+ title = {WeMM-Embedding: WeChat Multi-Modal Embedding Technical Report},
129
+ author = {{WeChat Vision}},
130
+ institution = {Tencent Inc.},
131
+ year = {2026}
132
+ }
133
+ ```
134
+
135
+ ## License
136
+
137
+ WeMM-Embedding-2B, including the code, model parameters, and weights made publicly
138
+ available by Tencent, is licensed under the [Apache License 2.0](https://huggingface.co/tencent/WeMM-Embedding-2B/blob/main/LICENSE).
139
+ Third-party components remain subject to their respective original licenses.
chat_template.jinja ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set image_count = namespace(value=0) %}
2
+ {%- set video_count = namespace(value=0) %}
3
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
4
+ {%- if content is string %}
5
+ {{- content }}
6
+ {%- elif content is iterable and content is not mapping %}
7
+ {%- for item in content %}
8
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
9
+ {%- if is_system_content %}
10
+ {{- raise_exception('System message cannot contain images.') }}
11
+ {%- endif %}
12
+ {%- if do_vision_count %}
13
+ {%- set image_count.value = image_count.value + 1 %}
14
+ {%- endif %}
15
+ {%- if add_vision_id %}
16
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
17
+ {%- endif %}
18
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
19
+ {%- elif 'video' in item or item.type == 'video' %}
20
+ {%- if is_system_content %}
21
+ {{- raise_exception('System message cannot contain videos.') }}
22
+ {%- endif %}
23
+ {%- if do_vision_count %}
24
+ {%- set video_count.value = video_count.value + 1 %}
25
+ {%- endif %}
26
+ {%- if add_vision_id %}
27
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
28
+ {%- endif %}
29
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
30
+ {%- elif 'text' in item %}
31
+ {{- item.text }}
32
+ {%- else %}
33
+ {{- raise_exception('Unexpected item type in content.') }}
34
+ {%- endif %}
35
+ {%- endfor %}
36
+ {%- elif content is none or content is undefined %}
37
+ {{- '' }}
38
+ {%- else %}
39
+ {{- raise_exception('Unexpected content type.') }}
40
+ {%- endif %}
41
+ {%- endmacro %}
42
+ {%- if not messages %}
43
+ {{- raise_exception('No messages provided.') }}
44
+ {%- endif %}
45
+ {%- if tools and tools is iterable and tools is not mapping %}
46
+ {{- '<|im_start|>system\n' }}
47
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
48
+ {%- for tool in tools %}
49
+ {{- "\n" }}
50
+ {{- tool | tojson }}
51
+ {%- endfor %}
52
+ {{- "\n</tools>" }}
53
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
54
+ {%- if messages[0].role == 'system' %}
55
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
56
+ {%- if content %}
57
+ {{- '\n\n' + content }}
58
+ {%- endif %}
59
+ {%- endif %}
60
+ {{- '<|im_end|>\n' }}
61
+ {%- else %}
62
+ {%- if messages[0].role == 'system' %}
63
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
64
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
65
+ {%- endif %}
66
+ {%- endif %}
67
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
68
+ {%- for message in messages[::-1] %}
69
+ {%- set index = (messages|length - 1) - loop.index0 %}
70
+ {%- if ns.multi_step_tool and message.role == "user" %}
71
+ {%- set content = render_content(message.content, false)|trim %}
72
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
73
+ {%- set ns.multi_step_tool = false %}
74
+ {%- set ns.last_query_index = index %}
75
+ {%- endif %}
76
+ {%- endif %}
77
+ {%- endfor %}
78
+ {%- if ns.multi_step_tool %}
79
+ {{- raise_exception('No user query found in messages.') }}
80
+ {%- endif %}
81
+ {%- for message in messages %}
82
+ {%- set content = render_content(message.content, true)|trim %}
83
+ {%- if message.role == "system" %}
84
+ {%- if not loop.first %}
85
+ {{- raise_exception('System message must be at the beginning.') }}
86
+ {%- endif %}
87
+ {%- elif message.role == "user" %}
88
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
89
+ {%- elif message.role == "assistant" %}
90
+ {%- set reasoning_content = '' %}
91
+ {%- if message.reasoning_content is string %}
92
+ {%- set reasoning_content = message.reasoning_content %}
93
+ {%- else %}
94
+ {%- if '</think>' in content %}
95
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
96
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
97
+ {%- endif %}
98
+ {%- endif %}
99
+ {%- set reasoning_content = reasoning_content|trim %}
100
+ {%- if loop.index0 > ns.last_query_index %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- else %}
103
+ {{- '<|im_start|>' + message.role + '\n' + content }}
104
+ {%- endif %}
105
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
106
+ {%- for tool_call in message.tool_calls %}
107
+ {%- if tool_call.function is defined %}
108
+ {%- set tool_call = tool_call.function %}
109
+ {%- endif %}
110
+ {%- if loop.first %}
111
+ {%- if content|trim %}
112
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
113
+ {%- else %}
114
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- else %}
117
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
118
+ {%- endif %}
119
+ {%- if tool_call.arguments is defined %}
120
+ {%- for args_name, args_value in tool_call.arguments|items %}
121
+ {{- '<parameter=' + args_name + '>\n' }}
122
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
123
+ {{- args_value }}
124
+ {{- '\n</parameter>\n' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '</function>\n</tool_call>' }}
128
+ {%- endfor %}
129
+ {%- endif %}
130
+ {{- '<|im_end|>\n' }}
131
+ {%- elif message.role == "tool" %}
132
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
133
+ {{- '<|im_start|>user' }}
134
+ {%- endif %}
135
+ {{- '\n<tool_response>\n' }}
136
+ {{- content }}
137
+ {{- '\n</tool_response>' }}
138
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
139
+ {{- '<|im_end|>\n' }}
140
+ {%- elif loop.last %}
141
+ {{- '<|im_end|>\n' }}
142
+ {%- endif %}
143
+ {%- else %}
144
+ {{- raise_exception('Unexpected message role.') }}
145
+ {%- endif %}
146
+ {%- endfor %}
147
+ {%- if add_generation_prompt %}
148
+ {{- '<|im_start|>assistant\n' }}
149
+ {%- if enable_thinking is defined and enable_thinking is true %}
150
+ {{- '<think>\n' }}
151
+ {%- else %}
152
+ {{- '<think>\n\n</think>\n\n' }}
153
+ {%- endif %}
154
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3_5ForConditionalGeneration"
4
+ ],
5
+ "dtype": "bfloat16",
6
+ "image_token_id": 248056,
7
+ "model_type": "qwen3_5",
8
+ "text_config": {
9
+ "attention_bias": false,
10
+ "attention_dropout": 0.0,
11
+ "attn_output_gate": true,
12
+ "bos_token_id": null,
13
+ "dtype": "bfloat16",
14
+ "eos_token_id": 248044,
15
+ "full_attention_interval": 4,
16
+ "head_dim": 256,
17
+ "hidden_act": "silu",
18
+ "hidden_size": 2048,
19
+ "initializer_range": 0.02,
20
+ "intermediate_size": 6144,
21
+ "layer_types": [
22
+ "linear_attention",
23
+ "linear_attention",
24
+ "linear_attention",
25
+ "full_attention",
26
+ "linear_attention",
27
+ "linear_attention",
28
+ "linear_attention",
29
+ "full_attention",
30
+ "linear_attention",
31
+ "linear_attention",
32
+ "linear_attention",
33
+ "full_attention",
34
+ "linear_attention",
35
+ "linear_attention",
36
+ "linear_attention",
37
+ "full_attention",
38
+ "linear_attention",
39
+ "linear_attention",
40
+ "linear_attention",
41
+ "full_attention",
42
+ "linear_attention",
43
+ "linear_attention",
44
+ "linear_attention",
45
+ "full_attention"
46
+ ],
47
+ "linear_conv_kernel_dim": 4,
48
+ "linear_key_head_dim": 128,
49
+ "linear_num_key_heads": 16,
50
+ "linear_num_value_heads": 16,
51
+ "linear_value_head_dim": 128,
52
+ "mamba_ssm_dtype": "float32",
53
+ "max_position_embeddings": 262144,
54
+ "mlp_only_layers": [],
55
+ "model_type": "qwen3_5_text",
56
+ "mtp_num_hidden_layers": 1,
57
+ "mtp_use_dedicated_embeddings": false,
58
+ "num_attention_heads": 8,
59
+ "num_hidden_layers": 24,
60
+ "num_key_value_heads": 2,
61
+ "pad_token_id": null,
62
+ "partial_rotary_factor": 0.25,
63
+ "rms_norm_eps": 1e-06,
64
+ "rope_parameters": {
65
+ "mrope_interleaved": true,
66
+ "mrope_section": [
67
+ 11,
68
+ 11,
69
+ 10
70
+ ],
71
+ "partial_rotary_factor": 0.25,
72
+ "rope_theta": 10000000,
73
+ "rope_type": "default"
74
+ },
75
+ "tie_word_embeddings": false,
76
+ "use_cache": true,
77
+ "vocab_size": 248078
78
+ },
79
+ "tie_word_embeddings": false,
80
+ "transformers_version": "5.2.0",
81
+ "video_token_id": 248057,
82
+ "vision_config": {
83
+ "deepstack_visual_indexes": [],
84
+ "depth": 24,
85
+ "dtype": "bfloat16",
86
+ "hidden_act": "gelu_pytorch_tanh",
87
+ "hidden_size": 1024,
88
+ "in_channels": 3,
89
+ "initializer_range": 0.02,
90
+ "intermediate_size": 4096,
91
+ "model_type": "qwen3_5",
92
+ "num_heads": 16,
93
+ "num_position_embeddings": 2304,
94
+ "out_hidden_size": 2048,
95
+ "patch_size": 16,
96
+ "spatial_merge_size": 2,
97
+ "temporal_patch_size": 2
98
+ },
99
+ "vision_end_token_id": 248054,
100
+ "vision_start_token_id": 248053,
101
+ "auto_map": {
102
+ "AutoModel": "modeling_wemm_embedding.WeMMEmbedding",
103
+ "AutoModelForCausalLM": "modeling_wemm_embedding.WeMMEmbedding"
104
+ },
105
+ "matryoshka_dimensions": [
106
+ 64,
107
+ 128,
108
+ 256,
109
+ 512,
110
+ 1024,
111
+ 2048
112
+ ]
113
+ }
embedding_chat_template.jinja ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {# Direct-tokenization template for vLLM 0.27 embedding requests.
2
+ Qwen's processor post-processor removes the role newline before images,
3
+ keeps it before text/video, and appends <embedding> without a preceding
4
+ newline. vLLM 0.27 adds each frame's vision boundaries itself, so video
5
+ uses a bare <video_pad> placeholder. #}
6
+ {%- for message in messages %}
7
+ {{- '<|im_start|>' + message.role }}
8
+ {%- if message.content is string %}
9
+ {{- '\n' + message.content }}
10
+ {%- else %}
11
+ {%- for item in message.content %}
12
+ {%- if item.type in ['image', 'image_url'] or 'image' in item or 'image_url' in item %}
13
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
14
+ {%- elif item.type in ['video', 'video_url'] or 'video' in item or 'video_url' in item %}
15
+ {{- '\n<|video_pad|>' }}
16
+ {%- elif item.type == 'text' or 'text' in item %}
17
+ {{- ('\n' if loop.first else '') + item.text }}
18
+ {%- else %}
19
+ {{- raise_exception('Unsupported embedding content type') }}
20
+ {%- endif %}
21
+ {%- endfor %}
22
+ {%- endif %}
23
+ {{- '<|im_end|>' }}
24
+ {%- if not loop.last %}
25
+ {{- '\n' }}
26
+ {%- endif %}
27
+ {%- endfor %}
28
+ {{- '<embedding>' }}
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1a1ad752808c26965aa97d37bf4a9bca71d838513f41e83790cb1e71cac6e59
3
+ size 5441695216
modeling_wemm_embedding.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn.functional as F
3
+ from transformers import Qwen3_5ForConditionalGeneration
4
+
5
+
6
+ class WeMMEmbedding(Qwen3_5ForConditionalGeneration):
7
+ def embedding(self, input_ids=None, attention_mask=None, **kwargs):
8
+ outputs = self.model(
9
+ input_ids=input_ids,
10
+ attention_mask=attention_mask,
11
+ **kwargs
12
+ )
13
+
14
+ last_hidden_state = outputs.last_hidden_state
15
+
16
+ if attention_mask is not None:
17
+ eos_positions = attention_mask.sum(dim=1) - 1
18
+ else:
19
+ eos_positions = torch.full((last_hidden_state.shape[0],), last_hidden_state.shape[1] - 1, device=last_hidden_state.device)
20
+
21
+ eos_positions = eos_positions.clamp(min=0)
22
+
23
+ batch_indices = torch.arange(last_hidden_state.size(0), device=last_hidden_state.device)
24
+
25
+ embeddings = last_hidden_state[batch_indices, eos_positions]
26
+
27
+ embeddings = F.normalize(embeddings, dim=-1)
28
+
29
+ return embeddings
patch_sglang_video.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Align SGLang 0.5.9 video preprocessing with WeMM-Embedding."""
3
+
4
+ import importlib.metadata
5
+ import py_compile
6
+ import shutil
7
+ from pathlib import Path
8
+
9
+ import sglang
10
+
11
+
12
+ EXPECTED_VERSION = "0.5.9"
13
+ REPLACEMENTS = (
14
+ (
15
+ "IMAGE_FACTOR = 28",
16
+ "IMAGE_FACTOR = 32 # patch_size=16 * spatial_merge_size=2",
17
+ ),
18
+ (
19
+ " idx = np.linspace(0, total_frames - 1, num=nframes, dtype=np.int64)",
20
+ " idx = torch.linspace(0, total_frames - 1, nframes).round().long().cpu().numpy()",
21
+ ),
22
+ (
23
+ """ video = torchvision.transforms.functional.resize(
24
+ video,
25
+ [resized_height, resized_width],
26
+ interpolation=InterpolationMode.BILINEAR,
27
+ )
28
+ """,
29
+ """ video = torchvision.transforms.functional.resize(
30
+ video,
31
+ [resized_height, resized_width],
32
+ interpolation=InterpolationMode.BICUBIC,
33
+ antialias=True,
34
+ ).float()
35
+ """,
36
+ ),
37
+ )
38
+
39
+
40
+ def main() -> None:
41
+ version = importlib.metadata.version("sglang")
42
+ if version != EXPECTED_VERSION:
43
+ raise RuntimeError(f"Expected sglang=={EXPECTED_VERSION}, found {version}")
44
+
45
+ path = (
46
+ Path(sglang.__file__).resolve().parent
47
+ / "srt"
48
+ / "multimodal"
49
+ / "processors"
50
+ / "qwen_vl.py"
51
+ )
52
+ text = path.read_text(encoding="utf-8")
53
+ if all(new in text for _, new in REPLACEMENTS):
54
+ print("SGLang video preprocessing is ready.")
55
+ return
56
+
57
+ updated = text
58
+ for old, new in REPLACEMENTS:
59
+ if updated.count(old) != 1:
60
+ raise RuntimeError(f"Unexpected SGLang source: {old.splitlines()[0]}")
61
+ updated = updated.replace(old, new, 1)
62
+
63
+ backup = path.with_suffix(path.suffix + ".original")
64
+ if not backup.exists():
65
+ shutil.copy2(path, backup)
66
+ path.write_text(updated, encoding="utf-8")
67
+ py_compile.compile(str(path), doraise=True)
68
+ print("SGLang video preprocessing is ready.")
69
+
70
+
71
+ if __name__ == "__main__":
72
+ main()
73
+
processor_config.json ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "image_processor": {
3
+ "do_convert_rgb": true,
4
+ "do_normalize": true,
5
+ "do_rescale": true,
6
+ "do_resize": true,
7
+ "image_mean": [
8
+ 0.5,
9
+ 0.5,
10
+ 0.5
11
+ ],
12
+ "image_processor_type": "Qwen2VLImageProcessor",
13
+ "image_std": [
14
+ 0.5,
15
+ 0.5,
16
+ 0.5
17
+ ],
18
+ "merge_size": 2,
19
+ "patch_size": 16,
20
+ "resample": 3,
21
+ "rescale_factor": 0.00392156862745098,
22
+ "size": {
23
+ "longest_edge": 16777216,
24
+ "shortest_edge": 65536
25
+ },
26
+ "temporal_patch_size": 2
27
+ },
28
+ "processor_class": "Qwen3VLProcessor",
29
+ "video_processor": {
30
+ "do_convert_rgb": true,
31
+ "do_normalize": true,
32
+ "do_rescale": true,
33
+ "do_resize": true,
34
+ "do_sample_frames": true,
35
+ "fps": 2,
36
+ "image_mean": [
37
+ 0.5,
38
+ 0.5,
39
+ 0.5
40
+ ],
41
+ "image_std": [
42
+ 0.5,
43
+ 0.5,
44
+ 0.5
45
+ ],
46
+ "max_frames": 768,
47
+ "merge_size": 2,
48
+ "min_frames": 4,
49
+ "patch_size": 16,
50
+ "resample": 3,
51
+ "rescale_factor": 0.00392156862745098,
52
+ "return_metadata": false,
53
+ "size": {
54
+ "longest_edge": 234881024,
55
+ "shortest_edge": 4096
56
+ },
57
+ "temporal_patch_size": 2,
58
+ "video_processor_type": "Qwen3VLVideoProcessor"
59
+ }
60
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:40e444c744512f423da4c8443c47c21e22ff76056ba4e9796a81c04c13a9daf0
3
+ size 19990378
tokenizer_config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "audio_bos_token": "<|audio_start|>",
4
+ "audio_eos_token": "<|audio_end|>",
5
+ "audio_token": "<|audio_pad|>",
6
+ "backend": "tokenizers",
7
+ "bos_token": null,
8
+ "clean_up_tokenization_spaces": false,
9
+ "eos_token": "<|endoftext|>",
10
+ "errors": "replace",
11
+ "image_token": "<|image_pad|>",
12
+ "is_local": true,
13
+ "model_max_length": 262144,
14
+ "model_specific_special_tokens": {
15
+ "audio_bos_token": "<|audio_start|>",
16
+ "audio_eos_token": "<|audio_end|>",
17
+ "audio_token": "<|audio_pad|>",
18
+ "image_token": "<|image_pad|>",
19
+ "video_token": "<|video_pad|>",
20
+ "vision_bos_token": "<|vision_start|>",
21
+ "vision_eos_token": "<|vision_end|>"
22
+ },
23
+ "pad_token": "<|endoftext|>",
24
+ "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
25
+ "processor_class": "Qwen3VLProcessor",
26
+ "split_special_tokens": false,
27
+ "tokenizer_class": "Qwen2TokenizerFast",
28
+ "unk_token": null,
29
+ "video_token": "<|video_pad|>",
30
+ "vision_bos_token": "<|vision_start|>",
31
+ "vision_eos_token": "<|vision_end|>"
32
+ }
wemm_sentence_transformers.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Sentence-Transformers adapter for WeMM-Embedding."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import torch
10
+ from qwen_vl_utils import process_vision_info
11
+ from sentence_transformers import SentenceTransformer
12
+ from sentence_transformers.sentence_transformer.modules import InputModule
13
+ from transformers import AutoModel, AutoProcessor
14
+
15
+
16
+ def _as_messages(
17
+ value: Any,
18
+ prompt: str | None = None,
19
+ ) -> list[dict[str, Any]]:
20
+ if isinstance(value, str):
21
+ text = f"{prompt or ''}{value}"
22
+ return [{"role": "user", "content": [{"type": "text", "text": text}]}]
23
+
24
+ if isinstance(value, list):
25
+ if not value or not all(
26
+ isinstance(message, dict) and "role" in message for message in value
27
+ ):
28
+ raise TypeError("A list input must be one chat-style conversation.")
29
+ messages = [dict(message) for message in value]
30
+ if prompt:
31
+ messages.insert(0, {"role": "user", "content": prompt})
32
+ return messages
33
+
34
+ if not isinstance(value, dict):
35
+ raise TypeError(
36
+ "Input must be text, a chat conversation, or a multimodal dict."
37
+ )
38
+ if "messages" in value:
39
+ return _as_messages(value["messages"], prompt=prompt)
40
+
41
+ content: list[dict[str, Any]] = []
42
+ for modality in ("image", "video"):
43
+ if value.get(modality) is not None:
44
+ content.append({"type": modality, modality: value[modality]})
45
+ if value.get("text") is not None:
46
+ content.append(
47
+ {"type": "text", "text": f"{prompt or ''}{value['text']}"}
48
+ )
49
+ elif prompt:
50
+ content.append({"type": "text", "text": prompt})
51
+ if not content:
52
+ raise ValueError("Input must contain text, image, or video.")
53
+ return [{"role": "user", "content": content}]
54
+
55
+
56
+ class WeMMInputModule(InputModule):
57
+ config_keys = ["model_name_or_path"]
58
+ save_in_root = False
59
+
60
+ def __init__(
61
+ self,
62
+ model_name_or_path: str,
63
+ *,
64
+ device: str | torch.device | None = None,
65
+ **_: Any,
66
+ ) -> None:
67
+ super().__init__()
68
+ self.model_name_or_path = str(model_name_or_path)
69
+ self.processor = AutoProcessor.from_pretrained(
70
+ self.model_name_or_path,
71
+ trust_remote_code=True,
72
+ )
73
+ self.tokenizer = self.processor.tokenizer
74
+ self.tokenizer.padding_side = "right"
75
+ self.auto_model = AutoModel.from_pretrained(
76
+ self.model_name_or_path,
77
+ trust_remote_code=True,
78
+ dtype=torch.bfloat16,
79
+ device_map=device,
80
+ attn_implementation="sdpa",
81
+ experts_implementation="eager",
82
+ ).eval()
83
+ self.embedding_token_id = self.tokenizer.convert_tokens_to_ids(
84
+ "<embedding>"
85
+ )
86
+ text_config = getattr(
87
+ self.auto_model.config,
88
+ "text_config",
89
+ self.auto_model.config,
90
+ )
91
+ self.embedding_dimension = int(text_config.hidden_size)
92
+
93
+ @property
94
+ def modalities(self):
95
+ return [
96
+ "text",
97
+ "image",
98
+ "video",
99
+ "message",
100
+ ("image", "text"),
101
+ ("text", "video"),
102
+ ]
103
+
104
+ @property
105
+ def max_seq_length(self) -> int:
106
+ return int(self.tokenizer.model_max_length)
107
+
108
+ def preprocess(
109
+ self,
110
+ inputs: list[Any],
111
+ prompt: str | None = None,
112
+ **_: Any,
113
+ ) -> dict[str, torch.Tensor | Any]:
114
+ conversations = [
115
+ _as_messages(value, prompt=prompt)
116
+ for value in inputs
117
+ ]
118
+ prompts = [
119
+ self.processor.apply_chat_template(
120
+ messages,
121
+ tokenize=False,
122
+ add_generation_prompt=False,
123
+ )
124
+ for messages in conversations
125
+ ]
126
+ images, videos, video_kwargs = process_vision_info(
127
+ conversations,
128
+ image_patch_size=16,
129
+ return_video_kwargs=True,
130
+ return_video_metadata=True,
131
+ )
132
+ if videos is not None:
133
+ videos, video_metadata = zip(*videos)
134
+ videos, video_metadata = list(videos), list(video_metadata)
135
+ else:
136
+ video_metadata = None
137
+
138
+ features = self.processor(
139
+ text=prompts,
140
+ images=images,
141
+ videos=videos,
142
+ video_metadata=video_metadata,
143
+ padding=True,
144
+ return_tensors="pt",
145
+ **video_kwargs,
146
+ )
147
+ input_ids = features["input_ids"]
148
+ positions = features["attention_mask"].sum(dim=1) - 1
149
+ batch = torch.arange(input_ids.shape[0])
150
+ terminal_ids = input_ids[batch, positions]
151
+ if not torch.all(terminal_ids == self.embedding_token_id):
152
+ raise RuntimeError("Each input must end with <embedding>.")
153
+ features["modality"] = "message"
154
+ return dict(features)
155
+
156
+ def forward(
157
+ self,
158
+ features: dict[str, torch.Tensor | Any],
159
+ **_: Any,
160
+ ) -> dict[str, torch.Tensor | Any]:
161
+ model_inputs = {
162
+ key: value
163
+ for key, value in features.items()
164
+ if key != "modality"
165
+ }
166
+ inner = getattr(self.auto_model, "model", None)
167
+ if inner is not None and hasattr(inner, "rope_deltas"):
168
+ inner.rope_deltas = None
169
+ features["sentence_embedding"] = self.auto_model.embedding(
170
+ **model_inputs
171
+ ).float()
172
+ return features
173
+
174
+ def get_embedding_dimension(self) -> int:
175
+ return self.embedding_dimension
176
+
177
+ def save(
178
+ self,
179
+ output_path: str,
180
+ *args: Any,
181
+ safe_serialization: bool = True,
182
+ **kwargs: Any,
183
+ ) -> None:
184
+ del args, safe_serialization, kwargs
185
+ self.save_config(output_path)
186
+
187
+
188
+ def load_wemm_sentence_transformer(
189
+ model_name_or_path: str | Path,
190
+ *,
191
+ device: str | torch.device = "cuda:0",
192
+ ) -> SentenceTransformer:
193
+ return SentenceTransformer(
194
+ modules=[WeMMInputModule(str(model_name_or_path), device=device)],
195
+ device=str(device),
196
+ similarity_fn_name="cosine",
197
+ )
198
+