Spaces:
Runtime error
Runtime error
docs: improve enterprise code documentation, formatting, and 10-agent Copilot architecture details
2817797 | """ | |
| ================================================================================ | |
| CONFIGURATION LOADER - Centralized Settings Management | |
| ================================================================================ | |
| PURPOSE: | |
| Single-point configuration loading for the entire application. Reads config.yaml | |
| once at startup, caches the result, and resolves relative paths to absolute | |
| paths for consistent behavior regardless of working directory. | |
| KEY RESPONSIBILITIES: | |
| 1. Parse config.yaml (YAML format) | |
| 2. Cache configuration globally (singleton pattern) | |
| 3. Resolve relative paths to absolute paths | |
| 4. Support both project-root and working-directory lookups | |
| 5. Provide consistent paths for models, data, and ML artifacts | |
| CONFIGURATION STRUCTURE (config.yaml): | |
| graph: # Graph analysis settings | |
| pagerank_alpha: 0.85 # PageRank damping factor | |
| pagerank_max_iter: 100 # PageRank iterations | |
| betweenness_k: auto # Betweenness centrality sampling | |
| ml: # Machine learning configuration | |
| model_path: models/... # Scikit-learn model location | |
| scaler_path: models/... # Feature scaler pickle | |
| gnn_model_path: models/... # PyTorch GNN weights | |
| feature_columns: [...] # Expected input features | |
| data: # Data paths | |
| raw_path: data/raw/ # Raw transaction CSV | |
| processed_path: data/proc/ # Processed data | |
| transactions_path: data/... # Transaction database | |
| alerts_db_path: data/alerts.db # Alert cache | |
| detection: # Detector thresholds | |
| cycle_threshold: 3 # Min cycle length | |
| mule_threshold: 5 # Min mule members | |
| round_trip_threshold: 0.8 # Confidence cutoff | |
| api: # API configuration | |
| host: 0.0.0.0 | |
| port: 8000 | |
| debug: true | |
| PATH RESOLUTION: | |
| Relative paths are resolved relative to project root: | |
| config.yaml location → parent dir → project root | |
| Lookup strategy: | |
| 1. Try config_path = ${PROJECT_ROOT}/config.yaml | |
| 2. If not found: Try config_path = cwd/config.yaml | |
| 3. Use whichever directory contains config.yaml as base | |
| Path resolution (ml and data sections): | |
| - Absolute paths (starting with /) are used as-is | |
| - Relative paths are joined with project_root | |
| - Result: paths work regardless of cwd | |
| SINGLETON PATTERN: | |
| _config: Global cache (module-level) | |
| - None until first get_config() call | |
| - Loaded once, reused thereafter | |
| - Thread-safe for read operations | |
| - (Update requires module reload) | |
| PERFORMANCE: | |
| - Single YAML parse (not per-request) | |
| - Cached in memory | |
| - Path resolution happens once at load time | |
| - No file I/O after initial load | |
| DEPENDENCIES: | |
| - PyYAML: YAML parsing | |
| - os: Path manipulation | |
| USAGE EXAMPLE: | |
| from src.config_loader import get_config | |
| # First call loads and caches | |
| cfg = get_config() | |
| # Subsequent calls return cached result | |
| cfg = get_config() # No file I/O, instant | |
| # Access settings | |
| pagerank_alpha = cfg['graph']['pagerank_alpha'] | |
| model_path = cfg['ml']['model_path'] # Absolute path | |
| # Create loader with config | |
| loader = DataLoader(cfg['data']['raw_path']) | |
| predictor = HybridPredictor() | |
| predictor.load_models() # Uses cfg['ml']['...'] | |
| CONFIGURATION BEST PRACTICES: | |
| 1. Store config.yaml in project root (not in src/) | |
| 2. Use relative paths (so it works in any deployment) | |
| 3. Never hardcode paths in code | |
| 4. Use get_config() for all settings | |
| 5. Document all config options in config.yaml | |
| ERROR HANDLING: | |
| - FileNotFoundError if config.yaml not found | |
| - yaml.YAMLError if YAML syntax invalid | |
| - KeyError if accessing non-existent config key (handle explicitly) | |
| NOTES: | |
| - Configuration is read-only after startup | |
| - To change config: restart the application | |
| - Environment variables can override (if added to loader) | |
| - No validation of config values (application code must check) | |
| ================================================================================ | |
| """ | |
| import yaml | |
| import os | |
| _config = None | |
| def get_config() -> dict: | |
| global _config | |
| if _config is None: | |
| project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| config_path = os.path.join(project_root, 'config.yaml') | |
| if not os.path.exists(config_path): | |
| config_path = 'config.yaml' | |
| project_root = os.getcwd() | |
| with open(config_path, 'r') as f: | |
| _config = yaml.safe_load(f) | |
| # Resolve relative model/data paths to absolute so they work regardless of cwd | |
| if 'ml' in _config: | |
| for key in ('model_path', 'scaler_path', 'gnn_model_path'): | |
| if key in _config['ml'] and not os.path.isabs(_config['ml'][key]): | |
| _config['ml'][key] = os.path.join(project_root, _config['ml'][key]) | |
| if 'data' in _config: | |
| for key in ('raw_path', 'processed_path', 'transactions_path', 'alerts_db_path'): | |
| if key in _config['data'] and not os.path.isabs(_config['data'][key]): | |
| _config['data'][key] = os.path.join(project_root, _config['data'][key]) | |
| return _config | |