mcli-framework 7.12.2__py3-none-any.whl → 7.12.4__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.
- mcli/app/__init__.py +0 -2
- mcli/app/commands_cmd.py +30 -26
- mcli/app/completion_helpers.py +5 -5
- mcli/app/init_cmd.py +10 -10
- mcli/app/lock_cmd.py +29 -24
- mcli/app/main.py +2 -8
- mcli/app/model/model.py +5 -10
- mcli/app/store_cmd.py +8 -8
- mcli/app/video/__init__.py +0 -2
- mcli/app/video/video.py +1 -14
- mcli/chat/chat.py +90 -108
- mcli/chat/command_rag.py +0 -4
- mcli/chat/enhanced_chat.py +32 -41
- mcli/chat/system_controller.py +37 -37
- mcli/chat/system_integration.py +4 -5
- mcli/cli.py +2 -3
- mcli/lib/api/api.py +4 -9
- mcli/lib/api/daemon_client.py +19 -20
- mcli/lib/api/daemon_client_local.py +1 -3
- mcli/lib/api/daemon_decorator.py +6 -6
- mcli/lib/api/mcli_decorators.py +4 -8
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/auth/auth.py +4 -5
- mcli/lib/auth/mcli_manager.py +7 -12
- mcli/lib/auth/token_util.py +5 -5
- mcli/lib/config/__init__.py +29 -1
- mcli/lib/config/config.py +0 -1
- mcli/lib/custom_commands.py +1 -1
- mcli/lib/discovery/command_discovery.py +15 -15
- mcli/lib/erd/erd.py +7 -7
- mcli/lib/files/files.py +1 -1
- mcli/lib/fs/__init__.py +31 -1
- mcli/lib/fs/fs.py +12 -13
- mcli/lib/lib.py +0 -1
- mcli/lib/logger/logger.py +7 -10
- mcli/lib/performance/optimizer.py +25 -27
- mcli/lib/performance/rust_bridge.py +22 -27
- mcli/lib/performance/uvloop_config.py +0 -1
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/pickles/pickles.py +0 -2
- mcli/lib/secrets/commands.py +0 -2
- mcli/lib/secrets/manager.py +0 -1
- mcli/lib/secrets/repl.py +2 -3
- mcli/lib/secrets/store.py +1 -2
- mcli/lib/services/data_pipeline.py +34 -34
- mcli/lib/services/lsh_client.py +38 -40
- mcli/lib/shell/shell.py +2 -2
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/ui/styling.py +0 -1
- mcli/lib/ui/visual_effects.py +33 -41
- mcli/lib/watcher/watcher.py +0 -1
- mcli/ml/__init__.py +1 -1
- mcli/ml/api/__init__.py +1 -1
- mcli/ml/api/app.py +8 -9
- mcli/ml/api/middleware.py +10 -10
- mcli/ml/api/routers/__init__.py +1 -1
- mcli/ml/api/routers/admin_router.py +3 -3
- mcli/ml/api/routers/auth_router.py +17 -18
- mcli/ml/api/routers/backtest_router.py +2 -2
- mcli/ml/api/routers/data_router.py +2 -2
- mcli/ml/api/routers/model_router.py +14 -15
- mcli/ml/api/routers/monitoring_router.py +2 -2
- mcli/ml/api/routers/portfolio_router.py +2 -2
- mcli/ml/api/routers/prediction_router.py +10 -9
- mcli/ml/api/routers/trade_router.py +2 -2
- mcli/ml/api/routers/websocket_router.py +6 -7
- mcli/ml/api/schemas.py +2 -2
- mcli/ml/auth/__init__.py +1 -1
- mcli/ml/auth/auth_manager.py +22 -23
- mcli/ml/auth/models.py +17 -17
- mcli/ml/auth/permissions.py +17 -17
- mcli/ml/backtesting/__init__.py +1 -1
- mcli/ml/backtesting/backtest_engine.py +31 -35
- mcli/ml/backtesting/performance_metrics.py +12 -14
- mcli/ml/backtesting/run.py +1 -2
- mcli/ml/cache.py +35 -36
- mcli/ml/cli/__init__.py +1 -1
- mcli/ml/cli/main.py +21 -24
- mcli/ml/config/__init__.py +1 -1
- mcli/ml/config/settings.py +28 -29
- mcli/ml/configs/__init__.py +1 -1
- mcli/ml/configs/dvc_config.py +14 -15
- mcli/ml/configs/mlflow_config.py +12 -13
- mcli/ml/configs/mlops_manager.py +19 -21
- mcli/ml/dashboard/__init__.py +4 -4
- mcli/ml/dashboard/app.py +20 -30
- mcli/ml/dashboard/app_supabase.py +16 -19
- mcli/ml/dashboard/app_training.py +11 -14
- mcli/ml/dashboard/cli.py +2 -2
- mcli/ml/dashboard/common.py +2 -3
- mcli/ml/dashboard/components/__init__.py +1 -1
- mcli/ml/dashboard/components/charts.py +13 -11
- mcli/ml/dashboard/components/metrics.py +7 -7
- mcli/ml/dashboard/components/tables.py +12 -9
- mcli/ml/dashboard/overview.py +2 -2
- mcli/ml/dashboard/pages/__init__.py +1 -1
- mcli/ml/dashboard/pages/cicd.py +15 -18
- mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
- mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
- mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
- mcli/ml/dashboard/pages/test_portfolio.py +3 -6
- mcli/ml/dashboard/pages/trading.py +16 -18
- mcli/ml/dashboard/pages/workflows.py +20 -30
- mcli/ml/dashboard/utils.py +9 -9
- mcli/ml/dashboard/warning_suppression.py +3 -3
- mcli/ml/data_ingestion/__init__.py +1 -1
- mcli/ml/data_ingestion/api_connectors.py +41 -46
- mcli/ml/data_ingestion/data_pipeline.py +36 -46
- mcli/ml/data_ingestion/stream_processor.py +43 -46
- mcli/ml/database/__init__.py +1 -1
- mcli/ml/database/migrations/env.py +2 -2
- mcli/ml/database/models.py +22 -24
- mcli/ml/database/session.py +14 -14
- mcli/ml/experimentation/__init__.py +1 -1
- mcli/ml/experimentation/ab_testing.py +45 -46
- mcli/ml/features/__init__.py +1 -1
- mcli/ml/features/ensemble_features.py +22 -27
- mcli/ml/features/recommendation_engine.py +30 -30
- mcli/ml/features/stock_features.py +29 -32
- mcli/ml/features/test_feature_engineering.py +10 -11
- mcli/ml/logging.py +4 -4
- mcli/ml/mlops/__init__.py +1 -1
- mcli/ml/mlops/data_versioning.py +29 -30
- mcli/ml/mlops/experiment_tracker.py +24 -24
- mcli/ml/mlops/model_serving.py +31 -34
- mcli/ml/mlops/pipeline_orchestrator.py +27 -35
- mcli/ml/models/__init__.py +5 -6
- mcli/ml/models/base_models.py +23 -23
- mcli/ml/models/ensemble_models.py +31 -31
- mcli/ml/models/recommendation_models.py +18 -19
- mcli/ml/models/test_models.py +14 -16
- mcli/ml/monitoring/__init__.py +1 -1
- mcli/ml/monitoring/drift_detection.py +32 -36
- mcli/ml/monitoring/metrics.py +2 -2
- mcli/ml/optimization/__init__.py +1 -1
- mcli/ml/optimization/optimize.py +1 -2
- mcli/ml/optimization/portfolio_optimizer.py +30 -32
- mcli/ml/predictions/__init__.py +1 -1
- mcli/ml/preprocessing/__init__.py +1 -1
- mcli/ml/preprocessing/data_cleaners.py +22 -23
- mcli/ml/preprocessing/feature_extractors.py +23 -26
- mcli/ml/preprocessing/ml_pipeline.py +23 -23
- mcli/ml/preprocessing/test_preprocessing.py +7 -8
- mcli/ml/scripts/populate_sample_data.py +0 -4
- mcli/ml/serving/serve.py +1 -2
- mcli/ml/tasks.py +17 -17
- mcli/ml/tests/test_integration.py +29 -30
- mcli/ml/tests/test_training_dashboard.py +21 -21
- mcli/ml/trading/__init__.py +1 -1
- mcli/ml/trading/migrations.py +5 -5
- mcli/ml/trading/models.py +21 -23
- mcli/ml/trading/paper_trading.py +16 -13
- mcli/ml/trading/risk_management.py +17 -18
- mcli/ml/trading/trading_service.py +25 -28
- mcli/ml/training/__init__.py +1 -1
- mcli/ml/training/train.py +0 -1
- mcli/public/oi/oi.py +1 -2
- mcli/self/completion_cmd.py +6 -10
- mcli/self/logs_cmd.py +19 -24
- mcli/self/migrate_cmd.py +22 -20
- mcli/self/redis_cmd.py +10 -11
- mcli/self/self_cmd.py +10 -18
- mcli/self/store_cmd.py +10 -12
- mcli/self/visual_cmd.py +9 -14
- mcli/self/zsh_cmd.py +2 -4
- mcli/workflow/daemon/async_command_database.py +23 -24
- mcli/workflow/daemon/async_process_manager.py +27 -29
- mcli/workflow/daemon/client.py +27 -33
- mcli/workflow/daemon/daemon.py +32 -36
- mcli/workflow/daemon/enhanced_daemon.py +24 -33
- mcli/workflow/daemon/process_cli.py +11 -12
- mcli/workflow/daemon/process_manager.py +23 -26
- mcli/workflow/daemon/test_daemon.py +4 -5
- mcli/workflow/dashboard/dashboard_cmd.py +0 -1
- mcli/workflow/doc_convert.py +15 -17
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/gcloud/gcloud.py +11 -8
- mcli/workflow/git_commit/ai_service.py +14 -15
- mcli/workflow/lsh_integration.py +9 -11
- mcli/workflow/model_service/client.py +26 -31
- mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
- mcli/workflow/model_service/lightweight_embedder.py +25 -35
- mcli/workflow/model_service/lightweight_model_server.py +26 -32
- mcli/workflow/model_service/lightweight_test.py +7 -10
- mcli/workflow/model_service/model_service.py +80 -91
- mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
- mcli/workflow/model_service/openai_adapter.py +23 -23
- mcli/workflow/model_service/pdf_processor.py +21 -26
- mcli/workflow/model_service/test_efficient_runner.py +12 -16
- mcli/workflow/model_service/test_example.py +11 -13
- mcli/workflow/model_service/test_integration.py +3 -5
- mcli/workflow/model_service/test_new_features.py +7 -8
- mcli/workflow/notebook/converter.py +1 -1
- mcli/workflow/notebook/notebook_cmd.py +5 -6
- mcli/workflow/notebook/schema.py +0 -1
- mcli/workflow/notebook/validator.py +7 -3
- mcli/workflow/openai/openai.py +1 -2
- mcli/workflow/registry/registry.py +4 -1
- mcli/workflow/repo/repo.py +6 -7
- mcli/workflow/scheduler/cron_parser.py +16 -19
- mcli/workflow/scheduler/job.py +10 -10
- mcli/workflow/scheduler/monitor.py +15 -15
- mcli/workflow/scheduler/persistence.py +17 -18
- mcli/workflow/scheduler/scheduler.py +37 -38
- mcli/workflow/secrets/__init__.py +1 -1
- mcli/workflow/sync/test_cmd.py +0 -1
- mcli/workflow/wakatime/__init__.py +5 -9
- mcli/workflow/wakatime/wakatime.py +1 -2
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/METADATA +1 -1
- mcli_framework-7.12.4.dist-info/RECORD +279 -0
- mcli_framework-7.12.2.dist-info/RECORD +0 -279
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/WHEEL +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/top_level.txt +0 -0
|
@@ -6,13 +6,11 @@ This script uses the Ollama API to pull the most efficient models and then
|
|
|
6
6
|
integrates them with the MCLI model service for local inference.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import json
|
|
10
|
-
import os
|
|
11
9
|
import subprocess
|
|
12
10
|
import sys
|
|
13
11
|
import time
|
|
14
12
|
from pathlib import Path
|
|
15
|
-
from typing import Dict,
|
|
13
|
+
from typing import Dict, Optional
|
|
16
14
|
|
|
17
15
|
import click
|
|
18
16
|
import requests
|
|
@@ -20,7 +18,6 @@ import requests
|
|
|
20
18
|
# Add the parent directory to the path so we can import the model service
|
|
21
19
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
22
20
|
|
|
23
|
-
from mcli.workflow.model_service.model_service import ModelManager, ModelService
|
|
24
21
|
|
|
25
22
|
# Efficient models from Ollama with their model names
|
|
26
23
|
EFFICIENT_MODELS = {
|
|
@@ -73,7 +70,7 @@ EFFICIENT_MODELS = {
|
|
|
73
70
|
|
|
74
71
|
|
|
75
72
|
def check_ollama_installed():
|
|
76
|
-
"""Check if Ollama is installed and running"""
|
|
73
|
+
"""Check if Ollama is installed and running."""
|
|
77
74
|
try:
|
|
78
75
|
# Check if ollama command exists
|
|
79
76
|
result = subprocess.run(["ollama", "--version"], capture_output=True, text=True, timeout=5)
|
|
@@ -93,7 +90,7 @@ def check_ollama_installed():
|
|
|
93
90
|
|
|
94
91
|
|
|
95
92
|
def check_ollama_server():
|
|
96
|
-
"""Check if Ollama server is running"""
|
|
93
|
+
"""Check if Ollama server is running."""
|
|
97
94
|
try:
|
|
98
95
|
response = requests.get("http://localhost:11434/api/tags", timeout=5)
|
|
99
96
|
if response.status_code == 200:
|
|
@@ -116,7 +113,7 @@ def check_ollama_server():
|
|
|
116
113
|
|
|
117
114
|
|
|
118
115
|
def get_system_info():
|
|
119
|
-
"""Get system information for model selection"""
|
|
116
|
+
"""Get system information for model selection."""
|
|
120
117
|
import psutil
|
|
121
118
|
|
|
122
119
|
# Get CPU info
|
|
@@ -151,7 +148,7 @@ def get_system_info():
|
|
|
151
148
|
|
|
152
149
|
|
|
153
150
|
def recommend_model(system_info: Dict) -> str:
|
|
154
|
-
"""Recommend the best model based on system capabilities"""
|
|
151
|
+
"""Recommend the best model based on system capabilities."""
|
|
155
152
|
print("🔍 Analyzing system capabilities...")
|
|
156
153
|
print(f" CPU Cores: {system_info['cpu_count']}")
|
|
157
154
|
print(f" CPU Frequency: {system_info['cpu_freq_mhz']:.0f} MHz")
|
|
@@ -175,7 +172,7 @@ def recommend_model(system_info: Dict) -> str:
|
|
|
175
172
|
|
|
176
173
|
|
|
177
174
|
def pull_ollama_model(model_key: str) -> bool:
|
|
178
|
-
"""Pull a model from Ollama"""
|
|
175
|
+
"""Pull a model from Ollama."""
|
|
179
176
|
model_info = EFFICIENT_MODELS[model_key]
|
|
180
177
|
|
|
181
178
|
print(f"\n📥 Pulling {model_info['name']} from Ollama...")
|
|
@@ -209,7 +206,7 @@ def pull_ollama_model(model_key: str) -> bool:
|
|
|
209
206
|
|
|
210
207
|
|
|
211
208
|
def test_ollama_model(model_key: str):
|
|
212
|
-
"""Test the Ollama model with sample prompts"""
|
|
209
|
+
"""Test the Ollama model with sample prompts."""
|
|
213
210
|
model_info = EFFICIENT_MODELS[model_key]
|
|
214
211
|
|
|
215
212
|
print(f"\n🧪 Testing {model_info['name']} via Ollama...")
|
|
@@ -247,7 +244,7 @@ def test_ollama_model(model_key: str):
|
|
|
247
244
|
|
|
248
245
|
|
|
249
246
|
def list_available_models():
|
|
250
|
-
"""List models available in Ollama"""
|
|
247
|
+
"""List models available in Ollama."""
|
|
251
248
|
try:
|
|
252
249
|
response = requests.get("http://localhost:11434/api/tags", timeout=5)
|
|
253
250
|
if response.status_code == 200:
|
|
@@ -265,17 +262,16 @@ def list_available_models():
|
|
|
265
262
|
|
|
266
263
|
|
|
267
264
|
def create_mcli_integration_script(model_key: str):
|
|
268
|
-
"""Create a script to integrate the Ollama model with MCLI"""
|
|
269
|
-
|
|
265
|
+
"""Create a script to integrate the Ollama model with MCLI."""
|
|
266
|
+
EFFICIENT_MODELS[model_key]
|
|
270
267
|
|
|
271
|
-
script_content =
|
|
268
|
+
script_content = '''#!/usr/bin/env python3
|
|
272
269
|
"""
|
|
273
270
|
Integration script for {model_info['name']} with MCLI model service.
|
|
274
271
|
This script provides a bridge between Ollama and MCLI model service.
|
|
275
272
|
"""
|
|
276
273
|
|
|
277
274
|
import requests
|
|
278
|
-
import json
|
|
279
275
|
import time
|
|
280
276
|
from typing import Dict, Any
|
|
281
277
|
|
|
@@ -363,7 +359,7 @@ if __name__ == "__main__":
|
|
|
363
359
|
@click.option("--list-models", is_flag=True, help="List available models in Ollama")
|
|
364
360
|
@click.option("--create-bridge", is_flag=True, help="Create MCLI integration script")
|
|
365
361
|
def main(model: Optional[str], auto: bool, test: bool, list_models: bool, create_bridge: bool):
|
|
366
|
-
"""Download and run efficient models from Ollama"""
|
|
362
|
+
"""Download and run efficient models from Ollama."""
|
|
367
363
|
|
|
368
364
|
print("🚀 Ollama Efficient Model Runner")
|
|
369
365
|
print("=" * 50)
|
|
@@ -415,8 +411,8 @@ def main(model: Optional[str], auto: bool, test: bool, list_models: bool, create
|
|
|
415
411
|
model_info = EFFICIENT_MODELS[selected_model]
|
|
416
412
|
print(f"\n🎉 Setup complete! Model {model_info['name']} is ready to use.")
|
|
417
413
|
print(f"📊 Model: {model_info['ollama_name']}")
|
|
418
|
-
print(
|
|
419
|
-
print(
|
|
414
|
+
print("🌐 Ollama API: http://localhost:11434")
|
|
415
|
+
print("📝 Use 'ollama list' to see all models")
|
|
420
416
|
|
|
421
417
|
return 0
|
|
422
418
|
|
|
@@ -10,9 +10,9 @@ import uuid
|
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from typing import Any, AsyncGenerator, Dict, List, Optional
|
|
12
12
|
|
|
13
|
-
from fastapi import APIRouter, Depends, Header, HTTPException,
|
|
13
|
+
from fastapi import APIRouter, Depends, Header, HTTPException, status
|
|
14
14
|
from fastapi.responses import StreamingResponse
|
|
15
|
-
from pydantic import BaseModel
|
|
15
|
+
from pydantic import BaseModel
|
|
16
16
|
|
|
17
17
|
from mcli.lib.logger.logger import get_logger
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ logger = get_logger(__name__)
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class Message(BaseModel):
|
|
23
|
-
"""OpenAI message format"""
|
|
23
|
+
"""OpenAI message format."""
|
|
24
24
|
|
|
25
25
|
role: str
|
|
26
26
|
content: str
|
|
@@ -28,7 +28,7 @@ class Message(BaseModel):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class ChatCompletionRequest(BaseModel):
|
|
31
|
-
"""OpenAI chat completion request"""
|
|
31
|
+
"""OpenAI chat completion request."""
|
|
32
32
|
|
|
33
33
|
model: str
|
|
34
34
|
messages: List[Message]
|
|
@@ -44,7 +44,7 @@ class ChatCompletionRequest(BaseModel):
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class ChatCompletionChoice(BaseModel):
|
|
47
|
-
"""Chat completion choice"""
|
|
47
|
+
"""Chat completion choice."""
|
|
48
48
|
|
|
49
49
|
index: int
|
|
50
50
|
message: Message
|
|
@@ -52,7 +52,7 @@ class ChatCompletionChoice(BaseModel):
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class Usage(BaseModel):
|
|
55
|
-
"""Token usage information"""
|
|
55
|
+
"""Token usage information."""
|
|
56
56
|
|
|
57
57
|
prompt_tokens: int
|
|
58
58
|
completion_tokens: int
|
|
@@ -60,7 +60,7 @@ class Usage(BaseModel):
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class ChatCompletionResponse(BaseModel):
|
|
63
|
-
"""OpenAI chat completion response"""
|
|
63
|
+
"""OpenAI chat completion response."""
|
|
64
64
|
|
|
65
65
|
id: str
|
|
66
66
|
object: str = "chat.completion"
|
|
@@ -71,7 +71,7 @@ class ChatCompletionResponse(BaseModel):
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class ModelInfo(BaseModel):
|
|
74
|
-
"""Model information"""
|
|
74
|
+
"""Model information."""
|
|
75
75
|
|
|
76
76
|
id: str
|
|
77
77
|
object: str = "model"
|
|
@@ -80,20 +80,20 @@ class ModelInfo(BaseModel):
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class ModelListResponse(BaseModel):
|
|
83
|
-
"""Model list response"""
|
|
83
|
+
"""Model list response."""
|
|
84
84
|
|
|
85
85
|
object: str = "list"
|
|
86
86
|
data: List[ModelInfo]
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
class APIKeyManager:
|
|
90
|
-
"""Manages API key authentication"""
|
|
90
|
+
"""Manages API key authentication."""
|
|
91
91
|
|
|
92
92
|
def __init__(self):
|
|
93
93
|
self.valid_keys: Dict[str, Dict[str, Any]] = {}
|
|
94
94
|
|
|
95
95
|
def add_key(self, key: str, name: str = "default", metadata: Optional[Dict] = None):
|
|
96
|
-
"""Add a valid API key"""
|
|
96
|
+
"""Add a valid API key."""
|
|
97
97
|
self.valid_keys[key] = {
|
|
98
98
|
"name": name,
|
|
99
99
|
"created_at": datetime.now().isoformat(),
|
|
@@ -102,19 +102,19 @@ class APIKeyManager:
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
def validate_key(self, key: str) -> bool:
|
|
105
|
-
"""Validate an API key"""
|
|
105
|
+
"""Validate an API key."""
|
|
106
106
|
if key in self.valid_keys:
|
|
107
107
|
self.valid_keys[key]["usage_count"] += 1
|
|
108
108
|
return True
|
|
109
109
|
return False
|
|
110
110
|
|
|
111
111
|
def remove_key(self, key: str):
|
|
112
|
-
"""Remove an API key"""
|
|
112
|
+
"""Remove an API key."""
|
|
113
113
|
if key in self.valid_keys:
|
|
114
114
|
del self.valid_keys[key]
|
|
115
115
|
|
|
116
116
|
def list_keys(self) -> List[Dict[str, Any]]:
|
|
117
|
-
"""List all API keys (without showing the actual key)"""
|
|
117
|
+
"""List all API keys (without showing the actual key)."""
|
|
118
118
|
return [
|
|
119
119
|
{
|
|
120
120
|
"name": info["name"],
|
|
@@ -126,7 +126,7 @@ class APIKeyManager:
|
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
class OpenAIAdapter:
|
|
129
|
-
"""Adapter to make MCLI model service OpenAI-compatible"""
|
|
129
|
+
"""Adapter to make MCLI model service OpenAI-compatible."""
|
|
130
130
|
|
|
131
131
|
def __init__(self, model_manager, require_auth: bool = True):
|
|
132
132
|
self.model_manager = model_manager
|
|
@@ -138,11 +138,11 @@ class OpenAIAdapter:
|
|
|
138
138
|
self._setup_routes()
|
|
139
139
|
|
|
140
140
|
def _setup_routes(self):
|
|
141
|
-
"""Setup OpenAI-compatible routes"""
|
|
141
|
+
"""Setup OpenAI-compatible routes."""
|
|
142
142
|
|
|
143
143
|
@self.router.get("/models", response_model=ModelListResponse)
|
|
144
144
|
async def list_models(api_key: str = Depends(self.verify_api_key)):
|
|
145
|
-
"""List available models (OpenAI compatible)"""
|
|
145
|
+
"""List available models (OpenAI compatible)."""
|
|
146
146
|
models = []
|
|
147
147
|
|
|
148
148
|
# Get loaded models from model manager
|
|
@@ -177,7 +177,7 @@ class OpenAIAdapter:
|
|
|
177
177
|
async def create_chat_completion(
|
|
178
178
|
request: ChatCompletionRequest, api_key: str = Depends(self.verify_api_key)
|
|
179
179
|
):
|
|
180
|
-
"""Create a chat completion (OpenAI compatible)"""
|
|
180
|
+
"""Create a chat completion (OpenAI compatible)."""
|
|
181
181
|
try:
|
|
182
182
|
# Extract the conversation history
|
|
183
183
|
messages = request.messages
|
|
@@ -219,7 +219,7 @@ class OpenAIAdapter:
|
|
|
219
219
|
raise HTTPException(status_code=500, detail=str(e))
|
|
220
220
|
|
|
221
221
|
def _messages_to_prompt(self, messages: List[Message]) -> str:
|
|
222
|
-
"""Convert OpenAI messages format to a simple prompt"""
|
|
222
|
+
"""Convert OpenAI messages format to a simple prompt."""
|
|
223
223
|
prompt_parts = []
|
|
224
224
|
|
|
225
225
|
for message in messages:
|
|
@@ -236,7 +236,7 @@ class OpenAIAdapter:
|
|
|
236
236
|
return "\n\n".join(prompt_parts)
|
|
237
237
|
|
|
238
238
|
async def _generate_response(self, request: ChatCompletionRequest, prompt: str) -> str:
|
|
239
|
-
"""Generate a response from the model"""
|
|
239
|
+
"""Generate a response from the model."""
|
|
240
240
|
try:
|
|
241
241
|
# Use the lightweight model server if available
|
|
242
242
|
if hasattr(self.model_manager, "loaded_models"):
|
|
@@ -275,7 +275,7 @@ class OpenAIAdapter:
|
|
|
275
275
|
async def _generate_stream(
|
|
276
276
|
self, request: ChatCompletionRequest, prompt: str
|
|
277
277
|
) -> AsyncGenerator[str, None]:
|
|
278
|
-
"""Generate a streaming response"""
|
|
278
|
+
"""Generate a streaming response."""
|
|
279
279
|
completion_id = f"chatcmpl-{uuid.uuid4().hex[:24]}"
|
|
280
280
|
|
|
281
281
|
# Generate response
|
|
@@ -304,7 +304,7 @@ class OpenAIAdapter:
|
|
|
304
304
|
yield "data: [DONE]\n\n"
|
|
305
305
|
|
|
306
306
|
async def verify_api_key(self, authorization: Optional[str] = Header(None)) -> str:
|
|
307
|
-
"""Verify API key from Authorization header"""
|
|
307
|
+
"""Verify API key from Authorization header."""
|
|
308
308
|
if not self.require_auth:
|
|
309
309
|
return "no-auth-required"
|
|
310
310
|
|
|
@@ -343,5 +343,5 @@ class OpenAIAdapter:
|
|
|
343
343
|
|
|
344
344
|
|
|
345
345
|
def create_openai_adapter(model_manager, require_auth: bool = True) -> OpenAIAdapter:
|
|
346
|
-
"""Create an OpenAI adapter instance"""
|
|
346
|
+
"""Create an OpenAI adapter instance."""
|
|
347
347
|
return OpenAIAdapter(model_manager, require_auth)
|
|
@@ -7,19 +7,14 @@ that integrate with the lightweight model service for AI-powered
|
|
|
7
7
|
document analysis.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
import base64
|
|
11
10
|
import json
|
|
12
11
|
import logging
|
|
13
12
|
import os
|
|
14
|
-
import shutil
|
|
15
|
-
import sys
|
|
16
13
|
import tempfile
|
|
17
14
|
from datetime import datetime
|
|
18
15
|
from pathlib import Path
|
|
19
16
|
from typing import Any, Dict, List, Optional
|
|
20
17
|
|
|
21
|
-
import requests
|
|
22
|
-
|
|
23
18
|
# PDF processing libraries
|
|
24
19
|
try:
|
|
25
20
|
import fitz # PyMuPDF
|
|
@@ -34,7 +29,7 @@ logger = logging.getLogger(__name__)
|
|
|
34
29
|
|
|
35
30
|
|
|
36
31
|
class PDFProcessor:
|
|
37
|
-
"""PDF processing with lightweight model integration"""
|
|
32
|
+
"""PDF processing with lightweight model integration."""
|
|
38
33
|
|
|
39
34
|
def __init__(self, models_dir: str = "./models/lightweight", port: int = 8080):
|
|
40
35
|
self.models_dir = Path(models_dir)
|
|
@@ -43,7 +38,7 @@ class PDFProcessor:
|
|
|
43
38
|
self.temp_dir = Path(tempfile.mkdtemp(prefix="pdf_processor_"))
|
|
44
39
|
|
|
45
40
|
def extract_text_from_pdf(self, pdf_path: str) -> Dict[str, Any]:
|
|
46
|
-
"""Extract text from PDF with enhanced processing"""
|
|
41
|
+
"""Extract text from PDF with enhanced processing."""
|
|
47
42
|
try:
|
|
48
43
|
pdf_path = Path(pdf_path)
|
|
49
44
|
if not pdf_path.exists():
|
|
@@ -69,7 +64,7 @@ class PDFProcessor:
|
|
|
69
64
|
return {"error": str(e)}
|
|
70
65
|
|
|
71
66
|
def _extract_pdf_text_enhanced(self, pdf_path: Path) -> str:
|
|
72
|
-
"""Enhanced PDF text extraction using multiple methods"""
|
|
67
|
+
"""Enhanced PDF text extraction using multiple methods."""
|
|
73
68
|
text_content = ""
|
|
74
69
|
|
|
75
70
|
try:
|
|
@@ -100,7 +95,7 @@ class PDFProcessor:
|
|
|
100
95
|
return text_content
|
|
101
96
|
|
|
102
97
|
def process_pdf_with_ai(self, pdf_path: str, model_key: Optional[str] = None) -> Dict[str, Any]:
|
|
103
|
-
"""Process PDF with AI model for enhanced analysis"""
|
|
98
|
+
"""Process PDF with AI model for enhanced analysis."""
|
|
104
99
|
try:
|
|
105
100
|
# Extract text first
|
|
106
101
|
extraction_result = self.extract_text_from_pdf(pdf_path)
|
|
@@ -137,7 +132,7 @@ class PDFProcessor:
|
|
|
137
132
|
return {"error": str(e)}
|
|
138
133
|
|
|
139
134
|
def _analyze_text_with_ai(self, text_content: str, model_key: str) -> Dict[str, Any]:
|
|
140
|
-
"""Analyze text content with AI model"""
|
|
135
|
+
"""Analyze text content with AI model."""
|
|
141
136
|
try:
|
|
142
137
|
# For now, provide basic analysis
|
|
143
138
|
# In a full implementation, this would use the actual model for inference
|
|
@@ -159,7 +154,7 @@ class PDFProcessor:
|
|
|
159
154
|
return {"error": str(e)}
|
|
160
155
|
|
|
161
156
|
def _generate_summary(self, text: str) -> str:
|
|
162
|
-
"""Generate a basic summary of the text"""
|
|
157
|
+
"""Generate a basic summary of the text."""
|
|
163
158
|
sentences = text.split(".")
|
|
164
159
|
if len(sentences) <= 3:
|
|
165
160
|
return text[:500] + "..." if len(text) > 500 else text
|
|
@@ -169,7 +164,7 @@ class PDFProcessor:
|
|
|
169
164
|
return summary[:500] + "..." if len(summary) > 500 else summary
|
|
170
165
|
|
|
171
166
|
def _extract_key_topics(self, text: str) -> List[str]:
|
|
172
|
-
"""Extract key topics from text"""
|
|
167
|
+
"""Extract key topics from text."""
|
|
173
168
|
# Simple keyword extraction
|
|
174
169
|
words = text.lower().split()
|
|
175
170
|
word_freq = {}
|
|
@@ -187,7 +182,7 @@ class PDFProcessor:
|
|
|
187
182
|
"at",
|
|
188
183
|
"to",
|
|
189
184
|
"for",
|
|
190
|
-
"
|
|
185
|
+
"o",
|
|
191
186
|
"with",
|
|
192
187
|
"by",
|
|
193
188
|
"is",
|
|
@@ -236,7 +231,7 @@ class PDFProcessor:
|
|
|
236
231
|
return [word for word, freq in sorted_words[:5]]
|
|
237
232
|
|
|
238
233
|
def _classify_document_type(self, text: str) -> str:
|
|
239
|
-
"""Classify the type of document"""
|
|
234
|
+
"""Classify the type of document."""
|
|
240
235
|
text_lower = text.lower()
|
|
241
236
|
|
|
242
237
|
if any(word in text_lower for word in ["contract", "agreement", "terms", "conditions"]):
|
|
@@ -253,7 +248,7 @@ class PDFProcessor:
|
|
|
253
248
|
return "general"
|
|
254
249
|
|
|
255
250
|
def _calculate_complexity_score(self, text: str) -> float:
|
|
256
|
-
"""Calculate text complexity score (0-1)"""
|
|
251
|
+
"""Calculate text complexity score (0-1)."""
|
|
257
252
|
sentences = text.split(".")
|
|
258
253
|
words = text.split()
|
|
259
254
|
|
|
@@ -268,7 +263,7 @@ class PDFProcessor:
|
|
|
268
263
|
return min(1.0, max(0.0, complexity))
|
|
269
264
|
|
|
270
265
|
def start_pdf_processing_service(self, port: int = 8080) -> bool:
|
|
271
|
-
"""Start the PDF processing service"""
|
|
266
|
+
"""Start the PDF processing service."""
|
|
272
267
|
try:
|
|
273
268
|
self.port = port
|
|
274
269
|
self.lightweight_server.port = port
|
|
@@ -280,7 +275,7 @@ class PDFProcessor:
|
|
|
280
275
|
return False
|
|
281
276
|
|
|
282
277
|
def get_service_status(self) -> Dict[str, Any]:
|
|
283
|
-
"""Get the status of the PDF processing service"""
|
|
278
|
+
"""Get the status of the PDF processing service."""
|
|
284
279
|
return {
|
|
285
280
|
"service_running": self.lightweight_server.running,
|
|
286
281
|
"port": self.port,
|
|
@@ -291,9 +286,9 @@ class PDFProcessor:
|
|
|
291
286
|
|
|
292
287
|
|
|
293
288
|
def create_pdf_processor_api():
|
|
294
|
-
"""Create a simple API for PDF processing"""
|
|
289
|
+
"""Create a simple API for PDF processing."""
|
|
295
290
|
import urllib.parse
|
|
296
|
-
from http.server import BaseHTTPRequestHandler
|
|
291
|
+
from http.server import BaseHTTPRequestHandler
|
|
297
292
|
|
|
298
293
|
class PDFProcessorHandler(BaseHTTPRequestHandler):
|
|
299
294
|
def __init__(self, *args, processor=None, **kwargs):
|
|
@@ -301,11 +296,11 @@ def create_pdf_processor_api():
|
|
|
301
296
|
super().__init__(*args, **kwargs)
|
|
302
297
|
|
|
303
298
|
def do_POST(self):
|
|
304
|
-
"""Handle PDF processing requests"""
|
|
299
|
+
"""Handle PDF processing requests."""
|
|
305
300
|
parsed_path = urllib.parse.urlparse(self.path)
|
|
306
301
|
path = parsed_path.path
|
|
307
302
|
|
|
308
|
-
if path == "/process-
|
|
303
|
+
if path == "/process-pd":
|
|
309
304
|
self._handle_process_pdf()
|
|
310
305
|
elif path == "/extract-text":
|
|
311
306
|
self._handle_extract_text()
|
|
@@ -313,7 +308,7 @@ def create_pdf_processor_api():
|
|
|
313
308
|
self._send_response(404, {"error": "Endpoint not found"})
|
|
314
309
|
|
|
315
310
|
def do_GET(self):
|
|
316
|
-
"""Handle status requests"""
|
|
311
|
+
"""Handle status requests."""
|
|
317
312
|
parsed_path = urllib.parse.urlparse(self.path)
|
|
318
313
|
path = parsed_path.path
|
|
319
314
|
|
|
@@ -324,7 +319,7 @@ def create_pdf_processor_api():
|
|
|
324
319
|
self._send_response(404, {"error": "Endpoint not found"})
|
|
325
320
|
|
|
326
321
|
def _handle_process_pdf(self):
|
|
327
|
-
"""Handle PDF processing with AI"""
|
|
322
|
+
"""Handle PDF processing with AI."""
|
|
328
323
|
try:
|
|
329
324
|
content_length = int(self.headers.get("Content-Length", 0))
|
|
330
325
|
post_data = self.rfile.read(content_length)
|
|
@@ -344,7 +339,7 @@ def create_pdf_processor_api():
|
|
|
344
339
|
self._send_response(500, {"error": str(e)})
|
|
345
340
|
|
|
346
341
|
def _handle_extract_text(self):
|
|
347
|
-
"""Handle text extraction from PDF"""
|
|
342
|
+
"""Handle text extraction from PDF."""
|
|
348
343
|
try:
|
|
349
344
|
content_length = int(self.headers.get("Content-Length", 0))
|
|
350
345
|
post_data = self.rfile.read(content_length)
|
|
@@ -363,7 +358,7 @@ def create_pdf_processor_api():
|
|
|
363
358
|
self._send_response(500, {"error": str(e)})
|
|
364
359
|
|
|
365
360
|
def _send_response(self, status_code, data):
|
|
366
|
-
"""Send JSON response"""
|
|
361
|
+
"""Send JSON response."""
|
|
367
362
|
self.send_response(status_code)
|
|
368
363
|
self.send_header("Content-Type", "application/json")
|
|
369
364
|
self.send_header("Access-Control-Allow-Origin", "*")
|
|
@@ -378,7 +373,7 @@ if __name__ == "__main__":
|
|
|
378
373
|
processor = PDFProcessor()
|
|
379
374
|
|
|
380
375
|
# Test with a sample PDF if available
|
|
381
|
-
test_pdf = "test.
|
|
376
|
+
test_pdf = "test.pd"
|
|
382
377
|
if os.path.exists(test_pdf):
|
|
383
378
|
result = processor.process_pdf_with_ai(test_pdf)
|
|
384
379
|
print(json.dumps(result, indent=2))
|
|
@@ -3,20 +3,22 @@
|
|
|
3
3
|
Test script for the efficient model runner functionality.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import os
|
|
7
6
|
import sys
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
|
|
9
|
+
import psutil
|
|
10
|
+
|
|
10
11
|
# Add the parent directory to the path so we can import the modules
|
|
11
12
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
12
13
|
|
|
14
|
+
from mcli.workflow.model_service.model_service import ModelService
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
def test_imports():
|
|
15
|
-
"""Test that all required modules can be imported"""
|
|
18
|
+
"""Test that all required modules can be imported."""
|
|
16
19
|
print("🧪 Testing imports...")
|
|
17
20
|
|
|
18
21
|
try:
|
|
19
|
-
import requests
|
|
20
22
|
|
|
21
23
|
print("✅ requests imported")
|
|
22
24
|
except ImportError as e:
|
|
@@ -24,7 +26,6 @@ def test_imports():
|
|
|
24
26
|
return False
|
|
25
27
|
|
|
26
28
|
try:
|
|
27
|
-
import click
|
|
28
29
|
|
|
29
30
|
print("✅ click imported")
|
|
30
31
|
except ImportError as e:
|
|
@@ -32,7 +33,6 @@ def test_imports():
|
|
|
32
33
|
return False
|
|
33
34
|
|
|
34
35
|
try:
|
|
35
|
-
import psutil
|
|
36
36
|
|
|
37
37
|
print("✅ psutil imported")
|
|
38
38
|
except ImportError as e:
|
|
@@ -40,7 +40,6 @@ def test_imports():
|
|
|
40
40
|
return False
|
|
41
41
|
|
|
42
42
|
try:
|
|
43
|
-
from mcli.workflow.model_service.model_service import ModelService
|
|
44
43
|
|
|
45
44
|
print("✅ ModelService imported")
|
|
46
45
|
except ImportError as e:
|
|
@@ -51,11 +50,10 @@ def test_imports():
|
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
def test_system_analysis():
|
|
54
|
-
"""Test system analysis functionality"""
|
|
53
|
+
"""Test system analysis functionality."""
|
|
55
54
|
print("\n🧪 Testing system analysis...")
|
|
56
55
|
|
|
57
56
|
try:
|
|
58
|
-
import psutil
|
|
59
57
|
|
|
60
58
|
# Get basic system info
|
|
61
59
|
cpu_count = psutil.cpu_count()
|
|
@@ -84,7 +82,7 @@ def test_system_analysis():
|
|
|
84
82
|
|
|
85
83
|
|
|
86
84
|
def test_model_selection():
|
|
87
|
-
"""Test model selection logic"""
|
|
85
|
+
"""Test model selection logic."""
|
|
88
86
|
print("\n🧪 Testing model selection...")
|
|
89
87
|
|
|
90
88
|
try:
|
|
@@ -102,7 +100,7 @@ def test_model_selection():
|
|
|
102
100
|
|
|
103
101
|
# Test system info
|
|
104
102
|
system_info = get_system_info()
|
|
105
|
-
print(
|
|
103
|
+
print("✅ System info collected")
|
|
106
104
|
|
|
107
105
|
# Test model recommendation
|
|
108
106
|
recommended = recommend_model(system_info)
|
|
@@ -116,7 +114,7 @@ def test_model_selection():
|
|
|
116
114
|
|
|
117
115
|
|
|
118
116
|
def test_ollama_check():
|
|
119
|
-
"""Test Ollama installation check"""
|
|
117
|
+
"""Test Ollama installation check."""
|
|
120
118
|
print("\n🧪 Testing Ollama check...")
|
|
121
119
|
|
|
122
120
|
try:
|
|
@@ -138,11 +136,10 @@ def test_ollama_check():
|
|
|
138
136
|
|
|
139
137
|
|
|
140
138
|
def test_mcli_service():
|
|
141
|
-
"""Test MCLI model service functionality"""
|
|
139
|
+
"""Test MCLI model service functionality."""
|
|
142
140
|
print("\n🧪 Testing MCLI model service...")
|
|
143
141
|
|
|
144
142
|
try:
|
|
145
|
-
from mcli.workflow.model_service.model_service import ModelService
|
|
146
143
|
|
|
147
144
|
# Create service instance
|
|
148
145
|
service = ModelService()
|
|
@@ -164,11 +161,10 @@ def test_mcli_service():
|
|
|
164
161
|
|
|
165
162
|
|
|
166
163
|
def test_api_endpoints():
|
|
167
|
-
"""Test API endpoint definitions"""
|
|
164
|
+
"""Test API endpoint definitions."""
|
|
168
165
|
print("\n🧪 Testing API endpoints...")
|
|
169
166
|
|
|
170
167
|
try:
|
|
171
|
-
from mcli.workflow.model_service.model_service import ModelService
|
|
172
168
|
|
|
173
169
|
service = ModelService()
|
|
174
170
|
|
|
@@ -191,7 +187,7 @@ def test_api_endpoints():
|
|
|
191
187
|
|
|
192
188
|
|
|
193
189
|
def main():
|
|
194
|
-
"""Run all tests"""
|
|
190
|
+
"""Run all tests."""
|
|
195
191
|
print("🚀 Testing Efficient Model Runner")
|
|
196
192
|
print("=" * 50)
|
|
197
193
|
|