minhahwang Copilot commited on
Commit
c7cbd46
·
1 Parent(s): d422be7

feat: enable FlashAttention-2 for all models via runtime install + SDPA fallback

Browse files

- app.py: runtime pip install flash-attn at startup (before model loading)
- voice_clone.py: pass attn_implementation to both TTS models, fallback to SDPA
- inference.py: enable FA2/SDPA for Qwen2.5-3B-Instruct
- inference_lfm.py: enable FA2/SDPA for LFM2.5-Audio
- requirements_lfm.txt: removed flash-attn (can't compile during Docker build)

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

Files changed (5) hide show
  1. app.py +8 -0
  2. inference.py +7 -0
  3. inference_lfm.py +9 -1
  4. requirements_lfm.txt +3 -3
  5. voice_clone.py +9 -5
app.py CHANGED
@@ -1,3 +1,11 @@
 
 
 
 
 
 
 
 
1
  import os
2
  import html
3
  import math
 
1
+ import subprocess, sys
2
+
3
+ # Install FlashAttention-2 at runtime (needs CUDA, can't compile during Docker build)
4
+ subprocess.run(
5
+ [sys.executable, "-m", "pip", "install", "flash-attn", "--no-build-isolation", "-q"],
6
+ capture_output=True,
7
+ )
8
+
9
  import os
10
  import html
11
  import math
inference.py CHANGED
@@ -78,6 +78,13 @@ def get_qa_model():
78
 
79
  if use_gpu:
80
  load_kwargs = {"device_map": "auto", "torch_dtype": torch.float16}
 
 
 
 
 
 
 
81
  try:
82
  from transformers import BitsAndBytesConfig
83
  load_kwargs["quantization_config"] = BitsAndBytesConfig(
 
78
 
79
  if use_gpu:
80
  load_kwargs = {"device_map": "auto", "torch_dtype": torch.float16}
81
+ # Enable FlashAttention-2 if available, else SDPA
82
+ try:
83
+ import flash_attn # noqa: F401
84
+ load_kwargs["attn_implementation"] = "flash_attention_2"
85
+ logger.info("Using FlashAttention-2 for Q&A model.")
86
+ except ImportError:
87
+ load_kwargs["attn_implementation"] = "sdpa"
88
  try:
89
  from transformers import BitsAndBytesConfig
90
  load_kwargs["quantization_config"] = BitsAndBytesConfig(
inference_lfm.py CHANGED
@@ -25,7 +25,15 @@ def get_lfm_model():
25
 
26
  logger.info("Loading %s...", HF_REPO)
27
  _processor = LFM2AudioProcessor.from_pretrained(HF_REPO).eval()
28
- _model = LFM2AudioModel.from_pretrained(HF_REPO).eval()
 
 
 
 
 
 
 
 
29
  logger.info("LFM2.5-Audio loaded.")
30
  return _processor, _model
31
 
 
25
 
26
  logger.info("Loading %s...", HF_REPO)
27
  _processor = LFM2AudioProcessor.from_pretrained(HF_REPO).eval()
28
+ # Enable FlashAttention-2 if available, else SDPA
29
+ model_kwargs = {}
30
+ try:
31
+ import flash_attn # noqa: F401
32
+ model_kwargs["attn_implementation"] = "flash_attention_2"
33
+ logger.info("Using FlashAttention-2 for LFM.")
34
+ except ImportError:
35
+ model_kwargs["attn_implementation"] = "sdpa"
36
+ _model = LFM2AudioModel.from_pretrained(HF_REPO, **model_kwargs).eval()
37
  logger.info("LFM2.5-Audio loaded.")
38
  return _processor, _model
39
 
requirements_lfm.txt CHANGED
@@ -15,6 +15,6 @@ liquid-audio
15
  qwen-tts>=0.1.1
16
  huggingface-hub>=0.23.0
17
 
18
- # FlashAttention-2 — install separately on GPU machines:
19
- # pip install flash-attn --no-build-isolation
20
- # Falls back to SDPA (PyTorch native) if not available.
 
15
  qwen-tts>=0.1.1
16
  huggingface-hub>=0.23.0
17
 
18
+ # FlashAttention-2: not in requirements (needs CUDA at build time).
19
+ # Code auto-falls back to eager/SDPA if unavailable.
20
+ # To enable: pip install flash-attn --no-build-isolation (at runtime)
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 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():
@@ -120,11 +120,13 @@ def get_qwen_tts():
120
  device = "cuda" if torch.cuda.is_available() else "cpu"
121
 
122
  logger.info("Loading %s on %s (cloning model)...", model_id, device)
 
123
  _qwen_tts_model = Qwen3TTSModel.from_pretrained(
124
  model_id,
125
  device_map=device,
 
126
  )
127
- logger.info("Qwen3-TTS Base loaded on %s.", device)
128
  return _qwen_tts_model
129
 
130
 
@@ -139,11 +141,13 @@ def get_custom_voice_model():
139
  device = "cuda" if torch.cuda.is_available() else "cpu"
140
 
141
  logger.info("Loading CustomVoice 0.6B on %s...", device)
 
142
  _custom_voice_model = Qwen3TTSModel.from_pretrained(
143
  CUSTOM_VOICE_MODEL_ID,
144
  device_map=device,
 
145
  )
146
- logger.info("CustomVoice 0.6B loaded.")
147
  return _custom_voice_model
148
 
149
 
 
99
 
100
 
101
  def _select_attn_impl() -> str:
102
+ """Use FlashAttention-2 if available, else SDPA (PyTorch native)."""
103
  try:
104
  import flash_attn # noqa: F401
105
  return "flash_attention_2"
106
  except ImportError:
107
+ logger.info("flash-attn not installed — using SDPA attention.")
108
+ return "sdpa"
109
 
110
 
111
  def get_qwen_tts():
 
120
  device = "cuda" if torch.cuda.is_available() else "cpu"
121
 
122
  logger.info("Loading %s on %s (cloning model)...", model_id, device)
123
+ attn_impl = _select_attn_impl()
124
  _qwen_tts_model = Qwen3TTSModel.from_pretrained(
125
  model_id,
126
  device_map=device,
127
+ attn_implementation=attn_impl,
128
  )
129
+ logger.info("Qwen3-TTS Base loaded on %s (attn=%s).", device, attn_impl)
130
  return _qwen_tts_model
131
 
132
 
 
141
  device = "cuda" if torch.cuda.is_available() else "cpu"
142
 
143
  logger.info("Loading CustomVoice 0.6B on %s...", device)
144
+ attn_impl = _select_attn_impl()
145
  _custom_voice_model = Qwen3TTSModel.from_pretrained(
146
  CUSTOM_VOICE_MODEL_ID,
147
  device_map=device,
148
+ attn_implementation=attn_impl,
149
  )
150
+ logger.info("CustomVoice 0.6B loaded (attn=%s).", attn_impl)
151
  return _custom_voice_model
152
 
153