eeuuia commited on
Commit
e3108f3
·
verified ·
1 Parent(s): bc01875

Update builder.sh

Browse files
Files changed (1) hide show
  1. builder.sh +224 -184
builder.sh CHANGED
@@ -1,13 +1,14 @@
1
  #!/usr/bin/env bash
2
  set -euo pipefail
3
 
4
- echo "🚀 Builder (FlashAttn [ROCm/CUDA] + Apex + Q8) — runtime com GPU visível"
5
 
6
  # ===== Config e diretórios =====
 
 
7
  mkdir -p /app/wheels /app/cuda_cache /app/wheels/src
8
  chmod -R 777 /app/wheels || true
9
- export CUDA_CACHE_PATH="/app/cuda_cache" # Para CUDA
10
- # Para ROCm, o cache é gerenciado automaticamente (ex: ~/.cache/miopenkerneldb)
11
 
12
  # Preserva licença NGC (se existir)
13
  if [ -f "/NGC-DL-CONTAINER-LICENSE" ]; then
@@ -17,7 +18,7 @@ fi
17
  # ===== Dependências mínimas =====
18
  python -m pip install -v -U pip build setuptools wheel hatchling hatch-vcs scikit-build-core cmake ninja packaging "huggingface_hub[hf_transfer]" || true
19
 
20
- # ===== Tags de ambiente (Python/Plataforma/Torch) =====
21
  PY_TAG="$(python -c 'import sys; print(f"cp{sys.version_info[0]}{sys.version_info[1]}")' 2>/dev/null || echo cp310)"
22
  TORCH_VER="$(python - <<'PY'
23
  try:
@@ -28,38 +29,38 @@ except Exception:
28
  print("unknown")
29
  PY
30
  )"
31
- PLATFORM_TAG="$(python - <<'PY'
32
  try:
33
  import torch
34
- if getattr(torch.version, "cuda", None):
35
- print("cu" + torch.version.cuda.replace(".", ""))
36
- elif getattr(torch.version, "hip", None):
37
- rocm_ver = torch.version.hip.split('.')[0:2]
38
- print("rocm" + "".join(rocm_ver))
39
- else:
40
- print("cpu")
41
  except Exception:
42
- print("cpu")
43
  PY
44
  )"
45
- echo "[env] PY_TAG=${PY_TAG} TORCH_VER=${TORCH_VER} PLATFORM_TAG=${PLATFORM_TAG}"
46
 
47
  # ============================================================================
48
  # CHECKERS
49
  # ============================================================================
50
 
51
- # Checa a instalação completa do Flash Attention (funciona para CUDA e ROCm)
52
- check_flash_attn () {
53
  python - <<'PY'
54
  import importlib
55
- try:
56
- importlib.import_module("flash_attn")
57
- # Tenta importar uma função chave para ter mais certeza
58
- from flash_attn import flash_attn_func
59
- ok = True
60
- except Exception as e:
61
- print(f"Check failed: {e}")
62
- ok = False
 
 
 
 
 
63
  raise SystemExit(0 if ok else 1)
64
  PY
65
  }
@@ -70,8 +71,7 @@ try:
70
  from apex.normalization import FusedLayerNorm
71
  import importlib; importlib.import_module("fused_layer_norm_cuda")
72
  ok = True
73
- except Exception as e:
74
- print(f"Check failed: {e}")
75
  ok = False
76
  raise SystemExit(0 if ok else 1)
77
  PY
@@ -89,43 +89,70 @@ PY
89
  # DOWNLOAD DO HUB (GENÉRICO)
90
  # ============================================================================
91
 
92
- # Instala uma wheel do HF por prefixo (ex.: apex-, flash-attn-)
93
  install_from_hf_by_prefix () {
94
  local PREFIX="$1"
95
- echo "[hub] Procurando wheels '${PREFIX}*.whl' em ${SELF_HF_REPO_ID} com tags ${PY_TAG}/${PLATFORM_TAG}"
96
- # O script python interno fará o download e imprimirá o caminho local do arquivo
97
- python - "$PREFIX" "$PY_TAG" "$PLATFORM_TAG" <<'PY' || return 1
98
  import os, sys
99
  from huggingface_hub import HfApi, hf_hub_download, HfFolder
100
 
101
- prefix, py_tag, platform_tag = sys.argv[1], sys.argv[2], sys.argv[3]
102
- repo = os.environ.get("SELF_HF_REPO_ID","eeuuia/Tmp")
103
  api = HfApi(token=os.getenv("HF_TOKEN") or HfFolder.get_token())
104
  try:
105
  files = api.list_repo_files(repo_id=repo, repo_type="model")
106
- except Exception as e:
107
- print(f"Não foi possível listar arquivos do repo: {e}", file=sys.stderr)
108
- raise SystemExit(1)
109
 
110
  def match(name: str) -> bool:
111
- filename = name.rsplit("/",1)[-1]
112
- # Aceita 'flash-attn-' ou 'flash_attn-'
113
- normalized_prefix = prefix.replace('-', '_')
114
- return name.endswith(".whl") and \
115
- (filename.startswith(prefix) or filename.startswith(normalized_prefix)) and \
116
- (py_tag in name)
117
 
118
  cands = [f for f in files if match(f)]
119
- # Prioriza wheels com a tag da plataforma (cu121, rocm57, etc.)
120
- pref = [f for f in cands if platform_tag and platform_tag in f] or cands
121
  if not pref:
122
- print(f"Nenhuma wheel compatível encontrada para {prefix}", file=sys.stderr)
123
- raise SystemExit(1)
124
 
125
  target = sorted(pref, reverse=True)[0]
126
- print(f"Wheel candidata encontrada no Hub: {target}", file=sys.stderr)
127
  path = hf_hub_download(repo_id=repo, filename=target, repo_type="model", local_dir="/app/wheels")
128
- print(path) # Saída principal usada pelo script bash
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  PY
130
  }
131
 
@@ -133,80 +160,146 @@ PY
133
  # BUILDERS
134
  # ============================================================================
135
 
136
- # Compila Flash Attention para ROCm (AMD GPUs)
137
- build_flash_attn_rocm () {
138
- local SRC="/app/wheels/src/flash-attention-rocm"
139
- echo "[build] Preparando fonte FlashAttention (ROCm) em ${SRC}"
140
-
141
- # Clona o repositório específico da ROCm, branch main_perf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  if [ -d "$SRC/.git" ]; then
143
- ( cd "$SRC"; git fetch --all -p; git reset --hard origin/main_perf; git clean -fdx; )
 
 
144
  else
145
  rm -rf "$SRC"
146
- git clone --depth 1 --branch main_perf https://github.com/ROCm/flash-attention.git "$SRC"
147
  fi
148
 
149
- echo "[build] Compilando FlashAttention (ROCm) -> wheel"
150
-
151
- # Variável de ambiente CRÍTICA para habilitar o backend Triton no ROCm
152
- export FLASH_ATTENTION_TRITON_AMD_ENABLE="TRUE"
153
-
154
- # Gera a wheel usando setup.py bdist_wheel, que é confiável para este repo
155
- ( cd "$SRC"; python setup.py bdist_wheel -d /app/wheels; )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
- local W="$(ls -t /app/wheels/flash_attn-*.whl 2>/dev/null | head -n1 || true)"
158
  if [ -n "${W}" ]; then
159
- python -m pip install -v -U --no-deps "${W}"
160
- echo "[build] FlashAttention (ROCm) instalado da wheel recém-compilada: ${W}"
161
  else
162
- echo "[build] ERRO: Nenhuma wheel FlashAttention (ROCm) foi gerada."
163
- return 1
 
 
 
 
 
 
164
  fi
 
 
165
  }
166
 
167
- # Compila Apex (NVIDIA GPUs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  build_apex () {
169
  local SRC="/app/wheels/src/apex"
170
  echo "[build] Preparando fonte Apex em ${SRC}"
171
  if [ -d "$SRC/.git" ]; then
172
- ( cd "$SRC"; git fetch --all -p; git reset --hard HEAD; git clean -fdx; )
 
 
173
  else
174
  rm -rf "$SRC"
175
  git clone --depth 1 https://github.com/NVIDIA/apex "$SRC"
176
  fi
177
  echo "[build] Compilando Apex -> wheel"
178
- export APEX_CPP_EXT=1 APEX_CUDA_EXT=1
179
- python -m pip wheel -v --no-build-isolation --no-deps "$SRC" -w /app/wheels
180
-
181
  local W="$(ls -t /app/wheels/apex-*.whl 2>/dev/null | head -n1 || true)"
182
  if [ -n "${W}" ]; then
183
- python -m pip install -v -U --no-deps "${W}"
184
  echo "[build] Apex instalado da wheel recém-compilada: ${W}"
185
  else
186
- echo "[build] ERRO: Nenhuma wheel do Apex foi gerada."
187
- return 1
188
  fi
189
  }
190
 
191
- # Compila Q8 Kernels
192
  Q8_REPO="${Q8_REPO:-https://github.com/Lightricks/LTX-Video-Q8-Kernels}"
193
  Q8_COMMIT="${Q8_COMMIT:-f3066edea210082799ca5a2bbf9ef0321c5dd8fc}"
194
  build_q8 () {
195
  local SRC="/app/wheels/src/q8_kernels"
196
  rm -rf "$SRC"
197
  git clone --filter=blob:none "$Q8_REPO" "$SRC"
198
- ( cd "$SRC"; git checkout "$Q8_COMMIT"; git submodule update --init --recursive; )
199
-
200
  echo "[build] Compilando Q8 Kernels -> wheel"
201
- python -m pip wheel -v --no-build-isolation "$SRC" -w /app/wheels
202
-
203
  local W="$(ls -t /app/wheels/q8_kernels-*.whl 2>/dev/null | head -n1 || true)"
204
  if [ -n "${W}" ]; then
205
- python -m pip install -v -U --no-deps "${W}"
206
  echo "[build] Q8 instalado da wheel recém-compilada: ${W}"
207
  else
208
- echo "[build] ERRO: Nenhuma wheel q8_kernels foi gerada."
209
- return 1
210
  fi
211
  }
212
 
@@ -214,115 +307,62 @@ build_q8 () {
214
  # EXECUÇÃO
215
  # ============================================================================
216
 
217
- # --- FLASH ATTENTION (Condicional para ROCm) ---
218
- if [[ "${PLATFORM_TAG}" == rocm* ]]; then
219
- echo "[flow] === Flash Attention (ROCm) ==="
220
- if check_flash_attn; then
221
- echo "[flow] Flash Attention (ROCm) parece estar instalado. Pulando."
222
- else
223
- HF_WHEEL_PATH="$(install_from_hf_by_prefix "flash-attn-" || true)"
224
- if [ -n "${HF_WHEEL_PATH:-}" ]; then
225
- echo "[hub] Wheel encontrada: ${HF_WHEEL_PATH}"
226
- python -m pip install -v -U --no-deps "${HF_WHEEL_PATH}"
227
- if check_flash_attn; then
228
- echo "[flow] Flash Attention (ROCm): OK via wheel do Hub."
229
- else
230
- echo "[flow] Wheel do Hub falhou na verificação. Compilando do zero..."
231
- build_flash_attn_rocm
232
- fi
233
- else
234
- echo "[hub] Nenhuma wheel compatível encontrada. Compilando do zero..."
235
- build_flash_attn_rocm
236
- fi
237
- # Verificação final
238
- if ! check_flash_attn; then echo "[flow] ERRO: Falha ao instalar Flash Attention (ROCm)." >&2; fi
239
- fi
240
- # Adicionar aqui a lógica para CUDA se for necessário compilar o Flash Attention completo
241
- # else
242
- # echo "[flow] Pulando Flash Attention (não é ambiente ROCm)."
243
- fi
244
-
245
-
246
- # --- APEX (Condicional para CUDA) ---
247
- if [[ "${PLATFORM_TAG}" == cu* ]]; then
248
- echo "[flow] === Apex (CUDA) ==="
249
- if check_apex; then
250
- echo "[flow] Apex já parece estar instalado. Pulando."
251
- else
252
- HF_WHEEL_PATH="$(install_from_hf_by_prefix "apex-" || true)"
253
- if [ -n "${HF_WHEEL_PATH:-}" ]; then
254
- echo "[hub] Wheel encontrada: ${HF_WHEEL_PATH}"
255
- python -m pip install -v -U --no-deps "${HF_WHEEL_PATH}"
256
- if check_apex; then
257
- echo "[flow] Apex: OK via wheel do Hub."
258
- else
259
- echo "[flow] Wheel do Hub falhou na verificação. Compilando do zero..."
260
- build_apex
261
- fi
262
- else
263
- echo "[hub] Nenhuma wheel compatível encontrada. Compilando do zero..."
264
- build_apex
265
- fi
266
- if ! check_apex; then echo "[flow] ERRO: Falha ao instalar Apex." >&2; fi
267
- fi
268
- else
269
- echo "[flow] Pulando Apex (não é ambiente CUDA)."
270
- fi
271
-
272
-
273
- # --- Q8 KERNELS (Independente de plataforma, mas requer GPU) ---
274
- echo "[flow] === q8_kernels ==="
275
- if check_q8; then
276
- echo "[flow] q8_kernels já parece estar instalado. Pulando."
277
- else
278
- HF_WHEEL_PATH="$(install_from_hf_by_prefix "q8_kernels-" || true)"
279
- if [ -n "${HF_WHEEL_PATH:-}" ]; then
280
- echo "[hub] Wheel encontrada: ${HF_WHEEL_PATH}"
281
- python -m pip install -v -U --no-deps "${HF_WHEEL_PATH}"
282
- if check_q8; then
283
- echo "[flow] q8_kernels: OK via wheel do Hub."
284
- else
285
- echo "[flow] Wheel do Hub falhou na verificação. Compilando do zero..."
286
- build_q8
287
- fi
288
- else
289
- echo "[hub] Nenhuma wheel compatível encontrada. Compilando do zero..."
290
- build_q8
291
- fi
292
- if ! check_q8; then echo "[flow] ERRO: Falha ao instalar q8_kernels." >&2; fi
293
- fi
294
-
295
-
296
- # --- UPLOAD DE WHEELS PARA O HUB ---
297
- echo "[upload] Sincronizando wheels geradas para o Hugging Face Hub..."
298
  python - <<'PY'
299
  import os
300
  from huggingface_hub import HfApi, HfFolder
301
 
302
- repo = os.environ.get("SELF_HF_REPO_ID","eeuuia/Tmp")
303
  token = os.getenv("HF_TOKEN") or HfFolder.get_token()
304
  if not token:
305
- print("HF_TOKEN não encontrado. Upload desabilitado.")
306
- raise SystemExit(0)
307
-
308
- wheels_dir = "/app/wheels"
309
- if not any(f.endswith('.whl') for f in os.listdir(wheels_dir)):
310
- print("Nenhuma wheel nova para fazer upload.")
311
- raise SystemExit(0)
312
 
313
  api = HfApi(token=token)
314
- try:
315
- api.upload_folder(
316
- folder_path=wheels_dir,
317
- repo_id=repo,
318
- repo_type="model",
319
- allow_patterns=["*.whl", "NGC-DL-CONTAINER-LICENSE"],
320
- ignore_patterns=["src/**", "*.log"],
321
- )
322
- print("Upload de wheels concluído.")
323
- except Exception as e:
324
- print(f"Falha no upload: {e}")
325
  PY
326
 
327
  chmod -R 777 /app/wheels || true
328
- echo "✅ Builder finalizado."
 
1
  #!/usr/bin/env bash
2
  set -euo pipefail
3
 
4
+ echo "🚀 Builder (FlashAttn LayerNorm extra + Apex + Q8) — runtime com GPU visível"
5
 
6
  # ===== Config e diretórios =====
7
+
8
+
9
  mkdir -p /app/wheels /app/cuda_cache /app/wheels/src
10
  chmod -R 777 /app/wheels || true
11
+ export CUDA_CACHE_PATH="/app/cuda_cache"
 
12
 
13
  # Preserva licença NGC (se existir)
14
  if [ -f "/NGC-DL-CONTAINER-LICENSE" ]; then
 
18
  # ===== Dependências mínimas =====
19
  python -m pip install -v -U pip build setuptools wheel hatchling hatch-vcs scikit-build-core cmake ninja packaging "huggingface_hub[hf_transfer]" || true
20
 
21
+ # ===== Tags de ambiente (Python/CUDA/Torch) =====
22
  PY_TAG="$(python -c 'import sys; print(f"cp{sys.version_info[0]}{sys.version_info[1]}")' 2>/dev/null || echo cp310)"
23
  TORCH_VER="$(python - <<'PY'
24
  try:
 
29
  print("unknown")
30
  PY
31
  )"
32
+ CU_TAG="$(python - <<'PY'
33
  try:
34
  import torch
35
+ cu = getattr(torch.version, "cuda", None)
36
+ print("cu"+cu.replace(".","")) if cu else print("")
 
 
 
 
 
37
  except Exception:
38
+ print("")
39
  PY
40
  )"
41
+ echo "[env] PY_TAG=${PY_TAG} TORCH_VER=${TORCH_VER} CU_TAG=${CU_TAG}"
42
 
43
  # ============================================================================
44
  # CHECKERS
45
  # ============================================================================
46
 
47
+ # Checa especificamente o módulo nativo requerido pelo layer_norm (sem checar 'flash-attn' geral)
48
+ check_flash_layer_norm_bin () {
49
  python - <<'PY'
50
  import importlib
51
+ ok = False
52
+ # extensões conhecidas produzidas por csrc/layer_norm
53
+ for name in [
54
+ "dropout_layer_norm", # nome do módulo nativo
55
+ "flash_attn.ops.layer_norm", # wrapper python que usa o nativo
56
+ "flash_attn.ops.rms_norm", # pode depender do mesmo backend em alguns empacotamentos
57
+ ]:
58
+ try:
59
+ importlib.import_module(name)
60
+ ok = True
61
+ break
62
+ except Exception:
63
+ pass
64
  raise SystemExit(0 if ok else 1)
65
  PY
66
  }
 
71
  from apex.normalization import FusedLayerNorm
72
  import importlib; importlib.import_module("fused_layer_norm_cuda")
73
  ok = True
74
+ except Exception:
 
75
  ok = False
76
  raise SystemExit(0 if ok else 1)
77
  PY
 
89
  # DOWNLOAD DO HUB (GENÉRICO)
90
  # ============================================================================
91
 
92
+ # Instala uma wheel do HF por prefixo simples (ex.: apex-, q8_kernels-)
93
  install_from_hf_by_prefix () {
94
  local PREFIX="$1"
95
+ echo "[hub] Procurando wheels '${PREFIX}-*.whl' em ${SELF_HF_REPO_ID} com tags ${PY_TAG}/${CU_TAG}"
96
+ python - "$PREFIX" "$PY_TAG" "$CU_TAG" <<'PY' || exit 0
 
97
  import os, sys
98
  from huggingface_hub import HfApi, hf_hub_download, HfFolder
99
 
100
+ prefix, py_tag, cu_tag = sys.argv[1], sys.argv[2], sys.argv[3]
101
+ repo = os.environ.get("SELF_HF_REPO_ID","euIaxs22/Aduc-sdr")
102
  api = HfApi(token=os.getenv("HF_TOKEN") or HfFolder.get_token())
103
  try:
104
  files = api.list_repo_files(repo_id=repo, repo_type="model")
105
+ except Exception:
106
+ raise SystemExit(0)
 
107
 
108
  def match(name: str) -> bool:
109
+ return name.endswith(".whl") and name.rsplit("/",1)[-1].startswith(prefix + "-") and (py_tag in name)
 
 
 
 
 
110
 
111
  cands = [f for f in files if match(f)]
112
+ pref = [f for f in cands if cu_tag and cu_tag in f] or cands
 
113
  if not pref:
114
+ raise SystemExit(0)
 
115
 
116
  target = sorted(pref, reverse=True)[0]
117
+ print(target)
118
  path = hf_hub_download(repo_id=repo, filename=target, repo_type="model", local_dir="/app/wheels")
119
+ print(path)
120
+ PY
121
+ }
122
+
123
+ # Instala wheels do submódulo layer_norm aceitando variantes de nome
124
+ install_flash_layer_norm_from_hf () {
125
+ echo "[hub] Procurando wheels FlashAttention LayerNorm em ${SELF_HF_REPO_ID}"
126
+ python - "$PY_TAG" "$CU_TAG" <<'PY' || exit 0
127
+ import os, sys, re
128
+ from huggingface_hub import HfApi, hf_hub_download, HfFolder
129
+
130
+ py_tag, cu_tag = sys.argv[1], sys.argv[2]
131
+ repo = os.environ.get("SELF_HF_REPO_ID","euIaxs22/Aduc-sdr")
132
+ api = HfApi(token=os.getenv("HF_TOKEN") or HfFolder.get_token())
133
+ try:
134
+ files = api.list_repo_files(repo_id=repo, repo_type="model")
135
+ except Exception:
136
+ raise SystemExit(0)
137
+
138
+ pats = [
139
+ r"^flash[_-]?attn[_-]?.*layer[_-]?norm-.*\.whl$",
140
+ r"^dropout[_-]?layer[_-]?norm-.*\.whl$",
141
+ ]
142
+ def ok(fn: str) -> bool:
143
+ name = fn.rsplit("/",1)[-1]
144
+ if py_tag not in name: return False
145
+ return any(re.search(p, name, flags=re.I) for p in pats)
146
+
147
+ cands = [f for f in files if ok(f)]
148
+ pref = [f for f in cands if cu_tag and cu_tag in f] or cands
149
+ if not pref:
150
+ raise SystemExit(0)
151
+
152
+ target = sorted(pref, reverse=True)[0]
153
+ print(target)
154
+ path = hf_hub_download(repo_id=repo, filename=target, repo_type="model", local_dir="/app/wheels")
155
+ print(path)
156
  PY
157
  }
158
 
 
160
  # BUILDERS
161
  # ============================================================================
162
 
163
+ # Passo extra: SIEMPRE tenta instalar o submódulo layer_norm via wheel do HF;
164
+ # se não houver wheel compatível, compila a partir de csrc/layer_norm e gera wheel.
165
+ build_or_install_flash_layer_norm () {
166
+ echo "[flow] === FlashAttn LayerNorm (passo extra) ==="
167
+
168
+ # 1) Tentar instalar wheel do HF primeiro (evita recompilar)
169
+ HF_OUT="$(install_flash_layer_norm_from_hf || true)"
170
+ if [ -n "${HF_OUT:-}" ]; then
171
+ WHEEL_PATH="$(printf "%s\n" "${HF_OUT}" | tail -n1)"
172
+ echo "[hub] Baixado: ${WHEEL_PATH}"
173
+ python -m pip install -v -U --no-build-isolation --no-deps "${WHEEL_PATH}" || true
174
+ if check_flash_layer_norm_bin; then
175
+ echo "[flow] FlashAttn LayerNorm: OK via wheel do Hub"
176
+ return 0
177
+ fi
178
+ echo "[flow] Wheel do Hub não resolveu import; seguirá com build"
179
+ else
180
+ echo "[hub] Nenhuma wheel compatível encontrada para FlashAttn LayerNorm"
181
+ fi
182
+
183
+ # 2) Build from source do submódulo csrc/layer_norm -> wheel
184
+ local SRC="/app/wheels/src/flash-attn"
185
+ echo "[build] Preparando fonte FlashAttention (layer_norm) em ${SRC}"
186
  if [ -d "$SRC/.git" ]; then
187
+ git -C "$SRC" fetch --all -p || true
188
+ git -C "$SRC" reset --hard origin/main || true
189
+ git -C "$SRC" clean -fdx || true
190
  else
191
  rm -rf "$SRC"
192
+ git clone --depth 1 https://github.com/Dao-AILab/flash-attention "$SRC"
193
  fi
194
 
195
+ # Define CC alvo a partir da GPU ativa (reduz tempo/ruído de build)
196
+ export TORCH_CUDA_ARCH_LIST="$(python - <<'PY'
197
+ import torch
198
+ try:
199
+ cc = "%d.%d" % torch.cuda.get_device_capability(0)
200
+ print(cc)
201
+ except Exception:
202
+ print("8.9") # fallback p/ Ada (L40S) caso build sem GPU visível
203
+ PY
204
+ )"
205
+ echo "[build] TORCH_CUDA_ARCH_LIST=${TORCH_CUDA_ARCH_LIST}"
206
+
207
+ pushd "$SRC/csrc/layer_norm" >/dev/null
208
+ export MAX_JOBS="${MAX_JOBS:-90}"
209
+ # Gera wheel reutilizável
210
+ python -m pip wheel -v --no-build-isolation --no-deps . -w /app/wheels || true
211
+ popd >/dev/null
212
+
213
+ # Instala a wheel gerada
214
+ local W="$(ls -t /app/wheels/*flash*attn*layer*norm*-*.whl 2>/dev/null | head -n1 || true)"
215
+ if [ -z "${W}" ]; then
216
+ W="$(ls -t /app/wheels/*dropout*layer*norm*-*.whl 2>/dev/null | head -n1 || true)"
217
+ fi
218
+ if [ -z "${W}" ]; then
219
+ # fallback para qualquer .whl recém gerado
220
+ W="$(ls -t /app/wheels/*.whl 2>/dev/null | head -n1 || true)"
221
+ fi
222
 
 
223
  if [ -n "${W}" ]; then
224
+ python -m pip install -v -U --no-deps "${W}" || true
225
+ echo "[build] FlashAttn LayerNorm instalado da wheel: ${W}"
226
  else
227
+ echo "[build] Nenhuma wheel gerada; instalando direto do source (último recurso)"
228
+ python -m pip install -v --no-build-isolation "$SRC/csrc/layer_norm" || true
229
+ fi
230
+
231
+ # Checagem final do binário
232
+ if check_flash_layer_norm_bin; then
233
+ echo "[flow] FlashAttn LayerNorm: import OK após build"
234
+ return 0
235
  fi
236
+ echo "[flow] FlashAttn LayerNorm: falhou import após build"
237
+ return 1
238
  }
239
 
240
+
241
+ ## Instalação do FlashAttention completo do GitHub
242
+ echo "Instalando FlashAttention completo do GitHub"
243
+ # clonagem do repositório
244
+ git clone --depth 1 https://github.com/Dao-AILab/flash-attention appwheelssrc/flash-attention-full
245
+ # build de wheel para a GPU ativa (ajusta para L40s via TORCHCUDAARCHLIST)
246
+ pushd appwheelssrc/flash-attention-full > /dev/null
247
+ export TORCH_CUDA_ARCH_LIST="${TORCHCUDAARCHLIST}"
248
+ python -m pip wheel -v --no-build-isolation --no-deps . -w ../../appwheels
249
+ popd > /dev/null
250
+ # instalação do wheel gerado
251
+ WHEEL=$(ls -t appwheels/flash_attn-*.whl | head -n1)
252
+ if [ -n "$WHEEL" ]; then
253
+ python -m pip install -v --no-build-isolation --no-deps "$WHEEL"
254
+ else
255
+ # fallback para pip direto do Git
256
+ python -m pip install -v --no-build-isolation --no-deps git+https://github.com/Dao-AILab/flash-attention
257
+ fi
258
+ echo "FlashAttention completo instalado com sucesso"
259
+
260
+
261
+
262
  build_apex () {
263
  local SRC="/app/wheels/src/apex"
264
  echo "[build] Preparando fonte Apex em ${SRC}"
265
  if [ -d "$SRC/.git" ]; then
266
+ git -C "$SRC" fetch --all -p || true
267
+ git -C "$SRC" reset --hard HEAD || true
268
+ git -C "$SRC" clean -fdx || true
269
  else
270
  rm -rf "$SRC"
271
  git clone --depth 1 https://github.com/NVIDIA/apex "$SRC"
272
  fi
273
  echo "[build] Compilando Apex -> wheel"
274
+ export APEX_CPP_EXT=1 APEX_CUDA_EXT=1 APEX_ALL_CONTRIB_EXT=0
275
+ python -m pip wheel -v --no-build-isolation --no-deps "$SRC" -w /app/wheels || true
 
276
  local W="$(ls -t /app/wheels/apex-*.whl 2>/dev/null | head -n1 || true)"
277
  if [ -n "${W}" ]; then
278
+ python -m pip install -v -U --no-deps "${W}" || true
279
  echo "[build] Apex instalado da wheel recém-compilada: ${W}"
280
  else
281
+ echo "[build] Nenhuma wheel Apex gerada; instalando do source"
282
+ python -m pip install -v --no-build-isolation "$SRC" || true
283
  fi
284
  }
285
 
 
286
  Q8_REPO="${Q8_REPO:-https://github.com/Lightricks/LTX-Video-Q8-Kernels}"
287
  Q8_COMMIT="${Q8_COMMIT:-f3066edea210082799ca5a2bbf9ef0321c5dd8fc}"
288
  build_q8 () {
289
  local SRC="/app/wheels/src/q8_kernels"
290
  rm -rf "$SRC"
291
  git clone --filter=blob:none "$Q8_REPO" "$SRC"
292
+ git -C "$SRC" checkout "$Q8_COMMIT"
293
+ git -C "$SRC" submodule update --init --recursive
294
  echo "[build] Compilando Q8 Kernels -> wheel"
295
+ python -m pip wheel -v --no-build-isolation "$SRC" -w /app/wheels || true
 
296
  local W="$(ls -t /app/wheels/q8_kernels-*.whl 2>/dev/null | head -n1 || true)"
297
  if [ -n "${W}" ]; then
298
+ python -m pip install -v -U --no-deps "${W}" || true
299
  echo "[build] Q8 instalado da wheel recém-compilada: ${W}"
300
  else
301
+ echo "[build] Nenhuma wheel q8_kernels gerada; instalando do source"
302
+ python -m pip install -v --no-build-isolation "$SRC" || true
303
  fi
304
  }
305
 
 
307
  # EXECUÇÃO
308
  # ============================================================================
309
 
310
+ # Passo adicional SEM depender de "flash-attn" já instalado: trata somente o layer_norm
311
+ #build_q8 || true
312
+
313
+ # Apex (mantido)
314
+ # Tenta primeiro via wheel no HF e, se não houver, compila e instala em wheel
315
+ #echo "[flow] === apex ==="
316
+ #HF_OUT="$(install_from_hf_by_prefix "apex" || true)"
317
+ #if [ -n "${HF_OUT:-}" ]; then
318
+ # WHEEL_PATH="$(printf "%s\n" "${HF_OUT}" | tail -n1)"
319
+ # echo "[hub] Baixado: ${WHEEL_PATH}"
320
+ # python -m pip install -v -U --no-build-isolation "${WHEEL_PATH}" || true
321
+ # if ! check_apex; then
322
+ # echo "[flow] apex: import falhou após wheel; compilando"
323
+ # #build_apex || true
324
+ # fi
325
+ #else
326
+ # echo "[hub] Nenhuma wheel apex compatível; compilando"
327
+ # build_apex || true
328
+ #fi
329
+
330
+ #Q8 (opcional)
331
+ echo "[flow] === q8_kernels ==="
332
+ HF_OUT="$(install_from_hf_by_prefix "q8_kernels" || true)"
333
+ if [ -n "${HF_OUT:-}" ]; then
334
+ WHEEL_PATH="$(printf "%s\n" "${HF_OUT}" | tail -n1)"
335
+ echo "[hub] Baixado: ${WHEEL_PATH}"
336
+ python -m pip install -v -U --no-build-isolation "${WHEEL_PATH}" || true
337
+ if ! check_q8; then
338
+ echo "[flow] q8_kernels: import falhou após wheel; compilando"
339
+ build_q8 || true
340
+ fi
341
+ else
342
+ echo "[hub] Nenhuma wheel q8_kernels compatível; compilando"
343
+ build_q8 || true
344
+ fi
345
+
346
+ # Upload de wheels produzidas para o HF (cache cross-restarts)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  python - <<'PY'
348
  import os
349
  from huggingface_hub import HfApi, HfFolder
350
 
351
+ repo = os.environ.get("SELF_HF_REPO_ID","euIaxs22/Aduc-sdr")
352
  token = os.getenv("HF_TOKEN") or HfFolder.get_token()
353
  if not token:
354
+ raise SystemExit("HF_TOKEN ausente; upload desabilitado")
 
 
 
 
 
 
355
 
356
  api = HfApi(token=token)
357
+ api.upload_folder(
358
+ folder_path="/app/wheels",
359
+ repo_id=repo,
360
+ repo_type="model",
361
+ allow_patterns=["*.whl","NGC-DL-CONTAINER-LICENSE"],
362
+ ignore_patterns=["**/src/**","**/*.log","**/logs/**",".git/**"],
363
+ )
364
+ print("Upload concluído (wheels + licença).")
 
 
 
365
  PY
366
 
367
  chmod -R 777 /app/wheels || true
368
+ echo "✅ Builder finalizado."