FABLESLIP commited on
Commit
2de1d31
·
verified ·
1 Parent(s): ce9842f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -56
app.py CHANGED
@@ -106,7 +106,14 @@ warmup_state: Dict[str, Any] = {
106
  "total": 0,
107
  "idx": 0,
108
  "job_id": "default",
 
 
 
 
 
 
109
  }
 
110
  warmup_lock = threading.Lock()
111
  warmup_stop = threading.Event()
112
 
@@ -187,25 +194,13 @@ def _download_one(repo_id: str, tries: int = 3) -> bool:
187
  return False
188
 
189
  def _warmup_thread(models: List[str]):
190
- with warmup_lock:
191
- warmup_state.update({
192
- "running": True,
193
- "percent": 0,
194
- "ok_count": 0,
195
- "done": False,
196
- "logs": [],
197
- "current": None,
198
- "total": len(models),
199
- "idx": 0,
200
- })
201
- warmup_stop.clear()
202
  ok_count = 0
203
  t_global = time.time()
204
  _log_warmup(f"[JOB] start • {len(models)} dépôts")
205
 
206
  for i, repo in enumerate(models):
207
  if warmup_stop.is_set():
208
- _log_warmup("[STOP] Arrêt demandé par l’utilisateur — fin du job après ce point")
209
  break
210
 
211
  with warmup_lock:
@@ -214,12 +209,14 @@ def _warmup_thread(models: List[str]):
214
  warmup_state["percent"] = int((i / max(1, len(models))) * 100)
215
 
216
  ok = _download_one(repo)
217
- if ok:
218
- ok_count += 1
219
- with warmup_lock:
220
- warmup_state["ok_count"] = ok_count
221
- # progression après dépôt (OK ou FAIL)
222
  with warmup_lock:
 
 
 
 
 
 
 
223
  warmup_state["percent"] = int(((i + 1) / max(1, len(models))) * 100)
224
 
225
  if warmup_stop.is_set():
@@ -231,8 +228,10 @@ def _warmup_thread(models: List[str]):
231
  warmup_state["done"] = True
232
  warmup_state["running"] = False
233
  warmup_state["ok_count"] = ok_count
 
234
  _log_warmup(f"[JOB] done • {ok_count}/{len(models)} • {time.time()-t_global:.1f}s")
235
 
 
236
  # <<<< HUGINFACE PATCH: WARMUP STATE+HELPERS END >>>>
237
  # ---------- Helpers ----------
238
 
@@ -519,7 +518,7 @@ from copy import deepcopy
519
 
520
  @app.post("/warmup/start", tags=["warmup"])
521
  async def warmup_start(payload: Optional[Dict[str, Any]] = Body(None)):
522
- """
523
  Démarre le téléchargement séquentiel des modèles.
524
  Corps JSON optionnel: { "models": ["repo1","repo2", ...] }
525
  Si vide: lit la variable d'env WARMUP_MODELS (JSON).
@@ -538,20 +537,31 @@ async def warmup_start(payload: Optional[Dict[str, Any]] = Body(None)):
538
 
539
  with warmup_lock:
540
  if warmup_state.get("running"):
541
- # Déjà en cours : on renvoie l'état actuel pour info
542
- return {
543
- "ok": False,
544
- "already_running": True,
545
- "status": deepcopy(warmup_state),
546
- }
547
- # Lancer un nouveau thread
548
  job_id = uuid.uuid4().hex[:8]
549
- warmup_state["job_id"] = job_id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550
  th = threading.Thread(target=_warmup_thread, args=(models,), daemon=True)
551
  th.start()
552
 
553
  return {"ok": True, "started": True, "total": len(models), "job_id": job_id}
554
 
 
555
  @app.get("/warmup/status", tags=["warmup"])
556
  def warmup_status():
557
  """Retourne l'état courant du warm-up (progression, logs, etc.)."""
@@ -835,12 +845,12 @@ HTML_TEMPLATE = r"""
835
 
836
  <!-- >>> A2B2_BEGIN warmup_topbar -->
837
  <div style="display:flex;gap:8px;align-items:center">
838
- <button id="warmupStartBtn" class="btn" title="Télécharger les modèles (séquentiel)">🔥 Préparer modèles</button>
839
- <button id="warmupStopBtn" class="btn" title="Arrêter le warm-up en cours" style="display:none">⏹️ Stop warm-up</button>
840
- <button id="warmupSelectBtn" class="btn" title="Sélectionner les repos à préparer">🧩 Choisir modèles</button>
841
-
842
- <button id="warmupLogsBtn" class="btn" title="Voir les logs du warm-up">📜 Logs warm-up</button>
843
  <span id="warmupStatus" class="muted"></span>
 
844
  </div>
845
  <!-- >>> A2B2_END warmup_topbar -->
846
 
@@ -920,7 +930,8 @@ HTML_TEMPLATE = r"""
920
 
921
  <!-- >>> A2B2_BEGIN warmup_popup -->
922
  <div id="warmupPopup" style="display:none; position:fixed; top:22%; left:50%; transform:translate(-50%,-50%); background:#fff; padding:20px; border-radius:8px; box-shadow:0 0 10px rgba(0,0,0,0.2); z-index:1001; min-width:360px">
923
- <h3>Préparation des modèles (warm-up)</h3>
 
924
  <div class="muted" id="warmupPopupStatus">—</div>
925
  <div style="background:#f3f4f6;border-radius:4px;height:8px;margin:10px 0">
926
  <div id="warmup-progress-fill" style="background:#2563eb;height:100%;width:0;border-radius:4px"></div>
@@ -937,7 +948,8 @@ HTML_TEMPLATE = r"""
937
  <button id="selectAllBtn" class="btn">Tout cocher</button>
938
  <button id="selectNoneBtn" class="btn">Tout décocher</button>
939
  <button id="selectCancelBtn" class="btn">Annuler</button>
940
- <button id="launchSelectedBtn" class="btn">Lancer la préparation</button>
 
941
  </div>
942
  </div>
943
  <!-- >>> A2B2_END warmup_popup -->
@@ -1001,6 +1013,32 @@ window._lastInstanceId = null;
1001
  const warmupCloseBtn = document.getElementById('warmupCloseBtn');
1002
 
1003
  // Helpers popup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1004
 
1005
 
1006
  // >>> C2_BEGIN warmup_preface
@@ -1048,32 +1086,25 @@ async function refreshWarmupUI(){
1048
  if (warmupStatusEl) {
1049
  const tot = (s.total ?? 0);
1050
  if (running) {
1051
- const idx = (s.idx ?? 0) + 1;
1052
  warmupStatusEl.textContent = `⏳ ${pct}% — ${s.current||''} (${idx}/${tot}) [inst:${instanceId}]`;
1053
  } else {
1054
-
1055
- // Détection fin de run (par job_id) => toast récap une seule fois
1056
- if (s.done && s.job_id && window._lastNotifiedJobId !== s.job_id) {
1057
- const tot2 = (s.total ?? 0);
1058
- const ok2 = Number.isFinite(s.ok_count) ? s.ok_count : '';
1059
- showToast(`Warm-up terminé ${ok2}/${tot2} téléchargés (inst:${instanceId})`);
1060
- window._lastNotifiedJobId = s.job_id;
1061
- }
1062
-
1063
- if (s.done && Number.isFinite(s.ok_count)) {
1064
- warmupStatusEl.textContent = `✅ Terminé — ${s.ok_count}/${tot} téléchargés (inst:${instanceId})`;
1065
- } else {
1066
- const nCache = Number.isFinite(s.audit_count)
1067
- ? s.audit_count
1068
- : (Array.isArray(s.audit_cached) ? s.audit_cached.length : 0);
1069
- if (nCache > 0) {
1070
- warmupStatusEl.textContent = `✅ Prêt — cache local: ${nCache} (inst:${instanceId})`;
1071
- } else {
1072
- warmupStatusEl.textContent = `Prêt (aucun run)`;
1073
  }
1074
- }
1075
 
1076
- }
1077
  }
1078
 
1079
  if (warmupProgressFill) warmupProgressFill.style.width = pct + '%';
 
106
  "total": 0,
107
  "idx": 0,
108
  "job_id": "default",
109
+ # NOUVEAUX CHAMPS POUR RÉCAP
110
+ "asked": [], # liste demandée au lancement
111
+ "ok_repos": [], # liste des repos téléchargés OK
112
+ "failed_repos": [], # liste des repos en échec
113
+ "started_at": 0.0, # timestamp début
114
+ "finished_at": 0.0, # timestamp fin
115
  }
116
+
117
  warmup_lock = threading.Lock()
118
  warmup_stop = threading.Event()
119
 
 
194
  return False
195
 
196
  def _warmup_thread(models: List[str]):
 
 
 
 
 
 
 
 
 
 
 
 
197
  ok_count = 0
198
  t_global = time.time()
199
  _log_warmup(f"[JOB] start • {len(models)} dépôts")
200
 
201
  for i, repo in enumerate(models):
202
  if warmup_stop.is_set():
203
+ _log_warmup("[STOP] Arrêt demandé — fin du job après ce point")
204
  break
205
 
206
  with warmup_lock:
 
209
  warmup_state["percent"] = int((i / max(1, len(models))) * 100)
210
 
211
  ok = _download_one(repo)
 
 
 
 
 
212
  with warmup_lock:
213
+ if ok:
214
+ ok_count += 1
215
+ warmup_state["ok_count"] = ok_count
216
+ warmup_state["ok_repos"].append(repo)
217
+ else:
218
+ warmup_state["failed_repos"].append(repo)
219
+
220
  warmup_state["percent"] = int(((i + 1) / max(1, len(models))) * 100)
221
 
222
  if warmup_stop.is_set():
 
228
  warmup_state["done"] = True
229
  warmup_state["running"] = False
230
  warmup_state["ok_count"] = ok_count
231
+ warmup_state["finished_at"] = time.time()
232
  _log_warmup(f"[JOB] done • {ok_count}/{len(models)} • {time.time()-t_global:.1f}s")
233
 
234
+
235
  # <<<< HUGINFACE PATCH: WARMUP STATE+HELPERS END >>>>
236
  # ---------- Helpers ----------
237
 
 
518
 
519
  @app.post("/warmup/start", tags=["warmup"])
520
  async def warmup_start(payload: Optional[Dict[str, Any]] = Body(None)):
521
+ """
522
  Démarre le téléchargement séquentiel des modèles.
523
  Corps JSON optionnel: { "models": ["repo1","repo2", ...] }
524
  Si vide: lit la variable d'env WARMUP_MODELS (JSON).
 
537
 
538
  with warmup_lock:
539
  if warmup_state.get("running"):
540
+ return {"ok": False, "already_running": True, "status": deepcopy(warmup_state)}
541
+ # RESET d’un nouveau job
 
 
 
 
 
542
  job_id = uuid.uuid4().hex[:8]
543
+ warmup_state.update({
544
+ "job_id": job_id,
545
+ "asked": models[:],
546
+ "ok_repos": [],
547
+ "failed_repos": [],
548
+ "ok_count": 0,
549
+ "logs": [],
550
+ "idx": 0,
551
+ "total": len(models),
552
+ "percent": 0,
553
+ "running": True,
554
+ "done": False,
555
+ "current": None,
556
+ "started_at": time.time(),
557
+ "finished_at": 0.0,
558
+ })
559
  th = threading.Thread(target=_warmup_thread, args=(models,), daemon=True)
560
  th.start()
561
 
562
  return {"ok": True, "started": True, "total": len(models), "job_id": job_id}
563
 
564
+
565
  @app.get("/warmup/status", tags=["warmup"])
566
  def warmup_status():
567
  """Retourne l'état courant du warm-up (progression, logs, etc.)."""
 
845
 
846
  <!-- >>> A2B2_BEGIN warmup_topbar -->
847
  <div style="display:flex;gap:8px;align-items:center">
848
+ <button id="warmupStartBtn" class="btn" title="Télécharger les modèles (séquentiel)">🔥 Télécharger modèles</button>
849
+ <button id="warmupStopBtn" class="btn" title="Arrêter le téléchargement en cours" style="display:none">⏹️ Stop téléchargement</button>
850
+ <button id="warmupSelectBtn" class="btn" title="Sélectionner les repos à télécharger">🧩 Choisir modèles</button>
851
+ <button id="warmupLogsBtn" class="btn" title="Voir les logs du téléchargement">📜 Logs téléchargement</button>
 
852
  <span id="warmupStatus" class="muted"></span>
853
+
854
  </div>
855
  <!-- >>> A2B2_END warmup_topbar -->
856
 
 
930
 
931
  <!-- >>> A2B2_BEGIN warmup_popup -->
932
  <div id="warmupPopup" style="display:none; position:fixed; top:22%; left:50%; transform:translate(-50%,-50%); background:#fff; padding:20px; border-radius:8px; box-shadow:0 0 10px rgba(0,0,0,0.2); z-index:1001; min-width:360px">
933
+ <h3>Téléchargement des modèles (warm-up)</h3>
934
+
935
  <div class="muted" id="warmupPopupStatus">—</div>
936
  <div style="background:#f3f4f6;border-radius:4px;height:8px;margin:10px 0">
937
  <div id="warmup-progress-fill" style="background:#2563eb;height:100%;width:0;border-radius:4px"></div>
 
948
  <button id="selectAllBtn" class="btn">Tout cocher</button>
949
  <button id="selectNoneBtn" class="btn">Tout décocher</button>
950
  <button id="selectCancelBtn" class="btn">Annuler</button>
951
+ <button id="launchSelectedBtn" class="btn">Lancer le téléchargement</button>
952
+
953
  </div>
954
  </div>
955
  <!-- >>> A2B2_END warmup_popup -->
 
1013
  const warmupCloseBtn = document.getElementById('warmupCloseBtn');
1014
 
1015
  // Helpers popup
1016
+ function buildFinalSummary(s){
1017
+ const asked = Array.isArray(s.asked) ? s.asked : [];
1018
+ const okL = Array.isArray(s.ok_repos) ? s.ok_repos : [];
1019
+ const failL = Array.isArray(s.failed_repos) ? s.failed_repos : [];
1020
+ const cached = Array.isArray(s.audit_cached) ? s.audit_cached : [];
1021
+ const tot = s.total ?? asked.length ?? 0;
1022
+
1023
+ const lines = [];
1024
+ lines.push("RÉCAP FINAL");
1025
+ lines.push(`Demandés : ${asked.length}`);
1026
+ if (asked.length) lines.push(asked.map(m=>' • '+m).join('\n'));
1027
+
1028
+ lines.push("");
1029
+ lines.push(`✅ Téléchargés : ${okL.length}/${tot}`);
1030
+ if (okL.length) lines.push(okL.map(m=>' • '+m).join('\n'));
1031
+
1032
+ lines.push("");
1033
+ lines.push(`❌ Échecs : ${failL.length}`);
1034
+ if (failL.length) lines.push(failL.map(m=>' • '+m).join('\n'));
1035
+
1036
+ lines.push("");
1037
+ lines.push(`📦 En cache maintenant : ${cached.length}`);
1038
+ if (cached.length) lines.push(cached.map(m=>' • '+m).join('\n'));
1039
+
1040
+ return lines.join('\n');
1041
+ }
1042
 
1043
 
1044
  // >>> C2_BEGIN warmup_preface
 
1086
  if (warmupStatusEl) {
1087
  const tot = (s.total ?? 0);
1088
  if (running) {
1089
+ const idx = (s.idx ?? 0) + 1;
1090
  warmupStatusEl.textContent = `⏳ ${pct}% — ${s.current||''} (${idx}/${tot}) [inst:${instanceId}]`;
1091
  } else {
1092
+ if (s.done) {
1093
+ const ok = Number.isFinite(s.ok_count) ? s.ok_count : 0;
1094
+ const fail = Array.isArray(s.failed_repos) ? s.failed_repos.length : Math.max(0, tot - ok);
1095
+ warmupStatusEl.textContent = `✅ Terminé — ${ok}/${tot} téléchargés, ${fail} échec(s) [inst:${instanceId}]`;
1096
+ if (warmupPopupStatus) warmupPopupStatus.textContent = 'Terminé';
1097
+ if (warmupLogs) warmupLogs.textContent = buildFinalSummary(s);
1098
+ } else {
1099
+ const nCache = Number.isFinite(s.audit_count)
1100
+ ? s.audit_count
1101
+ : (Array.isArray(s.audit_cached) ? s.audit_cached.length : 0);
1102
+ warmupStatusEl.textContent = nCache > 0
1103
+ ? `✅ Prêt — cache local: ${nCache} [inst:${instanceId}]`
1104
+ : `Prêt (aucun run)`;
1105
+ }
 
 
 
 
 
1106
  }
 
1107
 
 
1108
  }
1109
 
1110
  if (warmupProgressFill) warmupProgressFill.style.width = pct + '%';