feat: compact durable logs and refine framework routing
This commit is contained in:
@@ -31,7 +31,7 @@ DEFAULT_OUTCOME_CHECKPOINT_PATH = Path(".modelhub_state/outcome_checkpoint.json"
|
||||
DEFAULT_RECENT_OUTCOMES_PATH = Path(".modelhub_state/recent_outcomes.jsonl")
|
||||
DEFAULT_ARCHIVE_PENDING_DIR = Path(".modelhub_state/archive_pending/outcomes")
|
||||
OUTCOME_CHECKPOINT_VERSION = 1
|
||||
DEFAULT_OUTCOME_COMPACT_THRESHOLD = 2000
|
||||
DEFAULT_OUTCOME_COMPACT_THRESHOLD = 1000
|
||||
DEFAULT_RECENT_OUTCOME_LIMIT = 1000
|
||||
FAILURE_ENRICHMENT_LIMIT = 40
|
||||
FAILURE_ENRICHMENT_WORKERS = 4
|
||||
@@ -215,6 +215,25 @@ class OutcomeTracker:
|
||||
}
|
||||
return contexts
|
||||
|
||||
def merge_task_contexts(self, contexts: dict[str, dict[str, Any]] | None) -> int:
|
||||
"""Repair framework/profile fields omitted by the platform history API."""
|
||||
if not isinstance(contexts, dict):
|
||||
return 0
|
||||
changed = 0
|
||||
for task_id, context in contexts.items():
|
||||
record = self._by_task_id.get(str(task_id))
|
||||
if record is None or not isinstance(context, dict):
|
||||
continue
|
||||
before = json.dumps(record, ensure_ascii=False, sort_keys=True)
|
||||
self._merge_record_metadata(record, self._enrich_history_task({}, context))
|
||||
if json.dumps(record, ensure_ascii=False, sort_keys=True) != before:
|
||||
changed += 1
|
||||
if changed:
|
||||
write_jsonl(self.recent_path, self._recent_records)
|
||||
self._rebuild_indexes()
|
||||
self.save()
|
||||
return changed
|
||||
|
||||
def get_strategy_history_records(self) -> list[dict[str, Any]]:
|
||||
"""Expose only successes and evidence-attributable failures for GPU ranking."""
|
||||
records: list[dict[str, Any]] = []
|
||||
@@ -331,7 +350,12 @@ class OutcomeTracker:
|
||||
self._rebuild_failed_index()
|
||||
return marked
|
||||
|
||||
def sync_from_api(self, client: ModelHubClient | ModelHubClientPool) -> int:
|
||||
def sync_from_api(
|
||||
self,
|
||||
client: ModelHubClient | ModelHubClientPool,
|
||||
*,
|
||||
task_contexts: dict[str, dict[str, Any]] | None = None,
|
||||
) -> int:
|
||||
try:
|
||||
begin = self._last_sync_time
|
||||
end = utc_now()
|
||||
@@ -350,13 +374,32 @@ class OutcomeTracker:
|
||||
if not task_id:
|
||||
continue
|
||||
|
||||
task = self._enrich_history_task(task, (task_contexts or {}).get(task_id))
|
||||
|
||||
existing = self._by_task_id.get(task_id)
|
||||
if existing is not None:
|
||||
metadata_before = (
|
||||
existing.get("modelId"),
|
||||
existing.get("targetGpu"),
|
||||
existing.get("framework"),
|
||||
existing.get("taskType"),
|
||||
existing.get("modelProfile"),
|
||||
)
|
||||
self._merge_record_metadata(existing, task)
|
||||
metadata_changed = metadata_before != (
|
||||
existing.get("modelId"),
|
||||
existing.get("targetGpu"),
|
||||
existing.get("framework"),
|
||||
existing.get("taskType"),
|
||||
existing.get("modelProfile"),
|
||||
)
|
||||
if existing.get("outcome") in {"pending", "policy_cancelled"}:
|
||||
self._update_record_from_task(existing, task)
|
||||
if existing.get("outcome") == "failed" and existing.get("logCosUrl"):
|
||||
enrichment_candidates.append(existing)
|
||||
updated_count += 1
|
||||
elif metadata_changed:
|
||||
updated_count += 1
|
||||
else:
|
||||
status = str(task.get("status") or "").lower()
|
||||
if status in TERMINAL_TASK_STATUSES:
|
||||
@@ -393,6 +436,7 @@ class OutcomeTracker:
|
||||
if updated_count or enrichment_attempts:
|
||||
self._last_sync_time = end
|
||||
self._rebuild_failed_index()
|
||||
write_jsonl(self.recent_path, self._recent_records)
|
||||
self.save()
|
||||
|
||||
return updated_count
|
||||
@@ -630,6 +674,18 @@ class OutcomeTracker:
|
||||
now = now or utc_now()
|
||||
return failed_at >= now - timedelta(hours=max(0, int(cooldown_hours)))
|
||||
|
||||
def has_non_transformers_failure(self, model_id: str) -> bool:
|
||||
"""Return platform evidence that unlocks prerequisite-gated transformers."""
|
||||
for record in [*self._recent_records, *self._records]:
|
||||
if str(record.get("modelId") or "") != str(model_id):
|
||||
continue
|
||||
if record.get("outcome") != "failed":
|
||||
continue
|
||||
framework = str(record.get("framework") or "").strip().casefold()
|
||||
if framework and framework != "transformers":
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_stats_report(self) -> dict[str, Any]:
|
||||
now_datetime = utc_now()
|
||||
now = now_datetime.isoformat()
|
||||
|
||||
Reference in New Issue
Block a user