multimodalart HF Staff commited on
Commit
7e6376b
·
verified ·
1 Parent(s): ab07500

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +37 -19
  2. requirements.txt +2 -1
app.py CHANGED
@@ -6,6 +6,7 @@ import spaces # MUST come before torch / any CUDA-touching import
6
  import torch
7
  import gradio as gr
8
  import numpy as np
 
9
  from transformers import (
10
  Qwen2_5OmniForConditionalGeneration,
11
  Qwen2_5OmniProcessor,
@@ -20,6 +21,11 @@ model = Qwen2_5OmniForConditionalGeneration.from_pretrained(
20
  attn_implementation="sdpa",
21
  ).to("cuda").eval()
22
 
 
 
 
 
 
23
 
24
  @spaces.GPU(duration=120)
25
  def answer_audio_question(
@@ -39,6 +45,8 @@ def answer_audio_question(
39
  temperature: Sampling temperature (0.0 = greedy).
40
  enable_thinking: If True, the model reasons step-by-step before answering.
41
  """
 
 
42
  if audio_path is None:
43
  return "Please upload an audio file.", ""
44
  if not question.strip():
@@ -49,14 +57,26 @@ def answer_audio_question(
49
  system_content = (
50
  "You are an expert audio understanding assistant. "
51
  "Listen carefully and answer questions about the audio. "
52
- "Always think step by step inside <think> tags, "
53
- "then give the final answer inside <answer> tags."
 
 
 
 
54
  )
55
  user_text = (
56
  f"Listen to the audio carefully and answer the following question.\n\n"
57
  f"Question: {question}\n\n"
58
- "First, reason step by step inside tags.\n"
59
- "Then output your final answer inside <answer> ... </answer> tags."
 
 
 
 
 
 
 
 
60
  )
61
  else:
62
  system_content = (
@@ -84,13 +104,12 @@ def answer_audio_question(
84
  messages, tokenize=False, add_generation_prompt=True
85
  )
86
 
87
- # Load audio from file
88
- from pathlib import Path
89
 
90
- audio_file = Path(audio_path)
91
  inputs = processor(
92
  text=text,
93
- audios=[str(audio_file)],
94
  return_tensors="pt",
95
  padding=True,
96
  ).to("cuda").to(model.dtype)
@@ -109,26 +128,25 @@ def answer_audio_question(
109
  response = processor.decode(generated_ids, skip_special_tokens=True)
110
 
111
  # Parse thinking and answer
112
- import re
 
113
 
114
- think_match = re.search(
115
- r"<think>\s*(.*?)\s*</think>", response, flags=re.DOTALL | re.IGNORECASE
116
- )
117
- answer_match = re.search(
118
- r"<answer>\s*(.*?)\s*</answer>", response, flags=re.DOTALL | re.IGNORECASE
119
- )
120
 
121
  thinking_text = think_match.group(1).strip() if think_match else ""
122
  answer_text = answer_match.group(1).strip() if answer_match else ""
123
 
124
  # If no tags found, return the full response as the answer
125
- if not answer_text:
126
  answer_text = response.strip()
127
  thinking_text = ""
 
 
128
 
129
  # Format nicely
130
  if thinking_text:
131
- formatted_thinking = f"💭 **Reasoning:**\n{thinking_text}"
132
  else:
133
  formatted_thinking = ""
134
 
@@ -143,10 +161,10 @@ CSS = """
143
  with gr.Blocks() as demo:
144
  with gr.Column(elem_id="col-container"):
145
  gr.Markdown(
146
- "# 🎧 AudioRubrics: Audio Reasoning with Evolving Rubric Rewards\n"
147
  "Upload an audio clip and ask a question about it. The model reasons step-by-step "
148
  "about what it hears.\n\n"
149
- "Based on [Reinforcement Learning with Evolving Rubrics as Rewards for Audio Reasoning](https://huggingface.co/papers/2608.02831) "
150
  "a Qwen2.5-Omni-7B model fine-tuned with GRPO using self-evolving, audio-grounded rubric rewards."
151
  )
152
 
 
6
  import torch
7
  import gradio as gr
8
  import numpy as np
9
+ import librosa
10
  from transformers import (
11
  Qwen2_5OmniForConditionalGeneration,
12
  Qwen2_5OmniProcessor,
 
21
  attn_implementation="sdpa",
22
  ).to("cuda").eval()
23
 
24
+ THINK_OPEN = "<think>"
25
+ THINK_CLOSE = "</think>"
26
+ ANSWER_OPEN = "<answer>"
27
+ ANSWER_CLOSE = "</answer>"
28
+
29
 
30
  @spaces.GPU(duration=120)
31
  def answer_audio_question(
 
45
  temperature: Sampling temperature (0.0 = greedy).
46
  enable_thinking: If True, the model reasons step-by-step before answering.
47
  """
48
+ import re
49
+
50
  if audio_path is None:
51
  return "Please upload an audio file.", ""
52
  if not question.strip():
 
57
  system_content = (
58
  "You are an expert audio understanding assistant. "
59
  "Listen carefully and answer questions about the audio. "
60
+ "Always think step by step inside "
61
+ + THINK_OPEN
62
+ + " tags, "
63
+ "then give the final answer inside "
64
+ + ANSWER_OPEN
65
+ + " tags."
66
  )
67
  user_text = (
68
  f"Listen to the audio carefully and answer the following question.\n\n"
69
  f"Question: {question}\n\n"
70
+ "First, reason step by step inside "
71
+ + THINK_OPEN
72
+ + " ... "
73
+ + THINK_CLOSE
74
+ + " tags.\n"
75
+ "Then output your final answer inside "
76
+ + ANSWER_OPEN
77
+ + " ... "
78
+ + ANSWER_CLOSE
79
+ + " tags."
80
  )
81
  else:
82
  system_content = (
 
104
  messages, tokenize=False, add_generation_prompt=True
105
  )
106
 
107
+ # Load audio as numpy array (resampled to 16kHz for Whisper feature extractor)
108
+ audio_data, sr = librosa.load(audio_path, sr=16000, mono=True)
109
 
 
110
  inputs = processor(
111
  text=text,
112
+ audio=audio_data,
113
  return_tensors="pt",
114
  padding=True,
115
  ).to("cuda").to(model.dtype)
 
128
  response = processor.decode(generated_ids, skip_special_tokens=True)
129
 
130
  # Parse thinking and answer
131
+ think_pattern = re.escape(THINK_OPEN) + r"\s*(.*?)\s*" + re.escape(THINK_CLOSE)
132
+ answer_pattern = re.escape(ANSWER_OPEN) + r"\s*(.*?)\s*" + re.escape(ANSWER_CLOSE)
133
 
134
+ think_match = re.search(think_pattern, response, flags=re.DOTALL | re.IGNORECASE)
135
+ answer_match = re.search(answer_pattern, response, flags=re.DOTALL | re.IGNORECASE)
 
 
 
 
136
 
137
  thinking_text = think_match.group(1).strip() if think_match else ""
138
  answer_text = answer_match.group(1).strip() if answer_match else ""
139
 
140
  # If no tags found, return the full response as the answer
141
+ if not answer_text and not thinking_text:
142
  answer_text = response.strip()
143
  thinking_text = ""
144
+ elif not answer_text:
145
+ answer_text = response.strip()
146
 
147
  # Format nicely
148
  if thinking_text:
149
+ formatted_thinking = f"**Reasoning:**\n{thinking_text}"
150
  else:
151
  formatted_thinking = ""
152
 
 
161
  with gr.Blocks() as demo:
162
  with gr.Column(elem_id="col-container"):
163
  gr.Markdown(
164
+ "# AudioRubrics: Audio Reasoning with Evolving Rubric Rewards\n"
165
  "Upload an audio clip and ask a question about it. The model reasons step-by-step "
166
  "about what it hears.\n\n"
167
+ "Based on [Reinforcement Learning with Evolving Rubrics as Rewards for Audio Reasoning](https://huggingface.co/papers/2608.02831) | "
168
  "a Qwen2.5-Omni-7B model fine-tuned with GRPO using self-evolving, audio-grounded rubric rewards."
169
  )
170
 
requirements.txt CHANGED
@@ -3,4 +3,5 @@ accelerate
3
  sentencepiece
4
  soundfile
5
  numpy
6
- torchvision
 
 
3
  sentencepiece
4
  soundfile
5
  numpy
6
+ torchvision
7
+ librosa