mcli-framework 7.12.1__py3-none-any.whl → 7.12.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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (216) hide show
  1. mcli/app/__init__.py +0 -2
  2. mcli/app/commands_cmd.py +19 -23
  3. mcli/app/completion_helpers.py +5 -5
  4. mcli/app/init_cmd.py +10 -10
  5. mcli/app/lock_cmd.py +82 -27
  6. mcli/app/main.py +2 -8
  7. mcli/app/model/model.py +5 -10
  8. mcli/app/store_cmd.py +8 -8
  9. mcli/app/video/__init__.py +0 -2
  10. mcli/app/video/video.py +1 -14
  11. mcli/chat/chat.py +90 -108
  12. mcli/chat/command_rag.py +0 -4
  13. mcli/chat/enhanced_chat.py +32 -41
  14. mcli/chat/system_controller.py +37 -37
  15. mcli/chat/system_integration.py +4 -5
  16. mcli/cli.py +2 -3
  17. mcli/lib/api/api.py +4 -9
  18. mcli/lib/api/daemon_client.py +19 -20
  19. mcli/lib/api/daemon_client_local.py +1 -3
  20. mcli/lib/api/daemon_decorator.py +6 -6
  21. mcli/lib/api/mcli_decorators.py +4 -8
  22. mcli/lib/auth/__init__.py +0 -1
  23. mcli/lib/auth/auth.py +4 -5
  24. mcli/lib/auth/mcli_manager.py +7 -12
  25. mcli/lib/auth/token_util.py +5 -5
  26. mcli/lib/config/__init__.py +29 -1
  27. mcli/lib/config/config.py +0 -1
  28. mcli/lib/custom_commands.py +1 -1
  29. mcli/lib/discovery/command_discovery.py +15 -15
  30. mcli/lib/erd/erd.py +7 -7
  31. mcli/lib/files/files.py +1 -1
  32. mcli/lib/fs/__init__.py +31 -1
  33. mcli/lib/fs/fs.py +12 -13
  34. mcli/lib/lib.py +0 -1
  35. mcli/lib/logger/logger.py +7 -10
  36. mcli/lib/performance/optimizer.py +25 -27
  37. mcli/lib/performance/rust_bridge.py +22 -27
  38. mcli/lib/performance/uvloop_config.py +0 -1
  39. mcli/lib/pickles/__init__.py +0 -1
  40. mcli/lib/pickles/pickles.py +0 -2
  41. mcli/lib/secrets/commands.py +0 -2
  42. mcli/lib/secrets/manager.py +0 -1
  43. mcli/lib/secrets/repl.py +2 -3
  44. mcli/lib/secrets/store.py +1 -2
  45. mcli/lib/services/data_pipeline.py +34 -34
  46. mcli/lib/services/lsh_client.py +38 -40
  47. mcli/lib/shell/shell.py +2 -2
  48. mcli/lib/toml/__init__.py +0 -1
  49. mcli/lib/ui/styling.py +0 -1
  50. mcli/lib/ui/visual_effects.py +33 -41
  51. mcli/lib/watcher/watcher.py +0 -1
  52. mcli/ml/__init__.py +1 -1
  53. mcli/ml/api/__init__.py +1 -1
  54. mcli/ml/api/app.py +8 -9
  55. mcli/ml/api/middleware.py +10 -10
  56. mcli/ml/api/routers/__init__.py +1 -1
  57. mcli/ml/api/routers/admin_router.py +3 -3
  58. mcli/ml/api/routers/auth_router.py +17 -18
  59. mcli/ml/api/routers/backtest_router.py +2 -2
  60. mcli/ml/api/routers/data_router.py +2 -2
  61. mcli/ml/api/routers/model_router.py +14 -15
  62. mcli/ml/api/routers/monitoring_router.py +2 -2
  63. mcli/ml/api/routers/portfolio_router.py +2 -2
  64. mcli/ml/api/routers/prediction_router.py +10 -9
  65. mcli/ml/api/routers/trade_router.py +2 -2
  66. mcli/ml/api/routers/websocket_router.py +6 -7
  67. mcli/ml/api/schemas.py +2 -2
  68. mcli/ml/auth/__init__.py +1 -1
  69. mcli/ml/auth/auth_manager.py +22 -23
  70. mcli/ml/auth/models.py +17 -17
  71. mcli/ml/auth/permissions.py +17 -17
  72. mcli/ml/backtesting/__init__.py +1 -1
  73. mcli/ml/backtesting/backtest_engine.py +31 -35
  74. mcli/ml/backtesting/performance_metrics.py +12 -14
  75. mcli/ml/backtesting/run.py +1 -2
  76. mcli/ml/cache.py +35 -36
  77. mcli/ml/cli/__init__.py +1 -1
  78. mcli/ml/cli/main.py +21 -24
  79. mcli/ml/config/__init__.py +1 -1
  80. mcli/ml/config/settings.py +28 -29
  81. mcli/ml/configs/__init__.py +1 -1
  82. mcli/ml/configs/dvc_config.py +14 -15
  83. mcli/ml/configs/mlflow_config.py +12 -13
  84. mcli/ml/configs/mlops_manager.py +19 -21
  85. mcli/ml/dashboard/__init__.py +4 -4
  86. mcli/ml/dashboard/app.py +20 -30
  87. mcli/ml/dashboard/app_supabase.py +16 -19
  88. mcli/ml/dashboard/app_training.py +11 -14
  89. mcli/ml/dashboard/cli.py +2 -2
  90. mcli/ml/dashboard/common.py +2 -3
  91. mcli/ml/dashboard/components/__init__.py +1 -1
  92. mcli/ml/dashboard/components/charts.py +13 -11
  93. mcli/ml/dashboard/components/metrics.py +7 -7
  94. mcli/ml/dashboard/components/tables.py +12 -9
  95. mcli/ml/dashboard/overview.py +2 -2
  96. mcli/ml/dashboard/pages/__init__.py +1 -1
  97. mcli/ml/dashboard/pages/cicd.py +15 -18
  98. mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
  99. mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
  100. mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
  101. mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
  102. mcli/ml/dashboard/pages/test_portfolio.py +3 -6
  103. mcli/ml/dashboard/pages/trading.py +16 -18
  104. mcli/ml/dashboard/pages/workflows.py +20 -30
  105. mcli/ml/dashboard/utils.py +9 -9
  106. mcli/ml/dashboard/warning_suppression.py +3 -3
  107. mcli/ml/data_ingestion/__init__.py +1 -1
  108. mcli/ml/data_ingestion/api_connectors.py +41 -46
  109. mcli/ml/data_ingestion/data_pipeline.py +36 -46
  110. mcli/ml/data_ingestion/stream_processor.py +43 -46
  111. mcli/ml/database/__init__.py +1 -1
  112. mcli/ml/database/migrations/env.py +2 -2
  113. mcli/ml/database/models.py +22 -24
  114. mcli/ml/database/session.py +14 -14
  115. mcli/ml/experimentation/__init__.py +1 -1
  116. mcli/ml/experimentation/ab_testing.py +45 -46
  117. mcli/ml/features/__init__.py +1 -1
  118. mcli/ml/features/ensemble_features.py +22 -27
  119. mcli/ml/features/recommendation_engine.py +30 -30
  120. mcli/ml/features/stock_features.py +29 -32
  121. mcli/ml/features/test_feature_engineering.py +10 -11
  122. mcli/ml/logging.py +4 -4
  123. mcli/ml/mlops/__init__.py +1 -1
  124. mcli/ml/mlops/data_versioning.py +29 -30
  125. mcli/ml/mlops/experiment_tracker.py +24 -24
  126. mcli/ml/mlops/model_serving.py +31 -34
  127. mcli/ml/mlops/pipeline_orchestrator.py +27 -35
  128. mcli/ml/models/__init__.py +5 -6
  129. mcli/ml/models/base_models.py +23 -23
  130. mcli/ml/models/ensemble_models.py +31 -31
  131. mcli/ml/models/recommendation_models.py +18 -19
  132. mcli/ml/models/test_models.py +14 -16
  133. mcli/ml/monitoring/__init__.py +1 -1
  134. mcli/ml/monitoring/drift_detection.py +32 -36
  135. mcli/ml/monitoring/metrics.py +2 -2
  136. mcli/ml/optimization/__init__.py +1 -1
  137. mcli/ml/optimization/optimize.py +1 -2
  138. mcli/ml/optimization/portfolio_optimizer.py +30 -32
  139. mcli/ml/predictions/__init__.py +1 -1
  140. mcli/ml/preprocessing/__init__.py +1 -1
  141. mcli/ml/preprocessing/data_cleaners.py +22 -23
  142. mcli/ml/preprocessing/feature_extractors.py +23 -26
  143. mcli/ml/preprocessing/ml_pipeline.py +23 -23
  144. mcli/ml/preprocessing/test_preprocessing.py +7 -8
  145. mcli/ml/scripts/populate_sample_data.py +0 -4
  146. mcli/ml/serving/serve.py +1 -2
  147. mcli/ml/tasks.py +17 -17
  148. mcli/ml/tests/test_integration.py +29 -30
  149. mcli/ml/tests/test_training_dashboard.py +21 -21
  150. mcli/ml/trading/__init__.py +1 -1
  151. mcli/ml/trading/migrations.py +5 -5
  152. mcli/ml/trading/models.py +21 -23
  153. mcli/ml/trading/paper_trading.py +16 -13
  154. mcli/ml/trading/risk_management.py +17 -18
  155. mcli/ml/trading/trading_service.py +25 -28
  156. mcli/ml/training/__init__.py +1 -1
  157. mcli/ml/training/train.py +0 -1
  158. mcli/public/oi/oi.py +1 -2
  159. mcli/self/completion_cmd.py +6 -10
  160. mcli/self/logs_cmd.py +19 -24
  161. mcli/self/migrate_cmd.py +22 -20
  162. mcli/self/redis_cmd.py +10 -11
  163. mcli/self/self_cmd.py +10 -18
  164. mcli/self/store_cmd.py +10 -12
  165. mcli/self/visual_cmd.py +9 -14
  166. mcli/self/zsh_cmd.py +2 -4
  167. mcli/workflow/daemon/async_command_database.py +23 -24
  168. mcli/workflow/daemon/async_process_manager.py +27 -29
  169. mcli/workflow/daemon/client.py +27 -33
  170. mcli/workflow/daemon/daemon.py +32 -36
  171. mcli/workflow/daemon/enhanced_daemon.py +24 -33
  172. mcli/workflow/daemon/process_cli.py +11 -12
  173. mcli/workflow/daemon/process_manager.py +23 -26
  174. mcli/workflow/daemon/test_daemon.py +4 -5
  175. mcli/workflow/dashboard/dashboard_cmd.py +0 -1
  176. mcli/workflow/doc_convert.py +15 -17
  177. mcli/workflow/gcloud/__init__.py +0 -1
  178. mcli/workflow/gcloud/gcloud.py +11 -8
  179. mcli/workflow/git_commit/ai_service.py +14 -15
  180. mcli/workflow/lsh_integration.py +9 -11
  181. mcli/workflow/model_service/client.py +26 -31
  182. mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
  183. mcli/workflow/model_service/lightweight_embedder.py +25 -35
  184. mcli/workflow/model_service/lightweight_model_server.py +26 -32
  185. mcli/workflow/model_service/lightweight_test.py +7 -10
  186. mcli/workflow/model_service/model_service.py +80 -91
  187. mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
  188. mcli/workflow/model_service/openai_adapter.py +23 -23
  189. mcli/workflow/model_service/pdf_processor.py +21 -26
  190. mcli/workflow/model_service/test_efficient_runner.py +12 -16
  191. mcli/workflow/model_service/test_example.py +11 -13
  192. mcli/workflow/model_service/test_integration.py +3 -5
  193. mcli/workflow/model_service/test_new_features.py +7 -8
  194. mcli/workflow/notebook/converter.py +1 -1
  195. mcli/workflow/notebook/notebook_cmd.py +5 -6
  196. mcli/workflow/notebook/schema.py +0 -1
  197. mcli/workflow/notebook/validator.py +7 -3
  198. mcli/workflow/openai/openai.py +1 -2
  199. mcli/workflow/registry/registry.py +4 -1
  200. mcli/workflow/repo/repo.py +6 -7
  201. mcli/workflow/scheduler/cron_parser.py +16 -19
  202. mcli/workflow/scheduler/job.py +10 -10
  203. mcli/workflow/scheduler/monitor.py +15 -15
  204. mcli/workflow/scheduler/persistence.py +17 -18
  205. mcli/workflow/scheduler/scheduler.py +37 -38
  206. mcli/workflow/secrets/__init__.py +1 -1
  207. mcli/workflow/sync/test_cmd.py +0 -1
  208. mcli/workflow/wakatime/__init__.py +5 -9
  209. mcli/workflow/wakatime/wakatime.py +1 -2
  210. {mcli_framework-7.12.1.dist-info → mcli_framework-7.12.3.dist-info}/METADATA +1 -1
  211. mcli_framework-7.12.3.dist-info/RECORD +279 -0
  212. mcli_framework-7.12.1.dist-info/RECORD +0 -279
  213. {mcli_framework-7.12.1.dist-info → mcli_framework-7.12.3.dist-info}/WHEEL +0 -0
  214. {mcli_framework-7.12.1.dist-info → mcli_framework-7.12.3.dist-info}/entry_points.txt +0 -0
  215. {mcli_framework-7.12.1.dist-info → mcli_framework-7.12.3.dist-info}/licenses/LICENSE +0 -0
  216. {mcli_framework-7.12.1.dist-info → mcli_framework-7.12.3.dist-info}/top_level.txt +0 -0
@@ -1,21 +1,18 @@
1
- """REST API for model serving"""
1
+ """REST API for model serving."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  import logging
6
5
  import os
7
6
  import sys
8
7
  from contextlib import asynccontextmanager
9
8
  from datetime import datetime
10
- from pathlib import Path
11
- from typing import Any, Dict, List, Optional, Union
9
+ from typing import Any, Dict, List, Optional
12
10
 
13
11
  import numpy as np
14
12
  import pandas as pd
15
13
  import torch
16
14
  import uvicorn
17
15
  from fastapi import BackgroundTasks, FastAPI, File, HTTPException, UploadFile
18
- from fastapi.responses import JSONResponse
19
16
  from pydantic import BaseModel, Field
20
17
 
21
18
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
@@ -30,7 +27,7 @@ logger = logging.getLogger(__name__)
30
27
 
31
28
  # Pydantic models for API
32
29
  class PredictionRequest(BaseModel):
33
- """Request model for predictions"""
30
+ """Request model for predictions."""
34
31
 
35
32
  trading_data: Dict[str, Any] = Field(..., description="Politician trading data")
36
33
  stock_data: Optional[Dict[str, Any]] = Field(None, description="Stock price data")
@@ -39,7 +36,7 @@ class PredictionRequest(BaseModel):
39
36
 
40
37
 
41
38
  class PredictionResponse(BaseModel):
42
- """Response model for predictions"""
39
+ """Response model for predictions."""
43
40
 
44
41
  recommendations: List[Dict[str, Any]]
45
42
  timestamp: str
@@ -48,7 +45,7 @@ class PredictionResponse(BaseModel):
48
45
 
49
46
 
50
47
  class HealthResponse(BaseModel):
51
- """Health check response"""
48
+ """Health check response."""
52
49
 
53
50
  status: str
54
51
  model_loaded: bool
@@ -57,7 +54,7 @@ class HealthResponse(BaseModel):
57
54
 
58
55
 
59
56
  class ModelMetricsResponse(BaseModel):
60
- """Model metrics response"""
57
+ """Model metrics response."""
61
58
 
62
59
  accuracy: float
63
60
  precision: float
@@ -67,14 +64,14 @@ class ModelMetricsResponse(BaseModel):
67
64
 
68
65
 
69
66
  class BatchPredictionRequest(BaseModel):
70
- """Batch prediction request"""
67
+ """Batch prediction request."""
71
68
 
72
69
  batch_id: str
73
70
  data: List[PredictionRequest]
74
71
 
75
72
 
76
73
  class BatchPredictionResponse(BaseModel):
77
- """Batch prediction response"""
74
+ """Batch prediction response."""
78
75
 
79
76
  batch_id: str
80
77
  status: str
@@ -83,7 +80,7 @@ class BatchPredictionResponse(BaseModel):
83
80
 
84
81
 
85
82
  class ModelEndpoint:
86
- """Model endpoint manager"""
83
+ """Model endpoint manager."""
87
84
 
88
85
  def __init__(self, model_path: Optional[str] = None):
89
86
  self.model = None
@@ -100,7 +97,7 @@ class ModelEndpoint:
100
97
  self._setup_feature_extractors()
101
98
 
102
99
  def _setup_feature_extractors(self):
103
- """Initialize feature extractors"""
100
+ """Initialize feature extractors."""
104
101
  self.feature_extractors = {
105
102
  "stock": StockRecommendationFeatures(),
106
103
  "political": PoliticalInfluenceFeatures(),
@@ -109,7 +106,7 @@ class ModelEndpoint:
109
106
  logger.info("Feature extractors initialized")
110
107
 
111
108
  def load_model(self, model_path: str):
112
- """Load model from file"""
109
+ """Load model from file."""
113
110
  try:
114
111
  checkpoint = torch.load(model_path, map_location="cpu")
115
112
 
@@ -151,7 +148,7 @@ class ModelEndpoint:
151
148
  def extract_features(
152
149
  self, trading_data: pd.DataFrame, stock_data: Optional[pd.DataFrame] = None
153
150
  ) -> np.ndarray:
154
- """Extract features from raw data"""
151
+ """Extract features from raw data."""
155
152
  features = pd.DataFrame()
156
153
 
157
154
  # Extract political features
@@ -176,7 +173,7 @@ class ModelEndpoint:
176
173
  return features.values if not features.empty else np.array([[]])
177
174
 
178
175
  async def predict(self, request: PredictionRequest) -> PredictionResponse:
179
- """Generate predictions"""
176
+ """Generate predictions."""
180
177
  start_time = datetime.now()
181
178
 
182
179
  try:
@@ -259,7 +256,7 @@ class ModelEndpoint:
259
256
  raise HTTPException(status_code=500, detail=str(e))
260
257
 
261
258
  def _generate_mock_recommendations(self, tickers: List[str]) -> List[PortfolioRecommendation]:
262
- """Generate mock recommendations for testing"""
259
+ """Generate mock recommendations for testing."""
263
260
  recommendations = []
264
261
  for ticker in tickers:
265
262
  rec = PortfolioRecommendation(
@@ -276,7 +273,7 @@ class ModelEndpoint:
276
273
  return recommendations
277
274
 
278
275
  def get_health(self) -> HealthResponse:
279
- """Get endpoint health status"""
276
+ """Get endpoint health status."""
280
277
  uptime = (datetime.now() - self.start_time).total_seconds()
281
278
 
282
279
  return HealthResponse(
@@ -287,7 +284,7 @@ class ModelEndpoint:
287
284
  )
288
285
 
289
286
  def get_metrics(self) -> Dict[str, Any]:
290
- """Get endpoint metrics"""
287
+ """Get endpoint metrics."""
291
288
  return {
292
289
  **self.metrics,
293
290
  "model_version": self.model_version,
@@ -297,7 +294,7 @@ class ModelEndpoint:
297
294
 
298
295
 
299
296
  class PredictionService:
300
- """Async prediction service for batch processing"""
297
+ """Async prediction service for batch processing."""
301
298
 
302
299
  def __init__(self, model_endpoint: ModelEndpoint):
303
300
  self.model_endpoint = model_endpoint
@@ -305,7 +302,7 @@ class PredictionService:
305
302
  self.executor = None
306
303
 
307
304
  async def process_batch(self, batch_request: BatchPredictionRequest) -> BatchPredictionResponse:
308
- """Process batch predictions asynchronously"""
305
+ """Process batch predictions asynchronously."""
309
306
  batch_id = batch_request.batch_id
310
307
 
311
308
  # Initialize batch job
@@ -341,7 +338,7 @@ class PredictionService:
341
338
  )
342
339
 
343
340
  def get_batch_status(self, batch_id: str) -> BatchPredictionResponse:
344
- """Get batch job status"""
341
+ """Get batch job status."""
345
342
  if batch_id not in self.batch_jobs:
346
343
  raise HTTPException(status_code=404, detail="Batch job not found")
347
344
 
@@ -356,7 +353,7 @@ class PredictionService:
356
353
 
357
354
 
358
355
  class ModelServer:
359
- """FastAPI model server"""
356
+ """FastAPI model server."""
360
357
 
361
358
  def __init__(self, model_path: Optional[str] = None):
362
359
  self.model_endpoint = ModelEndpoint(model_path)
@@ -365,7 +362,7 @@ class ModelServer:
365
362
 
366
363
  @asynccontextmanager
367
364
  async def lifespan(self, app: FastAPI):
368
- """Manage application lifecycle"""
365
+ """Manage application lifecycle."""
369
366
  # Startup
370
367
  logger.info("Starting model server...")
371
368
  yield
@@ -373,7 +370,7 @@ class ModelServer:
373
370
  logger.info("Shutting down model server...")
374
371
 
375
372
  def _create_app(self) -> FastAPI:
376
- """Create FastAPI application"""
373
+ """Create FastAPI application."""
377
374
  app = FastAPI(
378
375
  title="Stock Recommendation API",
379
376
  description="ML-powered stock recommendation system based on politician trading data",
@@ -384,19 +381,19 @@ class ModelServer:
384
381
  # Health check
385
382
  @app.get("/health", response_model=HealthResponse)
386
383
  async def health():
387
- """Health check endpoint"""
384
+ """Health check endpoint."""
388
385
  return self.model_endpoint.get_health()
389
386
 
390
387
  # Metrics
391
388
  @app.get("/metrics")
392
389
  async def metrics():
393
- """Get service metrics"""
390
+ """Get service metrics."""
394
391
  return self.model_endpoint.get_metrics()
395
392
 
396
393
  # Single prediction
397
394
  @app.post("/predict", response_model=PredictionResponse)
398
395
  async def predict(request: PredictionRequest):
399
- """Generate stock recommendations"""
396
+ """Generate stock recommendations."""
400
397
  return await self.model_endpoint.predict(request)
401
398
 
402
399
  # Batch prediction
@@ -404,7 +401,7 @@ class ModelServer:
404
401
  async def batch_predict(
405
402
  batch_request: BatchPredictionRequest, background_tasks: BackgroundTasks
406
403
  ):
407
- """Submit batch prediction job"""
404
+ """Submit batch prediction job."""
408
405
  background_tasks.add_task(self.prediction_service.process_batch, batch_request)
409
406
 
410
407
  return BatchPredictionResponse(
@@ -414,13 +411,13 @@ class ModelServer:
414
411
  # Batch status
415
412
  @app.get("/batch/{batch_id}", response_model=BatchPredictionResponse)
416
413
  async def batch_status(batch_id: str):
417
- """Get batch job status"""
414
+ """Get batch job status."""
418
415
  return self.prediction_service.get_batch_status(batch_id)
419
416
 
420
417
  # Model reload
421
418
  @app.post("/model/reload")
422
419
  async def reload_model(model_path: str):
423
- """Reload model from new path"""
420
+ """Reload model from new path."""
424
421
  try:
425
422
  self.model_endpoint.load_model(model_path)
426
423
  return {"status": "success", "model_version": self.model_endpoint.model_version}
@@ -430,7 +427,7 @@ class ModelServer:
430
427
  # Upload and predict
431
428
  @app.post("/upload/predict")
432
429
  async def upload_predict(file: UploadFile = File(...)):
433
- """Upload CSV and get predictions"""
430
+ """Upload CSV and get predictions."""
434
431
  try:
435
432
  # Read uploaded file
436
433
  content = await file.read()
@@ -455,12 +452,12 @@ class ModelServer:
455
452
  return app
456
453
 
457
454
  def run(self, host: str = "0.0.0.0", port: int = 8000):
458
- """Run the server"""
455
+ """Run the server."""
459
456
  uvicorn.run(self.app, host=host, port=port)
460
457
 
461
458
 
462
459
  def main():
463
- """Run the model server"""
460
+ """Run the model server."""
464
461
  import argparse
465
462
 
466
463
  parser = argparse.ArgumentParser(description="Stock Recommendation Model Server")
@@ -1,33 +1,25 @@
1
- """End-to-end ML pipeline orchestrator"""
1
+ """End-to-end ML pipeline orchestrator."""
2
2
 
3
3
  import os
4
4
  import sys
5
5
 
6
6
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
7
7
 
8
- import json
9
8
  import logging
10
9
  import pickle
11
10
  from dataclasses import dataclass, field
12
11
  from datetime import datetime
13
12
  from enum import Enum
14
13
  from pathlib import Path
15
- from typing import Any, Callable, Dict, List, Optional, Union
14
+ from typing import Any, Callable, Dict, List, Optional
16
15
 
17
16
  import numpy as np
18
17
  import pandas as pd
19
18
  import torch
20
19
  from ml.features.ensemble_features import EnsembleFeatureBuilder
21
20
  from ml.features.political_features import PoliticalInfluenceFeatures
22
- from ml.features.recommendation_engine import RecommendationConfig as FeatureRecommendationConfig
23
- from ml.features.recommendation_engine import StockRecommendationEngine
24
21
  from ml.features.stock_features import StockRecommendationFeatures
25
- from ml.models.ensemble_models import (
26
- DeepEnsembleModel,
27
- EnsembleConfig,
28
- EnsembleTrainer,
29
- ModelConfig,
30
- )
22
+ from ml.models.ensemble_models import EnsembleConfig, ModelConfig
31
23
  from ml.models.recommendation_models import (
32
24
  RecommendationConfig,
33
25
  RecommendationTrainer,
@@ -41,7 +33,7 @@ logger = logging.getLogger(__name__)
41
33
 
42
34
 
43
35
  class PipelineStage(Enum):
44
- """Pipeline execution stages"""
36
+ """Pipeline execution stages."""
45
37
 
46
38
  DATA_INGESTION = "data_ingestion"
47
39
  DATA_PREPROCESSING = "data_preprocessing"
@@ -53,7 +45,7 @@ class PipelineStage(Enum):
53
45
 
54
46
  @dataclass
55
47
  class PipelineStep:
56
- """Individual pipeline step configuration"""
48
+ """Individual pipeline step configuration."""
57
49
 
58
50
  name: str
59
51
  stage: PipelineStage
@@ -68,7 +60,7 @@ class PipelineStep:
68
60
 
69
61
  @dataclass
70
62
  class PipelineConfig:
71
- """Complete pipeline configuration"""
63
+ """Complete pipeline configuration."""
72
64
 
73
65
  name: str = "politician-trading-ml-pipeline"
74
66
  version: str = "1.0.0"
@@ -93,7 +85,7 @@ class PipelineConfig:
93
85
 
94
86
 
95
87
  class MLPipeline:
96
- """End-to-end ML pipeline orchestrator"""
88
+ """End-to-end ML pipeline orchestrator."""
97
89
 
98
90
  def __init__(self, config: PipelineConfig):
99
91
  self.config = config
@@ -115,7 +107,7 @@ class MLPipeline:
115
107
  self._setup_default_pipeline()
116
108
 
117
109
  def _setup_default_pipeline(self):
118
- """Setup default pipeline steps"""
110
+ """Setup default pipeline steps."""
119
111
  # Data ingestion
120
112
  self.add_step(
121
113
  PipelineStep(
@@ -189,12 +181,12 @@ class MLPipeline:
189
181
  )
190
182
 
191
183
  def add_step(self, step: PipelineStep):
192
- """Add step to pipeline"""
184
+ """Add step to pipeline."""
193
185
  self.steps.append(step)
194
186
  logger.debug(f"Added pipeline step: {step.name}")
195
187
 
196
188
  def _load_raw_data(self) -> Dict[str, pd.DataFrame]:
197
- """Load raw data from sources"""
189
+ """Load raw data from sources."""
198
190
  logger.info("Loading raw data...")
199
191
 
200
192
  # Load politician trading data
@@ -222,7 +214,7 @@ class MLPipeline:
222
214
  def _preprocess_data(
223
215
  self, trading_data: pd.DataFrame, stock_data: pd.DataFrame
224
216
  ) -> Dict[str, pd.DataFrame]:
225
- """Preprocess raw data"""
217
+ """Preprocess raw data."""
226
218
  logger.info("Preprocessing data...")
227
219
 
228
220
  # Initialize data processor
@@ -251,7 +243,7 @@ class MLPipeline:
251
243
  def _extract_features(
252
244
  self, trading_data: pd.DataFrame, stock_data: pd.DataFrame
253
245
  ) -> Dict[str, Any]:
254
- """Extract features from preprocessed data"""
246
+ """Extract features from preprocessed data."""
255
247
  logger.info("Extracting features...")
256
248
 
257
249
  # Initialize feature extractors
@@ -294,7 +286,7 @@ class MLPipeline:
294
286
  }
295
287
 
296
288
  def _train_model(self, X: np.ndarray, y: np.ndarray) -> Dict[str, Any]:
297
- """Train ensemble model"""
289
+ """Train ensemble model."""
298
290
  logger.info("Training model...")
299
291
 
300
292
  # Split data
@@ -380,7 +372,7 @@ class MLPipeline:
380
372
  def _evaluate_model(
381
373
  self, model: StockRecommendationModel, X_test: np.ndarray, y_test: np.ndarray
382
374
  ) -> Dict[str, Any]:
383
- """Evaluate trained model"""
375
+ """Evaluate trained model."""
384
376
  logger.info("Evaluating model...")
385
377
 
386
378
  # Generate predictions
@@ -407,9 +399,9 @@ class MLPipeline:
407
399
 
408
400
  # Calculate AUC if binary classification
409
401
  if probabilities.shape[1] == 2:
410
- try:
402
+ try: # noqa: SIM105
411
403
  evaluation_metrics["test_auc"] = roc_auc_score(y_test, probabilities[:, 1])
412
- except:
404
+ except Exception:
413
405
  pass
414
406
 
415
407
  logger.info(f"Model evaluation - Test accuracy: {evaluation_metrics['test_accuracy']:.3f}")
@@ -419,7 +411,7 @@ class MLPipeline:
419
411
  def _deploy_model(
420
412
  self, model: StockRecommendationModel, metrics: Dict[str, float]
421
413
  ) -> Dict[str, Any]:
422
- """Deploy model (save to disk)"""
414
+ """Deploy model (save to disk)."""
423
415
  logger.info("Deploying model...")
424
416
 
425
417
  # Save model
@@ -445,7 +437,7 @@ class MLPipeline:
445
437
  def run(
446
438
  self, start_step: Optional[str] = None, end_step: Optional[str] = None
447
439
  ) -> Dict[str, Any]:
448
- """Execute pipeline"""
440
+ """Execute pipeline."""
449
441
  logger.info(f"Starting pipeline: {self.config.name} v{self.config.version}")
450
442
 
451
443
  # Start MLflow run if enabled
@@ -502,7 +494,7 @@ class MLPipeline:
502
494
  self.artifacts[output_key] = value
503
495
 
504
496
  # Log to MLflow
505
- if self.experiment_tracker and "metrics" in str(result):
497
+ if self.experiment_tracker and "metrics" in str(result): # noqa: SIM102
506
498
  if isinstance(result, dict) and any("metric" in k for k in result.keys()):
507
499
  metrics_dict = result.get(
508
500
  "training_metrics", result.get("evaluation_metrics", {})
@@ -540,7 +532,7 @@ class MLPipeline:
540
532
  return {"artifacts": self.artifacts, "metrics": self.metrics, "model": self.model}
541
533
 
542
534
  def _save_checkpoint(self, step_number: int):
543
- """Save pipeline checkpoint"""
535
+ """Save pipeline checkpoint."""
544
536
  checkpoint_path = self.config.cache_dir / f"checkpoint_step_{step_number}.pkl"
545
537
 
546
538
  checkpoint = {
@@ -560,7 +552,7 @@ class MLPipeline:
560
552
  logger.debug(f"Saved checkpoint at step {step_number}")
561
553
 
562
554
  def load_checkpoint(self, checkpoint_path: Path):
563
- """Load pipeline checkpoint"""
555
+ """Load pipeline checkpoint."""
564
556
  with open(checkpoint_path, "rb") as f:
565
557
  checkpoint = pickle.load(f)
566
558
 
@@ -570,7 +562,7 @@ class MLPipeline:
570
562
  logger.info(f"Loaded checkpoint from step {checkpoint['step_number']}")
571
563
 
572
564
  def _generate_mock_trading_data(self) -> pd.DataFrame:
573
- """Generate mock politician trading data for testing"""
565
+ """Generate mock politician trading data for testing."""
574
566
  np.random.seed(42)
575
567
  n_records = 500
576
568
 
@@ -593,7 +585,7 @@ class MLPipeline:
593
585
  return pd.DataFrame(data)
594
586
 
595
587
  def _generate_mock_stock_data(self) -> pd.DataFrame:
596
- """Generate mock stock price data for testing"""
588
+ """Generate mock stock price data for testing."""
597
589
  np.random.seed(42)
598
590
  tickers = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA"]
599
591
  dates = pd.date_range(end=pd.Timestamp.now(), periods=100)
@@ -619,20 +611,20 @@ class MLPipeline:
619
611
 
620
612
 
621
613
  class PipelineExecutor:
622
- """Execute and manage multiple pipeline runs"""
614
+ """Execute and manage multiple pipeline runs."""
623
615
 
624
616
  def __init__(self, config: PipelineConfig):
625
617
  self.config = config
626
618
  self.pipelines: Dict[str, MLPipeline] = {}
627
619
 
628
620
  def create_pipeline(self, name: str) -> MLPipeline:
629
- """Create new pipeline instance"""
621
+ """Create new pipeline instance."""
630
622
  pipeline = MLPipeline(self.config)
631
623
  self.pipelines[name] = pipeline
632
624
  return pipeline
633
625
 
634
626
  def run_pipeline(self, name: str, **kwargs) -> Dict[str, Any]:
635
- """Run specific pipeline"""
627
+ """Run specific pipeline."""
636
628
  if name not in self.pipelines:
637
629
  self.pipelines[name] = MLPipeline(self.config)
638
630
 
@@ -641,7 +633,7 @@ class PipelineExecutor:
641
633
  def run_experiment(
642
634
  self, n_runs: int = 5, param_grid: Optional[Dict[str, List]] = None
643
635
  ) -> pd.DataFrame:
644
- """Run multiple experiments with different parameters"""
636
+ """Run multiple experiments with different parameters."""
645
637
  results = []
646
638
 
647
639
  for i in range(n_runs):
@@ -1,7 +1,6 @@
1
- """ML Models for Stock Recommendation System"""
1
+ """ML Models for Stock Recommendation System."""
2
2
 
3
- from pathlib import Path
4
- from typing import Any, Dict, Optional
3
+ from typing import Any, Dict
5
4
 
6
5
  import torch
7
6
 
@@ -27,7 +26,7 @@ _loaded_models: Dict[str, Any] = {}
27
26
 
28
27
 
29
28
  async def load_production_models():
30
- """Load production models into memory"""
29
+ """Load production models into memory."""
31
30
  from mcli.ml.config import settings
32
31
  from mcli.ml.logging import get_logger
33
32
 
@@ -49,7 +48,7 @@ async def load_production_models():
49
48
 
50
49
 
51
50
  async def get_model_by_id(model_id: str):
52
- """Get loaded model by ID"""
51
+ """Get loaded model by ID."""
53
52
  from mcli.ml.config import settings
54
53
 
55
54
  if model_id not in _loaded_models:
@@ -62,7 +61,7 @@ async def get_model_by_id(model_id: str):
62
61
 
63
62
 
64
63
  def initialize_models():
65
- """Initialize models on startup"""
64
+ """Initialize models on startup."""
66
65
  from mcli.ml.logging import get_logger
67
66
 
68
67
  logger = get_logger(__name__)