forked from luopingyi/xc_agent_platform_demo
89 lines
4.7 KiB
Python
Executable File
89 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Read-only Phase2 pending draft report. Token-resolvable build-config first; explicit sample fallback."""
|
||
import json
|
||
import os
|
||
import sys
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
from zoneinfo import ZoneInfo
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
sys.path.insert(0, str(ROOT))
|
||
from src.pending_pool import build_ordered_candidates, input_path, experience_order
|
||
from src.config_params import build_config_params_with_meta, SOURCE, GAP
|
||
from src.queue_depth import queue_depth
|
||
from src.task_add_client import build_payload
|
||
|
||
TZ = ZoneInfo('Asia/Shanghai')
|
||
|
||
|
||
def _load_candidates(path):
|
||
data = json.loads(path.read_text())
|
||
return data if isinstance(data, list) else list(data['candidates'])
|
||
|
||
|
||
def _render(candidates, ts, src):
|
||
candidates = [c for c in candidates if not os.environ.get('PENDING_SECTION') or
|
||
c.get('section', 'B') == os.environ['PENDING_SECTION'].strip().upper()]
|
||
depth = queue_depth()
|
||
lines = [f'# 代提候选 / 需 Victor 确认 — Dry-run — {ts} (Asia/Shanghai)', '',
|
||
'> 模式:dry-run;仅配置生成 API;无任务提交;需 Victor 人工提交/确认',
|
||
'> 积分:待平台核实', '> perf_order=unset;order_source=experience(经验序 / 待平台核实)',
|
||
f'> configParams source: {SOURCE}', '> API foothold evidence: GAP (not wired)', f'> {GAP}', '',
|
||
'## A→B 顺序草稿', '', f'输入:{src};候选条数:{len(candidates)}',
|
||
f'队列深度:{depth if depth is not None else "未知,需人工确认"}',
|
||
'队列≥95:禁 live;适配 W1 优先,不抢空位。', '']
|
||
if depth is not None and depth >= 95:
|
||
lines.extend(['> **禁 live / 队列≥95**', ''])
|
||
for i, c in enumerate(candidates, 1):
|
||
model = c.get('model_address') or c.get('modelAddress') or c.get('model_id') or '<MODEL>'
|
||
gpus = experience_order(c.get('try_next_gpus', []))
|
||
target = gpus[0] if gpus else c.get('targetGpu', '<TARGET_GPU:需人工确认>')
|
||
status = c.get('status', 'needs_human')
|
||
lines.extend([f'### {i}. Section {c.get("section", "B")} — `{model}`', '',
|
||
f'状态:{status};needs_human={c.get("needs_human", True)}',
|
||
f'过滤:{c.get("skip_reason") or "名称硬门未命中;元数据/唯一性待人工核实"}', ''])
|
||
lines.extend([f'未适配卡(仅 pending 缺口):{", ".join(gpus) or "未提供,需确认"}',
|
||
'perf_order=unset;order_source=experience;天垓100 一般不扇出', ''])
|
||
yaml, meta = build_config_params_with_meta(target)
|
||
lines.extend([f'foothold_class={c.get("foothold_class", "unknown")}; evidence_source={c.get("evidence_source", "GAP")}; no_download={c.get("no_download", False)}',
|
||
'; '.join(f'{key}={value}' for key, value in meta.items()), ''])
|
||
draft = build_payload(model, target, 'vllm', strategy_id='<STRATEGY_ID>',
|
||
config_params=yaml)
|
||
# Display only; this truncated draft must never be submitted.
|
||
draft['configParams'] = draft['configParams'][:400] + '\n… [truncated; dry-run only]'
|
||
lines.extend(['build-config query: gpuType=<targetGpu>&framework=vllm&taskType=text-generation; POST empty body', 'POST 字段草稿(skipped 行禁止提交):', '```json', json.dumps(draft, ensure_ascii=False, indent=2), '```',
|
||
'需 Victor 人工提交/确认;积分:待平台核实', ''])
|
||
report = '\n'.join(lines)
|
||
# Defensive redaction even if an input happens to contain an injected credential.
|
||
secrets = [os.environ.get(k, '') for k in ('XC_TOKEN', 'MODELHUB_XC_TOKEN', 'EXTERNAL_SERVICE_TOKEN', 'Xc-Token')]
|
||
if os.environ.get('XC_TOKEN_FILE'):
|
||
try:
|
||
secrets.append(Path(os.environ['XC_TOKEN_FILE']).read_text().strip())
|
||
except OSError:
|
||
pass
|
||
for secret in secrets:
|
||
if secret:
|
||
report = report.replace(secret, '[REDACTED]')
|
||
return report
|
||
|
||
|
||
def main():
|
||
md = input_path('PENDING_SUBMIT_MD', 'pending-submit.md')
|
||
txt = input_path('PENDING_SUBMIT_TXT', 'pending-submit.txt')
|
||
if md.is_file() or txt.is_file():
|
||
src = md if md.is_file() else txt
|
||
candidates = build_ordered_candidates(md, txt)
|
||
else:
|
||
src = Path(os.environ.get('DRY_RUN_CANDIDATES', ROOT / 'config/candidates.example.json'))
|
||
candidates = _load_candidates(src)
|
||
now = datetime.now(TZ)
|
||
out = ROOT / 'reports' / f'dry-run-{now:%Y%m%d-%H%M%S}.md'
|
||
out.parent.mkdir(exist_ok=True)
|
||
out.write_text(_render(candidates, now.strftime('%Y-%m-%d %H:%M:%S'), src), encoding='utf-8')
|
||
print(f'Wrote {out}')
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|