use crate::resources::{ResourceRequirement, ResourceType, CapabilityLevel};
use crate::types::SystemProfile;
use crate::error::{SystemAnalysisError, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub trait Workload: Send + Sync + std::fmt::Debug {
fn workload_type(&self) -> WorkloadType;
fn resource_requirements(&self) -> Vec<ResourceRequirement>;
fn estimated_utilization(&self) -> HashMap<ResourceType, f64>;
fn performance_characteristics(&self) -> PerformanceCharacteristics;
fn metadata(&self) -> WorkloadMetadata;
fn validate(&self) -> crate::error::Result<()>;
fn clone_workload(&self) -> Box<dyn Workload>;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WorkloadType {
AIInference,
AITraining,
NPUInference,
TPUTraining,
FPGAInference,
EdgeAI,
ComputerVision,
NaturalLanguageProcessing,
LLMInference,
LLMTraining,
Robotics,
IoTEdge,
DataProcessing,
WebApplication,
Database,
ComputeIntensive,
MemoryIntensive,
IOIntensive,
Custom(String),
}
impl std::fmt::Display for WorkloadType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
WorkloadType::AIInference => write!(f, "AI Inference"),
WorkloadType::AITraining => write!(f, "AI Training"),
WorkloadType::NPUInference => write!(f, "NPU Inference"),
WorkloadType::TPUTraining => write!(f, "TPU Training"),
WorkloadType::FPGAInference => write!(f, "FPGA Inference"),
WorkloadType::EdgeAI => write!(f, "Edge AI"),
WorkloadType::ComputerVision => write!(f, "Computer Vision"),
WorkloadType::NaturalLanguageProcessing => write!(f, "Natural Language Processing"),
WorkloadType::LLMInference => write!(f, "Large Language Model Inference"),
WorkloadType::LLMTraining => write!(f, "Large Language Model Training"),
WorkloadType::Robotics => write!(f, "Robotics"),
WorkloadType::IoTEdge => write!(f, "IoT Edge"),
WorkloadType::DataProcessing => write!(f, "Data Processing"),
WorkloadType::WebApplication => write!(f, "Web Application"),
WorkloadType::Database => write!(f, "Database"),
WorkloadType::ComputeIntensive => write!(f, "Compute Intensive"),
WorkloadType::MemoryIntensive => write!(f, "Memory Intensive"),
WorkloadType::IOIntensive => write!(f, "I/O Intensive"),
WorkloadType::Custom(name) => write!(f, "Custom: {name}"),
}
}
}
impl WorkloadType {
pub fn estimated_utilization(&self) -> f64 {
match self {
WorkloadType::AIInference => 0.6,
WorkloadType::AITraining => 0.9,
WorkloadType::NPUInference => 0.7,
WorkloadType::TPUTraining => 0.95,
WorkloadType::FPGAInference => 0.8,
WorkloadType::EdgeAI => 0.5,
WorkloadType::ComputerVision => 0.7,
WorkloadType::NaturalLanguageProcessing => 0.6,
WorkloadType::LLMInference => 0.8,
WorkloadType::LLMTraining => 0.95,
WorkloadType::Robotics => 0.6,
WorkloadType::IoTEdge => 0.4,
WorkloadType::DataProcessing => 0.5,
WorkloadType::WebApplication => 0.3,
WorkloadType::Database => 0.4,
WorkloadType::ComputeIntensive => 0.8,
WorkloadType::MemoryIntensive => 0.6,
WorkloadType::IOIntensive => 0.7,
WorkloadType::Custom(_) => 0.5,
}
}
pub fn validate(&self) -> crate::error::Result<()> {
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceCharacteristics {
pub latency_profile: LatencyProfile,
pub throughput_profile: ThroughputProfile,
pub scalability: ScalabilityProfile,
pub resource_patterns: ResourcePatterns,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LatencyProfile {
pub expected_latency_ms: f64,
pub acceptable_latency_ms: f64,
pub sensitivity: LatencySensitivity,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum LatencySensitivity {
VeryLow,
Low,
Medium,
High,
VeryHigh,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThroughputProfile {
pub expected_ops_per_sec: f64,
pub minimum_ops_per_sec: f64,
pub peak_ops_per_sec: f64,
pub consistency_requirement: ThroughputConsistency,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ThroughputConsistency {
Variable,
Consistent,
Guaranteed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScalabilityProfile {
pub horizontal_scaling: ScalingCapability,
pub vertical_scaling: ScalingCapability,
pub scaling_efficiency: f64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ScalingCapability {
None,
Limited,
Good,
Excellent,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourcePatterns {
pub cpu_pattern: UsagePattern,
pub memory_pattern: UsagePattern,
pub io_pattern: UsagePattern,
pub network_pattern: UsagePattern,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum UsagePattern {
Constant,
Bursty,
Periodic,
Ramping,
Unpredictable,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkloadMetadata {
pub name: String,
pub description: String,
pub version: String,
pub tags: Vec<String>,
pub vendor: Option<String>,
pub license: Option<String>,
pub documentation_url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AIInferenceWorkload {
pub model_params: ModelParameters,
pub inference_config: InferenceConfig,
pub metadata: WorkloadMetadata,
}
impl AIInferenceWorkload {
pub fn new(model_params: ModelParameters) -> Self {
Self {
model_params,
inference_config: InferenceConfig::default(),
metadata: WorkloadMetadata {
name: "AI Inference".to_string(),
description: "AI/ML model inference workload".to_string(),
version: "1.0.0".to_string(),
tags: vec!["ai".to_string(), "inference".to_string(), "ml".to_string()],
vendor: None,
license: None,
documentation_url: None,
},
}
}
pub fn with_config(mut self, config: InferenceConfig) -> Self {
self.inference_config = config;
self
}
pub fn with_metadata(mut self, metadata: WorkloadMetadata) -> Self {
self.metadata = metadata;
self
}
}
impl Workload for AIInferenceWorkload {
fn workload_type(&self) -> WorkloadType {
WorkloadType::AIInference
}
fn resource_requirements(&self) -> Vec<ResourceRequirement> {
let mut requirements = Vec::new();
let memory_gb = self.model_params.memory_required;
requirements.push(
ResourceRequirement::new(ResourceType::Memory)
.minimum_gb(memory_gb)
.recommended_gb(memory_gb * 1.5)
.critical()
);
if self.model_params.prefer_gpu {
let gpu_level = match self.model_params.parameters {
params if params >= 70_000_000_000 => CapabilityLevel::Exceptional,
params if params >= 13_000_000_000 => CapabilityLevel::VeryHigh,
params if params >= 7_000_000_000 => CapabilityLevel::High,
params if params >= 1_000_000_000 => CapabilityLevel::Medium,
_ => CapabilityLevel::Low,
};
requirements.push(
ResourceRequirement::new(ResourceType::GPU)
.minimum_level(gpu_level)
.preferred_vendor(Some("NVIDIA"))
);
}
let cpu_level = match self.model_params.compute_required {
compute if compute >= 8.0 => CapabilityLevel::VeryHigh,
compute if compute >= 6.0 => CapabilityLevel::High,
compute if compute >= 4.0 => CapabilityLevel::Medium,
compute if compute >= 2.0 => CapabilityLevel::Low,
_ => CapabilityLevel::VeryLow,
};
requirements.push(
ResourceRequirement::new(ResourceType::CPU)
.minimum_level(cpu_level)
);
let storage_gb = (self.model_params.parameters as f64 * 4.0 / 1_000_000_000.0) + 10.0; requirements.push(
ResourceRequirement::new(ResourceType::Storage)
.minimum_gb(storage_gb)
.recommended_gb(storage_gb * 2.0)
);
requirements
}
fn estimated_utilization(&self) -> HashMap<ResourceType, f64> {
let mut utilization = HashMap::new();
let cpu_util = if self.model_params.prefer_gpu { 20.0 } else { 80.0 };
utilization.insert(ResourceType::CPU, cpu_util);
if self.model_params.prefer_gpu {
utilization.insert(ResourceType::GPU, 75.0);
}
utilization.insert(ResourceType::Memory, 60.0);
utilization.insert(ResourceType::Storage, 15.0);
utilization.insert(ResourceType::Network, 25.0);
utilization
}
fn performance_characteristics(&self) -> PerformanceCharacteristics {
let latency_ms = if self.model_params.prefer_gpu { 50.0 } else { 200.0 };
let throughput = if self.model_params.prefer_gpu { 20.0 } else { 5.0 };
PerformanceCharacteristics {
latency_profile: LatencyProfile {
expected_latency_ms: latency_ms,
acceptable_latency_ms: latency_ms * 2.0,
sensitivity: LatencySensitivity::High,
},
throughput_profile: ThroughputProfile {
expected_ops_per_sec: throughput,
minimum_ops_per_sec: throughput * 0.5,
peak_ops_per_sec: throughput * 1.5,
consistency_requirement: ThroughputConsistency::Consistent,
},
scalability: ScalabilityProfile {
horizontal_scaling: ScalingCapability::Good,
vertical_scaling: ScalingCapability::Excellent,
scaling_efficiency: 0.8,
},
resource_patterns: ResourcePatterns {
cpu_pattern: if self.model_params.prefer_gpu { UsagePattern::Bursty } else { UsagePattern::Constant },
memory_pattern: UsagePattern::Constant,
io_pattern: UsagePattern::Bursty,
network_pattern: UsagePattern::Bursty,
},
}
}
fn metadata(&self) -> WorkloadMetadata {
self.metadata.clone()
}
fn validate(&self) -> crate::error::Result<()> {
if self.model_params.parameters == 0 {
return Err(crate::error::SystemAnalysisError::invalid_workload(
"Model parameters cannot be zero"
));
}
if self.model_params.memory_required <= 0.0 {
return Err(crate::error::SystemAnalysisError::invalid_workload(
"Memory requirement must be positive"
));
}
if self.model_params.compute_required <= 0.0 {
return Err(crate::error::SystemAnalysisError::invalid_workload(
"Compute requirement must be positive"
));
}
Ok(())
}
fn clone_workload(&self) -> Box<dyn Workload> {
Box::new(self.clone())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelParameters {
pub parameters: u64,
pub memory_required: f64,
pub compute_required: f64,
pub prefer_gpu: bool,
pub architecture: Option<String>,
pub quantization: QuantizationLevel,
pub context_length: Option<u32>,
pub batch_size: u32,
}
impl ModelParameters {
pub fn new() -> Self {
Self {
parameters: 0,
memory_required: 0.0,
compute_required: 0.0,
prefer_gpu: false,
architecture: None,
quantization: QuantizationLevel::None,
context_length: None,
batch_size: 1,
}
}
pub fn parameters(mut self, params: u64) -> Self {
self.parameters = params;
self.memory_required = (params as f64 * 4.0 / 1_000_000_000.0) * 1.2; self.compute_required = (params as f64 / 1_000_000_000.0).clamp(1.0, 10.0); self
}
pub fn memory_required(mut self, gb: f64) -> Self {
self.memory_required = gb;
self
}
pub fn compute_required(mut self, compute: f64) -> Self {
self.compute_required = compute.clamp(0.0, 10.0);
self
}
pub fn prefer_gpu(mut self, prefer: bool) -> Self {
self.prefer_gpu = prefer;
self
}
pub fn architecture(mut self, arch: impl Into<String>) -> Self {
self.architecture = Some(arch.into());
self
}
pub fn quantization(mut self, quant: QuantizationLevel) -> Self {
self.quantization = quant;
match quant {
QuantizationLevel::None => {},
QuantizationLevel::Int8 => self.memory_required *= 0.5,
QuantizationLevel::Int4 => self.memory_required *= 0.25,
QuantizationLevel::Custom(_) => self.memory_required *= 0.5,
}
self
}
pub fn context_length(mut self, length: u32) -> Self {
self.context_length = Some(length);
self
}
pub fn batch_size(mut self, size: u32) -> Self {
self.batch_size = size;
self
}
}
impl Default for ModelParameters {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum QuantizationLevel {
None,
Int8,
Int4,
Custom(f64),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InferenceConfig {
pub max_concurrent_requests: u32,
pub request_timeout_sec: u32,
pub enable_batching: bool,
pub dynamic_batching: Option<DynamicBatchingConfig>,
pub caching: CachingConfig,
}
impl Default for InferenceConfig {
fn default() -> Self {
Self {
max_concurrent_requests: 10,
request_timeout_sec: 30,
enable_batching: true,
dynamic_batching: Some(DynamicBatchingConfig::default()),
caching: CachingConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DynamicBatchingConfig {
pub max_batch_size: u32,
pub max_wait_time_ms: u32,
pub preferred_batch_sizes: Vec<u32>,
}
impl Default for DynamicBatchingConfig {
fn default() -> Self {
Self {
max_batch_size: 8,
max_wait_time_ms: 100,
preferred_batch_sizes: vec![1, 2, 4, 8],
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CachingConfig {
pub enable_kv_cache: bool,
pub cache_size_mb: u32,
pub eviction_policy: CacheEvictionPolicy,
}
impl Default for CachingConfig {
fn default() -> Self {
Self {
enable_kv_cache: true,
cache_size_mb: 1024,
eviction_policy: CacheEvictionPolicy::LRU,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum CacheEvictionPolicy {
LRU,
LFU,
FIFO,
Random,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AITrainingWorkload {
pub model_params: ModelParameters,
pub training_config: TrainingConfig,
pub metadata: WorkloadMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrainingConfig {
pub batch_size: u32,
pub epochs: u32,
pub learning_rate: f64,
pub distributed: bool,
}
impl Default for TrainingConfig {
fn default() -> Self {
Self {
batch_size: 32,
epochs: 10,
learning_rate: 0.001,
distributed: false,
}
}
}
pub trait CustomWorkload: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn resource_requirements(&self) -> Vec<ResourceRequirement>;
fn estimate_performance(&self, system: &SystemProfile) -> Result<f64>;
fn metadata(&self) -> HashMap<String, String> {
HashMap::new()
}
fn validate(&self) -> Result<()> {
Ok(())
}
fn recommended_upgrades(&self, _system: &SystemProfile) -> Vec<String> {
Vec::new()
}
}
pub struct WorkloadRegistry {
workloads: HashMap<String, Box<dyn CustomWorkload>>,
}
impl WorkloadRegistry {
pub fn new() -> Self {
Self {
workloads: HashMap::new(),
}
}
pub fn register<W: CustomWorkload + 'static>(&mut self, workload: W) -> Result<()> {
let name = workload.name().to_string();
workload.validate()?;
self.workloads.insert(name, Box::new(workload));
Ok(())
}
pub fn get(&self, name: &str) -> Option<&dyn CustomWorkload> {
self.workloads.get(name).map(|w| w.as_ref())
}
pub fn list_workloads(&self) -> Vec<&str> {
self.workloads.keys().map(|s| s.as_str()).collect()
}
pub fn unregister(&mut self, name: &str) -> bool {
self.workloads.remove(name).is_some()
}
pub fn count(&self) -> usize {
self.workloads.len()
}
}
impl Default for WorkloadRegistry {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomWorkloadBuilder {
name: String,
description: String,
requirements: Vec<ResourceRequirement>,
metadata: HashMap<String, String>,
performance_formula: Option<String>,
}
impl CustomWorkloadBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
description: String::new(),
requirements: Vec::new(),
metadata: HashMap::new(),
performance_formula: None,
}
}
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = desc.into();
self
}
pub fn add_requirement(mut self, requirement: ResourceRequirement) -> Self {
self.requirements.push(requirement);
self
}
pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
pub fn performance_formula(mut self, formula: impl Into<String>) -> Self {
self.performance_formula = Some(formula.into());
self
}
pub fn build(self) -> BuiltCustomWorkload {
BuiltCustomWorkload {
name: self.name,
description: self.description,
requirements: self.requirements,
metadata: self.metadata,
performance_formula: self.performance_formula,
}
}
}
pub struct BuiltCustomWorkload {
name: String,
description: String,
requirements: Vec<ResourceRequirement>,
metadata: HashMap<String, String>,
performance_formula: Option<String>,
}
impl CustomWorkload for BuiltCustomWorkload {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn resource_requirements(&self) -> Vec<ResourceRequirement> {
self.requirements.clone()
}
fn estimate_performance(&self, system: &SystemProfile) -> Result<f64> {
if let Some(_formula) = &self.performance_formula {
}
let cpu_score = system.cpu_score() / 10.0;
let gpu_score = system.gpu_score() / 10.0;
let memory_score = system.memory_score() / 10.0;
let storage_score = system.storage_score() / 10.0;
let mut total_weight = 0.0;
let mut weighted_score = 0.0;
for req in &self.requirements {
let (score, weight) = match req.resource_type {
crate::resources::ResourceType::CPU => (cpu_score, 1.0),
crate::resources::ResourceType::GPU => (gpu_score, 1.0),
crate::resources::ResourceType::Memory => (memory_score, 1.0),
crate::resources::ResourceType::Storage => (storage_score, 1.0),
crate::resources::ResourceType::Network => (0.5, 0.5), crate::resources::ResourceType::Custom(_) => (0.5, 0.5), };
weighted_score += score * weight;
total_weight += weight;
}
if total_weight == 0.0 {
Ok(5.0) } else {
Ok((weighted_score / total_weight * 10.0).clamp(0.0, 10.0))
}
}
fn metadata(&self) -> HashMap<String, String> {
self.metadata.clone()
}
fn validate(&self) -> Result<()> {
if self.name.is_empty() {
return Err(SystemAnalysisError::invalid_workload(
"Workload name cannot be empty".to_string()
));
}
if self.requirements.is_empty() {
return Err(SystemAnalysisError::invalid_workload(
"Workload must have at least one resource requirement".to_string()
));
}
Ok(())
}
fn recommended_upgrades(&self, system: &SystemProfile) -> Vec<String> {
let mut upgrades = Vec::new();
for req in &self.requirements {
match req.resource_type {
crate::resources::ResourceType::CPU => {
if system.cpu_score < 7.0 {
upgrades.push("Consider upgrading to a higher-performance CPU".to_string());
}
},
crate::resources::ResourceType::GPU => {
if system.gpu_score < 7.0 {
upgrades.push("Consider upgrading to a more powerful GPU".to_string());
}
},
crate::resources::ResourceType::Memory => {
let system_memory_gb = system.system_info.memory_info.total_ram as f64 / 1024.0; if let crate::resources::ResourceAmount::Gigabytes(min_gb) = req.minimum {
if min_gb > system_memory_gb {
upgrades.push(format!(
"Increase RAM to at least {min_gb:.1}GB"
));
}
}
},
crate::resources::ResourceType::Storage => {
if system.storage_score < 7.0 {
upgrades.push("Consider upgrading to faster storage (NVMe SSD)".to_string());
}
},
crate::resources::ResourceType::Network => {
},
crate::resources::ResourceType::Custom(_) => {
},
}
}
upgrades
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AIModel {
pub name: String,
pub architecture: String,
pub parameters: u64,
pub size_in_bytes: u64,
pub memory_required: f64,
pub quantization: QuantizationLevel,
pub framework: String,
pub task: AITaskType,
pub max_input_size: Option<u32>,
pub max_context_length: Option<u32>,
pub version: String,
pub metadata: HashMap<String, String>,
}
impl AIModel {
pub fn new(name: impl Into<String>, architecture: impl Into<String>, parameters: u64) -> Self {
let params = parameters;
let size_bytes = params * 4;
let memory_gb = (size_bytes as f64 / 1_073_741_824.0) * 1.2;
Self {
name: name.into(),
architecture: architecture.into(),
parameters: params,
size_in_bytes: size_bytes,
memory_required: memory_gb,
quantization: QuantizationLevel::None,
framework: "Unknown".to_string(),
task: AITaskType::Other,
max_input_size: None,
max_context_length: None,
version: "1.0.0".to_string(),
metadata: HashMap::new(),
}
}
pub fn with_framework(mut self, framework: impl Into<String>) -> Self {
self.framework = framework.into();
self
}
pub fn with_task(mut self, task: AITaskType) -> Self {
self.task = task;
self
}
pub fn with_quantization(mut self, level: QuantizationLevel) -> Self {
self.quantization = level;
match level {
QuantizationLevel::None => {},
QuantizationLevel::Int8 => self.memory_required *= 0.5, QuantizationLevel::Int4 => self.memory_required *= 0.25, QuantizationLevel::Custom(ratio) => self.memory_required *= ratio,
}
self
}
pub fn with_context_length(mut self, length: u32) -> Self {
self.max_context_length = Some(length);
self
}
pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AITaskType {
TextGeneration,
ImageClassification,
ObjectDetection,
ImageSegmentation,
NLP,
SpeechRecognition,
SpeechSynthesis,
Translation,
Recommendation,
Other,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_model_parameters_creation() {
let params = ModelParameters::new()
.parameters(1_000_000_000) .quantization(QuantizationLevel::Int8)
.context_length(2048)
.batch_size(4);
assert_eq!(params.parameters, 1_000_000_000);
assert_eq!(params.quantization, QuantizationLevel::Int8);
assert_eq!(params.context_length, Some(2048));
assert_eq!(params.batch_size, 4);
}
#[test]
fn test_ai_inference_workload_creation() {
let model_params = ModelParameters::new()
.parameters(7_000_000_000) .context_length(4096);
let workload = AIInferenceWorkload::new(model_params);
let requirements = workload.resource_requirements();
assert!(!requirements.is_empty());
assert_eq!(workload.workload_type(), WorkloadType::AIInference);
}
#[test]
fn test_workload_type_display() {
assert_eq!(format!("{}", WorkloadType::AIInference), "AI Inference");
assert_eq!(format!("{}", WorkloadType::AIInference), "AI Inference");
assert_eq!(format!("{}", WorkloadType::DataProcessing), "Data Processing");
assert_eq!(format!("{}", WorkloadType::WebApplication), "Web Application");
assert_eq!(format!("{}", WorkloadType::Custom("Custom Task".to_string())), "Custom: Custom Task");
}
#[test]
fn test_quantization_level() {
let _none = QuantizationLevel::None;
let _int8 = QuantizationLevel::Int8;
let _int4 = QuantizationLevel::Int4;
let _custom = QuantizationLevel::Custom(0.5);
assert_eq!(format!("{_none:?}"), "None");
assert_eq!(format!("{_int8:?}"), "Int8");
assert_eq!(format!("{_int4:?}"), "Int4");
assert_eq!(format!("{_custom:?}"), "Custom(0.5)");
}
#[test]
fn test_workload_validation() {
let model_params = ModelParameters::new()
.parameters(1_000_000_000);
let workload = AIInferenceWorkload::new(model_params);
assert!(workload.validate().is_ok());
}
#[test]
fn test_model_parameters_builder() {
let params = ModelParameters::new()
.parameters(1_000_000_000)
.memory_required(8.0)
.compute_required(7.5)
.prefer_gpu(true)
.architecture("transformer")
.quantization(QuantizationLevel::Int8)
.context_length(2048)
.batch_size(4);
assert_eq!(params.parameters, 1_000_000_000);
assert_eq!(params.compute_required, 7.5);
assert!(params.prefer_gpu);
assert_eq!(params.architecture, Some("transformer".to_string()));
assert_eq!(params.context_length, Some(2048));
assert_eq!(params.batch_size, 4);
}
}