353 lines
11 KiB
Rust
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"));
|
|
}
|
|
}
|