forked from luopingyi/xc_agent_platform_demo
- Overlay ModelHub XC Phase1 (health/status, STRATEGY_ID gate, dry-run) - Dockerfile CMD -> python -m src.server; FROM stays platform TCR base - Remove demo main.py and requirements.txt (stdlib only) - Add tests/, scripts/, docs/, Makefile, config/examples (no secrets)
108 lines
4.1 KiB
Python
Executable File
108 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Generate a dry-run adaptation report (no platform side effects).
|
||
|
||
Reads config/candidates.example.json (or DRY_RUN_CANDIDATES path).
|
||
Writes reports/dry-run-<Asia/Shanghai-timestamp>.md
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import os
|
||
import sys
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
from zoneinfo import ZoneInfo
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
TZ = ZoneInfo("Asia/Shanghai")
|
||
|
||
|
||
def _load_candidates(path: Path) -> list[dict]:
|
||
data = json.loads(path.read_text(encoding="utf-8"))
|
||
if isinstance(data, list):
|
||
return data
|
||
if isinstance(data, dict) and "candidates" in data:
|
||
return list(data["candidates"])
|
||
raise SystemExit(f"unexpected candidates schema in {path}")
|
||
|
||
|
||
def _render(candidates: list[dict], ts: str, src: Path) -> str:
|
||
lines = [
|
||
f"# Dry-run 适配建议报告 — {ts} (Asia/Shanghai)",
|
||
"",
|
||
"> **模式:dry-run** — 本报告不产生平台侧真实提交。",
|
||
"> **需 Victor 人工提交**:请登录模盒控制台按草稿确认后手工提交。",
|
||
"> **积分:待平台核实**(发布智能体本身不得分;成功适配按账本计)。",
|
||
"",
|
||
"## 闸门状态",
|
||
"",
|
||
f"- ALLOW_LIVE_SUBMIT is 1: {os.environ.get('ALLOW_LIVE_SUBMIT', '0').strip() == '1'}",
|
||
f"- LIVE_CONFIRM set: {'yes' if os.environ.get('LIVE_CONFIRM', '').strip() else 'no'}",
|
||
f"- STRATEGY_ID present: {'yes' if os.environ.get('STRATEGY_ID', '').strip() else 'no'}",
|
||
"",
|
||
"## 输入",
|
||
"",
|
||
f"- 候选文件:`{src}`",
|
||
f"- 候选条数:{len(candidates)}",
|
||
"",
|
||
"## 建议草稿(字段示意,非真实 POST)",
|
||
"",
|
||
]
|
||
for i, c in enumerate(candidates, 1):
|
||
model = c.get("modelAddress") or c.get("model_id") or "(missing model_id)"
|
||
lines.append(f"### {i}. `{model}`")
|
||
lines.append("")
|
||
lines.append("```json")
|
||
draft = {
|
||
"modelAddress": model,
|
||
"taskType": c.get("taskType", "text-generation"),
|
||
"targetGpu": c.get("targetGpu", "(unset)"),
|
||
"framework": c.get("framework", "(unset)"),
|
||
"strategyId": "<PLATFORM_INJECTED_STRATEGY_ID>",
|
||
"configParams": "<from build-config — not fetched in Phase1 dry-run>",
|
||
"notes": c.get("notes", ""),
|
||
}
|
||
lines.append(json.dumps(draft, ensure_ascii=False, indent=2))
|
||
lines.append("```")
|
||
lines.append("")
|
||
lines.append("- 风险:Phase1 未做唯一性/硬门预检;提交前请对照 do-not-resubmit 与队列空位。")
|
||
lines.append("- **需 Victor 人工提交**(或经双重闸门的受控 live;本骨架默认拒绝 live)。")
|
||
lines.append("- **积分:待平台核实**")
|
||
lines.append("")
|
||
lines.extend(
|
||
[
|
||
"## 后续对接(Phase2)",
|
||
"",
|
||
"- **待对接 pending-submit**:尚未读取 `/workspace/modelhub-adapt/pending-submit.md`,未验证 A→B、PASS、硬门与 do-not-resubmit;本报告仅保留输入顺序。",
|
||
"- 适配 W1 优先;同一 100 队列,≥95 全体停交;空位先 A 再 B,人工核验后决定,不凭示例报告提交。",
|
||
"- 禁止 Makefile / 脚本调用 `/api/adapt/task/add` 或 `/agent_platform/strategies*` 写接口。",
|
||
"",
|
||
]
|
||
)
|
||
return "\n".join(lines)
|
||
|
||
|
||
def main() -> None:
|
||
src = Path(
|
||
os.environ.get(
|
||
"DRY_RUN_CANDIDATES",
|
||
str(ROOT / "config" / "candidates.example.json"),
|
||
)
|
||
)
|
||
if not src.is_file():
|
||
raise SystemExit(f"candidates file not found: {src}")
|
||
|
||
candidates = _load_candidates(src)
|
||
now = datetime.now(TZ)
|
||
ts = now.strftime("%Y%m%d-%H%M%S")
|
||
out_dir = ROOT / "reports"
|
||
out_dir.mkdir(parents=True, exist_ok=True)
|
||
out_path = out_dir / f"dry-run-{ts}.md"
|
||
out_path.write_text(_render(candidates, now.strftime("%Y-%m-%d %H:%M:%S"), src), encoding="utf-8")
|
||
print(f"Wrote {out_path}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|