minhahwang Copilot commited on
Commit
9df2e8c
·
1 Parent(s): ea9b474

fix: CUDA assert on T4 GPU - use eager attention, disable torch.compile

Browse files

- Revert dtype param to torch_dtype for qwen_tts compatibility
- Switch from SDPA to eager attention (SDPA causes asserts on T4/Turing)
- Disable torch.compile (unstable on older GPU architectures)
- Add clickable book cards on Explore tab (navigates to Library + plays)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Files changed (2) hide show
  1. app.py +32 -2
  2. voice_clone.py +9 -18
app.py CHANGED
@@ -140,6 +140,7 @@ with open(os.path.join(os.path.dirname(__file__), "static", "style.css"), encodi
140
  def generate_dashboard_html(books_list):
141
  featured = books_list[0]
142
  others = books_list[1:]
 
143
 
144
  html = f"""
145
  <div style="margin-bottom: 24px;">
@@ -148,7 +149,20 @@ def generate_dashboard_html(books_list):
148
  </div>
149
 
150
  <!-- Hero Spotlight Section -->
151
- <div class="hero-spotlight" style="display: flex; flex-direction: row; gap: 32px; align-items: center; margin-bottom: 32px; flex-wrap: wrap;">
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  <div style="flex: 1; min-width: 200px; max-width: 280px; text-align: center;">
153
  <img src="{featured['cover_url']}" style="width: 180px; height: 260px; object-fit: cover; border-radius: 16px; box-shadow: 0 8px 24px rgba(0,0,0,0.3); transform: rotate(-2deg);" referrerPolicy="no-referrer" />
154
  </div>
@@ -174,8 +188,24 @@ def generate_dashboard_html(books_list):
174
  """
175
 
176
  for bk in books_list:
 
177
  html += f"""
178
- <div class="shelf-card">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  <div>
180
  <img src="{bk['cover_url']}" class="cover-image" referrerPolicy="no-referrer" />
181
  </div>
 
140
  def generate_dashboard_html(books_list):
141
  featured = books_list[0]
142
  others = books_list[1:]
143
+ featured_js_title = featured['title'].replace("'", "\\'").replace('"', '\\"')
144
 
145
  html = f"""
146
  <div style="margin-bottom: 24px;">
 
149
  </div>
150
 
151
  <!-- Hero Spotlight Section -->
152
+ <div class="hero-spotlight" style="display: flex; flex-direction: row; gap: 32px; align-items: center; margin-bottom: 32px; flex-wrap: wrap; cursor: pointer;" onclick="
153
+ var tabs = document.querySelectorAll('button[role=tab]');
154
+ if (tabs.length > 1) {{ tabs[1].click(); }}
155
+ setTimeout(function() {{
156
+ var radios = document.querySelectorAll('.library-book-selector input[type=radio]');
157
+ radios.forEach(function(r) {{
158
+ if(r.value === '{featured_js_title}') {{
159
+ r.checked = true;
160
+ r.dispatchEvent(new Event('input', {{bubbles: true}}));
161
+ r.dispatchEvent(new Event('change', {{bubbles: true}}));
162
+ }}
163
+ }});
164
+ }}, 300);
165
+ ">
166
  <div style="flex: 1; min-width: 200px; max-width: 280px; text-align: center;">
167
  <img src="{featured['cover_url']}" style="width: 180px; height: 260px; object-fit: cover; border-radius: 16px; box-shadow: 0 8px 24px rgba(0,0,0,0.3); transform: rotate(-2deg);" referrerPolicy="no-referrer" />
168
  </div>
 
188
  """
189
 
190
  for bk in books_list:
191
+ js_safe_title = bk['title'].replace("'", "\\'").replace('"', '\\"')
192
  html += f"""
193
+ <div class="shelf-card" style="cursor: pointer;" onclick="
194
+ // Switch to My Library tab (2nd tab button)
195
+ var tabs = document.querySelectorAll('button[role=tab]');
196
+ if (tabs.length > 1) {{ tabs[1].click(); }}
197
+ // Select book in hidden radio
198
+ setTimeout(function() {{
199
+ var radios = document.querySelectorAll('.library-book-selector input[type=radio]');
200
+ radios.forEach(function(r) {{
201
+ if(r.value === '{js_safe_title}') {{
202
+ r.checked = true;
203
+ r.dispatchEvent(new Event('input', {{bubbles: true}}));
204
+ r.dispatchEvent(new Event('change', {{bubbles: true}}));
205
+ }}
206
+ }});
207
+ }}, 300);
208
+ ">
209
  <div>
210
  <img src="{bk['cover_url']}" class="cover-image" referrerPolicy="no-referrer" />
211
  </div>
voice_clone.py CHANGED
@@ -99,13 +99,13 @@ def _select_dtype() -> torch.dtype:
99
 
100
 
101
  def _select_attn_impl() -> str:
102
- """Use FlashAttention-2 if available, else default."""
103
  try:
104
  import flash_attn # noqa: F401
105
  return "flash_attention_2"
106
  except ImportError:
107
- logger.info("flash-attn not installed — using default attention.")
108
- return "sdpa"
109
 
110
 
111
  def get_qwen_tts():
@@ -127,7 +127,7 @@ def get_qwen_tts():
127
  _qwen_tts_model = Qwen3TTSModel.from_pretrained(
128
  model_id,
129
  device_map="cuda" if torch.cuda.is_available() else "cpu",
130
- dtype=dtype,
131
  attn_implementation=attn_impl,
132
  )
133
 
@@ -156,7 +156,7 @@ def get_custom_voice_model():
156
  _custom_voice_model = Qwen3TTSModel.from_pretrained(
157
  CUSTOM_VOICE_MODEL_ID,
158
  device_map="cuda" if torch.cuda.is_available() else "cpu",
159
- dtype=dtype,
160
  attn_implementation=attn_impl,
161
  )
162
  _try_torch_compile(_custom_voice_model)
@@ -165,19 +165,10 @@ def get_custom_voice_model():
165
 
166
 
167
  def _try_torch_compile(wrapper):
168
- """Best-effort torch.compile on model submodules."""
169
- if not hasattr(torch, "compile"):
170
- return
171
- model = wrapper.model
172
- for name in ("decoder", "predictor", "speech_tokenizer"):
173
- submod = getattr(model, name, None)
174
- if submod is not None and isinstance(submod, torch.nn.Module):
175
- try:
176
- compiled = torch.compile(submod, mode="reduce-overhead")
177
- setattr(model, name, compiled)
178
- logger.info("torch.compile applied to model.%s", name)
179
- except Exception as exc:
180
- logger.debug("torch.compile skipped for %s: %s", name, exc)
181
 
182
 
183
  def _trim_reference_audio(audio_path: str) -> str:
 
99
 
100
 
101
  def _select_attn_impl() -> str:
102
+ """Use FlashAttention-2 if available, else eager (safest fallback)."""
103
  try:
104
  import flash_attn # noqa: F401
105
  return "flash_attention_2"
106
  except ImportError:
107
+ logger.info("flash-attn not installed — using eager attention.")
108
+ return "eager"
109
 
110
 
111
  def get_qwen_tts():
 
127
  _qwen_tts_model = Qwen3TTSModel.from_pretrained(
128
  model_id,
129
  device_map="cuda" if torch.cuda.is_available() else "cpu",
130
+ torch_dtype=dtype,
131
  attn_implementation=attn_impl,
132
  )
133
 
 
156
  _custom_voice_model = Qwen3TTSModel.from_pretrained(
157
  CUSTOM_VOICE_MODEL_ID,
158
  device_map="cuda" if torch.cuda.is_available() else "cpu",
159
+ torch_dtype=dtype,
160
  attn_implementation=attn_impl,
161
  )
162
  _try_torch_compile(_custom_voice_model)
 
165
 
166
 
167
  def _try_torch_compile(wrapper):
168
+ """Best-effort torch.compile on model submodules. Disabled for stability."""
169
+ # torch.compile can cause CUDA asserts on some GPU architectures (T4/Turing)
170
+ # Disable for now in favor of stability
171
+ return
 
 
 
 
 
 
 
 
 
172
 
173
 
174
  def _trim_reference_audio(audio_path: str) -> str: