Skip to main content

hanzo_hmm/
lib.rs

1//! Hamiltonian Hidden-Markov MarketMaker (HMM) for heterogeneous compute.
2//!
3//! AMM-analogue with HMM dynamics. Quotes prices for compute resources
4//! (different GPU classes, model sizes, latencies) using Hidden-Markov state
5//! transitions for market regimes plus Hamiltonian mechanics for energy-
6//! conserving price evolution. BitDelta 1-bit quantization compresses
7//! per-tenant price-adapter tables. Active-inference (expected free energy)
8//! drives quote width / inventory decisions.
9//!
10//! Distinct from the inference engine: this crate sets *prices*; the engine
11//! at `~/work/hanzo/engine` actually *runs* models.
12
13pub mod hmm_core;
14pub mod regime;
15pub mod hamiltonian;
16pub mod bitdelta;
17pub mod routing;
18pub mod adapter;
19pub mod storage;
20pub mod free_energy;
21
22use std::sync::Arc;
23
24use serde::{Serialize, Deserialize};
25use anyhow::Result;
26
27pub use regime::{Regime, RegimeDetector, MarkovChain};
28pub use hamiltonian::{HamiltonianDynamics, PhaseSpace, PriceDynamics};
29pub use bitdelta::{BitDeltaAdapter, BitQuantizer, AdapterCache};
30pub use routing::{Router, RoutingDecision, ModelSelection};
31pub use adapter::{UserAdapter, AdapterManager};
32pub use storage::{Storage, VectorIndex};
33pub use free_energy::{ExpectedFreeEnergy, BeliefState, Precision};
34
35/// Main MarketMaker system configuration
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct Config {
38    /// Number of regime states
39    pub num_regimes: usize,
40    
41    /// Transition probability threshold
42    pub transition_threshold: f64,
43    
44    /// Hamiltonian energy scale
45    pub energy_scale: f64,
46    
47    /// BitDelta quantization bits
48    pub quantization_bits: usize,
49    
50    /// Expected free energy precision
51    pub efe_precision: f64,
52    
53    /// Database path for storage
54    pub db_path: String,
55    
56    /// Vector dimension for embeddings
57    pub vector_dim: usize,
58    
59    /// Cache size for adapters
60    pub adapter_cache_size: usize,
61}
62
63impl Default for Config {
64    fn default() -> Self {
65        Self {
66            num_regimes: 4,  // Exploration, Exploitation, Crisis, Transition
67            transition_threshold: 0.15,
68            energy_scale: 1.0,
69            quantization_bits: 1,  // 1-bit for BitDelta
70            efe_precision: 0.01,
71            db_path: "./marketmaker_storage.db".to_string(),
72            vector_dim: 768,  // Standard embedding dimension
73            adapter_cache_size: 100,
74        }
75    }
76}
77
78/// Main MarketMaker system for routing decisions
79pub struct MarketMaker {
80    config: Config,
81    regime_detector: Arc<RegimeDetector>,
82    hamiltonian: Arc<HamiltonianDynamics>,
83    router: Arc<Router>,
84    adapter_manager: Arc<AdapterManager>,
85    storage: Arc<Storage>,
86}
87
88impl MarketMaker {
89    /// Create a new MarketMaker system
90    pub async fn new(config: Config) -> Result<Self> {
91        let storage = Arc::new(Storage::new(&config.db_path).await?);
92        
93        let regime_detector = Arc::new(RegimeDetector::new(
94            config.num_regimes,
95            config.transition_threshold,
96        )?);
97        
98        let hamiltonian = Arc::new(HamiltonianDynamics::new(
99            config.energy_scale,
100            config.vector_dim,
101        ));
102        
103        let router = Arc::new(Router::new(
104            regime_detector.clone(),
105            hamiltonian.clone(),
106        ));
107        
108        let adapter_manager = Arc::new(AdapterManager::new(
109            storage.clone(),
110            config.adapter_cache_size,
111            config.quantization_bits,
112        ));
113        
114        Ok(Self {
115            config,
116            regime_detector,
117            hamiltonian,
118            router,
119            adapter_manager,
120            storage,
121        })
122    }
123    
124    /// Get routing decision for a request
125    pub async fn route_request(
126        &self,
127        user_id: &str,
128        request: &RoutingRequest,
129    ) -> Result<RoutingDecision> {
130        // Get user adapter
131        let adapter_lock = self.adapter_manager.get_or_create(user_id).await?;
132        
133        // Detect current regime
134        let regime = self.regime_detector.detect_regime(&request.observations)?;
135        
136        // Calculate expected free energy
137        let efe = {
138            let adapter = adapter_lock.read().await;
139            self.calculate_efe(&*adapter, &regime, request).await?
140        };
141        
142        // Get routing decision
143        let decision = {
144            let adapter = adapter_lock.read().await;
145            self.router.decide(
146                regime,
147                efe,
148                adapter.get_adapter(),
149                request,
150            ).await?
151        };
152        
153        // Update adapter based on decision
154        self.adapter_manager.update_adapter(
155            user_id,
156            &decision,
157            request,
158        ).await?;
159        
160        Ok(decision)
161    }
162    
163    /// Calculate expected free energy for decision making
164    async fn calculate_efe(
165        &self,
166        adapter: &UserAdapter,
167        regime: &Regime,
168        request: &RoutingRequest,
169    ) -> Result<ExpectedFreeEnergy> {
170        let belief_state = BeliefState::from_request(request)?;
171        let precision = Precision::from_regime(regime);
172        
173        ExpectedFreeEnergy::calculate(
174            belief_state,
175            precision,
176            &adapter.get_parameters(),
177        )
178    }
179    
180    /// Get current system state
181    pub async fn get_state(&self) -> Result<SystemState> {
182        let regime_state = self.regime_detector.get_current_state()?;
183        let phase_space = self.hamiltonian.get_phase_space()?;
184        let cache_stats = self.adapter_manager.get_cache_stats().await?;
185        
186        Ok(SystemState {
187            current_regime: regime_state.current_regime,
188            transition_probabilities: regime_state.transition_matrix,
189            hamiltonian_energy: phase_space.total_energy(),
190            active_adapters: cache_stats.active_count,
191            total_requests: cache_stats.total_requests,
192        })
193    }
194}
195
196/// Request for routing decision
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct RoutingRequest {
199    /// Input text or prompt
200    pub input: String,
201    
202    /// Context history
203    pub context: Vec<String>,
204    
205    /// User preferences
206    pub preferences: UserPreferences,
207    
208    /// Performance requirements
209    pub requirements: PerformanceRequirements,
210    
211    /// Observations for regime detection
212    pub observations: Vec<f64>,
213}
214
215/// User preferences for model selection
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct UserPreferences {
218    pub max_latency_ms: Option<u64>,
219    pub max_cost_per_token: Option<f64>,
220    pub preferred_models: Vec<String>,
221    pub quality_threshold: f64,
222}
223
224/// Performance requirements
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct PerformanceRequirements {
227    pub min_tokens_per_second: Option<f64>,
228    pub max_memory_gb: Option<f64>,
229    pub requires_function_calling: bool,
230    pub requires_vision: bool,
231}
232
233/// System state snapshot
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct SystemState {
236    pub current_regime: Regime,
237    pub transition_probabilities: Vec<Vec<f64>>,
238    pub hamiltonian_energy: f64,
239    pub active_adapters: usize,
240    pub total_requests: u64,
241}
242
243#[cfg(test)]
244mod tests {
245    use super::*;
246    
247    #[tokio::test]
248    async fn test_marketmaker_creation() {
249        let config = Config::default();
250        let mm = MarketMaker::new(config).await.unwrap();
251        let state = mm.get_state().await.unwrap();
252
253        assert!(state.hamiltonian_energy >= 0.0);
254        // Regime can be any valid state on initialization
255        assert!(matches!(
256            state.current_regime,
257            Regime::Exploration | Regime::Exploitation | Regime::Transition
258        ));
259    }
260}