Views
No views yet
thinker component of Qwen2.5 Omni and drops the talker component.pip install "sentence_transformers[image,audio,video]" "transformers>=5.6.0"1import torch
2from sentence_transformers import SentenceTransformer
3
4model = SentenceTransformer(
5 "LCO-Embedding/LCO-Embedding-Omni-3B",
6 model_kwargs={
7 "torch_dtype": torch.bfloat16,
8 "attn_implementation": "flash_attention_2", # pip install kernels; recommended but not mandatory
9 },
10)encode() takes plain text, file paths, URLs, or multimodal dicts directly.1query = "What is the tallest mountain in the world?"
2documents = [
3 "Mount Everest is Earth's highest mountain above sea level, located in the Mahalangur Himal sub-range of the Himalayas. Its elevation of 8,848.86 metres was established by a joint Chinese-Nepali survey in 2020.",
4 "K2, at 8,611 metres above sea level, is the second-highest mountain on Earth, after Mount Everest. It lies in the Karakoram range on the China-Pakistan border.",
5 "Mount Kilimanjaro is a dormant volcano in Tanzania. It is the highest mountain in Africa, with its summit about 5,895 metres above sea level.",
6]
7
8query_embedding = model.encode(query)
9document_embeddings = model.encode(documents)
10print(model.similarity(query_embedding, document_embeddings))
11# tensor([[0.6199, 0.5585, 0.5233]])1query = "How many input modalities does Qwen2.5-Omni support?"
2documents = [
3 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/qwen2.5omni_hgf.png",
4 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/llama4_hgf.png",
5]
6
7query_embedding = model.encode(query)
8document_embeddings = model.encode(documents, batch_size=1)
9print(model.similarity(query_embedding, document_embeddings))
10# tensor([[0.4396, 0.3418]])1query = "A light piano piece"
2documents = [
3 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/joe_hisaishi_summer.mp3",
4 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/jay_chou_superman_cant_fly.mp3",
5]
6
7query_embedding = model.encode(query)
8document_embeddings = model.encode(documents, batch_size=1)
9print(model.similarity(query_embedding, document_embeddings))
10# tensor([[0.3809, 0.0858]])1# For video on smaller GPUs, cap the processor up front:
2model[0].processing_kwargs.update({
3 "video": {"max_pixels": 64 * 28 * 28, "do_sample_frames": True, "fps": 1},
4})
5
6query = "How to cook Mapo Tofu?"
7documents = [
8 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/mapo_tofu.mp4",
9 "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/zhajiang_noodle.mp4",
10]
11
12query_embedding = model.encode(query)
13document_embeddings = model.encode(documents, batch_size=1)
14print(model.similarity(query_embedding, document_embeddings))
15# tensor([[0.6406, 0.5033]])"text", "image", "audio", and "video" keys instead of a single path or string:1documents = [
2 {
3 "text": "A cooking tutorial for Mapo Tofu",
4 "video": "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/mapo_tofu.mp4",
5 },
6 {
7 "image": "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/qwen2.5omni_hgf.png",
8 "audio": "https://huggingface.co/Tevatron/OmniEmbed-v0.1/resolve/main/assets/joe_hisaishi_summer.mp3",
9 },
10]
11document_embeddings = model.encode(documents, batch_size=1)1from transformers import Qwen2_5OmniThinkerForConditionalGeneration, Qwen2_5OmniProcessor
2from qwen_omni_utils import process_mm_info
3
4processor = Qwen2_5OmniProcessor.from_pretrained("LCO-Embedding/LCO-Embedding-Omni-3B") # or add a `max_pixels = 1280*28*28' for efficient encoding
5model = Qwen2_5OmniThinkerForConditionalGeneration.from_pretrained("LCO-Embedding/LCO-Embedding-Omni-3B",
6 torch_dtype=torch.bfloat16,
7 device_map="auto")1texts = ["some random text", "a second random text", "a third random text"] * 30
2batch_size = 8
3text_prompt = "{}\nSummarize the above text in one word:"
4
5all_text_embeddings = []
6
7with torch.no_grad():
8 for i in tqdm(range(0, len(texts), batch_size)):
9 batch_texts = texts[i : i + batch_size]
10 batch_texts = [text_prompt.format(text) for text in batch_texts]
11 messages = [[
12 {
13 "role": "user",
14 "content": [
15 {"type": "text", "text":text},
16 ],
17
18 }
19 ] for text in batch_texts]
20 text_inputs = processor.apply_chat_template(messages, tokenize = False, add_generation_prompt = True)
21 text_inputs = processor(
22 text = text_inputs,
23 padding = True,
24 return_tensors = "pt",
25 )
26 text_inputs = text_inputs.to("cuda")
27 text_outputs = model(
28 **text_inputs, output_hidden_states=True, return_dict=True
29 ).hidden_states[-1][:, -1, :]
30 all_text_embeddings.append(text_outputs.to(torch.float16).cpu())
31
32all_text_embeddings = torch.cat(all_text_embeddings, dim=0)1
2images = [some random PIL.Image] * 100 # will be good to load them using dataloader; see MIEB evaluation pipeline
3image_prompt = "\nSummarize the above image in one word:"
4batch_size = 8
5
6all_image_embeddings = []
7
8with torch.no_grad():
9 for i in tqdm(range(0, len(images), batch_size)):
10 batch_images = images[i : i + batch_size]
11 messages = [[
12 {
13 "role": "user",
14 "content": [
15 {"type": "image", "image":image},
16 {"type": "text", "text": image_prompt},
17 ],
18
19 }
20 ] for image in batch_images]
21 text = processor.apply_chat_template(
22 messages, tokenize=False, add_generation_prompt=True
23 )
24 audio_inputs, image_inputs, video_inputs = process_mm_info(messages, use_audio_in_video=True)
25 inputs = processor(
26 text=text,
27 audio=audio_inputs,
28 images=image_inputs,
29 videos=video_inputs,
30 return_tensors="pt",
31 padding=True
32 )
33 inputs = inputs.to("cuda")
34 image_outputs = model(
35 **inputs, output_hidden_states=True, return_dict=True
36 ).hidden_states[-1][:, -1, :]
37 all_image_embeddings.append(image_outputs.to(torch.float16).cpu())
38
39all_image_embeddings = torch.cat(all_image_embeddings, dim=0)1import logging
2logging.getLogger("root").setLevel(logging.ERROR)
3# set this to prevent getting the Qwen Omni system prompt mismatch warning.
4
5batch_size = 4
6audio_prompt = "\nSummarize the above audio in one word:"
7audis = [some audios] * 1000
8
9all_audio_embeddings = []
10
11with torch.no_grad():
12 for i in tqdm(range(0, len(audios), batch_size)):
13 torch.cuda.empty_cache()
14
15 batch_audios = audios[i : i + batch_size]
16 messages = [[
17 {
18 "role": "user",
19 "content": [
20 {"type": "audio", "audio": audio},
21 {"type": "text", "text": audio_prompt},
22 ],
23
24 }
25 ] for audio in batch_audios]
26
27 text = processor.apply_chat_template(
28 messages, tokenize=False, add_generation_prompt=True
29 )
30 audio_inputs, image_inputs, video_inputs = process_mm_info(
31 messages, use_audio_in_video=False
32 )
33 inputs = processor(
34 text=text,
35 audio=audio_inputs,
36 images=image_inputs,
37 videos=video_inputs,
38 return_tensors="pt",
39 padding=True
40 )
41 inputs = inputs.to("cuda")
42 audio_outputs = model(
43 **inputs, output_hidden_states=True, return_dict=True
44 ).hidden_states[-1][:, -1, :]
45 all_audio_embeddings.append(audio_outputs.to(torch.float16).cpu())
46 del inputs, audio_outputs
47 torch.cuda.empty_cache()
48
49all_audio_embeddings = torch.cat(all_audio_embeddings, dim=0)
501videos = [some videos] * 1000
2video_prompt = "\nSummarize the above video in one word:"
3batch_size = 4
4
5long_video = False
6# followed by some example hyperparameters to save RAM
7# for long videos. Not optimal. Tune case by case.
8
9all_video_embeddings = []
10with torch.no_grad():
11 for i in tqdm(range(0, len(videos), batch_size)):
12 torch.cuda.empty_cache()
13
14 batch_videos = videos[i : i + batch_size]
15 if long_video:
16 messages = [[
17 {
18 "role": "user",
19 "content": [
20 {
21 "type": "video",
22 "video": video,
23 "max_pixels": 224 * 224,
24 "fps": 1,
25 "max_frames": 10
26 },
27 {"type": "text", "text": video_prompt},
28 ],
29
30 }
31 ] for video in batch_videos]
32 else:
33 messages = [[
34 {
35 "role": "user",
36 "content": [
37 {
38 "type": "video",
39 "video": video,
40 },
41 {"type": "text", "text": video_prompt},
42 ],
43
44 }
45 ] for video in batch_videos]
46
47 text = processor.apply_chat_template(
48 messages, tokenize=False, add_generation_prompt=True
49 )
50 audio_inputs, image_inputs, video_inputs = process_mm_info(
51 messages, use_audio_in_video=False
52 )
53 inputs = processor(
54 text=text,
55 audio=audio_inputs,
56 images=image_inputs,
57 videos=video_inputs,
58 return_tensors="pt",
59 padding=True
60 )
61 inputs = inputs.to("cuda")
62 video_outputs = model(
63 **inputs, output_hidden_states=True, return_dict=True
64 ).hidden_states[-1][:, -1, :]
65 all_video_embeddings.append(video_outputs.to(torch.float16).cpu())
66
67 del inputs, video_outputs
68 torch.cuda.empty_cache()
69
70all_video_embeddings = torch.cat(all_video_embeddings, dim=0)




1@article{xiao2025scaling,
2 title={Scaling Language-Centric Omnimodal Representation Learning},
3 author={Xiao, Chenghao and Chan, Hou Pong and Zhang, Hao and Xu, Weiwen and Aljunied, Mahani and Rong, Yu},
4 journal={arXiv preprint arXiv:2510.11693},
5 year={2025}
6}