from __future__ import annotations import re from dataclasses import asdict, dataclass from typing import Iterable @dataclass(frozen=True) class FailureClassification: category: str scope: str action: str deterministic: bool needs_llm: bool reason: str def to_dict(self) -> dict[str, object]: return asdict(self) DETERMINISTIC_POLICIES: dict[str, FailureClassification] = { "PREFLIGHT_OOM": FailureClassification( "memory_capacity", "model_gpu", "reject_if_estimated_load_exceeds_memory", True, False, "structured_oom", ), "MODEL_FILE_NOT_FOUND": FailureClassification( "repository_structure", "model", "require_framework_specific_root_files", True, False, "structured_missing_files", ), "CONTEXT_LENGTH_ERROR": FailureClassification( "context_length", "configuration", "clamp_requested_context_to_model_limit", True, False, "structured_context_limit", ), "DEVICE_OOM": FailureClassification( "runtime_memory", "model_gpu", "lower_memory_risk_or_reject_combination", True, False, "structured_device_oom", ), "STORAGE_ERROR": FailureClassification( "platform_storage", "platform", "retry_later_without_blaming_model", True, False, "structured_storage_error", ), "NO_LOG_PROGRESS": FailureClassification( "platform_stall", "gpu_framework", "open_short_gpu_framework_circuit", True, False, "structured_no_progress", ), } SEMANTIC_POLICIES: dict[str, FailureClassification] = { "MODEL_NOT_SUPPORTED": FailureClassification( "architecture_compatibility", "model_gpu_framework", "consult_profile_history_then_llm", False, True, "framework_version_dependent", ), "MODEL_LOAD_FAILED": FailureClassification( "model_load", "model_gpu_framework", "inspect_root_exception_then_llm_if_unknown", False, True, "broad_load_error", ), "TOKENIZER_FAILED": FailureClassification( "tokenizer_compatibility", "model_framework", "check_tokenizer_files_then_llm", False, True, "broad_tokenizer_error", ), "MISSING_OPERATOR": FailureClassification( "backend_operator", "gpu_framework", "prefer_other_proven_framework_or_gpu", False, True, "backend_version_dependent", ), "ATTENTION_NOT_SUPPORTED": FailureClassification( "attention_backend", "gpu_framework", "prefer_other_proven_framework_or_gpu", False, True, "backend_version_dependent", ), } PLATFORM_PATTERNS = ( (re.compile(r"welcome\.sh: No such file|data: command not found", re.I), "broken_platform_launch_script"), (re.compile(r"id_rsa.*No such file", re.I), "missing_platform_credential"), (re.compile(r"找不到空闲卡|no idle (?:gpu|card)", re.I), "no_idle_device"), (re.compile(r"storage|download.*timed? out|connection reset", re.I), "platform_io_transient"), ) DETERMINISTIC_LOG_PATTERNS = ( (re.compile(r"PREFLIGHT_OOM|out of memory", re.I), "PREFLIGHT_OOM"), (re.compile(r"max_model_len.*greater than.*max_position_embeddings", re.I), "CONTEXT_LENGTH_ERROR"), (re.compile(r"config\.json.*(?:not found|no config)|Invalid repository ID or local directory", re.I), "MODEL_FILE_NOT_FOUND"), ) def classify_failure_report(report_code: str | None, log_lines: Iterable[str] = ()) -> FailureClassification: code = str(report_code or "").strip().upper() text = "\n".join(str(line) for line in log_lines) # Infrastructure signatures override broad report codes such as # EXECUTE_EMPTY_RESULT so they do not poison model compatibility feedback. for pattern, reason in PLATFORM_PATTERNS: if pattern.search(text): return FailureClassification( "platform_infrastructure", "gpu_framework", "open_short_gpu_framework_circuit_and_retry_other_models", True, False, reason, ) if code in DETERMINISTIC_POLICIES: return DETERMINISTIC_POLICIES[code] for pattern, inferred_code in DETERMINISTIC_LOG_PATTERNS: if pattern.search(text): return DETERMINISTIC_POLICIES[inferred_code] if code in SEMANTIC_POLICIES: return SEMANTIC_POLICIES[code] return FailureClassification( "ambiguous_runtime", "unknown", "send_compact_profile_and_root_exception_to_llm", False, True, code.lower() if code else "missing_structured_error_code", )