feat(tuning): release V0.8.2 Agent 界面重构
This commit is contained in:
@@ -148,6 +148,8 @@ class TuningManagerTest(unittest.TestCase):
|
||||
self.fail("session did not wait for approval")
|
||||
proposal = detail["proposals"][-1]
|
||||
patch = {"weights": {"pose": 1.1}, "params": {}}
|
||||
with self.assertRaisesRegex(Exception, "feedback"):
|
||||
self.manager.approve(session["id"], proposal["id"], {"feedback": {}})
|
||||
approved = self.manager.approve(
|
||||
session["id"], proposal["id"], {"feedback": "ok", "patch": patch}
|
||||
)
|
||||
@@ -155,6 +157,34 @@ class TuningManagerTest(unittest.TestCase):
|
||||
self.manager.cancel(session["id"])
|
||||
self.assertEqual(self.wait_terminal(session["id"])["state"], "cancelled")
|
||||
|
||||
def test_runtime_mode_switch_auto_approves_pending_proposal(self):
|
||||
session = self.manager.create(self.payload("approval"))
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
if detail["state"] == "awaiting_approval":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("session did not wait for approval")
|
||||
changed = self.manager.set_mode(session["id"], {"mode": "automatic"})
|
||||
self.assertEqual(changed["mode"], "automatic")
|
||||
self.assertEqual(changed["proposals"][-1]["state"], "approved")
|
||||
completed = self.wait_terminal(session["id"])
|
||||
self.assertEqual(completed["state"], "succeeded", completed["message"])
|
||||
|
||||
def test_trial_count_is_user_configurable(self):
|
||||
payload = self.payload()
|
||||
payload["trialCount"] = 1
|
||||
_, config, _, _ = self.manager.parse_create(payload)
|
||||
self.assertEqual(config["trialCount"], 1)
|
||||
payload["trialCount"] = 100
|
||||
_, config, _, _ = self.manager.parse_create(payload)
|
||||
self.assertEqual(config["trialCount"], 100)
|
||||
payload["trialCount"] = 101
|
||||
with self.assertRaisesRegex(Exception, "trialCount"):
|
||||
self.manager.parse_create(payload)
|
||||
|
||||
def test_resume_discards_only_interrupted_trial_and_continues(self):
|
||||
mode, config, objective, fallback = self.manager.parse_create(self.payload())
|
||||
session = self.manager.storage.create_session(mode, config, objective, fallback)
|
||||
@@ -178,8 +208,10 @@ class TuningManagerTest(unittest.TestCase):
|
||||
"trial-001-rung-0",
|
||||
)
|
||||
self.manager.storage.update_trial(interrupted["id"], state="interrupted")
|
||||
self.manager.storage.reset_step_gate(session["id"])
|
||||
self.manager.storage.update_session(session["id"], state="interrupted")
|
||||
self.manager.resume(session["id"])
|
||||
self.assertEqual(self.manager.storage.get_control(session["id"])["runPolicy"], "continuous")
|
||||
completed = self.wait_terminal(session["id"])
|
||||
self.assertEqual(completed["state"], "succeeded", completed["message"])
|
||||
self.assertNotIn(interrupted["id"], [trial["id"] for trial in completed["trials"]])
|
||||
@@ -190,6 +222,129 @@ class TuningManagerTest(unittest.TestCase):
|
||||
self.manager.parse_create({"taskId": "Other"})
|
||||
self.assertEqual(self.manager.test_agent()["model"], "fake")
|
||||
|
||||
def test_pause_closes_persistent_dispatch_gate_at_trial_boundary(self):
|
||||
mode, config, objective, fallback = self.manager.parse_create(self.payload())
|
||||
session = self.manager.storage.create_session(mode, config, objective, fallback)
|
||||
self.manager.storage.update_session(session["id"], state="running")
|
||||
self.manager.storage.grant_dispatch_token(session["id"])
|
||||
|
||||
paused = self.manager.pause(session["id"])
|
||||
|
||||
self.assertEqual(paused["state"], "paused")
|
||||
self.assertEqual(paused["control"]["runPolicy"], "step")
|
||||
self.assertEqual(paused["control"]["dispatchTokens"], 0)
|
||||
|
||||
def test_step_token_executes_exactly_one_trial_then_pauses(self):
|
||||
session = self.manager.create(self.payload("approval"))
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
if detail["state"] == "awaiting_approval":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("session did not wait for approval")
|
||||
baseline_count = len([trial for trial in detail["trials"] if trial["state"] == "completed"])
|
||||
stepped = self.manager.step(session["id"], {"count": 1})
|
||||
self.assertEqual(stepped["control"]["runPolicy"], "step")
|
||||
self.assertEqual(stepped["control"]["dispatchTokens"], 1)
|
||||
proposal = stepped["proposals"][-1]
|
||||
self.manager.approve(session["id"], proposal["id"], {})
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
completed_count = len(
|
||||
[trial for trial in detail["trials"] if trial["state"] == "completed"]
|
||||
)
|
||||
if detail["state"] == "paused" and completed_count == baseline_count + 1:
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("single-step trial did not pause at the next boundary")
|
||||
time.sleep(0.05)
|
||||
self.assertEqual(
|
||||
len(
|
||||
[
|
||||
trial
|
||||
for trial in self.manager.detail(session["id"])["trials"]
|
||||
if trial["state"] == "completed"
|
||||
]
|
||||
),
|
||||
baseline_count + 1,
|
||||
)
|
||||
self.manager.cancel(session["id"])
|
||||
self.assertEqual(self.wait_terminal(session["id"])["state"], "cancelled")
|
||||
|
||||
def test_constraints_are_revisioned_and_enforced_during_approval(self):
|
||||
session = self.manager.create(self.payload("approval"))
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
if detail["state"] == "awaiting_approval":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("session did not wait for approval")
|
||||
proposal = detail["proposals"][-1]
|
||||
constrained = self.manager.set_constraints(
|
||||
session["id"],
|
||||
{
|
||||
"revision": 0,
|
||||
"constraints": {"weights.track_linear_velocity": {"kind": "fixed", "value": 1.0}},
|
||||
},
|
||||
)
|
||||
self.assertEqual(constrained["control"]["constraintsRevision"], 1)
|
||||
with self.assertRaisesRegex(Exception, "已固定"):
|
||||
self.manager.approve(
|
||||
session["id"],
|
||||
proposal["id"],
|
||||
{"patch": {"weights": {"track_linear_velocity": 1.1}, "params": {}}},
|
||||
)
|
||||
with self.assertRaisesRegex(Exception, "revision"):
|
||||
self.manager.set_constraints(session["id"], {"revision": 0, "constraints": {}})
|
||||
self.manager.approve(session["id"], proposal["id"], {})
|
||||
self.manager.cancel(session["id"])
|
||||
self.assertEqual(self.wait_terminal(session["id"])["state"], "cancelled")
|
||||
|
||||
def test_rollback_uses_safe_completed_trial_as_next_proposal_base(self):
|
||||
session = self.manager.create(self.payload("approval"))
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
if detail["state"] == "awaiting_approval":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("session did not wait for approval")
|
||||
baseline = detail["trials"][0]
|
||||
old_proposal = detail["proposals"][-1]
|
||||
rolled_back = self.manager.rollback(
|
||||
session["id"], {"trialId": baseline["id"], "checkpoint": True}
|
||||
)
|
||||
self.assertEqual(rolled_back["state"], "paused")
|
||||
self.assertEqual(rolled_back["control"]["activeBaseTrialId"], baseline["id"])
|
||||
self.assertEqual(
|
||||
next(item for item in rolled_back["proposals"] if item["id"] == old_proposal["id"])[
|
||||
"state"
|
||||
],
|
||||
"rejected",
|
||||
)
|
||||
self.manager.step(session["id"], {"count": 1})
|
||||
deadline = time.monotonic() + 3
|
||||
while time.monotonic() < deadline:
|
||||
detail = self.manager.detail(session["id"])
|
||||
if (
|
||||
detail["state"] == "awaiting_approval"
|
||||
and detail["proposals"][-1]["id"] != old_proposal["id"]
|
||||
):
|
||||
break
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
self.fail("rollback base did not produce a replacement proposal")
|
||||
self.assertEqual(detail["proposals"][-1]["baseTrialId"], baseline["id"])
|
||||
self.manager.cancel(session["id"])
|
||||
self.assertEqual(self.wait_terminal(session["id"])["state"], "cancelled")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user