Move 17 library crates into crates/, CLI binary into bin/fxt, consolidate 10 test crates into testing/, split config crate from deployment config files. Root directory reduced from 38+ to ~17 directories. All Cargo.toml paths and build.rs proto refs updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
340 lines
8.9 KiB
Rust
340 lines
8.9 KiB
Rust
//! Model Factory for Testing
|
|
//!
|
|
//! This module provides factory functions for creating model instances
|
|
//! primarily for testing purposes.
|
|
|
|
use crate::{Features, MLModel, MLResult, ModelMetadata, ModelPrediction, ModelType};
|
|
use std::sync::Arc;
|
|
|
|
/// Simple `DQN` wrapper for testing
|
|
#[derive(Debug)]
|
|
pub struct DQNWrapper {
|
|
model_id: String,
|
|
}
|
|
|
|
impl DQNWrapper {
|
|
/// Create a new `DQN` wrapper
|
|
pub fn new(model_id: String) -> Self {
|
|
Self { model_id }
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl MLModel for DQNWrapper {
|
|
fn name(&self) -> &str {
|
|
&self.model_id
|
|
}
|
|
|
|
fn model_type(&self) -> ModelType {
|
|
ModelType::DQN
|
|
}
|
|
|
|
async fn predict(&self, _features: &Features) -> MLResult<ModelPrediction> {
|
|
// Simple stub implementation for testing
|
|
Ok(ModelPrediction::new(
|
|
self.model_id.clone(),
|
|
0.5, // prediction value
|
|
0.8, // confidence
|
|
))
|
|
}
|
|
|
|
fn get_confidence(&self) -> f64 {
|
|
0.8
|
|
}
|
|
|
|
fn get_metadata(&self) -> ModelMetadata {
|
|
ModelMetadata::new(
|
|
ModelType::DQN,
|
|
"1.0.0".to_owned(),
|
|
10, // features_used
|
|
128.0, // memory_usage_mb
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Create a `DQN` wrapper for testing
|
|
pub fn create_dqn_wrapper() -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(DQNWrapper::new("test_dqn".to_owned())))
|
|
}
|
|
|
|
/// Create a `DQN` wrapper with specific model ID
|
|
pub fn create_dqn_wrapper_with_id(model_id: String) -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(DQNWrapper::new(model_id)))
|
|
}
|
|
|
|
/// Simple PPO wrapper for testing
|
|
#[derive(Debug)]
|
|
pub struct PPOWrapper {
|
|
model_id: String,
|
|
}
|
|
|
|
impl PPOWrapper {
|
|
/// Create a new PPO wrapper
|
|
pub fn new(model_id: String) -> Self {
|
|
Self { model_id }
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl MLModel for PPOWrapper {
|
|
fn name(&self) -> &str {
|
|
&self.model_id
|
|
}
|
|
|
|
fn model_type(&self) -> ModelType {
|
|
ModelType::PPO
|
|
}
|
|
|
|
async fn predict(&self, _features: &Features) -> MLResult<ModelPrediction> {
|
|
// Simple stub implementation for testing
|
|
Ok(ModelPrediction::new(
|
|
self.model_id.clone(),
|
|
0.6, // prediction value
|
|
0.85, // confidence
|
|
))
|
|
}
|
|
|
|
fn get_confidence(&self) -> f64 {
|
|
0.85
|
|
}
|
|
|
|
fn get_metadata(&self) -> ModelMetadata {
|
|
ModelMetadata::new(
|
|
ModelType::PPO,
|
|
"1.0.0".to_owned(),
|
|
15, // features_used
|
|
145.0, // memory_usage_mb
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Create a PPO wrapper for testing
|
|
pub fn create_ppo_wrapper() -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(PPOWrapper::new("test_ppo".to_owned())))
|
|
}
|
|
|
|
/// Create a PPO wrapper with specific model ID
|
|
pub fn create_ppo_wrapper_with_id(model_id: String) -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(PPOWrapper::new(model_id)))
|
|
}
|
|
|
|
/// Simple TFT wrapper for testing
|
|
#[derive(Debug)]
|
|
pub struct TFTWrapper {
|
|
model_id: String,
|
|
}
|
|
|
|
impl TFTWrapper {
|
|
/// Create a new TFT wrapper
|
|
pub fn new(model_id: String) -> Self {
|
|
Self { model_id }
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl MLModel for TFTWrapper {
|
|
fn name(&self) -> &str {
|
|
&self.model_id
|
|
}
|
|
|
|
fn model_type(&self) -> ModelType {
|
|
ModelType::TFT
|
|
}
|
|
|
|
async fn predict(&self, _features: &Features) -> MLResult<ModelPrediction> {
|
|
// Simple stub implementation for testing
|
|
Ok(ModelPrediction::new(
|
|
self.model_id.clone(),
|
|
0.55, // prediction value
|
|
0.82, // confidence
|
|
))
|
|
}
|
|
|
|
fn get_confidence(&self) -> f64 {
|
|
0.82
|
|
}
|
|
|
|
fn get_metadata(&self) -> ModelMetadata {
|
|
ModelMetadata::new(
|
|
ModelType::TFT,
|
|
"1.0.0".to_owned(),
|
|
20, // features_used
|
|
125.0, // memory_usage_mb
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Create a TFT wrapper for testing
|
|
pub fn create_tft_wrapper() -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(TFTWrapper::new("test_tft".to_owned())))
|
|
}
|
|
|
|
/// Create a TFT wrapper with specific model ID
|
|
pub fn create_tft_wrapper_with_id(model_id: String) -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(TFTWrapper::new(model_id)))
|
|
}
|
|
|
|
/// Simple MAMBA wrapper for testing
|
|
#[derive(Debug)]
|
|
pub struct MambaWrapper {
|
|
model_id: String,
|
|
}
|
|
|
|
impl MambaWrapper {
|
|
/// Create a new MAMBA wrapper
|
|
pub fn new(model_id: String) -> Self {
|
|
Self { model_id }
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl MLModel for MambaWrapper {
|
|
fn name(&self) -> &str {
|
|
&self.model_id
|
|
}
|
|
|
|
fn model_type(&self) -> ModelType {
|
|
ModelType::MAMBA
|
|
}
|
|
|
|
async fn predict(&self, _features: &Features) -> MLResult<ModelPrediction> {
|
|
// Simple stub implementation for testing
|
|
Ok(ModelPrediction::new(
|
|
self.model_id.clone(),
|
|
0.58, // prediction value
|
|
0.87, // confidence
|
|
))
|
|
}
|
|
|
|
fn get_confidence(&self) -> f64 {
|
|
0.87
|
|
}
|
|
|
|
fn get_metadata(&self) -> ModelMetadata {
|
|
ModelMetadata::new(
|
|
ModelType::MAMBA,
|
|
"1.0.0".to_owned(),
|
|
25, // features_used
|
|
164.0, // memory_usage_mb
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Create a MAMBA wrapper for testing
|
|
pub fn create_mamba_wrapper() -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(MambaWrapper::new("test_mamba".to_owned())))
|
|
}
|
|
|
|
/// Create a MAMBA wrapper with specific model ID
|
|
pub fn create_mamba_wrapper_with_id(model_id: String) -> MLResult<Arc<dyn MLModel>> {
|
|
Ok(Arc::new(MambaWrapper::new(model_id)))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_create_dqn_wrapper() {
|
|
let model = create_dqn_wrapper().unwrap();
|
|
assert_eq!(model.name(), "test_dqn");
|
|
assert_eq!(model.model_type(), ModelType::DQN);
|
|
assert!(model.is_ready());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_dqn_wrapper_prediction() {
|
|
let model = create_dqn_wrapper().unwrap();
|
|
let features = Features::new(
|
|
vec![1.0, 2.0, 3.0],
|
|
vec!["f1".to_owned(), "f2".to_owned(), "f3".to_owned()],
|
|
);
|
|
|
|
let prediction = model.predict(&features).await.unwrap();
|
|
assert_eq!(prediction.value, 0.5);
|
|
assert_eq!(prediction.confidence, 0.8);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_ppo_wrapper() {
|
|
let model = create_ppo_wrapper().unwrap();
|
|
assert_eq!(model.name(), "test_ppo");
|
|
assert_eq!(model.model_type(), ModelType::PPO);
|
|
assert!(model.is_ready());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_ppo_wrapper_prediction() {
|
|
let model = create_ppo_wrapper().unwrap();
|
|
let features = Features::new(
|
|
vec![1.0, 2.0, 3.0],
|
|
vec!["f1".to_owned(), "f2".to_owned(), "f3".to_owned()],
|
|
);
|
|
|
|
let prediction = model.predict(&features).await.unwrap();
|
|
assert_eq!(prediction.value, 0.6);
|
|
assert_eq!(prediction.confidence, 0.85);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_tft_wrapper() {
|
|
let model = create_tft_wrapper().unwrap();
|
|
assert_eq!(model.name(), "test_tft");
|
|
assert_eq!(model.model_type(), ModelType::TFT);
|
|
assert!(model.is_ready());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_tft_wrapper_prediction() {
|
|
let model = create_tft_wrapper().unwrap();
|
|
let features = Features::new(
|
|
vec![1.0, 2.0, 3.0],
|
|
vec!["f1".to_owned(), "f2".to_owned(), "f3".to_owned()],
|
|
);
|
|
|
|
let prediction = model.predict(&features).await.unwrap();
|
|
assert_eq!(prediction.value, 0.55);
|
|
assert_eq!(prediction.confidence, 0.82);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_mamba_wrapper() {
|
|
let model = create_mamba_wrapper().unwrap();
|
|
assert_eq!(model.name(), "test_mamba");
|
|
assert_eq!(model.model_type(), ModelType::MAMBA);
|
|
assert!(model.is_ready());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_mamba_wrapper_prediction() {
|
|
let model = create_mamba_wrapper().unwrap();
|
|
let features = Features::new(
|
|
vec![1.0, 2.0, 3.0],
|
|
vec!["f1".to_owned(), "f2".to_owned(), "f3".to_owned()],
|
|
);
|
|
|
|
let prediction = model.predict(&features).await.unwrap();
|
|
assert_eq!(prediction.value, 0.58);
|
|
assert_eq!(prediction.confidence, 0.87);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_all_wrappers_with_custom_ids() {
|
|
let dqn = create_dqn_wrapper_with_id("custom_dqn".to_owned()).unwrap();
|
|
let ppo = create_ppo_wrapper_with_id("custom_ppo".to_owned()).unwrap();
|
|
let tft = create_tft_wrapper_with_id("custom_tft".to_owned()).unwrap();
|
|
let mamba = create_mamba_wrapper_with_id("custom_mamba".to_owned()).unwrap();
|
|
|
|
assert_eq!(dqn.name(), "custom_dqn");
|
|
assert_eq!(ppo.name(), "custom_ppo");
|
|
assert_eq!(tft.name(), "custom_tft");
|
|
assert_eq!(mamba.name(), "custom_mamba");
|
|
|
|
// All models should be ready
|
|
assert!(dqn.is_ready());
|
|
assert!(ppo.is_ready());
|
|
assert!(tft.is_ready());
|
|
assert!(mamba.is_ready());
|
|
}
|
|
}
|