106 lines
4.4 KiB
Python
106 lines
4.4 KiB
Python
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",
|
|
)
|