feat: make model age admission-only
This commit is contained in:
@@ -215,21 +215,21 @@ def make_candidate(index: int) -> dict:
|
||||
|
||||
|
||||
class ClientPoolConcurrencyTests(unittest.TestCase):
|
||||
def test_old_models_reserve_each_accounts_last_ten_queue_positions(self) -> None:
|
||||
below_threshold = FakeClient(active_count=89)
|
||||
at_threshold = FakeClient(active_count=90)
|
||||
def test_old_models_use_another_account_and_reserve_last_five_positions(self) -> None:
|
||||
below_threshold = FakeClient(active_count=94)
|
||||
at_threshold = FakeClient(active_count=95)
|
||||
pool = ModelHubClientPool(
|
||||
[below_threshold, at_threshold], # type: ignore[list-item]
|
||||
active_task_cap=100,
|
||||
active_counts_ttl=60,
|
||||
recent_model_reserve_slots=10,
|
||||
recent_model_reserve_slots=5,
|
||||
recent_model_days=7,
|
||||
instance_id="old-model-threshold-test",
|
||||
)
|
||||
submitted_at = datetime(2026, 8, 11, tzinfo=timezone.utc)
|
||||
|
||||
pool.add_task_for_model(
|
||||
{"model": "old-allowed-as-position-90"},
|
||||
{"model": "old-allowed-as-position-95"},
|
||||
model_last_modified=datetime(2026, 7, 1, tzinfo=timezone.utc),
|
||||
submitted_at=submitted_at,
|
||||
)
|
||||
@@ -251,13 +251,13 @@ class ClientPoolConcurrencyTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(2, len(below_threshold.submitted) + len(at_threshold.submitted))
|
||||
|
||||
def test_concurrent_old_model_submissions_cannot_enter_reserved_ten_slots(self) -> None:
|
||||
client = FakeClient(active_count=88)
|
||||
def test_concurrent_old_model_submissions_cannot_enter_reserved_five_slots(self) -> None:
|
||||
client = FakeClient(active_count=93)
|
||||
pool = ModelHubClientPool(
|
||||
[client], # type: ignore[list-item]
|
||||
active_task_cap=100,
|
||||
active_counts_ttl=60,
|
||||
recent_model_reserve_slots=10,
|
||||
recent_model_reserve_slots=5,
|
||||
recent_model_days=7,
|
||||
)
|
||||
submitted_at = datetime(2026, 8, 11, tzinfo=timezone.utc)
|
||||
@@ -295,11 +295,11 @@ class ClientPoolConcurrencyTests(unittest.TestCase):
|
||||
self.assertTrue(all(stage["updatedAfter"] >= now - timedelta(days=7) for stage in stages))
|
||||
|
||||
def test_submit_candidate_reports_old_model_policy_skip_at_dynamic_threshold(self) -> None:
|
||||
client = FakeClient(active_count=90)
|
||||
client = FakeClient(active_count=95)
|
||||
pool = ModelHubClientPool(
|
||||
[client], # type: ignore[list-item]
|
||||
active_task_cap=100,
|
||||
recent_model_reserve_slots=10,
|
||||
recent_model_reserve_slots=5,
|
||||
recent_model_days=7,
|
||||
)
|
||||
result = submit_candidate(
|
||||
@@ -315,25 +315,118 @@ class ClientPoolConcurrencyTests(unittest.TestCase):
|
||||
pool, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
self.assertEqual("old_model_policy_skipped", result["outcome"])
|
||||
self.assertEqual("age_policy_deferred", result["outcome"])
|
||||
self.assertEqual("age_policy_skipped", result["reason"])
|
||||
self.assertEqual([], client.submitted)
|
||||
|
||||
def test_old_model_threshold_tracks_a_discovered_capacity_increase(self) -> None:
|
||||
client = DynamicCapacityClient(active=100, limit=101)
|
||||
def test_age_policy_deferred_candidate_is_skipped_not_failed(self) -> None:
|
||||
class AdmissionRaceClient:
|
||||
@staticmethod
|
||||
def begin_cycle() -> None:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def old_model_submit_slots() -> int:
|
||||
return 1
|
||||
|
||||
@staticmethod
|
||||
def old_model_queue_thresholds() -> list[int]:
|
||||
return [95]
|
||||
|
||||
@staticmethod
|
||||
def available_submit_slots() -> int:
|
||||
return 1
|
||||
|
||||
@staticmethod
|
||||
def processed_gpus_for_model(_model_id: str) -> set[str]:
|
||||
return set()
|
||||
|
||||
@staticmethod
|
||||
def list_tasks_page(**_kwargs) -> dict: # noqa: ANN003
|
||||
return {"code": 0, "data": {"records": [], "pages": 0}}
|
||||
|
||||
@staticmethod
|
||||
def add_task_for_model(*_args, **_kwargs) -> dict: # noqa: ANN002, ANN003
|
||||
raise OldModelQueuePolicyError("old-model capacity filled during submission")
|
||||
|
||||
with tempfile.TemporaryDirectory() as temporary_dir:
|
||||
root = Path(temporary_dir)
|
||||
args = build_parser().parse_args(
|
||||
[
|
||||
"--gpus",
|
||||
"Iluvatar_bi-150",
|
||||
"--task-types",
|
||||
"text-generation",
|
||||
"--limit",
|
||||
"1",
|
||||
"--max-scan-models",
|
||||
"1",
|
||||
"--skip-outcome-sync",
|
||||
"--skip-history-archive",
|
||||
"--disable-candidate-preflight",
|
||||
"--disable-gpu-strategy",
|
||||
"--disable-market-intelligence",
|
||||
]
|
||||
)
|
||||
args.runs_dir = str(root / "runs")
|
||||
args.ledger_path = str(root / "ledger.jsonl")
|
||||
args.outcomes_path = str(root / "outcomes.jsonl")
|
||||
args.claims_path = str(root / "claims.jsonl")
|
||||
args.history_archive_path = str(root / "history.jsonl")
|
||||
args.submission_exclusions_path = str(root / "exclusions.jsonl")
|
||||
client = AdmissionRaceClient()
|
||||
|
||||
summary = run_submission(
|
||||
args,
|
||||
now=datetime(2026, 2, 1, tzinfo=timezone.utc),
|
||||
hf_discovery=FakeDiscovery(1), # type: ignore[arg-type]
|
||||
modelhub_client=client, # type: ignore[arg-type]
|
||||
template_selector=TemplateSelector(),
|
||||
)
|
||||
|
||||
self.assertEqual(0, summary["submittedCount"])
|
||||
self.assertEqual(0, summary["failedCount"])
|
||||
self.assertEqual(1, summary["skipReasonCounts"]["age_policy_skipped"])
|
||||
|
||||
def test_old_model_threshold_tracks_capacity_increase_from_100_to_200(self) -> None:
|
||||
client = DynamicCapacityClient(active=100, limit=200)
|
||||
pool = ModelHubClientPool(
|
||||
[client], # type: ignore[list-item]
|
||||
active_task_cap=100,
|
||||
recent_model_reserve_slots=10,
|
||||
recent_model_reserve_slots=5,
|
||||
capacity_probe_interval_cycles=1,
|
||||
capacity_state_path=None,
|
||||
)
|
||||
|
||||
self.assertEqual([90], pool.old_model_queue_thresholds())
|
||||
pool.configure_capacity_probe(1)
|
||||
pool.add_task({"model": "recent-capacity-probe"})
|
||||
self.assertEqual([100], pool.active_task_counts())
|
||||
self.assertEqual([95], pool.old_model_queue_thresholds())
|
||||
pool.observe_capacity_lower_bounds([200])
|
||||
|
||||
self.assertEqual([101], pool.account_capacity_limits())
|
||||
self.assertEqual([91], pool.old_model_queue_thresholds())
|
||||
self.assertEqual([200], pool.account_capacity_limits())
|
||||
self.assertEqual([195], pool.old_model_queue_thresholds())
|
||||
|
||||
def test_old_model_admission_fails_closed_when_active_count_is_unknown(self) -> None:
|
||||
class UnreadableCountClient(FakeClient):
|
||||
def count_active_tasks(self, **_kwargs) -> int: # noqa: ANN003
|
||||
raise TimeoutError("count unavailable")
|
||||
|
||||
client = UnreadableCountClient(active_count=0)
|
||||
pool = ModelHubClientPool(
|
||||
[client], # type: ignore[list-item]
|
||||
active_task_cap=100,
|
||||
recent_model_reserve_slots=5,
|
||||
capacity_state_path=None,
|
||||
)
|
||||
|
||||
with self.assertRaises(OldModelQueuePolicyError):
|
||||
pool.add_task_for_model(
|
||||
{"model": "old-deferred"},
|
||||
model_last_modified=datetime(2026, 7, 1, tzinfo=timezone.utc),
|
||||
submitted_at=datetime(2026, 8, 11, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
self.assertEqual([None], pool.old_model_queue_thresholds())
|
||||
self.assertEqual([], client.submitted)
|
||||
|
||||
def test_online_submission_does_not_construct_llm_even_when_key_is_present(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temporary_dir:
|
||||
@@ -617,6 +710,8 @@ class ProcessCoordinationTests(unittest.TestCase):
|
||||
"modelId": "owner/old-failure",
|
||||
"targetGpu": "gpu-a",
|
||||
"outcome": "failed",
|
||||
"failureCategory": "model_load",
|
||||
"failureScope": "model_gpu_framework",
|
||||
"submitTime": (now - timedelta(hours=26)).isoformat(),
|
||||
"lastSyncTime": (now - timedelta(hours=25)).isoformat(),
|
||||
},
|
||||
@@ -624,6 +719,8 @@ class ProcessCoordinationTests(unittest.TestCase):
|
||||
"modelId": "owner/recent-failure",
|
||||
"targetGpu": "gpu-a",
|
||||
"outcome": "failed",
|
||||
"failureCategory": "model_load",
|
||||
"failureScope": "model_gpu_framework",
|
||||
"submitTime": (now - timedelta(hours=2)).isoformat(),
|
||||
"lastSyncTime": (now - timedelta(hours=1)).isoformat(),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user