2026-10-20 13:45:33 +08:00
|
|
|
|
"""ModelHub XC 适配智能体 —— 低排队算力批次(5 条)
|
2026-10-20 10:03:55 +08:00
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
每条任务分配一张低排队算力卡,并选用该卡历史通过率较高的框架。
|
|
|
|
|
|
OSP 系列 max_position_embeddings=2048,配置里的 max_model_len 已由 4096 下调为 2048。
|
2026-10-20 10:03:55 +08:00
|
|
|
|
"""
|
|
|
|
|
|
import json
|
|
|
|
|
|
import os
|
|
|
|
|
|
import signal
|
|
|
|
|
|
import threading
|
|
|
|
|
|
import time
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
|
|
|
|
BASE_URL = os.environ.get("BASE_URL", "https://modelhub.org.cn")
|
|
|
|
|
|
ADD_TASK_ENDPOINT = "/api/adapt/task/add"
|
|
|
|
|
|
XC_TOKEN = os.environ.get("XC_TOKEN", "6616dfe75c874e61987b1f7c908e6d77")
|
|
|
|
|
|
STRATEGY_ID = os.environ.get("STRATEGY_ID", "")
|
2026-10-20 13:45:33 +08:00
|
|
|
|
TASK_TYPE = "text-generation"
|
2026-10-20 10:10:15 +08:00
|
|
|
|
|
|
|
|
|
|
TASKS = [
|
|
|
|
|
|
{
|
2026-10-22 09:59:32 +08:00
|
|
|
|
"label": "OSP-1.4B-100B-Muon-SSNorm-EmbProj",
|
|
|
|
|
|
"model": "https://www.modelscope.cn/models/dmis-lab/OSP-1.4B-100B-Muon-SSNorm-EmbProj",
|
|
|
|
|
|
"gpu": "Biren_166m",
|
2026-10-20 13:45:33 +08:00
|
|
|
|
"framework": "vllm_fix_tokenizer",
|
|
|
|
|
|
"config": "framework: vllm_fix_tokenizer\nlang: en\nmax_model_len: 2048\nsut_config:\n gpu_num: 1\n values:\n command:\n - /opt/entrypoint.sh - /model\n - --port\n - '80'\n - --served-model-name\n - llm\n - --max-model-len\n - '2048'\n - --enforce-eager\n - --trust-remote-code\n - -tp\n - '1'\nref_config:\n gpu_num: 1\n values:\n command:\n - /opt/entrypoint.sh - /model\n - --port\n - '80'\n - --served-model-name\n - llm\n - --max-model-len\n - '2048'\n - --enforce-eager\n - --trust-remote-code\n - -tp\n - '1'"
|
|
|
|
|
|
}
|
2026-10-20 10:10:15 +08:00
|
|
|
|
]
|
2026-10-20 10:03:55 +08:00
|
|
|
|
|
|
|
|
|
|
HEADERS = {"Content-Type": "application/json", "Xc-Token": XC_TOKEN}
|
|
|
|
|
|
HTTP_HOST, HTTP_PORT = "0.0.0.0", 8080
|
2026-10-20 13:45:33 +08:00
|
|
|
|
GAP = 4
|
2026-10-20 10:03:55 +08:00
|
|
|
|
_shutdown = threading.Event()
|
2026-10-20 13:45:33 +08:00
|
|
|
|
_state = {"phase": "starting", "total": len(TASKS), "submitted": 0, "failed": 0, "results": []}
|
2026-10-20 10:03:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
def submit_one(t):
|
|
|
|
|
|
body = {
|
|
|
|
|
|
"configParams": t["config"],
|
|
|
|
|
|
"framework": t["framework"],
|
|
|
|
|
|
"modelAddress": t["model"],
|
|
|
|
|
|
"targetGpu": t["gpu"],
|
2026-10-20 10:03:55 +08:00
|
|
|
|
"taskType": TASK_TYPE,
|
|
|
|
|
|
"strategyId": STRATEGY_ID,
|
|
|
|
|
|
}
|
2026-10-20 10:10:15 +08:00
|
|
|
|
try:
|
2026-10-20 13:45:33 +08:00
|
|
|
|
r = requests.post(BASE_URL + ADD_TASK_ENDPOINT, headers=HEADERS, json=body, timeout=90)
|
|
|
|
|
|
j = r.json()
|
2026-10-20 10:10:15 +08:00
|
|
|
|
except Exception as e: # noqa: BLE001
|
2026-10-20 13:45:33 +08:00
|
|
|
|
j = {"code": -1, "message": "exception: %s" % e}
|
|
|
|
|
|
tid = (j.get("data") or {}).get("id")
|
|
|
|
|
|
print("[submit] %s gpu=%s fw=%s code=%s msg=%s taskId=%s"
|
|
|
|
|
|
% (t["label"], t["gpu"], t["framework"], j.get("code"), j.get("message"), tid), flush=True)
|
|
|
|
|
|
return j.get("code"), tid
|
2026-10-20 10:10:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
def run():
|
2026-10-20 10:03:55 +08:00
|
|
|
|
_state["phase"] = "submitting"
|
2026-10-20 13:45:33 +08:00
|
|
|
|
for i, t in enumerate(TASKS, 1):
|
2026-10-20 10:03:55 +08:00
|
|
|
|
if _shutdown.is_set():
|
|
|
|
|
|
break
|
2026-10-20 13:45:33 +08:00
|
|
|
|
code, tid = submit_one(t)
|
|
|
|
|
|
_state["results"].append({"label": t["label"], "gpu": t["gpu"],
|
|
|
|
|
|
"framework": t["framework"], "code": code, "task_id": tid})
|
|
|
|
|
|
_state["submitted" if code == 0 else "failed"] += 1
|
2026-10-20 10:10:15 +08:00
|
|
|
|
if i < len(TASKS):
|
|
|
|
|
|
time.sleep(GAP)
|
|
|
|
|
|
_state["phase"] = "done"
|
2026-10-20 13:45:33 +08:00
|
|
|
|
print("[batch] 完成 submitted=%d failed=%d" % (_state["submitted"], _state["failed"]), flush=True)
|
2026-10-20 10:03:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
class H(BaseHTTPRequestHandler):
|
2026-10-20 10:03:55 +08:00
|
|
|
|
def do_GET(self):
|
|
|
|
|
|
if self.path == "/health":
|
|
|
|
|
|
self._json({"status": "ok"})
|
|
|
|
|
|
elif self.path in ("/", "/status"):
|
|
|
|
|
|
self._json(_state)
|
|
|
|
|
|
else:
|
|
|
|
|
|
self._json({"error": "not found"}, 404)
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
def _json(self, b, c=200):
|
|
|
|
|
|
raw = json.dumps(b, ensure_ascii=False, default=str).encode()
|
|
|
|
|
|
self.send_response(c)
|
2026-10-20 10:03:55 +08:00
|
|
|
|
self.send_header("Content-Type", "application/json")
|
|
|
|
|
|
self.send_header("Content-Length", str(len(raw)))
|
|
|
|
|
|
self.end_headers()
|
|
|
|
|
|
self.wfile.write(raw)
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
def log_message(self, *a):
|
|
|
|
|
|
pass
|
2026-10-20 10:10:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-10-20 10:03:55 +08:00
|
|
|
|
def main():
|
2026-10-20 13:45:33 +08:00
|
|
|
|
signal.signal(signal.SIGTERM, lambda *_: _shutdown.set())
|
2026-10-20 10:10:15 +08:00
|
|
|
|
print("[main] strategy_id=%s tasks=%d" % (STRATEGY_ID, len(TASKS)), flush=True)
|
|
|
|
|
|
for t in TASKS:
|
2026-10-20 13:45:33 +08:00
|
|
|
|
print("[main] 计划: %s @ %s / %s" % (t["label"], t["gpu"], t["framework"]), flush=True)
|
|
|
|
|
|
srv = ThreadingHTTPServer((HTTP_HOST, HTTP_PORT), H)
|
|
|
|
|
|
srv.timeout = 1
|
|
|
|
|
|
threading.Thread(target=run, daemon=True).start()
|
|
|
|
|
|
while not _shutdown.is_set():
|
|
|
|
|
|
srv.handle_request()
|
|
|
|
|
|
srv.server_close()
|
2026-10-20 10:03:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-10-20 13:45:33 +08:00
|
|
|
|
main()
|