101 lines
3.8 KiB
Python
101 lines
3.8 KiB
Python
"""圆桌后台作业真网关 —— headless 验证脚本(Phase 3b)。
|
|
|
|
用法(在能起完整后端栈 + 配好真模型的环境):
|
|
|
|
1) 用真网关启动后端:
|
|
ROUNDTABLE_JOB_GATEWAY=inprocess make gateway
|
|
(或 docker 里给 gateway 容器加该环境变量)
|
|
|
|
2) 跑本脚本,它会:POST 启动一个作业 → 轮询 GET 打印进度 → 跑到 done 打印报告长度。
|
|
PYTHONPATH=. uv run python scripts/probe_roundtable_job.py
|
|
|
|
环境变量:
|
|
GATEWAY_URL 默认 http://127.0.0.1:8001
|
|
AUTH_COOKIE 若后端开启鉴权,传 "session=xxx" 之类的 Cookie 头
|
|
PROBE_INTENT 自定义任务意图
|
|
PROBE_MODE recommend(默认)| chain
|
|
|
|
说明:鉴权关闭的 dev 模式无需 AUTH_COOKIE。真网关会进程内驱动 roundtable-coordinator /
|
|
各席位 / roundtable-report 真模型,耗时取决于模型,可能数分钟。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import os
|
|
import time
|
|
|
|
import httpx
|
|
|
|
GATEWAY_URL = os.getenv("GATEWAY_URL", "http://127.0.0.1:8001").rstrip("/")
|
|
AUTH_COOKIE = os.getenv("AUTH_COOKIE", "")
|
|
INTENT = os.getenv("PROBE_INTENT", "为一家中型制造企业设计一套数字化转型的整体方案")
|
|
MODE = os.getenv("PROBE_MODE", "recommend")
|
|
|
|
# 用 3 个内置圆桌席位(确保可见、已 seed)。
|
|
AGENTS = [
|
|
{"agentId": "roundtable-intelligence", "name": "情报收集"},
|
|
{"agentId": "roundtable-solution-design", "name": "方案设计"},
|
|
{"agentId": "roundtable-summary", "name": "总结陈述"},
|
|
]
|
|
|
|
TERMINAL = {"done", "error", "cancelled"}
|
|
|
|
|
|
def _headers() -> dict[str, str]:
|
|
h = {"Content-Type": "application/json"}
|
|
if AUTH_COOKIE:
|
|
h["Cookie"] = AUTH_COOKIE
|
|
return h
|
|
|
|
|
|
async def main() -> None:
|
|
async with httpx.AsyncClient(timeout=30.0, trust_env=False) as client:
|
|
print(f"[probe] POST {GATEWAY_URL}/api/roundtable-jobs mode={MODE}")
|
|
resp = await client.post(
|
|
f"{GATEWAY_URL}/api/roundtable-jobs",
|
|
headers=_headers(),
|
|
json={"intent": INTENT, "agents": AGENTS, "orchestrationMode": MODE},
|
|
)
|
|
if resp.status_code != 201:
|
|
print(f"[probe] start failed: HTTP {resp.status_code}: {resp.text[:500]}")
|
|
return
|
|
job = resp.json()
|
|
job_id = job["id"]
|
|
print(f"[probe] started job {job_id}")
|
|
|
|
last = ""
|
|
t0 = time.perf_counter()
|
|
while True:
|
|
await asyncio.sleep(2.0)
|
|
r = await client.get(f"{GATEWAY_URL}/api/roundtable-jobs/{job_id}", headers=_headers())
|
|
if r.status_code != 200:
|
|
print(f"[probe] get failed: HTTP {r.status_code}: {r.text[:300]}")
|
|
return
|
|
j = r.json()
|
|
line = (
|
|
f"status={j['status']} phase={j['phase']} cycle={j['cycle']} "
|
|
f"active={j.get('activeAgentId')} consensus={j['consensusPercentage']}%"
|
|
)
|
|
if line != last:
|
|
print(f"[probe] +{time.perf_counter() - t0:5.0f}s {line}")
|
|
last = line
|
|
if j["status"] in TERMINAL:
|
|
print(f"[probe] terminal: {j['status']}")
|
|
if j["status"] == "error":
|
|
print(f"[probe] error detail: {j.get('error')}")
|
|
# 读草稿 step3 验证报告已落库
|
|
if j.get("draftId"):
|
|
dr = await client.get(
|
|
f"{GATEWAY_URL}/api/roundtable-drafts/{j['draftId']}", headers=_headers()
|
|
)
|
|
if dr.status_code == 200:
|
|
step3 = dr.json().get("step3")
|
|
html_len = len((step3 or {}).get("html") or "")
|
|
print(f"[probe] draft.step3 html length = {html_len}")
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|