expops 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. expops-0.1.3.dist-info/METADATA +826 -0
  2. expops-0.1.3.dist-info/RECORD +86 -0
  3. expops-0.1.3.dist-info/WHEEL +5 -0
  4. expops-0.1.3.dist-info/entry_points.txt +3 -0
  5. expops-0.1.3.dist-info/licenses/LICENSE +674 -0
  6. expops-0.1.3.dist-info/top_level.txt +1 -0
  7. mlops/__init__.py +0 -0
  8. mlops/__main__.py +11 -0
  9. mlops/_version.py +34 -0
  10. mlops/adapters/__init__.py +12 -0
  11. mlops/adapters/base.py +86 -0
  12. mlops/adapters/config_schema.py +89 -0
  13. mlops/adapters/custom/__init__.py +3 -0
  14. mlops/adapters/custom/custom_adapter.py +447 -0
  15. mlops/adapters/plugin_manager.py +113 -0
  16. mlops/adapters/sklearn/__init__.py +3 -0
  17. mlops/adapters/sklearn/adapter.py +94 -0
  18. mlops/cluster/__init__.py +3 -0
  19. mlops/cluster/controller.py +496 -0
  20. mlops/cluster/process_runner.py +91 -0
  21. mlops/cluster/providers.py +258 -0
  22. mlops/core/__init__.py +95 -0
  23. mlops/core/custom_model_base.py +38 -0
  24. mlops/core/dask_networkx_executor.py +1265 -0
  25. mlops/core/executor_worker.py +1239 -0
  26. mlops/core/experiment_tracker.py +81 -0
  27. mlops/core/graph_types.py +64 -0
  28. mlops/core/networkx_parser.py +135 -0
  29. mlops/core/payload_spill.py +278 -0
  30. mlops/core/pipeline_utils.py +162 -0
  31. mlops/core/process_hashing.py +216 -0
  32. mlops/core/step_state_manager.py +1298 -0
  33. mlops/core/step_system.py +956 -0
  34. mlops/core/workspace.py +99 -0
  35. mlops/environment/__init__.py +10 -0
  36. mlops/environment/base.py +43 -0
  37. mlops/environment/conda_manager.py +307 -0
  38. mlops/environment/factory.py +70 -0
  39. mlops/environment/pyenv_manager.py +146 -0
  40. mlops/environment/setup_env.py +31 -0
  41. mlops/environment/system_manager.py +66 -0
  42. mlops/environment/utils.py +105 -0
  43. mlops/environment/venv_manager.py +134 -0
  44. mlops/main.py +527 -0
  45. mlops/managers/project_manager.py +400 -0
  46. mlops/managers/reproducibility_manager.py +575 -0
  47. mlops/platform.py +996 -0
  48. mlops/reporting/__init__.py +16 -0
  49. mlops/reporting/context.py +187 -0
  50. mlops/reporting/entrypoint.py +292 -0
  51. mlops/reporting/kv_utils.py +77 -0
  52. mlops/reporting/registry.py +50 -0
  53. mlops/runtime/__init__.py +9 -0
  54. mlops/runtime/context.py +34 -0
  55. mlops/runtime/env_export.py +113 -0
  56. mlops/storage/__init__.py +12 -0
  57. mlops/storage/adapters/__init__.py +9 -0
  58. mlops/storage/adapters/gcp_kv_store.py +778 -0
  59. mlops/storage/adapters/gcs_object_store.py +96 -0
  60. mlops/storage/adapters/memory_store.py +240 -0
  61. mlops/storage/adapters/redis_store.py +438 -0
  62. mlops/storage/factory.py +199 -0
  63. mlops/storage/interfaces/__init__.py +6 -0
  64. mlops/storage/interfaces/kv_store.py +118 -0
  65. mlops/storage/path_utils.py +38 -0
  66. mlops/templates/premier-league/charts/plot_metrics.js +70 -0
  67. mlops/templates/premier-league/charts/plot_metrics.py +145 -0
  68. mlops/templates/premier-league/charts/requirements.txt +6 -0
  69. mlops/templates/premier-league/configs/cluster_config.yaml +13 -0
  70. mlops/templates/premier-league/configs/project_config.yaml +207 -0
  71. mlops/templates/premier-league/data/England CSV.csv +12154 -0
  72. mlops/templates/premier-league/models/premier_league_model.py +638 -0
  73. mlops/templates/premier-league/requirements.txt +8 -0
  74. mlops/templates/sklearn-basic/README.md +22 -0
  75. mlops/templates/sklearn-basic/charts/plot_metrics.py +85 -0
  76. mlops/templates/sklearn-basic/charts/requirements.txt +3 -0
  77. mlops/templates/sklearn-basic/configs/project_config.yaml +64 -0
  78. mlops/templates/sklearn-basic/data/train.csv +14 -0
  79. mlops/templates/sklearn-basic/models/model.py +62 -0
  80. mlops/templates/sklearn-basic/requirements.txt +10 -0
  81. mlops/web/__init__.py +3 -0
  82. mlops/web/server.py +585 -0
  83. mlops/web/ui/index.html +52 -0
  84. mlops/web/ui/mlops-charts.js +357 -0
  85. mlops/web/ui/script.js +1244 -0
  86. mlops/web/ui/styles.css +248 -0
mlops/__main__.py ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MLOps Platform __main__ module
4
+
5
+ Allows the package to be run with `python -m mlops.main`
6
+ """
7
+
8
+ from .main import main
9
+
10
+ if __name__ == '__main__':
11
+ main()
mlops/_version.py ADDED
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.1.3'
32
+ __version_tuple__ = version_tuple = (0, 1, 3)
33
+
34
+ __commit_id__ = commit_id = None
@@ -0,0 +1,12 @@
1
+ """Adapter plugins package.
2
+
3
+ This package contains subpackages that each expose an `Adapter` symbol
4
+ for plugin discovery (e.g., `mlops.adapters.custom.Adapter`).
5
+ """
6
+
7
+ __all__ = [
8
+ "custom",
9
+ "sklearn",
10
+ ]
11
+
12
+
mlops/adapters/base.py ADDED
@@ -0,0 +1,86 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, Optional
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+ @dataclass
7
+ class ModelConfig:
8
+ """Configuration for a model adapter."""
9
+ name: str
10
+ framework: str
11
+ language: str
12
+ version: str
13
+ parameters: Dict[str, Any]
14
+ requirements: Dict[str, str]
15
+ hardware_requirements: Optional[Dict[str, Any]] = None
16
+
17
+ class ModelAdapter(ABC):
18
+ """Base class for all model adapters.
19
+
20
+ This interface defines the contract that all model adapters must implement.
21
+ It provides methods for training, evaluation, and model management.
22
+ """
23
+
24
+ def __init__(self, config: ModelConfig, python_interpreter: Optional[str] = None, environment_name: Optional[str] = None, conda_env_name: Optional[str] = None):
25
+ self.config = config
26
+ self.model = None
27
+ self.python_interpreter = python_interpreter
28
+
29
+ # Support both new and legacy parameter names
30
+ self.environment_name = environment_name or conda_env_name
31
+ # Keep legacy property for backward compatibility
32
+ self.conda_env_name = self.environment_name
33
+
34
+ if self.python_interpreter:
35
+ print(f"[{self.__class__.__name__}] Initialized with Python interpreter: {self.python_interpreter}")
36
+
37
+ if self.environment_name:
38
+ print(f"[{self.__class__.__name__}] Initialized with environment: {self.environment_name}")
39
+ else:
40
+ print(f"[{self.__class__.__name__}] Initialized without specific environment")
41
+
42
+ @abstractmethod
43
+ def initialize(self) -> None:
44
+ """Initialize the model with the given configuration."""
45
+ pass
46
+
47
+ @abstractmethod
48
+ def run(self, data_paths: Dict[str, Path] | None = None, **kwargs) -> Dict[str, Any]:
49
+ """Run the pipeline according to the configured processes/steps.
50
+
51
+ Args:
52
+ data_paths: Optional mapping of named data roles to paths (e.g., {"training": Path(...), "validation": Path(...)}).
53
+ **kwargs: Additional parameters forwarded to the adapter/pipeline.
54
+
55
+ Returns:
56
+ Dictionary containing pipeline results and/or metrics.
57
+ """
58
+ pass
59
+
60
+ @abstractmethod
61
+ def save(self, path: Path) -> None:
62
+ """Save the model to the specified path."""
63
+ pass
64
+
65
+ @abstractmethod
66
+ def load(self, path: Path) -> None:
67
+ """Load the model from the specified path."""
68
+ pass
69
+
70
+ # Optional prediction interface for adapters that expose direct predict APIs
71
+ def predict(self, data: Any) -> Any:
72
+ """Optional: Make predictions using the model if supported by the adapter."""
73
+ raise NotImplementedError("This adapter does not implement a direct predict() API.")
74
+
75
+ @classmethod
76
+ @abstractmethod
77
+ def validate_config(cls, config: ModelConfig) -> bool:
78
+ """Validate the configuration for this adapter.
79
+
80
+ Args:
81
+ config: Configuration to validate
82
+
83
+ Returns:
84
+ True if configuration is valid, False otherwise
85
+ """
86
+ pass
@@ -0,0 +1,89 @@
1
+ from typing import Dict, Any, Optional, List, Union
2
+ from pydantic import BaseModel, Field, ConfigDict
3
+
4
+ class HardwareRequirements(BaseModel):
5
+ """Hardware requirements for model training."""
6
+ gpu: bool = False
7
+ min_memory_gb: Optional[float] = None
8
+ min_cpu_cores: Optional[int] = None
9
+
10
+ class ModelParameters(BaseModel):
11
+ """Model-specific parameters."""
12
+ class_name: Optional[str] = Field(None, description="Fully qualified class name of the model (for pre-built frameworks)")
13
+ custom_script_path: Optional[str] = Field(None, description="Path to the custom Python script (relative to project root or absolute)")
14
+ custom_target: Optional[str] = Field(None, description="(Optional) Name of the class or function within the custom script. If not provided, the adapter will look for a MLOpsCustomModelBase subclass.")
15
+ hyperparameters: Dict[str, Any] = Field(default_factory=dict, description="Model initialization parameters")
16
+ training_params: Dict[str, Any] = Field(default_factory=dict, description="Training-specific parameters")
17
+ # Caching and execution
18
+ cache: Dict[str, Any] = Field(default_factory=dict, description="Caching configuration (ttl_hours, backend, object_store)")
19
+ executor: Dict[str, Any] = Field(default_factory=dict, description="Executor configuration (n_workers, scheduler_address)")
20
+
21
+ # NetworkX pipeline configuration - supports process-level DAGs with step-level loops
22
+ pipeline: Optional[Dict[str, Any]] = Field(None, description="NetworkX pipeline configuration with processes and steps")
23
+
24
+ class AdapterConfig(BaseModel):
25
+ """Configuration for a model adapter."""
26
+ name: str = Field(..., description="Name of the model")
27
+ framework: str = Field(..., description="ML framework (e.g., sklearn, pytorch, tensorflow, custom)")
28
+ language: str = Field(..., description="Programming language (e.g., python, cpp)")
29
+ version: str = Field(..., description="Version of the framework or custom model")
30
+ parameters: ModelParameters = Field(..., description="Model-specific parameters")
31
+ requirements: Dict[str, str] = Field(
32
+ default_factory=dict,
33
+ description="Package requirements (package_name: version)"
34
+ )
35
+ hardware_requirements: Optional[HardwareRequirements] = Field(
36
+ None,
37
+ description="Hardware requirements for training"
38
+ )
39
+
40
+ model_config = ConfigDict(
41
+ json_schema_extra={
42
+ "example": {
43
+ "name": "custom_model_with_loops",
44
+ "framework": "custom",
45
+ "language": "python",
46
+ "version": "1.0.0",
47
+ "parameters": {
48
+ "custom_script_path": "examples/custom_models/networkx_examples/models/kmeans_model.py",
49
+ "custom_target": "KMeansCustomModel",
50
+ "hyperparameters": {
51
+ "n_clusters": 3,
52
+ "max_iterations": 100,
53
+ "convergence_threshold": 0.001
54
+ },
55
+ # NetworkX pipeline configuration with process-level DAGs and step-level loops
56
+ "pipeline": {
57
+ "process_adjlist": "data_prep clustering\nclustering evaluation",
58
+ "processes": [
59
+ {"name": "data_prep", "max_iterations": 1},
60
+ {"name": "clustering", "max_iterations": 100, "convergence_threshold": 0.001},
61
+ {"name": "evaluation", "max_iterations": 1}
62
+ ],
63
+ "steps": [
64
+ {"name": "preprocess_data", "process": "data_prep"},
65
+ {"name": "initialize_centroids", "process": "clustering"},
66
+ {"name": "update_centroids", "process": "clustering", "loop_back_to": "assign_clusters"},
67
+ {"name": "assign_clusters", "process": "clustering", "depends_on": ["update_centroids"], "loop_back_to": "update_centroids"},
68
+ {"name": "evaluate_clustering", "process": "evaluation", "depends_on": ["assign_clusters"]}
69
+ ],
70
+ "execution": {
71
+ "parallel": True,
72
+ "failure_mode": "stop",
73
+ "max_workers": 4
74
+ }
75
+ }
76
+ },
77
+ "requirements": {
78
+ "networkx": "3.0",
79
+ "numpy": "1.24.0",
80
+ "scikit-learn": "1.3.0"
81
+ },
82
+ "hardware_requirements": {
83
+ "gpu": False,
84
+ "min_memory_gb": 4.0,
85
+ "min_cpu_cores": 2
86
+ }
87
+ }
88
+ }
89
+ )
@@ -0,0 +1,3 @@
1
+ from .custom_adapter import CustomModelAdapter
2
+
3
+ Adapter = CustomModelAdapter