Views
No views yet
1import torch
2import torch.nn.functional as F
3from transformers import AutoProcessor, Qwen2_5OmniThinkerForConditionalGeneration
4from qwen_omni_utils import process_mm_info
5
6def add_embed_token(tokenizer, model, emb_token="<emb>"):
7 emb_tokens = [emb_token]
8 num_new_tokens = tokenizer.add_tokens(emb_tokens)
9 if num_new_tokens > 0:
10 model.resize_token_embeddings(len(tokenizer))
11 emb_token_ids = tokenizer.convert_tokens_to_ids(emb_tokens)
12 model.config.emb_token_ids = emb_token_ids
13 return emb_token_ids[0]
14
15# Tokenize / process (audio side)
16def process_input(message, device):
17 texts = processor.apply_chat_template(message, tokenize=False, add_generation_prompt=False)
18 audios, images, videos = process_mm_info(message, use_audio_in_video=False)
19 inputs = processor(
20 text=texts,
21 audio=audios,
22 images=images,
23 videos=videos,
24 return_tensors="pt",
25 padding=True,
26 use_audio_in_video=False,
27 )
28 inputs = inputs.to(device)
29 return inputs
30
31# Extract features at the position before <emb> token
32def get_embed_feature(hidden_states, input_ids, embed_index):
33 embed_indices = torch.argmax((input_ids == embed_index).int(), dim=1)
34 embed_features = hidden_states[torch.arange(len(embed_indices)), embed_indices - 1]
35 return embed_features
36
37# 1) Load model + processor (same style as Qwen2.5-Omni)
38model_path = "Jazzcharles/AuroLA-7B-PT" # or your HF repo id
39
40device = "cuda" if torch.cuda.is_available() else "cpu"
41dtype = torch.bfloat16 if device == "cuda" else torch.float32
42
43model = Qwen2_5OmniThinkerForConditionalGeneration.from_pretrained(
44 model_path,
45 torch_dtype=dtype,
46 device_map="auto" if device == "cuda" else None,
47)
48processor = AutoProcessor.from_pretrained(model_path, use_fast=False)
49tokenizer = processor.tokenizer
50
51emb_token_ids = add_embed_token(tokenizer, model)
52
53
54# 2) Prepare retrieval inputs
55# audio paths and text queries can be any same-batch lists
56audio_files = [
57 "/mnt/data/AudioCaps/audio/--0w1YA1Hm4_30.wav",
58 "/mnt/data/AudioCaps/audio/-AheI8Epim4_30.wav",
59 "/mnt/data/AudioCaps/audio/-BUWGM7qeUM_10.wav",
60]
61text_queries = [
62 "A vehicle driving as a man and woman are talking and laughing",
63 "Muffled sounds followed by metal being hit",
64 "Wind is blowing and heavy rain is falling and splashing",
65]
66
67# Build audio-side messages
68audio_messages = [
69 [
70 {
71 "role": "user",
72 "content": [
73 {"type": "audio", "audio": a},
74 {"type": "text", "text": "Summarize above audio in one word:"},
75 ],
76 },
77 {
78 "role": "assistant",
79 "content": [{"type": "text", "text": "<emb>."}],
80 },
81 ]
82 for a in audio_files
83]
84
85# Build text-side messages
86text_messages = [
87 [
88 {
89 "role": "user",
90 "content": [{"type": "text", "text": f"{t}\nSummarize above sentence in one word:"}],
91 },
92 {
93 "role": "assistant",
94 "content": [{"type": "text", "text": "<emb>."}],
95 },
96 ]
97 for t in text_queries
98]
99
100# 3) Tokenize / process (audio side & text side)
101audio_inputs = process_input(audio_messages, device)
102text_inputs = process_input(text_messages, device)
103
104# 4) Forward and extract features
105with torch.inference_mode():
106 audio_out = model(**audio_inputs, output_hidden_states=True, return_dict=True, use_audio_in_video=False)
107 audio_feat = get_embed_feature(audio_out.hidden_states[-1], audio_inputs['input_ids'], emb_token_ids)
108
109 text_out = model(**text_inputs, output_hidden_states=True, return_dict=True, use_audio_in_video=False)
110 text_feat = get_embed_feature(text_out.hidden_states[-1], text_inputs['input_ids'], emb_token_ids)
111
112# 5) Similarity + top-k retrieval
113audio_feat = F.normalize(audio_feat, dim=-1)
114text_feat = F.normalize(text_feat, dim=-1)
115score = text_feat @ audio_feat.T # [N_text, N_audio]
116print(score.shape, score)1@misc{xu2026scalingaudiotextretrievalmultimodal,
2 title={Scaling Audio-Text Retrieval with Multimodal Large Language Models},
3 author={Jilan Xu and Carl Thomé and Danijela Horak and Weidi Xie and Andrew Zisserman},
4 year={2026},
5 eprint={2602.18010},
6 archivePrefix={arXiv},
7 primaryClass={cs.SD},
8 url={https://arxiv.org/abs/2602.18010},
9}