Compare commits

...

10 Commits

Author SHA1 Message Date
9cd1c49d10 Replace main.py with vLLM adapt-task batch submitter (fanyi account)
Port logic from submit_validation_only_ppu_zhoukaile.py into the
strategy-deployable framework (health/status HTTP server, STRATEGY_ID
env, SIGTERM handling). Uses /api/adapt/task/add with xc-Token auth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 20:02:06 +08:00
9aba1595db init 2026-07-14 16:44:33 +08:00
85f41bba58 Replace main.py with GGUF download + validation submit pipeline
Port logic from continuous_pipeline_download_gguf_zhoushasha_and_submit.py
into the strategy-deployable framework (health/status HTTP server,
STRATEGY_ID env, SIGTERM handling).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:45:51 +08:00
d6b0e416db update ppu 2026-07-13 19:43:35 +08:00
4dcfed6b6d update ppu 2026-07-13 18:38:55 +08:00
1e8cfacd8e uodate 2026-06-22 19:00:46 +08:00
d6cca90496 update main.py 2026-06-22 18:44:42 +08:00
031e0dc7a8 update main.py 2026-06-19 01:48:50 +08:00
af6f501a5a update main.py 2026-06-18 15:22:29 +08:00
94da35d152 clean up Dockerfile 2026-06-14 23:55:41 +08:00
4 changed files with 166 additions and 93 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.DS_Store
__pycache__/

View File

@@ -2,6 +2,7 @@ FROM modelhubxc-4pd.tencentcloudcr.com/xc_agent_platform/python:3.11-slim
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
WORKDIR /app WORKDIR /app
COPY requirements.txt . COPY requirements.txt .

View File

@@ -1,12 +1,13 @@
# xc_validation_strategy # xc_validation_strategy_vllm_submit
批量向 ModelHub XC 平台提交模型验证任务的策略服务,之后保持 HTTP 服务存活供平台探活。 批量向 ModelHub XC 平台提交 vLLM 模型适配任务的策略服务fanyi 账号),
之后保持 HTTP 服务存活供平台探活。
## 功能 ## 功能
- 自动登录 ModelHub 获取 Token - 通过 `/api/adapt/task/add` 接口xc-Token 认证)批量提交模型适配任务
- 批量提交模型验证任务vLLM 框架Cambricon MLU-370-x8 - vLLM 框架ppu_zw_810e GPU
- 提交结果写入 `submitted_validation_tasks.txt` - 提交成功的模型写入 `submitted_adapt_tasks.txt`
- 暴露 `/health``/status` 接口满足平台运行时契约 - 暴露 `/health``/status` 接口满足平台运行时契约
## 项目结构 ## 项目结构
@@ -16,7 +17,7 @@
├── main.py # 主入口HTTP 服务 + 提交逻辑 ├── main.py # 主入口HTTP 服务 + 提交逻辑
├── Dockerfile # 平台镜像构建配置 ├── Dockerfile # 平台镜像构建配置
├── requirements.txt # Python 依赖 ├── requirements.txt # Python 依赖
└── submitted_validation_tasks.txt # 运行后自动生成,记录提交结果 └── submitted_adapt_tasks.txt # 运行后自动生成,记录提交结果
``` ```
## 平台契约说明 ## 平台契约说明

227
main.py
View File

@@ -1,8 +1,11 @@
""" """
xc_validation_strategy — 主入口 xc_validation_strategy_vllm_submit — 主入口
启动后执行一次模型验证任务批量提交,之后保持 HTTP 服务存活。 启动后通过 /api/adapt/task/add 接口xc-Token 认证)批量提交
vLLM 模型适配任务ppu_zw_810e之后保持 HTTP 服务存活。
同时暴露 /healthK8s 探活)和 /status运行状态 同时暴露 /healthK8s 探活)和 /status运行状态
部署框架与 xc_validation_strategy 一致。
""" """
import json import json
@@ -11,24 +14,29 @@ import signal
import threading import threading
from datetime import datetime from datetime import datetime
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from typing import List, Tuple from typing import List
import requests import requests
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
# 配置(全部从环境变量读取,不硬编码敏感信息) # 配置
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
BASE_URL = os.environ.get("BASE_URL", "https://modelhub.org.cn") BASE_URL = os.environ.get("BASE_URL", "https://modelhub.org.cn")
SUBMIT_ENDPOINT = "/adminApi/async/task/create-contest-task" ADD_TASK_ENDPOINT = "/api/adapt/task/add"
# 通过 curl -X POST https://modelhub.org.cn/adminApi/user/login 获取后填入 # fanyi 账号的 xc-Token该接口使用 xc-Token 认证,无需登录)
AUTH_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyQWNjb3VudCI6Inpob3VzaGFzaGEiLCJpZCI6MTQsInVzZXJSb2xlIjoibGVhZGVyYm9hcmQiLCJleHAiOjE3ODE4NTE0NzcsImlhdCI6MTc4MTI0NjY3N30.p3uvCpG50aLNifNVVXxvzmWJahbLM5K1671FVCtj8E8" USER_ACCOUNT = "fanyi"
CONTEST_API_TOKEN = "ef1ef82f3c9efee413d602345fbe224d" XC_TOKEN = "f2d501c9ae6543a589cd6cb789108c41"
CONTRIBUTORS = "zhoushasha"
GPU_TYPE = "Cambricon_mlu-370-x8" GPU_TYPE = "ppu_zw_810e"
TASK_TYPE = "text-generation" TASK_TYPE = "text-generation"
STRATEGY_ID = os.environ.get("STRATEGY_ID", "") # 平台自动注入,无需修改 STRATEGY_ID = os.environ.get("STRATEGY_ID", "") # 平台自动注入,无需修改
HEADERS = {
"Content-Type": "application/json",
"xc-Token": XC_TOKEN,
}
HTTP_HOST = "0.0.0.0" HTTP_HOST = "0.0.0.0"
HTTP_PORT = 8080 HTTP_PORT = 8080
@@ -36,26 +44,71 @@ HTTP_PORT = 8080
# 模型列表 # 模型列表
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
ALL_MODEL_IDS = [ ALL_MODEL_IDS = [
"AI-ModelScope/gemma-2b",
"AI-ModelScope/falcon-mamba-7b", "Hyeji0101/qwen2_5_1_5b_demo",
"katanemo/deepseek-2", "GenueAI/geode-onyx",
"OpenBMB/MiniCPM4-0.5B", "GM77/qwen3-4b-verilog-grpo",
"NousResearch/Meta-Llama-3-8B-Instruct", "ChuGyouk/F_R13_T2",
"MediaTek-Research/Breeze-7B-Instruct-v1_0", "ChuGyouk/R17",
"QLUNLP/BianCang-Qwen2.5-7B-Instruct", "Ingingdo/bit-0.5b-final-logic",
"OpenBMB/MiniCPM4-Survey", "beomi/Llama-3-Open-Ko-8B",
"OpenBMB/MiniCPM4-8B", "Fiscus/trinitite_safe_rl_base_model",
"PaddlePaddle/ERNIE-4.5-0.3B-PT", "ChuGyouk/F_R12_T3",
"LLM-Research/Llama-Guard-3-8B", "ChuGyouk/F_R12_T2",
"OpenBMB/MiniCPM-2B-dpo-fp16", "xw1234gan/cnk12_Main_fixed_SFTanchor_3B_step_9",
"OpenBMB/MiniCPM4.1-8B", "xw1234gan/cnk12_Main_fixed_SFTanchor_3B_step_10",
"Cylingo/Xinyuan-LLM-14B-0428", "xw1234gan/cnk12_Main_fixed_BaseAnchor_3B_step_1",
"Fengshenbang/Ziya-LLaMA-13B-v1", "kmseong/llama3_2_3b-instruct-math-safedelta-scale0.99",
"baichuan-inc/Baichuan2-13B-Chat", "opencompass/anah-v2",
"LLM-Research/gemma-2-9b-it", "ChuGyouk/R14",
"Qwen/CodeQwen1.5-7B-Chat", "trishajean/qwen-math-cebuano-1.5b-merged",
"OpenBMB/cpm-bee-10b", "GyanAISystems/Gyan-AI-G1-Official",
"OpenBMB/MiniCPM3-4B", "Divij/Qwen2.5-3B-Instruct-sft-without-thoughts",
"Divij/Qwen2.5-3B-Instruct-sft-with-thoughts",
"ChuGyouk/R5_1",
"ChuGyouk/R18_1",
"ChuGyouk/R19_1",
"ChuGyouk/R12",
"ChuGyouk/F_R11_T4",
"ChuGyouk/F_R12",
"ChuGyouk/F_R11_T2",
"ChuGyouk/F_R11_T3",
"ChuGyouk/F_R13_1_T1",
"ChuGyouk/F_R12_T4",
"automerger/T3qm7xNeuralsirkrishna-7B",
"Ford91/clifford-ai-v2",
"ChuGyouk/R16_1",
"ChuGyouk/R15_1",
"nkatara/gita-text-generation-gpt2",
"HINT-lab/Qwen2.5-7B-Instruct-Self-Calibration",
"thirdeyeai/Qwen2.5-1.5B-Instruct-uncensored",
"karaselerm/qwen2.5-1.5b-instruct-ru-abliterated-hw6",
"xw1234gan/cnk12_Main_fixed_BaseAnchor_3B_step_2",
"ontocord/wide_3b_sft_stage1.1-ss1-with_intr_math.no_issue",
"mncai/Foundation_Law_epoch4",
"gauri0508/med-record-audit-qwen2.5-3b-grpo",
"unsloth/Phi-4-mini-instruct",
"E-motionAssistant/qwen-2.5-3b-tamil-therapy-merged",
"EscapeJeju/qwen2_5_1_5b_demo",
"AgPerry/Qwen3-8B-fim-v2v3pt-swe-lego-posttrain",
"ChuGyouk/F_R11",
"ChuGyouk/F_R11_1_T1",
"LorenaYannnnn/general_reward-Qwen3-0.6B-OURS_self-seed_1",
"Vortex5/Crimson-Constellation-12B",
"cloudyu/mistral_11B_instruct_v0.1",
"pkupie/Qwen2.5-3B-ug-cpt",
"iproskurina/qwen-hf-fewshot-iter-np-iter3",
"ontocord/wide_3b_sft_stage1.2-ss1-expert_wiki",
"kmseong/llama3_2_3b-instruct-math-safedelta-scale2",
"Thrillcrazyer/Qwen-2.5-1.5B_TAC_Teacher_Qwen32B",
"nyu-dice-lab/VeriThoughts-Reasoning-7B",
"ontocord/wide_3b",
"silvercoder67/Mistral-7b-instruct-v0.2-summ-sft-e2m",
"lihaoxin2020/qwen3-4b-sft-gpt54-ep2-instance-rubric-gpt54-step200",
"lihaoxin2020/qwen3-4b-sft-gpt54-ep2-instance-rubric-gpt54-step150",
"lihaoxin2020/qwen3-4b-sft-gpt54-ep2-evolving-rubric-gem3-flash-step150",
"Guilherme34/Firefly-V3",
] ]
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
@@ -108,98 +161,114 @@ def _run_http():
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
# 业务逻辑 # 业务逻辑
# ══════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════
def _submit_task(token: str, model_id: str) -> Tuple[bool, str]: def submit_task(model_id: str) -> bool:
headers = { config_content = f"""
"Content-Type": "application/json", gpu_type: ppu_zw_810e
"Authorization": f"Bearer {token}",
}
config_content = f"""docker_image: harbor.4pd.io/hardcore-tech/cambricon-mlu370-pytorch:v25.01-torch2.5.0-torchmlu1.24.1-ubuntu22.04-py310
nv_docker_image: harbor.4pd.io/dooke/vllm/vllm/vllm-openai:v0.11.0
framework: vllm framework: vllm
storage: gpfs docker_image: harbor.4pd.io/hardcore-tech/asllm:1.10.1-pytorch2.10.0-ubuntu24.04-sail2.1.0-cuda13.0-sglang0.5.10-vllm0.19.0-py312
modelhub_options: nv_docker_image: harbor-contest.4pd.io/sunruoxi/vllm-openai-fix-tokenizer:v0.11.0
srcRelativePath: leaderboard/modelHubXC/{model_id}
mountPoint: /model
sut_config: sut_config:
values: values:
gpu_num: 1 gpu_num: 1
env: env:
- name: MAX_MODEL_LEN - name: test
value: 8192 value: fp16
command: ["vllm", "serve", "/model", "--port", "8000", "--served-model-name", "llm", "--max-model-len", "8192", "--trust-remote-code", "--dtype", "float16"] command:
- bash
- /opt/t-head/entrypoint.sh
- python3
- -m
- asllm.entrypoints.api_server
- --model
- /model
- --port
- '30000'
- --host
- 0.0.0.0
- --served-model-name
- llm
ref_config: ref_config:
values: values:
cpu_num: 2
gpu_num: 1 gpu_num: 1
env: env:
- name: MAX_MODEL_LEN - name: test
value: 8192 value: fp16
command: ["vllm", "serve", "/model", "--port", "80", "--served-model-name", "llm", "--max-model-len", "8192", "--trust-remote-code", "--dtype", "float16"] command:
- vllm
- serve
- /model
- --port
- '80'
- --served-model-name
- llm
- --max-model-len
- '2048'
- --gpu-memory-utilization
- '0.9'
- --enforce-eager
- --trust-remote-code
- -tp
- '1'
""" """
payload = { payload = {
"contestApiToken": CONTEST_API_TOKEN, "configParams": config_content,
"contributors": CONTRIBUTORS,
"gpuTypes": [GPU_TYPE],
"taskType": TASK_TYPE,
"modelId": model_id,
"framework": "vllm", "framework": "vllm",
"strategyId": STRATEGY_ID, # 平台要求 "modelAddress": f"https://huggingface.co/{model_id}",
"submissionConfig": [{ "targetGpu": GPU_TYPE,
"config": config_content,
"gpuType": GPU_TYPE,
"taskType": TASK_TYPE, "taskType": TASK_TYPE,
}], "strategyId": STRATEGY_ID, # 平台要求;若接口不支持该字段会被忽略
} }
print(f"📤 提交任务: {model_id}", flush=True)
try: try:
resp = requests.post( resp = requests.post(
BASE_URL + SUBMIT_ENDPOINT, BASE_URL + ADD_TASK_ENDPOINT,
headers=headers, headers=HEADERS,
json=payload, json=payload,
timeout=15, timeout=30,
) )
print(f"status: {resp.status_code}", flush=True)
result = resp.json() result = resp.json()
print(result, flush=True)
if result.get("code") == 0: if result.get("code") == 0:
task_id = result.get("data", {}).get("id", "") print(f"✅ 提交成功: {model_id}", flush=True)
print(f"[worker] OK {model_id} task_id={task_id}", flush=True) return True
return True, task_id
else: else:
print(f"[worker] FAIL {model_id}: {result.get('message')}", flush=True) print(f"❌ 提交失败: {result.get('message')}", flush=True)
return False, "" return False
except Exception as e: except Exception as e:
print(f"[worker] ERROR {model_id}: {e}", flush=True) print(f"💥 异常 ({model_id}): {e}", flush=True)
return False, "" return False
def _run_worker(): def _run_worker():
_state["started_at"] = datetime.utcnow().isoformat() _state["started_at"] = datetime.utcnow().isoformat()
_state["phase"] = "submitting" _state["phase"] = "submitting"
successful: List[Tuple[str, str]] = [] successful: List[str] = []
token = AUTH_TOKEN
print("[worker] 使用预设 Token跳过登录", flush=True)
for model_id in ALL_MODEL_IDS: for model_id in ALL_MODEL_IDS:
if _shutdown.is_set(): if _shutdown.is_set():
break break
ok, task_id = _submit_task(token, model_id) if submit_task(model_id):
if ok:
_state["submitted"] += 1 _state["submitted"] += 1
successful.append((task_id, model_id)) successful.append(model_id)
else: else:
_state["failed"] += 1 _state["failed"] += 1
# 写入结果文件 # 写入结果文件
try: try:
with open("submitted_validation_tasks.txt", "w", encoding="utf-8") as f: with open("submitted_adapt_tasks.txt", "w", encoding="utf-8") as f:
for tid, mid in successful: for mid in successful:
f.write(f"{tid}\t{mid}\n") f.write(f"{mid}\n")
except Exception: except Exception:
pass pass
_state["finished_at"] = datetime.utcnow().isoformat() _state["finished_at"] = datetime.utcnow().isoformat()
_state["phase"] = "done" _state["phase"] = "done"
print( print(
f"[worker] 完成 submitted={_state['submitted']} failed={_state['failed']}", f"[worker] 完成 submitted={_state['submitted']} failed={_state['failed']} total={_state['total']}",
flush=True, flush=True,
) )
# 提交完成后继续保持进程存活,等待平台停止 # 提交完成后继续保持进程存活,等待平台停止