use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::sync::Arc;
use parking_lot::{Mutex, RwLock};
use thiserror::Error;
pub use haagenti::holotensor::{HolographicEncoding, QualityCurve};
pub mod arena;
pub mod converter;
pub mod memory;
pub mod provider;
pub mod streaming;
pub mod tiered_loading;
#[cfg(test)]
mod tests;
#[derive(Debug, Error)]
pub enum HoloInferenceError {
#[error("Memory allocation failed: {0}")]
MemoryAllocation(String),
#[error("Memory allocation failed in {tier:?}: {message}")]
MemoryAlloc {
tier: memory::MemoryTier,
message: String,
},
#[error("Fragment loading failed: {0}")]
FragmentLoad(String),
#[error("Fragment not found: layer {layer}, index {fragment_index}")]
FragmentNotFound {
layer: usize,
fragment_index: u16,
},
#[error("Cannot achieve quality {target}: only {available} fragments available")]
InsufficientQuality {
target: f32,
available: u16,
},
#[error("Quality not reached: target {target}, current {current}")]
QualityNotReached {
target: f32,
current: f32,
},
#[error("Insufficient memory in {tier:?}: need {required} bytes, have {available} bytes")]
InsufficientMemory {
tier: memory::MemoryTier,
required: usize,
available: usize,
},
#[error("Invalid configuration: {0}")]
InvalidConfig(String),
#[error("Conversion error: {0}")]
Conversion(String),
#[error("CUDA error: {0}")]
Cuda(String),
#[error("Device error: {0}")]
DeviceError(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Haagenti error: {0}")]
Haagenti(String),
}
pub type Result<T> = std::result::Result<T, HoloInferenceError>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum MemoryTier {
Vram = 0,
Ram = 1,
Nvme = 2,
Network = 3,
}
impl MemoryTier {
pub fn typical_latency_ns(&self) -> u64 {
match self {
MemoryTier::Vram => 100, MemoryTier::Ram => 100_000, MemoryTier::Nvme => 10_000_000, MemoryTier::Network => 50_000_000, }
}
pub fn typical_bandwidth_gbps(&self) -> f64 {
match self {
MemoryTier::Vram => 900.0, MemoryTier::Ram => 50.0, MemoryTier::Nvme => 7.0, MemoryTier::Network => 1.0, }
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct FragmentLocation {
fragment_id: u16,
tier: MemoryTier,
is_loading: bool,
offset: Option<u64>,
}
impl FragmentLocation {
pub fn new(fragment_id: u16, tier: MemoryTier) -> Self {
Self {
fragment_id,
tier,
is_loading: false,
offset: None,
}
}
pub fn fragment_id(&self) -> u16 {
self.fragment_id
}
pub fn tier(&self) -> MemoryTier {
self.tier
}
pub fn is_loading(&self) -> bool {
self.is_loading
}
pub fn promote_to(&mut self, tier: MemoryTier) {
if tier < self.tier {
self.tier = tier;
}
}
pub fn set_loading(&mut self, loading: bool) {
self.is_loading = loading;
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct QualityMetrics {
current_quality: f32,
target_quality: f32,
fragments_loaded: u16,
total_fragments: u16,
quality_history: Vec<(std::time::Instant, f32)>,
}
impl Default for QualityMetrics {
fn default() -> Self {
Self {
current_quality: 0.0,
target_quality: 1.0,
fragments_loaded: 0,
total_fragments: 8,
quality_history: Vec::new(),
}
}
}
impl QualityMetrics {
pub fn with_target(target: f32) -> Self {
Self {
target_quality: target,
..Default::default()
}
}
pub fn current_quality(&self) -> f32 {
self.current_quality
}
pub fn target_quality(&self) -> f32 {
self.target_quality
}
pub fn fragments_loaded(&self) -> u16 {
self.fragments_loaded
}
pub fn quality_gap(&self) -> f32 {
(self.target_quality - self.current_quality).max(0.0)
}
pub fn record_fragment_loaded(&mut self, new_quality: f32) {
self.fragments_loaded += 1;
self.current_quality = new_quality;
self.quality_history
.push((std::time::Instant::now(), new_quality));
}
pub fn target_reached(&self) -> bool {
self.current_quality >= self.target_quality
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct MemoryConfig {
vram_budget_bytes: u64,
ram_budget_bytes: u64,
nvme_cache_path: Option<PathBuf>,
enable_network_streaming: bool,
}
impl MemoryConfig {
pub fn builder() -> MemoryConfigBuilder {
MemoryConfigBuilder::default()
}
pub fn auto_detect() -> Self {
let recommended = crate::system_memory::RecommendedConfig::detect(None);
Self {
vram_budget_bytes: recommended.vram_bytes,
ram_budget_bytes: recommended.ram_bytes,
nvme_cache_path: None,
enable_network_streaming: false,
}
}
pub fn auto_detect_with_vram(vram_bytes: u64) -> Self {
let recommended = crate::system_memory::RecommendedConfig::with_gpu(vram_bytes);
Self {
vram_budget_bytes: (vram_bytes as f64 * 0.9) as u64, ram_budget_bytes: recommended.ram_bytes,
nvme_cache_path: None,
enable_network_streaming: recommended.use_nvme_cache,
}
}
pub fn vram_budget_bytes(&self) -> u64 {
self.vram_budget_bytes
}
pub fn ram_budget_bytes(&self) -> u64 {
self.ram_budget_bytes
}
}
#[derive(Debug, Default)]
pub struct MemoryConfigBuilder {
vram_budget_mb: Option<u64>,
ram_budget_mb: Option<u64>,
nvme_cache_path: Option<PathBuf>,
enable_network_streaming: bool,
}
impl MemoryConfigBuilder {
pub fn vram_budget_mb(mut self, mb: u64) -> Self {
self.vram_budget_mb = Some(mb);
self
}
pub fn ram_budget_mb(mut self, mb: u64) -> Self {
self.ram_budget_mb = Some(mb);
self
}
pub fn nvme_cache_path(mut self, path: impl Into<PathBuf>) -> Self {
self.nvme_cache_path = Some(path.into());
self
}
pub fn enable_network_streaming(mut self, enable: bool) -> Self {
self.enable_network_streaming = enable;
self
}
pub fn build(self) -> MemoryConfig {
MemoryConfig {
vram_budget_bytes: self.vram_budget_mb.unwrap_or(20_000) * 1024 * 1024,
ram_budget_bytes: self.ram_budget_mb.unwrap_or(64_000) * 1024 * 1024,
nvme_cache_path: self.nvme_cache_path,
enable_network_streaming: self.enable_network_streaming,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum StreamPriority {
Background = 0,
Normal = 1,
High = 2,
Critical = 3,
}
impl Default for StreamPriority {
fn default() -> Self {
Self::Normal
}
}
#[derive(Debug, Clone, Default)]
pub struct StreamStats {
pub bytes_transferred: u64,
pub fragments_loaded: u64,
pub avg_latency_ms: f64,
pub throughput_mbps: f64,
}
pub struct StreamManager {
max_concurrent: usize,
active_count: AtomicUsize,
stats: Mutex<StreamStats>,
}
impl StreamManager {
pub fn new(max_concurrent: usize) -> Self {
Self {
max_concurrent,
active_count: AtomicUsize::new(0),
stats: Mutex::new(StreamStats::default()),
}
}
pub fn max_concurrent_streams(&self) -> usize {
self.max_concurrent
}
pub fn active_streams(&self) -> usize {
self.active_count.load(Ordering::Relaxed)
}
pub fn stats(&self) -> StreamStats {
self.stats.lock().clone()
}
}
#[derive(Debug, Clone)]
pub struct HoloInferenceConfig {
pub initial_quality: f32,
pub target_quality: f32,
pub min_quality: f32,
pub background_improvement: bool,
pub enable_streaming: bool,
pub num_fragments: u16,
pub vram_budget: usize,
pub ram_budget: usize,
pub memory_config: MemoryConfig,
}
impl Default for HoloInferenceConfig {
fn default() -> Self {
Self {
initial_quality: 0.4,
target_quality: 0.95,
min_quality: 0.7,
background_improvement: true,
enable_streaming: true,
num_fragments: 32,
vram_budget: 22 * 1024 * 1024 * 1024, ram_budget: 64 * 1024 * 1024 * 1024, memory_config: MemoryConfig::auto_detect(),
}
}
}
impl HoloInferenceConfig {
pub fn builder() -> HoloInferenceConfigBuilder {
HoloInferenceConfigBuilder::default()
}
pub fn initial_quality(&self) -> f32 {
self.initial_quality
}
pub fn target_quality(&self) -> f32 {
self.target_quality
}
pub fn min_quality(&self) -> f32 {
self.min_quality
}
pub fn background_improvement_enabled(&self) -> bool {
self.background_improvement
}
pub fn streaming_enabled(&self) -> bool {
self.enable_streaming
}
}
#[derive(Debug, Default)]
pub struct HoloInferenceConfigBuilder {
initial_quality: Option<f32>,
target_quality: Option<f32>,
min_quality: Option<f32>,
background_improvement: Option<bool>,
enable_streaming: Option<bool>,
num_fragments: Option<u16>,
vram_budget: Option<usize>,
ram_budget: Option<usize>,
memory_config: Option<MemoryConfig>,
}
impl HoloInferenceConfigBuilder {
pub fn initial_quality(mut self, q: f32) -> Self {
self.initial_quality = Some(q);
self
}
pub fn target_quality(mut self, q: f32) -> Self {
self.target_quality = Some(q);
self
}
pub fn min_quality(mut self, q: f32) -> Self {
self.min_quality = Some(q);
self
}
pub fn enable_background_improvement(mut self, enable: bool) -> Self {
self.background_improvement = Some(enable);
self
}
pub fn enable_streaming(mut self, enable: bool) -> Self {
self.enable_streaming = Some(enable);
self
}
pub fn num_fragments(mut self, n: u16) -> Self {
self.num_fragments = Some(n);
self
}
pub fn vram_budget(mut self, bytes: usize) -> Self {
self.vram_budget = Some(bytes);
self
}
pub fn ram_budget(mut self, bytes: usize) -> Self {
self.ram_budget = Some(bytes);
self
}
pub fn memory_config(mut self, config: MemoryConfig) -> Self {
self.memory_config = Some(config);
self
}
pub fn build(self) -> HoloInferenceConfig {
HoloInferenceConfig {
initial_quality: self.initial_quality.unwrap_or(0.4),
target_quality: self.target_quality.unwrap_or(0.95),
min_quality: self.min_quality.unwrap_or(0.7),
background_improvement: self.background_improvement.unwrap_or(true),
enable_streaming: self.enable_streaming.unwrap_or(true),
num_fragments: self.num_fragments.unwrap_or(32),
vram_budget: self.vram_budget.unwrap_or(22 * 1024 * 1024 * 1024),
ram_budget: self.ram_budget.unwrap_or(64 * 1024 * 1024 * 1024),
memory_config: self.memory_config.unwrap_or_else(MemoryConfig::auto_detect),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct HoloInferenceStats {
pub total_inferences: u64,
pub avg_inference_quality: f64,
pub fragments_promoted: u64,
pub cache_hits: u64,
pub cache_misses: u64,
}
#[derive(Debug, Clone)]
pub struct HoloModelMetadata {
pub model_id: String,
pub total_parameters: u64,
pub total_fragments: u16,
pub encoding: HolographicEncoding,
pub layers: usize,
pub num_layers: usize,
pub hidden_size: usize,
pub num_heads: usize,
pub num_kv_heads: usize,
pub original_size: u64,
pub hct_size: u64,
pub verified_quality: f32,
}
pub struct HoloMemoryManager {
config: MemoryConfig,
vram_used: AtomicU64,
ram_used: AtomicU64,
fragment_locations: RwLock<HashMap<(usize, u16), FragmentLocation>>, }
impl HoloMemoryManager {
pub fn new(config: MemoryConfig) -> Self {
Self {
config,
vram_used: AtomicU64::new(0),
ram_used: AtomicU64::new(0),
fragment_locations: RwLock::new(HashMap::new()),
}
}
pub fn available_vram(&self) -> u64 {
let used = self.vram_used.load(Ordering::Relaxed);
self.config.vram_budget_bytes.saturating_sub(used)
}
pub fn available_ram(&self) -> u64 {
let used = self.ram_used.load(Ordering::Relaxed);
self.config.ram_budget_bytes.saturating_sub(used)
}
pub fn vram_used(&self) -> u64 {
self.vram_used.load(Ordering::Relaxed)
}
pub fn ram_used(&self) -> u64 {
self.ram_used.load(Ordering::Relaxed)
}
pub fn register_fragment(&self, layer: usize, fragment_id: u16, tier: MemoryTier) {
let mut locations = self.fragment_locations.write();
locations.insert(
(layer, fragment_id),
FragmentLocation::new(fragment_id, tier),
);
}
pub fn get_fragment_location(
&self,
layer: usize,
fragment_id: u16,
) -> Option<FragmentLocation> {
let locations = self.fragment_locations.read();
locations.get(&(layer, fragment_id)).cloned()
}
}
pub use converter::{
validate_hct_directory, ConversionConfig, ConversionMetadata, ConversionPhase,
ConversionProgress, ConvertedTensor, HoloModelConverter, TensorInfo, ValidationReport,
};
pub use tiered_loading::{
LayerWeightInfo, PlacementDecision, TieredConfig, TieredHoloLoader, TieredStats,
};
pub struct ProgressiveWeightProvider {
metadata: HoloModelMetadata,
memory_manager: Arc<HoloMemoryManager>,
stream_manager: Arc<StreamManager>,
layer_quality: RwLock<HashMap<usize, QualityMetrics>>,
}
impl ProgressiveWeightProvider {
pub fn new(
metadata: HoloModelMetadata,
memory_manager: Arc<HoloMemoryManager>,
stream_manager: Arc<StreamManager>,
) -> Self {
Self {
metadata,
memory_manager,
stream_manager,
layer_quality: RwLock::new(HashMap::new()),
}
}
pub fn metadata(&self) -> &HoloModelMetadata {
&self.metadata
}
pub fn layer_quality(&self, layer: usize) -> f32 {
self.layer_quality
.read()
.get(&layer)
.map(|m| m.current_quality())
.unwrap_or(0.0)
}
pub fn set_layer_target(&self, layer: usize, target: f32) {
let mut qualities = self.layer_quality.write();
qualities
.entry(layer)
.or_insert_with(QualityMetrics::default)
.target_quality = target;
}
pub fn memory_manager(&self) -> &Arc<HoloMemoryManager> {
&self.memory_manager
}
pub fn stream_manager(&self) -> &Arc<StreamManager> {
&self.stream_manager
}
}
#[cfg(feature = "cuda")]
pub use crate::cuda_inference::weight_store::LayerWeights;
#[cfg(not(feature = "cuda"))]
pub struct LayerWeights {
pub index: usize,
}