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,18 +1,11 @@
1
- import asyncio
2
- import base64
3
1
  import json
4
- import logging
5
2
  import os
6
- import shutil
7
3
  import signal
8
4
  import sqlite3
9
5
  import sys
10
- import tempfile
11
6
  import threading
12
7
  import time
13
- import urllib.parse
14
8
  import uuid
15
- from contextlib import asynccontextmanager
16
9
  from dataclasses import asdict, dataclass
17
10
  from datetime import datetime
18
11
  from pathlib import Path
@@ -21,20 +14,17 @@ from urllib.parse import urlparse
21
14
 
22
15
  # CLI Commands
23
16
  import click
24
- import numpy as np
25
17
  import psutil
26
18
  import requests
27
19
 
28
20
  # Model loading and inference
29
21
  import torch
30
- import transformers
31
22
  import uvicorn
32
23
 
33
24
  # FastAPI for REST API
34
- from fastapi import BackgroundTasks, FastAPI, HTTPException
25
+ from fastapi import FastAPI, HTTPException
35
26
  from fastapi.middleware.cors import CORSMiddleware
36
- from PIL import Image
37
- from pydantic import BaseModel, Field
27
+ from pydantic import BaseModel
38
28
  from transformers import AutoModel, AutoModelForCausalLM, AutoModelForSeq2SeqLM, AutoTokenizer
39
29
 
40
30
  # Import existing utilities
@@ -66,7 +56,7 @@ DEFAULT_CONFIG = {
66
56
 
67
57
  @dataclass
68
58
  class ModelInfo:
69
- """Represents a loaded model"""
59
+ """Represents a loaded model."""
70
60
 
71
61
  id: str
72
62
  name: str
@@ -91,7 +81,7 @@ class ModelInfo:
91
81
 
92
82
 
93
83
  class ModelDatabase:
94
- """Manages model metadata storage"""
84
+ """Manages model metadata storage."""
95
85
 
96
86
  def __init__(self, db_path: Optional[str] = None):
97
87
  if db_path is None:
@@ -103,7 +93,7 @@ class ModelDatabase:
103
93
  self.init_database()
104
94
 
105
95
  def init_database(self):
106
- """Initialize SQLite database"""
96
+ """Initialize SQLite database."""
107
97
  conn = sqlite3.connect(self.db_path)
108
98
  cursor = conn.cursor()
109
99
 
@@ -150,7 +140,7 @@ class ModelDatabase:
150
140
  conn.close()
151
141
 
152
142
  def add_model(self, model_info: ModelInfo) -> str:
153
- """Add a new model to the database"""
143
+ """Add a new model to the database."""
154
144
  conn = sqlite3.connect(self.db_path)
155
145
  cursor = conn.cursor()
156
146
 
@@ -192,7 +182,7 @@ class ModelDatabase:
192
182
  conn.close()
193
183
 
194
184
  def get_model(self, model_id: str) -> Optional[ModelInfo]:
195
- """Get a model by ID"""
185
+ """Get a model by ID."""
196
186
  conn = sqlite3.connect(self.db_path)
197
187
  cursor = conn.cursor()
198
188
 
@@ -216,7 +206,7 @@ class ModelDatabase:
216
206
  conn.close()
217
207
 
218
208
  def get_all_models(self) -> List[ModelInfo]:
219
- """Get all models"""
209
+ """Get all models."""
220
210
  conn = sqlite3.connect(self.db_path)
221
211
  cursor = conn.cursor()
222
212
 
@@ -236,7 +226,7 @@ class ModelDatabase:
236
226
  conn.close()
237
227
 
238
228
  def update_model(self, model_info: ModelInfo) -> bool:
239
- """Update model information"""
229
+ """Update model information."""
240
230
  conn = sqlite3.connect(self.db_path)
241
231
  cursor = conn.cursor()
242
232
 
@@ -277,7 +267,7 @@ class ModelDatabase:
277
267
  conn.close()
278
268
 
279
269
  def delete_model(self, model_id: str) -> bool:
280
- """Delete a model"""
270
+ """Delete a model."""
281
271
  conn = sqlite3.connect(self.db_path)
282
272
  cursor = conn.cursor()
283
273
 
@@ -302,7 +292,7 @@ class ModelDatabase:
302
292
  execution_time_ms: int = int(),
303
293
  error_message: str = str(),
304
294
  ):
305
- """Record inference request"""
295
+ """Record inference request."""
306
296
  conn = sqlite3.connect(self.db_path)
307
297
  cursor = conn.cursor()
308
298
 
@@ -335,7 +325,7 @@ class ModelDatabase:
335
325
  conn.close()
336
326
 
337
327
  def _row_to_model_info(self, row) -> ModelInfo:
338
- """Convert database row to ModelInfo object"""
328
+ """Convert database row to ModelInfo object."""
339
329
  return ModelInfo(
340
330
  id=row[0],
341
331
  name=row[1],
@@ -355,7 +345,7 @@ class ModelDatabase:
355
345
 
356
346
 
357
347
  class ModelManager:
358
- """Manages model loading, caching, and inference"""
348
+ """Manages model loading, caching, and inference."""
359
349
 
360
350
  def __init__(self, models_dir: str = "./models", max_cache_size: int = 2):
361
351
  self.models_dir = Path(models_dir)
@@ -370,7 +360,7 @@ class ModelManager:
370
360
  logger.info(f"Using device: {self.device}")
371
361
 
372
362
  def load_model(self, model_info: ModelInfo) -> bool:
373
- """Load a model into memory"""
363
+ """Load a model into memory."""
374
364
  with self.model_lock:
375
365
  try:
376
366
  logger.info(f"Loading model: {model_info.name}")
@@ -418,7 +408,7 @@ class ModelManager:
418
408
  return False
419
409
 
420
410
  def unload_model(self, model_id: str) -> bool:
421
- """Unload a model from memory"""
411
+ """Unload a model from memory."""
422
412
  with self.model_lock:
423
413
  if model_id in self.loaded_models:
424
414
  del self.loaded_models[model_id]
@@ -435,7 +425,7 @@ class ModelManager:
435
425
  return False
436
426
 
437
427
  def _load_text_generation_model(self, model_info: ModelInfo):
438
- """Load a text generation model"""
428
+ """Load a text generation model."""
439
429
  tokenizer = AutoTokenizer.from_pretrained(
440
430
  model_info.tokenizer_path or model_info.model_path, trust_remote_code=True
441
431
  )
@@ -453,7 +443,7 @@ class ModelManager:
453
443
  return model, tokenizer
454
444
 
455
445
  def _load_text_classification_model(self, model_info: ModelInfo):
456
- """Load a text classification model"""
446
+ """Load a text classification model."""
457
447
  tokenizer = AutoTokenizer.from_pretrained(
458
448
  model_info.tokenizer_path or model_info.model_path
459
449
  )
@@ -470,7 +460,7 @@ class ModelManager:
470
460
  return model, tokenizer
471
461
 
472
462
  def _load_translation_model(self, model_info: ModelInfo):
473
- """Load a translation model"""
463
+ """Load a translation model."""
474
464
  tokenizer = AutoTokenizer.from_pretrained(
475
465
  model_info.tokenizer_path or model_info.model_path
476
466
  )
@@ -487,13 +477,13 @@ class ModelManager:
487
477
  return model, tokenizer
488
478
 
489
479
  def _load_image_generation_model(self, model_info: ModelInfo):
490
- """Load an image generation model (placeholder)"""
480
+ """Load an image generation model (placeholder)."""
491
481
  # This would be implemented based on specific image generation frameworks
492
482
  # like Stable Diffusion, DALL-E, etc.
493
483
  raise NotImplementedError("Image generation models not yet implemented")
494
484
 
495
485
  def _evict_oldest_model(self):
496
- """Evict the oldest loaded model from cache"""
486
+ """Evict the oldest loaded model from cache."""
497
487
  if not self.loaded_models:
498
488
  return
499
489
 
@@ -501,7 +491,7 @@ class ModelManager:
501
491
  self.unload_model(oldest_id)
502
492
 
503
493
  def _get_model_memory_usage(self, model) -> float:
504
- """Get model memory usage in MB"""
494
+ """Get model memory usage in MB."""
505
495
  try:
506
496
  if self.device == "cuda":
507
497
  return torch.cuda.memory_allocated() / 1024 / 1024
@@ -509,7 +499,7 @@ class ModelManager:
509
499
  # Rough estimation for CPU
510
500
  total_params = sum(p.numel() for p in model.parameters())
511
501
  return total_params * 4 / 1024 / 1024 # 4 bytes per float32
512
- except:
502
+ except Exception:
513
503
  return 0.0
514
504
 
515
505
  def generate_text(
@@ -521,7 +511,7 @@ class ModelManager:
521
511
  top_p: float = float(),
522
512
  top_k: int = int(),
523
513
  ) -> str:
524
- """Generate text using a loaded model"""
514
+ """Generate text using a loaded model."""
525
515
  if model_id not in self.loaded_models:
526
516
  raise ValueError(f"Model {model_id} not loaded")
527
517
 
@@ -568,7 +558,7 @@ class ModelManager:
568
558
  raise
569
559
 
570
560
  def classify_text(self, model_id: str, text: str) -> Dict[str, float]:
571
- """Classify text using a loaded model"""
561
+ """Classify text using a loaded model."""
572
562
  if model_id not in self.loaded_models:
573
563
  raise ValueError(f"Model {model_id} not loaded")
574
564
 
@@ -599,7 +589,7 @@ class ModelManager:
599
589
  def translate_text(
600
590
  self, model_id: str, text: str, source_lang: str = "en", target_lang: str = "fr"
601
591
  ) -> str:
602
- """Translate text using a loaded model"""
592
+ """Translate text using a loaded model."""
603
593
  if model_id not in self.loaded_models:
604
594
  raise ValueError(f"Model {model_id} not loaded")
605
595
 
@@ -635,7 +625,7 @@ class ModelManager:
635
625
  def download_model_from_url(
636
626
  self, model_url: str, tokenizer_url: Optional[str] = None
637
627
  ) -> tuple[str, Optional[str]]:
638
- """Download model and tokenizer from URLs and return local paths"""
628
+ """Download model and tokenizer from URLs and return local paths."""
639
629
  try:
640
630
  # Parse URLs
641
631
  model_parsed = urlparse(model_url)
@@ -686,7 +676,7 @@ class ModelManager:
686
676
  top_p: float = 0.9,
687
677
  top_k: int = 50,
688
678
  ) -> str:
689
- """Add a model from URL by downloading it first"""
679
+ """Add a model from URL by downloading it first."""
690
680
  try:
691
681
  # Download model and tokenizer
692
682
  model_path, tokenizer_path = self.download_model_from_url(model_url, tokenizer_url)
@@ -721,7 +711,7 @@ class ModelManager:
721
711
  raise
722
712
 
723
713
  def get_models_summary(self) -> Dict[str, Any]:
724
- """Get a summary of all models with statistics"""
714
+ """Get a summary of all models with statistics."""
725
715
  models = self.db.get_all_models()
726
716
 
727
717
  summary = {
@@ -802,7 +792,7 @@ class TranslationRequest(BaseModel):
802
792
 
803
793
 
804
794
  class ModelService:
805
- """Main model service daemon"""
795
+ """Main model service daemon."""
806
796
 
807
797
  def __init__(self, config: Dict[str, Any] = dict[str(), object()]()):
808
798
  self.config = {**DEFAULT_CONFIG, **(config or {})}
@@ -850,7 +840,7 @@ class ModelService:
850
840
  self._setup_routes()
851
841
 
852
842
  def _setup_routes(self):
853
- """Setup FastAPI routes"""
843
+ """Setup FastAPI routes."""
854
844
 
855
845
  @self.app.get("/")
856
846
  async def root():
@@ -863,18 +853,18 @@ class ModelService:
863
853
 
864
854
  @self.app.get("/models")
865
855
  async def list_models():
866
- """List all available models"""
856
+ """List all available models."""
867
857
  models = self.model_manager.db.get_all_models()
868
858
  return [asdict(model) for model in models]
869
859
 
870
860
  @self.app.get("/models/summary")
871
861
  async def get_models_summary():
872
- """Get a summary of all models with statistics"""
862
+ """Get a summary of all models with statistics."""
873
863
  return self.model_manager.get_models_summary()
874
864
 
875
865
  @self.app.post("/models")
876
866
  async def load_model(request: ModelLoadRequest):
877
- """Load a new model"""
867
+ """Load a new model."""
878
868
  try:
879
869
  model_info = ModelInfo(
880
870
  id=str(uuid.uuid4()),
@@ -907,7 +897,7 @@ class ModelService:
907
897
 
908
898
  @self.app.post("/models/from-url")
909
899
  async def load_model_from_url(request: ModelLoadFromUrlRequest):
910
- """Load a new model from URL"""
900
+ """Load a new model from URL."""
911
901
  try:
912
902
  model_id = self.model_manager.add_model_from_url(
913
903
  name=request.name,
@@ -928,7 +918,7 @@ class ModelService:
928
918
 
929
919
  @self.app.delete("/models/{model_id}")
930
920
  async def unload_model(model_id: str):
931
- """Unload a model"""
921
+ """Unload a model."""
932
922
  try:
933
923
  success = self.model_manager.unload_model(model_id)
934
924
  if success:
@@ -940,7 +930,7 @@ class ModelService:
940
930
 
941
931
  @self.app.put("/models/{model_id}")
942
932
  async def update_model(model_id: str, request: Dict[str, Any]):
943
- """Update model configuration"""
933
+ """Update model configuration."""
944
934
  try:
945
935
  # Get current model info
946
936
  model_info = self.model_manager.db.get_model(model_id)
@@ -966,7 +956,7 @@ class ModelService:
966
956
 
967
957
  @self.app.delete("/models/{model_id}/remove")
968
958
  async def remove_model(model_id: str):
969
- """Remove a model from the database"""
959
+ """Remove a model from the database."""
970
960
  try:
971
961
  # First unload if loaded
972
962
  self.model_manager.unload_model(model_id)
@@ -985,7 +975,7 @@ class ModelService:
985
975
 
986
976
  @self.app.post("/models/{model_id}/generate")
987
977
  async def generate_text(model_id: str, request: TextGenerationRequest):
988
- """Generate text using a model"""
978
+ """Generate text using a model."""
989
979
  try:
990
980
  start_time = time.time()
991
981
 
@@ -1023,7 +1013,7 @@ class ModelService:
1023
1013
 
1024
1014
  @self.app.post("/models/{model_id}/classify")
1025
1015
  async def classify_text(model_id: str, request: TextClassificationRequest):
1026
- """Classify text using a model"""
1016
+ """Classify text using a model."""
1027
1017
  try:
1028
1018
  start_time = time.time()
1029
1019
 
@@ -1056,7 +1046,7 @@ class ModelService:
1056
1046
 
1057
1047
  @self.app.post("/models/{model_id}/translate")
1058
1048
  async def translate_text(model_id: str, request: TranslationRequest):
1059
- """Translate text using a model"""
1049
+ """Translate text using a model."""
1060
1050
  try:
1061
1051
  start_time = time.time()
1062
1052
 
@@ -1092,7 +1082,7 @@ class ModelService:
1092
1082
 
1093
1083
  @self.app.get("/health")
1094
1084
  async def health_check():
1095
- """Health check endpoint"""
1085
+ """Health check endpoint."""
1096
1086
  return {
1097
1087
  "status": "healthy",
1098
1088
  "models_loaded": len(self.model_manager.loaded_models),
@@ -1105,7 +1095,7 @@ class ModelService:
1105
1095
  # Lightweight server endpoints
1106
1096
  @self.app.get("/lightweight/models")
1107
1097
  async def list_lightweight_models():
1108
- """List available lightweight models"""
1098
+ """List available lightweight models."""
1109
1099
  return {
1110
1100
  "models": LIGHTWEIGHT_MODELS,
1111
1101
  "downloaded": self.lightweight_server.downloader.get_downloaded_models(),
@@ -1114,7 +1104,7 @@ class ModelService:
1114
1104
 
1115
1105
  @self.app.post("/lightweight/models/{model_key}/download")
1116
1106
  async def download_lightweight_model(model_key: str):
1117
- """Download a lightweight model"""
1107
+ """Download a lightweight model."""
1118
1108
  if model_key not in LIGHTWEIGHT_MODELS:
1119
1109
  raise HTTPException(status_code=404, detail="Model not found")
1120
1110
 
@@ -1129,7 +1119,7 @@ class ModelService:
1129
1119
 
1130
1120
  @self.app.post("/lightweight/start")
1131
1121
  async def start_lightweight_server():
1132
- """Start the lightweight server"""
1122
+ """Start the lightweight server."""
1133
1123
  try:
1134
1124
  self.lightweight_server.start_server()
1135
1125
  return {
@@ -1142,7 +1132,7 @@ class ModelService:
1142
1132
 
1143
1133
  @self.app.get("/lightweight/status")
1144
1134
  async def lightweight_status():
1145
- """Get lightweight server status"""
1135
+ """Get lightweight server status."""
1146
1136
  return {
1147
1137
  "running": self.lightweight_server.running,
1148
1138
  "port": self.lightweight_server.port,
@@ -1153,7 +1143,7 @@ class ModelService:
1153
1143
  # PDF processing endpoints
1154
1144
  @self.app.post("/pdf/extract-text")
1155
1145
  async def extract_pdf_text(request: Dict[str, Any]):
1156
- """Extract text from PDF"""
1146
+ """Extract text from PDF."""
1157
1147
  try:
1158
1148
  pdf_path = request.get("pdf_path")
1159
1149
  if not pdf_path:
@@ -1166,7 +1156,7 @@ class ModelService:
1166
1156
 
1167
1157
  @self.app.post("/pdf/process-with-ai")
1168
1158
  async def process_pdf_with_ai(request: Dict[str, Any]):
1169
- """Process PDF with AI analysis"""
1159
+ """Process PDF with AI analysis."""
1170
1160
  try:
1171
1161
  pdf_path = request.get("pdf_path")
1172
1162
  model_key = request.get("model_key")
@@ -1185,13 +1175,13 @@ class ModelService:
1185
1175
 
1186
1176
  @self.app.get("/pdf/status")
1187
1177
  async def pdf_processor_status():
1188
- """Get PDF processor status"""
1178
+ """Get PDF processor status."""
1189
1179
  return self.pdf_processor.get_service_status()
1190
1180
 
1191
1181
  # Embedding endpoints
1192
1182
  @self.app.post("/embed/text")
1193
1183
  async def embed_text(request: Dict[str, Any]):
1194
- """Embed text using lightweight embedder"""
1184
+ """Embed text using lightweight embedder."""
1195
1185
  try:
1196
1186
  text = request.get("text")
1197
1187
  method = request.get("method")
@@ -1210,7 +1200,7 @@ class ModelService:
1210
1200
 
1211
1201
  @self.app.post("/embed/document")
1212
1202
  async def embed_document(request: Dict[str, Any]):
1213
- """Embed document using lightweight embedder"""
1203
+ """Embed document using lightweight embedder."""
1214
1204
  try:
1215
1205
  text = request.get("text")
1216
1206
  chunk_size = request.get("chunk_size", 1000)
@@ -1225,7 +1215,7 @@ class ModelService:
1225
1215
 
1226
1216
  @self.app.post("/embed/search")
1227
1217
  async def search_embeddings(request: Dict[str, Any]):
1228
- """Search similar documents using embeddings"""
1218
+ """Search similar documents using embeddings."""
1229
1219
  try:
1230
1220
  query = request.get("query")
1231
1221
  embeddings = request.get("embeddings", [])
@@ -1241,11 +1231,11 @@ class ModelService:
1241
1231
 
1242
1232
  @self.app.get("/embed/status")
1243
1233
  async def embedder_status():
1244
- """Get embedder status"""
1234
+ """Get embedder status."""
1245
1235
  return self.embedder.get_status()
1246
1236
 
1247
1237
  def start(self):
1248
- """Start the model service"""
1238
+ """Start the model service."""
1249
1239
  if self.running:
1250
1240
  logger.info("Model service is already running")
1251
1241
  return
@@ -1289,7 +1279,7 @@ class ModelService:
1289
1279
  self.stop()
1290
1280
 
1291
1281
  def stop(self):
1292
- """Stop the model service"""
1282
+ """Stop the model service."""
1293
1283
  if not self.running:
1294
1284
  return
1295
1285
 
@@ -1306,13 +1296,13 @@ class ModelService:
1306
1296
  logger.info("Model service stopped")
1307
1297
 
1308
1298
  def _signal_handler(self, signum, frame):
1309
- """Handle shutdown signals"""
1299
+ """Handle shutdown signals."""
1310
1300
  logger.info(f"Received signal {signum}, shutting down...")
1311
1301
  self.stop()
1312
1302
  sys.exit(0)
1313
1303
 
1314
1304
  def status(self) -> Dict[str, Any]:
1315
- """Get service status"""
1305
+ """Get service status."""
1316
1306
  is_running = False
1317
1307
  pid = None
1318
1308
 
@@ -1334,13 +1324,12 @@ class ModelService:
1334
1324
 
1335
1325
 
1336
1326
  # CLI Commands
1337
- import click
1327
+ # import click # Already imported above
1338
1328
 
1339
1329
 
1340
1330
  @click.group(name="model-service")
1341
1331
  def model_service():
1342
- """Model service daemon for hosting language models"""
1343
- pass
1332
+ """Model service daemon for hosting language models."""
1344
1333
 
1345
1334
 
1346
1335
  @model_service.command()
@@ -1349,7 +1338,7 @@ def model_service():
1349
1338
  @click.option("--port", default=8000, help="Port to bind to")
1350
1339
  @click.option("--models-dir", default="./models", help="Directory for model storage")
1351
1340
  def start(config: Optional[str], host: str, port: int, models_dir: str):
1352
- """Start the model service daemon"""
1341
+ """Start the model service daemon."""
1353
1342
  # Load config if provided
1354
1343
  service_config = DEFAULT_CONFIG.copy()
1355
1344
  if config:
@@ -1371,7 +1360,7 @@ def start(config: Optional[str], host: str, port: int, models_dir: str):
1371
1360
 
1372
1361
  @model_service.command()
1373
1362
  def stop():
1374
- """Stop the model service daemon"""
1363
+ """Stop the model service daemon."""
1375
1364
  pid_file = Path.home() / ".local" / "mcli" / "model_service" / "model_service.pid"
1376
1365
 
1377
1366
  if not pid_file.exists():
@@ -1399,7 +1388,7 @@ def stop():
1399
1388
 
1400
1389
  @model_service.command()
1401
1390
  def status():
1402
- """Show model service status"""
1391
+ """Show model service status."""
1403
1392
  service = ModelService()
1404
1393
  status_info = service.status()
1405
1394
 
@@ -1416,7 +1405,7 @@ def status():
1416
1405
  @model_service.command()
1417
1406
  @click.option("--summary", is_flag=True, help="Show summary statistics")
1418
1407
  def list_models(summary: bool = False):
1419
- """List all models in the service"""
1408
+ """List all models in the service."""
1420
1409
  service = ModelService()
1421
1410
 
1422
1411
  try:
@@ -1481,7 +1470,7 @@ def list_models(summary: bool = False):
1481
1470
  def add_model(
1482
1471
  model_path: str, name: str, model_type: str, tokenizer_path: str = str(), device: str = "auto"
1483
1472
  ):
1484
- """Add a model to the service"""
1473
+ """Add a model to the service."""
1485
1474
  service = ModelService()
1486
1475
 
1487
1476
  try:
@@ -1534,7 +1523,7 @@ def add_model_from_url(
1534
1523
  top_p: float = 0.9,
1535
1524
  top_k: int = 50,
1536
1525
  ):
1537
- """Add a model from URL to the service"""
1526
+ """Add a model from URL to the service."""
1538
1527
  service = ModelService()
1539
1528
 
1540
1529
  try:
@@ -1577,7 +1566,7 @@ def update_model(
1577
1566
  top_k: Optional[int] = None,
1578
1567
  device: Optional[str] = None,
1579
1568
  ):
1580
- """Update model configuration"""
1569
+ """Update model configuration."""
1581
1570
  service = ModelService()
1582
1571
 
1583
1572
  try:
@@ -1627,7 +1616,7 @@ def update_model(
1627
1616
  @click.argument("model_id")
1628
1617
  @click.option("--force", is_flag=True, help="Force removal without confirmation")
1629
1618
  def remove_model(model_id: str, force: bool = False):
1630
- """Remove a model from the service"""
1619
+ """Remove a model from the service."""
1631
1620
  service = ModelService()
1632
1621
 
1633
1622
  try:
@@ -1638,7 +1627,7 @@ def remove_model(model_id: str, force: bool = False):
1638
1627
  return
1639
1628
 
1640
1629
  if not force:
1641
- click.echo(f"Model to remove:")
1630
+ click.echo("Model to remove:")
1642
1631
  click.echo(f" Name: {model_info.name}")
1643
1632
  click.echo(f" Type: {model_info.model_type}")
1644
1633
  click.echo(f" Path: {model_info.model_path}")
@@ -1672,7 +1661,7 @@ def remove_model(model_id: str, force: bool = False):
1672
1661
  @click.option("--start-server", is_flag=True, help="Start the lightweight server")
1673
1662
  @click.option("--port", default=8080, help="Port for lightweight server")
1674
1663
  def lightweight(list: bool, download: str, auto: bool, start_server: bool, port: int):
1675
- """Manage lightweight models and server"""
1664
+ """Manage lightweight models and server."""
1676
1665
  service = ModelService()
1677
1666
 
1678
1667
  if list:
@@ -1725,7 +1714,7 @@ def lightweight(list: bool, download: str, auto: bool, start_server: bool, port:
1725
1714
  service.lightweight_server.port = port
1726
1715
  service.lightweight_server.start_server()
1727
1716
 
1728
- click.echo(f"✅ Server started!")
1717
+ click.echo("✅ Server started!")
1729
1718
  click.echo(f"🌐 API: http://localhost:{port}")
1730
1719
  click.echo(f"📊 Health: http://localhost:{port}/health")
1731
1720
  click.echo(f"📋 Models: http://localhost:{port}/models")
@@ -1760,7 +1749,7 @@ def lightweight(list: bool, download: str, auto: bool, start_server: bool, port:
1760
1749
  def lightweight_run(
1761
1750
  model: Optional[str], auto: bool, port: int, list_models: bool, download_only: bool
1762
1751
  ):
1763
- """Run lightweight model server (standalone mode)"""
1752
+ """Run lightweight model server (standalone mode)."""
1764
1753
  service = ModelService()
1765
1754
 
1766
1755
  click.echo("🚀 MCLI Lightweight Model Server")
@@ -1799,7 +1788,7 @@ def lightweight_run(
1799
1788
  service.lightweight_server.port = port
1800
1789
  service.lightweight_server.start_server()
1801
1790
 
1802
- click.echo(f"\n📝 Usage:")
1791
+ click.echo("\n📝 Usage:")
1803
1792
  click.echo(f" - API: http://localhost:{port}")
1804
1793
  click.echo(f" - Health: http://localhost:{port}/health")
1805
1794
  click.echo(f" - Models: http://localhost:{port}/models")
@@ -1818,7 +1807,7 @@ def lightweight_run(
1818
1807
  @click.option("--model", help="Specific model to use for AI analysis")
1819
1808
  @click.option("--extract-only", is_flag=True, help="Only extract text, no AI analysis")
1820
1809
  def process_pdf(pdf_path: str, model: str, extract_only: bool):
1821
- """Process PDF with AI analysis"""
1810
+ """Process PDF with AI analysis."""
1822
1811
  service = ModelService()
1823
1812
 
1824
1813
  try:
@@ -1839,7 +1828,7 @@ def process_pdf(pdf_path: str, model: str, extract_only: bool):
1839
1828
  click.echo(f"📝 Preview: {result['text'][:200]}...")
1840
1829
  else:
1841
1830
  analysis = result["pdf_analysis"]["ai_analysis"]
1842
- click.echo(f"✅ PDF processed successfully!")
1831
+ click.echo("✅ PDF processed successfully!")
1843
1832
  click.echo(f"📊 Document type: {analysis['document_type']}")
1844
1833
  click.echo(f"📝 Summary: {analysis['summary'][:200]}...")
1845
1834
  click.echo(f"🔑 Key topics: {', '.join(analysis['key_topics'])}")
@@ -1854,7 +1843,7 @@ def process_pdf(pdf_path: str, model: str, extract_only: bool):
1854
1843
  @model_service.command()
1855
1844
  @click.option("--port", default=8080, help="Port for PDF processing service")
1856
1845
  def start_pdf_service(port: int):
1857
- """Start PDF processing service"""
1846
+ """Start PDF processing service."""
1858
1847
  service = ModelService()
1859
1848
 
1860
1849
  try:
@@ -1862,7 +1851,7 @@ def start_pdf_service(port: int):
1862
1851
  success = service.pdf_processor.start_pdf_processing_service(port)
1863
1852
 
1864
1853
  if success:
1865
- click.echo(f"✅ PDF processing service started!")
1854
+ click.echo("✅ PDF processing service started!")
1866
1855
  click.echo(f"🌐 API: http://localhost:{port}")
1867
1856
  click.echo(f"📊 Status: http://localhost:{port}/status")
1868
1857
 
@@ -1883,7 +1872,7 @@ def start_pdf_service(port: int):
1883
1872
  @click.argument("text")
1884
1873
  @click.option("--method", help="Embedding method (sentence_transformers, tfidf, simple_hash)")
1885
1874
  def embed_text(text: str, method: str):
1886
- """Embed text using lightweight embedder"""
1875
+ """Embed text using lightweight embedder."""
1887
1876
  service = ModelService()
1888
1877
 
1889
1878
  try:
@@ -1895,7 +1884,7 @@ def embed_text(text: str, method: str):
1895
1884
  result = service.embedder.embed_text(text)
1896
1885
 
1897
1886
  if result:
1898
- click.echo(f"✅ Text embedded successfully!")
1887
+ click.echo("✅ Text embedded successfully!")
1899
1888
  click.echo(f"📊 Method: {result['method']}")
1900
1889
  click.echo(f"📏 Dimensions: {result['dimensions']}")
1901
1890
  click.echo(f"📝 Text length: {result['text_length']}")
@@ -1910,7 +1899,7 @@ def embed_text(text: str, method: str):
1910
1899
  @click.argument("text")
1911
1900
  @click.option("--chunk-size", default=1000, help="Chunk size for document embedding")
1912
1901
  def embed_document(text: str, chunk_size: int):
1913
- """Embed document using lightweight embedder"""
1902
+ """Embed document using lightweight embedder."""
1914
1903
  service = ModelService()
1915
1904
 
1916
1905
  try:
@@ -1919,7 +1908,7 @@ def embed_document(text: str, chunk_size: int):
1919
1908
 
1920
1909
  if result.get("success"):
1921
1910
  doc_embedding = result["document_embedding"]
1922
- click.echo(f"✅ Document embedded successfully!")
1911
+ click.echo("✅ Document embedded successfully!")
1923
1912
  click.echo(f"📊 Method: {doc_embedding['method']}")
1924
1913
  click.echo(f"📄 Total chunks: {doc_embedding['total_chunks']}")
1925
1914
  click.echo(f"📏 Text length: {doc_embedding['total_text_length']}")
@@ -1932,7 +1921,7 @@ def embed_document(text: str, chunk_size: int):
1932
1921
 
1933
1922
  @model_service.command()
1934
1923
  def embedder_status():
1935
- """Show embedder status"""
1924
+ """Show embedder status."""
1936
1925
  service = ModelService()
1937
1926
 
1938
1927
  try: