Skip to content

Commit 2c6cbfb

Browse files
authored
Merge pull request #15 from phanhongan/template_manager
Add Template Manager
2 parents 420f80a + 22cf255 commit 2c6cbfb

28 files changed

Lines changed: 567 additions & 557 deletions
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Template Strategy
2+
3+
## Overview
4+
5+
This document outlines the strategy for managing configuration templates in the ML Systems Evaluation Framework.
6+
7+
## Current State
8+
9+
The framework uses external YAML files for template management:
10+
11+
1. **TemplateManager**: Loads templates from external files
12+
2. **Template Location**: `ml_eval/templates/files/` with categorized subdirectories
13+
14+
## Development Roadmap
15+
16+
### Phase 1: ✅ Current State (As-Is)
17+
18+
- ✅ TemplateManager loads from external files
19+
- ✅ Templates organized by categories
20+
21+
### Phase 2: 🔄 Future State (To-Be)
22+
23+
- 🔄 LLM-powered template generation and customization
24+
- 🔄 Natural language template creation and modification
25+
- 🔄 Intelligent template validation and error correction
26+
- 🔄 Template marketplace/registry for community contributions
27+
- 🔄 Template sharing and distribution ecosystem
28+
29+
## Template Structure
30+
31+
```
32+
ml_eval/templates/files/
33+
├── collectors/ # Data collection configurations
34+
├── evaluators/ # Evaluation method configurations
35+
├── reports/ # Report generation configurations
36+
└── industries/ # Industry-specific templates
37+
```
38+
39+
## Conclusion
40+
41+
The framework provides a template management system with:
42+
43+
- **Easy customization** and version control for all templates
44+
- **Organized structure** for better discoverability and maintenance
45+
- **Future-ready architecture** for advanced features
46+
47+
This approach enables future enhancements and ecosystem growth.

ml_eval/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@
4848
from .reports.reliability import ReliabilityReport
4949
from .reports.safety import SafetyReport
5050

51-
# Templates and examples
52-
from .templates.factory import TemplateFactory
53-
5451
__version__ = "0.1.0"
5552
__author__ = "ML Systems Evaluation Team"
5653
__description__ = "Industrial AI Reliability Assessment Framework"
@@ -87,6 +84,5 @@
8784
"SafetyEvaluator",
8885
"SafetyReport",
8986
"SchedulingAgent",
90-
"TemplateFactory",
9187
"cli_main",
9288
]

ml_eval/config/factory.py

Lines changed: 96 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pathlib import Path
55
from typing import Any
66

7+
from ..templates import TemplateManager
78
from .loader import ConfigLoader
89
from .validator import ConfigValidator
910

@@ -15,6 +16,7 @@ def __init__(self, config_dir: str | None = None):
1516
self.config_dir = config_dir or os.getcwd()
1617
self.loader = ConfigLoader()
1718
self.validator = ConfigValidator()
19+
self.template_manager = TemplateManager()
1820
self._config_cache: dict[str, dict[str, Any]] = {}
1921

2022
def create_config(self, config_path: str) -> dict[str, Any]:
@@ -44,7 +46,14 @@ def create_config(self, config_path: str) -> dict[str, Any]:
4446

4547
def create_collector_config(self, collector_type: str, **kwargs) -> dict[str, Any]:
4648
"""Create configuration for a specific collector type"""
47-
base_config = self._get_base_collector_config(collector_type)
49+
# Try to get from template first
50+
try:
51+
base_config = self.template_manager.get_template(
52+
"base", f"collector_{collector_type}"
53+
)
54+
except ValueError:
55+
# Fallback to hardcoded config
56+
base_config = self._get_base_collector_config(collector_type)
4857

4958
# Merge with provided kwargs
5059
config = {**base_config, **kwargs}
@@ -58,7 +67,14 @@ def create_collector_config(self, collector_type: str, **kwargs) -> dict[str, An
5867

5968
def create_evaluator_config(self, evaluator_type: str, **kwargs) -> dict[str, Any]:
6069
"""Create configuration for a specific evaluator type"""
61-
base_config = self._get_base_evaluator_config(evaluator_type)
70+
# Try to get from template first
71+
try:
72+
base_config = self.template_manager.get_template(
73+
"base", f"evaluator_{evaluator_type}"
74+
)
75+
except ValueError:
76+
# Fallback to hardcoded config
77+
base_config = self._get_base_evaluator_config(evaluator_type)
6278

6379
# Merge with provided kwargs
6480
config = {**base_config, **kwargs}
@@ -72,7 +88,14 @@ def create_evaluator_config(self, evaluator_type: str, **kwargs) -> dict[str, An
7288

7389
def create_report_config(self, report_type: str, **kwargs) -> dict[str, Any]:
7490
"""Create configuration for a specific report type"""
75-
base_config = self._get_base_report_config(report_type)
91+
# Try to get from template first
92+
try:
93+
base_config = self.template_manager.get_template(
94+
"base", f"report_{report_type}"
95+
)
96+
except ValueError:
97+
# Fallback to hardcoded config
98+
base_config = self._get_base_report_config(report_type)
7699

77100
# Merge with provided kwargs
78101
config = {**base_config, **kwargs}
@@ -85,123 +108,35 @@ def create_report_config(self, report_type: str, **kwargs) -> dict[str, Any]:
85108
return config
86109

87110
def _get_base_collector_config(self, collector_type: str) -> dict[str, Any]:
88-
"""Get base configuration for a collector type"""
89-
base_configs = {
90-
"environmental": {
91-
"type": "environmental",
92-
"sensor_types": ["temperature", "pressure", "humidity"],
93-
"sampling_interval": 60,
94-
"alert_thresholds": {},
95-
},
96-
"offline": {
97-
"type": "offline",
98-
"data_sources": [],
99-
"file_patterns": ["*.json", "*.csv"],
100-
"parsing_rules": {},
101-
},
102-
"online": {
103-
"type": "online",
104-
"endpoints": [],
105-
"polling_interval": 30,
106-
"timeout": 10,
107-
"retry_attempts": 3,
108-
},
109-
"regulatory": {
110-
"type": "regulatory",
111-
"compliance_frameworks": [],
112-
"audit_requirements": {},
113-
"reporting_frequency": "monthly",
114-
},
115-
}
116-
117-
result = base_configs.get(collector_type, {"type": collector_type})
118-
if not isinstance(result, dict):
119-
result = {"type": collector_type}
120-
return result
111+
"""Get base configuration for a collector type from template"""
112+
try:
113+
return self.template_manager.get_template(
114+
"base", f"collector_{collector_type}"
115+
)
116+
except Exception as e:
117+
raise ValueError(
118+
f"No template found for collector type '{collector_type}': {e}"
119+
) from e
121120

122121
def _get_base_evaluator_config(self, evaluator_type: str) -> dict[str, Any]:
123-
"""Get base configuration for an evaluator type"""
124-
base_configs = {
125-
"performance": {
126-
"type": "performance",
127-
"metrics": ["accuracy", "precision", "recall", "f1"],
128-
"thresholds": {},
129-
"baseline_comparison": True,
130-
},
131-
"reliability": {
132-
"type": "reliability",
133-
"availability_threshold": 0.99,
134-
"slo_targets": {
135-
"slos": {
136-
"availability": {
137-
"target": 0.99,
138-
"window": "24h",
139-
"description": "System availability",
140-
},
141-
},
142-
},
143-
},
144-
"safety": {
145-
"type": "safety",
146-
"safety_thresholds": {},
147-
"risk_assessment": True,
148-
"incident_tracking": True,
149-
},
150-
"compliance": {
151-
"type": "compliance",
152-
"standards": [],
153-
"audit_requirements": {},
154-
"reporting_frequency": "monthly",
155-
},
156-
"drift": {
157-
"type": "drift",
158-
"detection_methods": ["statistical", "ml_based"],
159-
"sensitivity": 0.05,
160-
"window_size": 1000,
161-
},
162-
}
163-
164-
result = base_configs.get(evaluator_type, {"type": evaluator_type})
165-
if not isinstance(result, dict):
166-
result = {"type": evaluator_type}
167-
return result
122+
"""Get base configuration for an evaluator type from template"""
123+
try:
124+
return self.template_manager.get_template(
125+
"base", f"evaluator_{evaluator_type}"
126+
)
127+
except Exception as e:
128+
raise ValueError(
129+
f"No template found for evaluator type '{evaluator_type}': {e}"
130+
) from e
168131

169132
def _get_base_report_config(self, report_type: str) -> dict[str, Any]:
170-
"""Get base configuration for a report type"""
171-
base_configs = {
172-
"business": {
173-
"type": "business",
174-
"metrics": ["revenue_impact", "cost_savings", "efficiency_gains"],
175-
"format": "html",
176-
"frequency": "weekly",
177-
},
178-
"compliance": {
179-
"type": "compliance",
180-
"standards": [],
181-
"audit_trail": True,
182-
"format": "pdf",
183-
"frequency": "monthly",
184-
},
185-
"reliability": {
186-
"type": "reliability",
187-
"slo_metrics": [],
188-
"error_budgets": {},
189-
"format": "html",
190-
"frequency": "daily",
191-
},
192-
"safety": {
193-
"type": "safety",
194-
"safety_metrics": [],
195-
"incident_reports": True,
196-
"format": "html",
197-
"frequency": "daily",
198-
},
199-
}
200-
201-
result = base_configs.get(report_type, {"type": report_type})
202-
if not isinstance(result, dict):
203-
result = {"type": report_type}
204-
return result
133+
"""Get base configuration for a report type from template"""
134+
try:
135+
return self.template_manager.get_template("base", f"report_{report_type}")
136+
except Exception as e:
137+
raise ValueError(
138+
f"No template found for report type '{report_type}': {e}"
139+
) from e
205140

206141
def list_available_configs(self) -> list[str]:
207142
"""List all available configuration files"""
@@ -226,6 +161,51 @@ def get_cached_config(self, config_path: str) -> dict[str, Any] | None:
226161
"""Get cached configuration if available"""
227162
return self._config_cache.get(config_path)
228163

164+
def create_template_files(self, output_dir: str | None = None) -> list[str]:
165+
"""Create external template files from hardcoded configurations"""
166+
created_files = []
167+
168+
# Create base collector templates
169+
collector_types = ["environmental", "offline", "online", "regulatory"]
170+
for collector_type in collector_types:
171+
self._get_base_collector_config(collector_type)
172+
file_path = self.template_manager.create_template_file(
173+
"base",
174+
f"collector_{collector_type}",
175+
output_dir and f"{output_dir}/base-collector_{collector_type}.yaml",
176+
)
177+
created_files.append(file_path)
178+
179+
# Create base evaluator templates
180+
evaluator_types = [
181+
"performance",
182+
"reliability",
183+
"safety",
184+
"compliance",
185+
"drift",
186+
]
187+
for evaluator_type in evaluator_types:
188+
self._get_base_evaluator_config(evaluator_type)
189+
file_path = self.template_manager.create_template_file(
190+
"base",
191+
f"evaluator_{evaluator_type}",
192+
output_dir and f"{output_dir}/base-evaluator_{evaluator_type}.yaml",
193+
)
194+
created_files.append(file_path)
195+
196+
# Create base report templates
197+
report_types = ["business", "compliance", "reliability", "safety"]
198+
for report_type in report_types:
199+
self._get_base_report_config(report_type)
200+
file_path = self.template_manager.create_template_file(
201+
"base",
202+
f"report_{report_type}",
203+
output_dir and f"{output_dir}/base-report_{report_type}.yaml",
204+
)
205+
created_files.append(file_path)
206+
207+
return created_files
208+
229209
def _validate_collector(self, collector: dict[str, Any]) -> bool:
230210
"""Validate a collector configuration"""
231211
return isinstance(collector, dict)

0 commit comments

Comments
 (0)