2 Commits
v2.2.0 ... main

Author SHA1 Message Date
78f8b5ad82 requeue downloads rejected for platform concurrency instead of discarding them
v2.3.0 burned through all 498 models in minutes with download_failed=498: the
platform already had 8 downloads running, every create returned "用户最多同时运行
8 个下载任务", and the worker treated a create failure as terminal (CREATE_FAILED)
and moved on.

Now a concurrency rejection puts the model back at the head of the queue and
waits for the next poll, so only genuine per-model failures (uniqueness check,
etc.) are recorded as failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 16:01:42 +08:00
251f21ac8f add DOWNLOAD_ONLY mode: run zhoushasha downloads without submitting any validation task
All 498 models in the current list already had their hygon and bi150 slots
reserved in earlier rounds, so this round only needs the downloads. Without a
switch the download list would be empty, since phase 2 only downloads models
reserved in the same run.

DOWNLOAD_ONLY skips the reservation phase entirely and downloads all of
ALL_MODEL_IDS. Also splits the worker into _reserve_phase / _download_phase and
gates bi150 behind ENABLE_BI150_SUBMIT for symmetry with hygon.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 15:56:45 +08:00

110
main.py
View File

@@ -41,11 +41,20 @@ HYGON_SUBMIT_ACCOUNT = "zhoukaile"
HYGON_XC_TOKEN = "bd7c52f3b9604ef48a14dd6174513935" HYGON_XC_TOKEN = "bd7c52f3b9604ef48a14dd6174513935"
# ── 本轮开关 ──────────────────────────────────────────────── # ── 本轮开关 ────────────────────────────────────────────────
# 纯下载模式:当前 498 个模型的 hygon 和 bi150 都已经在前几轮提前占位完成,
# 本轮只用 zhoushasha 跑下载任务,不再提交任何验证任务。
# 开启后会【跳过整个占位阶段】,直接下载 ALL_MODEL_IDS 里的全部模型。
# 换新模型列表时改回 False并把下面两个 ENABLE_* 打开。
DOWNLOAD_ONLY = True
# hygon 已经用 zhoukaile 把当前模型列表498个从头交到最后一个了 # hygon 已经用 zhoukaile 把当前模型列表498个从头交到最后一个了
# 再交只会全部撞 60028,所以本轮关掉 hygon只补 bi150让两张卡覆盖对齐 # 再交只会全部撞 60028。下次换新模型列表时把它改回 True
# 下次换新模型列表时把它改回 True。
ENABLE_HYGON_SUBMIT = False ENABLE_HYGON_SUBMIT = False
# bi150 已由 34 个零积分小号 + zhangyuanxi 兜底占位完成v2.2.0 补了 436 个)。
# 下次换新模型列表时把它改回 True。
ENABLE_BI150_SUBMIT = False
# bi150 兜底账号零积分小号每个只占1个用完之后 # bi150 兜底账号零积分小号每个只占1个用完之后
# 剩余模型的 bi150 统一用这个账号提交。 # 剩余模型的 bi150 统一用这个账号提交。
# 用独立账号而不是 zhoukaile避免和 hygon 抢同一个账号的额度。 # 用独立账号而不是 zhoukaile避免和 hygon 抢同一个账号的额度。
@@ -106,6 +115,9 @@ TASK_PAGE_ENDPOINT = "/api/adapt/task/page"
QUOTA_FULL_MSG = "当前等待中或运行中的异步模型验证任务数量已达上限" QUOTA_FULL_MSG = "当前等待中或运行中的异步模型验证任务数量已达上限"
_hygon_quota_full = False # zhoukaile 额度是否已打满 _hygon_quota_full = False # zhoukaile 额度是否已打满
_bi150_quota_full = False # bi150 兜底账号额度是否已打满 _bi150_quota_full = False # bi150 兜底账号额度是否已打满
# 平台下载并发上限提示(错误码 60005命中时把模型放回队列重试而不是丢弃
DOWNLOAD_BUSY_MSG = "个下载任务"
_download_busy = False
GPU_TYPE_HYGON = "hygon_k100-ai" GPU_TYPE_HYGON = "hygon_k100-ai"
GPU_TYPE_BI150 = "Iluvatar_bi-150" GPU_TYPE_BI150 = "Iluvatar_bi-150"
@@ -2636,7 +2648,14 @@ def create_download_task(token: str, model_id: str) -> bool:
print(f"✅ 下载任务已提交: {model_id}", flush=True) print(f"✅ 下载任务已提交: {model_id}", flush=True)
return True return True
else: else:
print(f"⚠️ 下载任务业务失败 ({model_id}): {data.get('message')}", flush=True) msg = str(data.get("message") or "")
if DOWNLOAD_BUSY_MSG in msg:
# 平台侧下载并发已满,不是这个模型的问题,稍后重试
global _download_busy
_download_busy = True
print(f"⏸️ 下载并发已满,稍后重试 ({model_id})", flush=True)
else:
print(f"⚠️ 下载任务业务失败 ({model_id}): {msg}", flush=True)
return False return False
else: else:
print(f"❌ HTTP 错误 ({model_id}): {resp.status_code} - {resp.text}", flush=True) print(f"❌ HTTP 错误 ({model_id}): {resp.status_code} - {resp.text}", flush=True)
@@ -2823,28 +2842,63 @@ def _run_worker():
# 对策:把提交挪到下载【之前】。先占位再下载,下载队列即使被爬也没用。 # 对策:把提交挪到下载【之前】。先占位再下载,下载队列即使被爬也没用。
# 触发的 adminProxy 代下载很慢无所谓——我方自己的下载会先完成。 # 触发的 adminProxy 代下载很慢无所谓——我方自己的下载会先完成。
# ══════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════
_state["phase"] = "reserving"
_init_bi150_queue()
reserved_models = [] # 占位成功、需要下载的模型(按占位顺序) reserved_models = [] # 占位成功、需要下载的模型(按占位顺序)
print( if DOWNLOAD_ONLY:
f"\n🔒 阶段一占位bi150 零积分待占位账号 {len(_bi150_pending)} 个," # 纯下载模式:占位已在前几轮完成,直接下载全部模型
f"用完后兜底账号={BI150_FALLBACK_ACCOUNT}" reserved_models = list(ALL_MODEL_IDS)
f"hygon={'启用' if ENABLE_HYGON_SUBMIT else '本轮关闭'}\n", print(
flush=True, f"\n⏭️ 纯下载模式DOWNLOAD_ONLY=True跳过占位阶段"
) f"直接下载全部 {len(reserved_models)} 个模型,不提交任何验证任务\n",
flush=True,
)
else:
_state["phase"] = "reserving"
_init_bi150_queue()
print(
f"\n🔒 阶段一占位bi150 零积分待占位账号 {len(_bi150_pending)} 个,"
f"用完后兜底账号={BI150_FALLBACK_ACCOUNT}"
f"bi150={'启用' if ENABLE_BI150_SUBMIT else '关闭'}"
f"hygon={'启用' if ENABLE_HYGON_SUBMIT else '关闭'}\n",
flush=True,
)
_reserve_phase(reserved_models)
print(
f"\n🔒 占位阶段完成bi150={_state['reserved_bi150']} "
f"hygon={_state['reserved_hygon']} "
f"待下载模型={len(reserved_models)}\n",
flush=True,
)
# ══════════════════════════════════════════════════════
# 阶段二下载机制Azhoushasha8 并发)
# 只下载已占到位的模型——这些位置已经是我方的,下载完即可开跑验证
# ══════════════════════════════════════════════════════
_state["phase"] = "downloading"
pending_models = list(reserved_models) # 尚未开始下载的模型
active_models: Set[str] = set() # 当前正在下载的模型
completed_results = {} # model_id -> status
print(f"🚀 阶段二:下载 {len(pending_models)} 个模型。最大并发数: {MAX_CONCURRENT_DOWNLOADS}\n", flush=True)
_download_phase(token, pending_models, active_models, completed_results)
def _reserve_phase(reserved_models: List[str]) -> None:
"""阶段一占位机制B。结果追加到 reserved_models。"""
for model_id in ALL_MODEL_IDS: for model_id in ALL_MODEL_IDS:
if _shutdown.is_set(): if _shutdown.is_set():
break break
if _bi150_quota_full and (_hygon_quota_full or not ENABLE_HYGON_SUBMIT): bi_done = _bi150_quota_full or not ENABLE_BI150_SUBMIT
hy_done = _hygon_quota_full or not ENABLE_HYGON_SUBMIT
if bi_done and hy_done:
print("🔒 bi150 与 hygon 均已无额度可用,占位阶段结束", flush=True) print("🔒 bi150 与 hygon 均已无额度可用,占位阶段结束", flush=True)
break break
got = False got = False
# bi150先用还没有 bi150 任务的零积分账号,用完后走兜底账号 # bi150先用还没有 bi150 任务的零积分账号,用完后走兜底账号
if not _bi150_quota_full: if ENABLE_BI150_SUBMIT and not _bi150_quota_full:
if submit_test_task_bi150(model_id): if submit_test_task_bi150(model_id):
_state["submitted"] += 1 _state["submitted"] += 1
_state["reserved_bi150"] += 1 _state["reserved_bi150"] += 1
@@ -2864,24 +2918,9 @@ def _run_worker():
if got: if got:
reserved_models.append(model_id) reserved_models.append(model_id)
print(
f"\n🔒 占位阶段完成bi150={_state['reserved_bi150']} "
f"hygon={_state['reserved_hygon']} "
f"待下载模型={len(reserved_models)}\n",
flush=True,
)
# ══════════════════════════════════════════════════════
# 阶段二下载机制Azhoushasha8 并发)
# 只下载已经占到位的模型——这些位置已经是我方的,下载完即可开跑验证
# ══════════════════════════════════════════════════════
_state["phase"] = "downloading"
pending_models = list(reserved_models) # 尚未开始下载的模型
active_models: Set[str] = set() # 当前正在下载的模型
completed_results = {} # model_id -> status
print(f"🚀 阶段二:下载 {len(pending_models)} 个已占位模型。最大并发数: {MAX_CONCURRENT_DOWNLOADS}\n", flush=True)
def _download_phase(token, pending_models, active_models, completed_results) -> None:
"""阶段二下载机制Azhoushasha"""
while (pending_models or active_models) and not _shutdown.is_set(): while (pending_models or active_models) and not _shutdown.is_set():
# 1. 检查活跃任务状态 # 1. 检查活跃任务状态
for model_id in list(active_models): for model_id in list(active_models):
@@ -2900,13 +2939,20 @@ def _run_worker():
_state["download_failed"] += 1 _state["download_failed"] += 1
# 2. 补充新任务(最多补到 MAX_CONCURRENT_DOWNLOADS 个) # 2. 补充新任务(最多补到 MAX_CONCURRENT_DOWNLOADS 个)
global _download_busy
_download_busy = False
while len(active_models) < MAX_CONCURRENT_DOWNLOADS and pending_models and not _shutdown.is_set(): while len(active_models) < MAX_CONCURRENT_DOWNLOADS and pending_models and not _shutdown.is_set():
next_model = pending_models.pop(0) next_model = pending_models.pop(0)
if create_download_task(token, next_model): if create_download_task(token, next_model):
active_models.add(next_model) active_models.add(next_model)
print(f"▶️ 启动下载: {next_model} (当前活跃: {len(active_models)})", flush=True) print(f"▶️ 启动下载: {next_model} (当前活跃: {len(active_models)})", flush=True)
elif _download_busy:
# 平台下载并发已满:放回队首等下一轮重试,不能当成失败丢弃,
# 否则整个列表会在几分钟内被空转消耗光v2.3.0 曾因此 498 个全部“失败”)
pending_models.insert(0, next_model)
break
else: else:
# 创建失败也视为完成避免卡住 # 模型本身的问题(如唯一性检查不通过),视为完成避免卡住
completed_results[next_model] = "CREATE_FAILED" completed_results[next_model] = "CREATE_FAILED"
_state["download_failed"] += 1 _state["download_failed"] += 1
print(f"❌ 创建失败: {next_model}", flush=True) print(f"❌ 创建失败: {next_model}", flush=True)