Add vLLM and SGLang usage examples

#4
Files changed (1) hide show
  1. README.md +268 -0
README.md CHANGED
@@ -149,6 +149,274 @@ print(similarity_scores.tolist())
149
  # [[0.74267578125, 0.6630859375, 0.6328125], [0.443603515625, 0.33349609375, 0.396484375], [0.3671875, 0.2354736328125, 0.289306640625], [0.060821533203125, -0.01557159423828125, 0.0165863037109375]]
150
  ```
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  For more usage examples, please visit our [GitHub repository](https://github.com/QwenLM/Qwen3-VL-Embedding).
153
 
154
 
 
149
  # [[0.74267578125, 0.6630859375, 0.6328125], [0.443603515625, 0.33349609375, 0.396484375], [0.3671875, 0.2354736328125, 0.289306640625], [0.060821533203125, -0.01557159423828125, 0.0165863037109375]]
150
  ```
151
 
152
+ ### vLLM Basic Usage Example
153
+ ```python
154
+ import argparse
155
+ import numpy as np
156
+ import os
157
+ from typing import List, Dict, Any
158
+ from vllm import LLM, EngineArgs
159
+ from vllm.multimodal.utils import fetch_image
160
+
161
+
162
+ # Define a list of query texts
163
+ queries = [
164
+ {"text": "A woman playing with her dog on a beach at sunset."},
165
+ {"text": "Pet owner training dog outdoors near water."},
166
+ {"text": "Woman surfing on waves during a sunny day."},
167
+ {"text": "City skyline view from a high-rise building at night."}
168
+ ]
169
+
170
+ # Define a list of document texts and images
171
+ documents = [
172
+ {"text": "A woman shares a joyful moment with her golden retriever on a sun-drenched beach at sunset, as the dog offers its paw in a heartwarming display of companionship and trust."},
173
+ {"image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"},
174
+ {"text": "A woman shares a joyful moment with her golden retriever on a sun-drenched beach at sunset, as the dog offers its paw in a heartwarming display of companionship and trust.", "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"}
175
+ ]
176
+
177
+ def format_input_to_conversation(input_dict: Dict[str, Any], instruction: str = "Represent the user's input.") -> List[Dict]:
178
+ content = []
179
+
180
+ text = input_dict.get('text')
181
+ image = input_dict.get('image')
182
+
183
+ if image:
184
+ image_content = None
185
+ if isinstance(image, str):
186
+ if image.startswith(('http', 'https', 'oss')):
187
+ image_content = image
188
+ else:
189
+ abs_image_path = os.path.abspath(image)
190
+ image_content = 'file://' + abs_image_path
191
+ else:
192
+ image_content = image
193
+
194
+ if image_content:
195
+ content.append({
196
+ 'type': 'image',
197
+ 'image': image_content,
198
+ })
199
+
200
+ if text:
201
+ content.append({'type': 'text', 'text': text})
202
+
203
+ if not content:
204
+ content.append({'type': 'text', 'text': ""})
205
+
206
+ conversation = [
207
+ {"role": "system", "content": [{"type": "text", "text": instruction}]},
208
+ {"role": "user", "content": content}
209
+ ]
210
+
211
+ return conversation
212
+
213
+ def prepare_vllm_inputs(input_dict: Dict[str, Any], llm, instruction: str = "Represent the user's input.") -> Dict[str, Any]:
214
+ text = input_dict.get('text')
215
+ image = input_dict.get('image')
216
+
217
+ conversation = format_input_to_conversation(input_dict, instruction)
218
+
219
+ prompt_text = llm.llm_engine.tokenizer.apply_chat_template(
220
+ conversation,
221
+ tokenize=False,
222
+ add_generation_prompt=True
223
+ )
224
+
225
+ multi_modal_data = None
226
+ if image:
227
+ if isinstance(image, str):
228
+ if image.startswith(('http', 'https', 'oss')):
229
+ try:
230
+ image_obj = fetch_image(image)
231
+ multi_modal_data = {"image": image_obj}
232
+ except Exception as e:
233
+ print(f"Warning: Failed to fetch image {image}: {e}")
234
+ else:
235
+ abs_image_path = os.path.abspath(image)
236
+ if os.path.exists(abs_image_path):
237
+ from PIL import Image
238
+ image_obj = Image.open(abs_image_path)
239
+ multi_modal_data = {"image": image_obj}
240
+ else:
241
+ print(f"Warning: Image file not found: {abs_image_path}")
242
+ else:
243
+ multi_modal_data = {"image": image}
244
+
245
+ result = {
246
+ "prompt": prompt_text,
247
+ "multi_modal_data": multi_modal_data
248
+ }
249
+ return result
250
+
251
+ def main():
252
+ parser = argparse.ArgumentParser(description="Offline Similarity Check with vLLM")
253
+ parser.add_argument("--model-path", type=str, default="models/Qwen3-VL-Embedding-8B", help="Path to the model")
254
+ parser.add_argument("--dtype", type=str, default="bfloat16", help="Data type (e.g., bfloat16)")
255
+ args = parser.parse_args()
256
+
257
+ print(f"Loading model from {args.model_path}...")
258
+
259
+ engine_args = EngineArgs(
260
+ model=args.model_path,
261
+ runner="pooling",
262
+ dtype=args.dtype,
263
+ trust_remote_code=True,
264
+ )
265
+
266
+ llm = LLM(**vars(engine_args))
267
+
268
+ all_inputs = queries + documents
269
+ vllm_inputs = [prepare_vllm_inputs(inp, llm) for inp in all_inputs]
270
+
271
+
272
+ outputs = llm.embed(vllm_inputs)
273
+
274
+ embeddings_list = []
275
+ for i, output in enumerate(outputs):
276
+ emb = output.outputs.embedding
277
+ embeddings_list.append(emb)
278
+ print(f"Input {i} embedding shape: {len(emb)}")
279
+
280
+ embeddings = np.array(embeddings_list)
281
+ print(f"\nEmbeddings shape: {embeddings.shape}")
282
+
283
+ num_queries = len(queries)
284
+ query_embeddings = embeddings[:num_queries]
285
+ doc_embeddings = embeddings[num_queries:]
286
+
287
+ similarity_scores = query_embeddings @ doc_embeddings.T
288
+
289
+ print("\nSimilarity Scores:")
290
+ print(similarity_scores.tolist())
291
+
292
+
293
+ if __name__ == "__main__":
294
+ main()
295
+ ```
296
+
297
+ ### SGLang Basic Usage Example
298
+ ```python
299
+ import argparse
300
+ import numpy as np
301
+ import torch
302
+ import os
303
+ from typing import List, Dict, Any
304
+ from sglang.srt.entrypoints.engine import Engine
305
+
306
+ # Define a list of query texts
307
+ queries = [
308
+ {"text": "A woman playing with her dog on a beach at sunset."},
309
+ {"text": "Pet owner training dog outdoors near water."},
310
+ {"text": "Woman surfing on waves during a sunny day."},
311
+ {"text": "City skyline view from a high-rise building at night."}
312
+ ]
313
+
314
+ # Define a list of document texts and images
315
+ documents = [
316
+ {"text": "A woman shares a joyful moment with her golden retriever on a sun-drenched beach at sunset, as the dog offers its paw in a heartwarming display of companionship and trust."},
317
+ {"image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"},
318
+ {"text": "A woman shares a joyful moment with her golden retriever on a sun-drenched beach at sunset, as the dog offers its paw in a heartwarming display of companionship and trust.", "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"}
319
+ ]
320
+
321
+ def format_input_to_conversation(input_dict: Dict[str, Any], instruction: str = "Represent the user's input.") -> List[Dict]:
322
+ content = []
323
+
324
+ text = input_dict.get('text')
325
+ image = input_dict.get('image')
326
+
327
+ if image:
328
+ image_content = None
329
+ if isinstance(image, str):
330
+ if image.startswith(('http', 'oss')):
331
+ image_content = image
332
+ else:
333
+ abs_image_path = os.path.abspath(image)
334
+ image_content = 'file://' + abs_image_path
335
+ else:
336
+ image_content = image
337
+ if image_content:
338
+ content.append({
339
+ 'type': 'image', 'image': image_content,
340
+ })
341
+
342
+ if text:
343
+ content.append({'type': 'text', 'text': text})
344
+
345
+ if not content:
346
+ content.append({'type': 'text', 'text': ""})
347
+
348
+ conversation = [
349
+ {"role": "system", "content": [{"type": "text", "text": instruction}]},
350
+ {"role": "user", "content": content}
351
+ ]
352
+
353
+ return conversation
354
+
355
+ def convert_to_sglang_format(input_dict: Dict[str, Any], engine: Engine, instruction: str = "Represent the user's input.") -> Dict[str, Any]:
356
+ conversation = format_input_to_conversation(input_dict, instruction)
357
+
358
+ text_for_api = engine.tokenizer_manager.tokenizer.apply_chat_template(
359
+ conversation,
360
+ tokenize=False,
361
+ add_generation_prompt=True
362
+ )
363
+
364
+ result = {"text": text_for_api}
365
+
366
+ image = input_dict.get('image')
367
+ if image and isinstance(image, str):
368
+ result["image"] = image
369
+
370
+
371
+ return result
372
+
373
+ def main():
374
+ parser = argparse.ArgumentParser(description="Offline Similarity Check with SGLang")
375
+ parser.add_argument("--model-path", type=str, default="models/Qwen3-VL-Embedding-8B", help="Path to the model")
376
+ parser.add_argument("--dtype", type=str, default="bfloat16", help="Data type (e.g., bfloat16)")
377
+ args = parser.parse_args()
378
+
379
+ print(f"Loading model from {args.model_path}...")
380
+
381
+ engine = Engine(
382
+ model_path=args.model_path,
383
+ is_embedding=True,
384
+ dtype=args.dtype,
385
+ trust_remote_code=True,
386
+ )
387
+
388
+ inputs = queries + documents
389
+ sglang_inputs = [convert_to_sglang_format(inp, engine) for inp in inputs]
390
+ print(sglang_inputs[:])
391
+ print(f"sglang_inputs: {sglang_inputs}")
392
+ print(f"Processing {len(sglang_inputs)} inputs...")
393
+
394
+ prompts = [inp['text'] for inp in sglang_inputs]
395
+ images = [inp.get('image') for inp in sglang_inputs]
396
+
397
+
398
+ results = engine.encode(prompts, image_data=images)
399
+
400
+ embeddings_list = []
401
+ for res in results:
402
+ embeddings_list.append(res['embedding'])
403
+
404
+ embeddings = np.array(embeddings_list)
405
+ print(f"Embeddings shape: {embeddings.shape}")
406
+
407
+ num_queries = len(queries)
408
+ query_embeddings = embeddings[:num_queries]
409
+ doc_embeddings = embeddings[num_queries:]
410
+
411
+ similarity_scores = (query_embeddings @ doc_embeddings.T)
412
+
413
+ print("\nSimilarity Scores:")
414
+ print(similarity_scores.tolist())
415
+
416
+ if __name__ == "__main__":
417
+ main()
418
+ ```
419
+
420
  For more usage examples, please visit our [GitHub repository](https://github.com/QwenLM/Qwen3-VL-Embedding).
421
 
422