139 lines
5.9 KiB
Python
139 lines
5.9 KiB
Python
"""ModelHub XC 适配智能体 · 只读探针 + 容器内提交测试 v1.0.2
|
|
|
|
关键实验:在容器里用注入的 EXTERNAL_SERVICE_TOKEN(=tmp) + STRATEGY_ID 真调一次 task/add,
|
|
验证平台是否靠「请求来自容器 pod」放行智能体提交(浏览器/脚本提交会被 60014 挡)。
|
|
|
|
诊断输出:
|
|
- dump 所有 env 的名字+长度(不打值)。
|
|
- EXTERNAL_SERVICE_TOKEN 值(短则原样、长则打码)。
|
|
- 容器内 build-config + task/add(真实模型) 的返回 code/msg。
|
|
|
|
约束:token 值不打(短占位除外);只提交这一次测试(真实模型可能进队列);SIGTERM 优雅停机。
|
|
"""
|
|
import json
|
|
import os
|
|
import signal
|
|
import threading
|
|
import time
|
|
import urllib.error
|
|
import urllib.request
|
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
|
|
MAIN = os.getenv("MAIN_HOST", "https://modelhub.org.cn")
|
|
TOKEN = os.getenv("EXTERNAL_SERVICE_TOKEN", "")
|
|
STRATEGY_ID = os.getenv("STRATEGY_ID", "")
|
|
PORT = int(os.getenv("PORT", "8080"))
|
|
|
|
TEST_MODEL = os.getenv("TEST_MODEL", "https://www.modelscope.cn/models/mradermacher/TrialSpace-1225-GGUF")
|
|
GPU, FW, TT = os.getenv("GPU", "MetaX_c-500"), os.getenv("FW", "vllm"), os.getenv("TT", "text-generation")
|
|
|
|
HARDCODED_CFG = (
|
|
"framework: vllm\napi: completion\nlang: en\nmax_model_len: 4096\nmax_tokens: 1024\n"
|
|
"temperature: 0.7\nrepetition_penalty: 1.1\ntop_p: 0.9\nsut_config:\n gpu_num: 1\n values:\n"
|
|
" command:\n - /opt/conda/bin/vllm\n - serve\n - /model\n - --port\n - '20644'\n"
|
|
" - --served-model-name\n - llm\n - --max-model-len\n - '4096'\n"
|
|
" - --gpu-memory-utilization\n - '0.9'\n - -tp\n - '1'\n - --enforce-eager\n"
|
|
" - --trust-remote-code\nref_config:\n gpu_num: 1\n values:\n command:\n - vllm\n"
|
|
" - serve\n - /model\n - --port\n - '80'\n - --served-model-name\n - llm\n"
|
|
" - --max-model-len\n - '4096'\n - -tp\n - '1'\n - --enforce-eager\n - --trust-remote-code\n"
|
|
)
|
|
|
|
shutdown = threading.Event()
|
|
PROBE = {"done": False, "results": []}
|
|
|
|
|
|
def log(msg: str) -> None:
|
|
print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}", flush=True)
|
|
|
|
|
|
def _mask(v: str) -> str:
|
|
return v if len(v) <= 8 else (v[:2] + "…" + v[-2:])
|
|
|
|
|
|
def _req(method: str, path: str, headers: dict, body=None, timeout: int = 30) -> dict:
|
|
data = body.encode() if isinstance(body, str) else body
|
|
req = urllib.request.Request(MAIN + path, data=data, method=method, headers=headers)
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=timeout) as r:
|
|
txt = r.read().decode("utf-8", "ignore")
|
|
status = r.status
|
|
except urllib.error.HTTPError as e:
|
|
txt = e.read().decode("utf-8", "ignore")
|
|
status = e.code
|
|
except Exception as e: # noqa: BLE001
|
|
return {"http": -1, "err": str(e)[:100]}
|
|
try:
|
|
j = json.loads(txt)
|
|
return {"http": status, "code": j.get("code"), "msg": (j.get("message") or "")[:100],
|
|
"data": j.get("data")}
|
|
except Exception: # noqa: BLE001
|
|
return {"http": status, "raw": txt[:100]}
|
|
|
|
|
|
def probe() -> None:
|
|
env_lens = {k: len(str(os.environ.get(k, ""))) for k in sorted(os.environ)}
|
|
log("env keys+lens: " + json.dumps(env_lens, ensure_ascii=False))
|
|
log(f"strategy_id={STRATEGY_ID or 'MISSING'} | EXTERNAL_SERVICE_TOKEN value={_mask(TOKEN)!r} len={len(TOKEN)}")
|
|
|
|
# 只读:token 有效性
|
|
page = _req("GET", "/api/adapt/task/page?current=1&pageSize=1", {"Xc-Token": TOKEN})
|
|
log("EST-token task/page -> " + json.dumps({k: page.get(k) for k in ("http", "code")}, ensure_ascii=False))
|
|
|
|
# 关键:容器内 build-config + task/add(真实模型)
|
|
bc = _req("POST", f"/api/adapt/task/build-config?gpuType={GPU}&framework={FW}&taskType={TT}", {"Xc-Token": TOKEN})
|
|
log("build-config(EST-token) -> " + json.dumps({k: bc.get(k) for k in ("http", "code", "msg")}, ensure_ascii=False))
|
|
cfg = bc.get("data") if isinstance(bc.get("data"), str) and bc.get("data") else HARDCODED_CFG
|
|
body = json.dumps({"modelAddress": TEST_MODEL, "taskType": TT, "targetGpu": GPU,
|
|
"framework": FW, "strategyId": STRATEGY_ID, "configParams": cfg})
|
|
ta = _req("POST", "/api/adapt/task/add", {"Xc-Token": TOKEN, "Content-Type": "application/json"}, body)
|
|
log("SUBMIT-TEST task/add(EST-token+strategyId, real model) -> " + json.dumps(ta, ensure_ascii=False))
|
|
PROBE["results"] = [{"task_page": page.get("code")}, {"build_config": bc.get("code")},
|
|
{"task_add": ta.get("code"), "msg": ta.get("msg")}]
|
|
PROBE["done"] = True
|
|
log("probe done | task/add code=0 => 容器提交通; 60014 => 容器来源也被判脚本; 401 => token 无效")
|
|
|
|
|
|
class Handler(BaseHTTPRequestHandler):
|
|
def _json(self, obj: dict, status: int = 200) -> None:
|
|
payload = json.dumps(obj, ensure_ascii=False).encode()
|
|
self.send_response(status)
|
|
self.send_header("Content-Type", "application/json")
|
|
self.send_header("Content-Length", str(len(payload)))
|
|
self.end_headers()
|
|
self.wfile.write(payload)
|
|
|
|
def do_GET(self) -> None:
|
|
if self.path == "/health":
|
|
self._json({"status": "ok"})
|
|
return
|
|
if self.path == "/":
|
|
self._json({"name": "huni-probe-agent", "mode": "submit-test-v1.0.2", "probe": PROBE})
|
|
return
|
|
self._json({"error": "not found"}, 404)
|
|
|
|
def log_message(self, *_a) -> None:
|
|
pass
|
|
|
|
|
|
def _handle_signal(signum: int, _frame) -> None:
|
|
shutdown.set()
|
|
log(f"received signal {signum}, shutting down")
|
|
|
|
|
|
def main() -> None:
|
|
signal.signal(signal.SIGTERM, _handle_signal)
|
|
signal.signal(signal.SIGINT, _handle_signal)
|
|
threading.Thread(target=probe, daemon=True).start()
|
|
|
|
server = ThreadingHTTPServer(("0.0.0.0", PORT), Handler)
|
|
server.timeout = 1
|
|
log(f"probe agent v1.0.2 listening on 0.0.0.0:{PORT}")
|
|
while not shutdown.is_set():
|
|
server.handle_request()
|
|
server.server_close()
|
|
log("stopped")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|