Files
rustytorch/crates/training/rtx-model-merging/src/error.rs
T
2026-03-04 00:08:42 +00:00

353 lines
11 KiB
Rust

//! Error handling for model merging operations
use thiserror::Error;
/// Result type for model merging operations
pub type Result<T> = std::result::Result<T, MergeError>;
/// Comprehensive error types for model merging
#[derive(Error, Debug)]
pub enum MergeError {
#[error("Model loading failed: {message}")]
ModelLoadError { message: String },
#[error("Model compatibility error: {details}")]
CompatibilityError { details: String },
#[error("Parameter mismatch: expected {expected}, found {found}")]
ParameterMismatch { expected: String, found: String },
#[error("Architecture incompatibility: {model1} vs {model2}")]
ArchitectureIncompatible { model1: String, model2: String },
#[error("Merge algorithm failed: {algorithm} - {reason}")]
AlgorithmError { algorithm: String, reason: String },
#[error("Expert selection failed: {reason}")]
ExpertSelectionError { reason: String },
#[error("Conflict resolution failed: {conflicts} conflicts unresolved")]
ConflictResolutionError { conflicts: usize },
#[error("Validation failed: {} validation checks failed", checks.len())]
ValidationError { checks: Vec<String> },
#[error("Performance evaluation error: {metric} computation failed")]
EvaluationError { metric: String },
#[error("Configuration error: {field} - {message}")]
ConfigError { field: String, message: String },
#[error("Memory allocation error: {size_mb}MB required")]
MemoryError { size_mb: usize },
#[error("GPU operation failed: {operation}")]
GpuError { operation: String },
#[error("Numerical instability detected: {operation}")]
NumericalError { operation: String },
#[error("File I/O error: {path}")]
IoError {
path: String,
#[source]
source: std::io::Error,
},
#[error("Serialization error")]
SerializationError(#[from] bincode::Error),
#[error("JSON error")]
JsonError(#[from] serde_json::Error),
#[error("TOML error")]
TomlError(#[from] toml::de::Error),
#[error("Async runtime error")]
AsyncError(#[from] tokio::task::JoinError),
#[error("Thread pool error")]
ThreadPoolError(String),
#[error("Timeout error: operation took longer than {timeout_ms}ms")]
TimeoutError { timeout_ms: u64 },
#[error("Resource exhaustion: {resource}")]
ResourceExhausted { resource: String },
#[error("Model format not supported: {format}")]
UnsupportedFormat { format: String },
#[error("Feature not implemented: {feature}")]
NotImplemented { feature: String },
#[error("Internal error: {message}")]
Internal { message: String },
}
impl MergeError {
/// Create a model loading error
pub fn model_load<S: Into<String>>(message: S) -> Self {
Self::ModelLoadError {
message: message.into(),
}
}
/// Create a compatibility error
pub fn compatibility<S: Into<String>>(details: S) -> Self {
Self::CompatibilityError {
details: details.into(),
}
}
/// Create a parameter mismatch error
pub fn parameter_mismatch<S: Into<String>>(expected: S, found: S) -> Self {
Self::ParameterMismatch {
expected: expected.into(),
found: found.into(),
}
}
/// Create an architecture incompatibility error
pub fn architecture_incompatible<S: Into<String>>(model1: S, model2: S) -> Self {
Self::ArchitectureIncompatible {
model1: model1.into(),
model2: model2.into(),
}
}
/// Create an algorithm error
pub fn algorithm<S: Into<String>>(algorithm: S, reason: S) -> Self {
Self::AlgorithmError {
algorithm: algorithm.into(),
reason: reason.into(),
}
}
/// Create an expert selection error
pub fn expert_selection<S: Into<String>>(reason: S) -> Self {
Self::ExpertSelectionError {
reason: reason.into(),
}
}
/// Create a conflict resolution error
pub fn conflict_resolution(conflicts: usize) -> Self {
Self::ConflictResolutionError { conflicts }
}
/// Create a validation error
pub fn validation(checks: Vec<String>) -> Self {
Self::ValidationError { checks }
}
/// Create an evaluation error
pub fn evaluation<S: Into<String>>(metric: S) -> Self {
Self::EvaluationError {
metric: metric.into(),
}
}
/// Create a configuration error
pub fn config<S: Into<String>>(field: S, message: S) -> Self {
Self::ConfigError {
field: field.into(),
message: message.into(),
}
}
/// Create a memory error
pub fn memory(size_mb: usize) -> Self {
Self::MemoryError { size_mb }
}
/// Create a GPU error
pub fn gpu<S: Into<String>>(operation: S) -> Self {
Self::GpuError {
operation: operation.into(),
}
}
/// Create a numerical error
pub fn numerical<S: Into<String>>(operation: S) -> Self {
Self::NumericalError {
operation: operation.into(),
}
}
/// Create an I/O error
pub fn io<S: Into<String>>(path: S, source: std::io::Error) -> Self {
Self::IoError {
path: path.into(),
source,
}
}
/// Create a timeout error
pub fn timeout(timeout_ms: u64) -> Self {
Self::TimeoutError { timeout_ms }
}
/// Create a resource exhaustion error
pub fn resource_exhausted<S: Into<String>>(resource: S) -> Self {
Self::ResourceExhausted {
resource: resource.into(),
}
}
/// Create an unsupported format error
pub fn unsupported_format<S: Into<String>>(format: S) -> Self {
Self::UnsupportedFormat {
format: format.into(),
}
}
/// Create a not implemented error
pub fn not_implemented<S: Into<String>>(feature: S) -> Self {
Self::NotImplemented {
feature: feature.into(),
}
}
/// Create an internal error
pub fn internal<S: Into<String>>(message: S) -> Self {
Self::Internal {
message: message.into(),
}
}
/// Check if this error is recoverable
pub fn is_recoverable(&self) -> bool {
match self {
Self::TimeoutError { .. } => true,
Self::MemoryError { .. } => true,
Self::GpuError { .. } => true,
Self::ThreadPoolError(_) => true,
Self::ResourceExhausted { .. } => true,
_ => false,
}
}
/// Get the error category
pub fn category(&self) -> ErrorCategory {
match self {
Self::ModelLoadError { .. } => ErrorCategory::Loading,
Self::CompatibilityError { .. } => ErrorCategory::Compatibility,
Self::ParameterMismatch { .. } => ErrorCategory::Compatibility,
Self::ArchitectureIncompatible { .. } => ErrorCategory::Compatibility,
Self::AlgorithmError { .. } => ErrorCategory::Algorithm,
Self::ExpertSelectionError { .. } => ErrorCategory::ExpertSelection,
Self::ConflictResolutionError { .. } => ErrorCategory::ConflictResolution,
Self::ValidationError { .. } => ErrorCategory::Validation,
Self::EvaluationError { .. } => ErrorCategory::Evaluation,
Self::ConfigError { .. } => ErrorCategory::Configuration,
Self::MemoryError { .. } => ErrorCategory::Resource,
Self::GpuError { .. } => ErrorCategory::Resource,
Self::NumericalError { .. } => ErrorCategory::Numerical,
Self::IoError { .. } => ErrorCategory::IO,
Self::SerializationError(_) => ErrorCategory::Serialization,
Self::JsonError(_) => ErrorCategory::Serialization,
Self::TomlError(_) => ErrorCategory::Serialization,
Self::AsyncError(_) => ErrorCategory::Runtime,
Self::ThreadPoolError(_) => ErrorCategory::Runtime,
Self::TimeoutError { .. } => ErrorCategory::Runtime,
Self::ResourceExhausted { .. } => ErrorCategory::Resource,
Self::UnsupportedFormat { .. } => ErrorCategory::Format,
Self::NotImplemented { .. } => ErrorCategory::NotImplemented,
Self::Internal { .. } => ErrorCategory::Internal,
}
}
}
/// Error categories for classification and handling
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorCategory {
Loading,
Compatibility,
Algorithm,
ExpertSelection,
ConflictResolution,
Validation,
Evaluation,
Configuration,
Resource,
Numerical,
IO,
Serialization,
Runtime,
Format,
NotImplemented,
Internal,
}
impl ErrorCategory {
/// Get a human-readable description of the error category
pub fn description(&self) -> &'static str {
match self {
Self::Loading => "Model loading and parsing errors",
Self::Compatibility => "Model compatibility and architecture mismatches",
Self::Algorithm => "Merge algorithm execution errors",
Self::ExpertSelection => "Expert selection and routing errors",
Self::ConflictResolution => "Parameter conflict resolution errors",
Self::Validation => "Model and parameter validation errors",
Self::Evaluation => "Performance evaluation and metric computation errors",
Self::Configuration => "Configuration parsing and validation errors",
Self::Resource => "Memory, GPU, and other resource errors",
Self::Numerical => "Numerical stability and computation errors",
Self::IO => "File system and network I/O errors",
Self::Serialization => "Data serialization and deserialization errors",
Self::Runtime => "Async runtime and thread pool errors",
Self::Format => "Unsupported or invalid format errors",
Self::NotImplemented => "Features not yet implemented",
Self::Internal => "Internal library errors",
}
}
/// Check if errors in this category are typically user-fixable
pub fn is_user_fixable(&self) -> bool {
match self {
Self::Loading => true,
Self::Compatibility => true,
Self::Configuration => true,
Self::IO => true,
Self::Format => true,
_ => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_creation() {
let err = MergeError::model_load("Test error");
assert!(matches!(err, MergeError::ModelLoadError { .. }));
}
#[test]
fn test_error_categories() {
let err = MergeError::compatibility("Test");
assert_eq!(err.category(), ErrorCategory::Compatibility);
assert!(err.category().is_user_fixable());
}
#[test]
fn test_recoverable_errors() {
let timeout_err = MergeError::timeout(1000);
assert!(timeout_err.is_recoverable());
let internal_err = MergeError::internal("Test");
assert!(!internal_err.is_recoverable());
}
#[test]
fn test_error_display() {
let err = MergeError::parameter_mismatch("expected", "found");
let display = format!("{}", err);
assert!(display.contains("expected"));
assert!(display.contains("found"));
}
}