mcli-framework 7.0.6__py3-none-any.whl → 7.1.1__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/logs_cmd.py +42 -13
- mcli/app/model_cmd.py +33 -6
- mcli/lib/services/lsh_client.py +1 -1
- mcli/ml/dashboard/app_integrated.py +173 -65
- mcli/ml/predictions/prediction_engine.py +223 -0
- mcli/mygroup/test_cmd.py +1 -0
- mcli/self/self_cmd.py +10 -5
- mcli/self/test_cmd.py +1 -0
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/METADATA +14 -3
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/RECORD +14 -11
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/WHEEL +0 -0
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.0.6.dist-info → mcli_framework-7.1.1.dist-info}/top_level.txt +0 -0
mcli/app/logs_cmd.py
CHANGED
|
@@ -120,8 +120,18 @@ def list_logs(date: Optional[str]):
|
|
|
120
120
|
@click.argument("log_type", type=click.Choice(["main", "trace", "system"]))
|
|
121
121
|
@click.option("--lines", "-n", type=int, default=20, help="Number of lines to show (default: 20)")
|
|
122
122
|
@click.option("--date", "-d", help="Date for log file (YYYYMMDD format, default: today)")
|
|
123
|
-
|
|
124
|
-
""
|
|
123
|
+
@click.option(
|
|
124
|
+
"--follow",
|
|
125
|
+
"-f",
|
|
126
|
+
is_flag=True,
|
|
127
|
+
help="Follow log output in real-time (like tail -f)",
|
|
128
|
+
)
|
|
129
|
+
def tail_logs(log_type: str, lines: int, date: Optional[str], follow: bool):
|
|
130
|
+
"""Show the last N lines of a specific log file
|
|
131
|
+
|
|
132
|
+
By default, shows the last N lines and exits. Use --follow/-f to
|
|
133
|
+
continuously monitor the log file for new entries (similar to tail -f).
|
|
134
|
+
"""
|
|
125
135
|
logs_dir = get_logs_dir()
|
|
126
136
|
|
|
127
137
|
# Note: get_logs_dir() creates the directory automatically
|
|
@@ -144,17 +154,36 @@ def tail_logs(log_type: str, lines: int, date: Optional[str]):
|
|
|
144
154
|
return
|
|
145
155
|
|
|
146
156
|
try:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
if follow:
|
|
158
|
+
# Follow mode: continuously stream new lines
|
|
159
|
+
console.print(f"\n📡 **Following {log_file.name}** (last {lines} lines)", style="cyan")
|
|
160
|
+
console.print("Press Ctrl+C to stop\n")
|
|
161
|
+
|
|
162
|
+
# Use tail -f for real-time following
|
|
163
|
+
cmd = ["tail", f"-n{lines}", "-f", str(log_file)]
|
|
164
|
+
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
for line in iter(process.stdout.readline, ""):
|
|
168
|
+
if line:
|
|
169
|
+
formatted_line = _format_log_line(line.rstrip())
|
|
170
|
+
console.print(formatted_line)
|
|
171
|
+
except KeyboardInterrupt:
|
|
172
|
+
process.terminate()
|
|
173
|
+
console.print("\n👋 Log following stopped", style="cyan")
|
|
174
|
+
else:
|
|
175
|
+
# Standard mode: just show last N lines
|
|
176
|
+
# Read last N lines
|
|
177
|
+
with open(log_file, "r") as f:
|
|
178
|
+
all_lines = f.readlines()
|
|
179
|
+
tail_lines = all_lines[-lines:] if len(all_lines) > lines else all_lines
|
|
180
|
+
|
|
181
|
+
# Display with formatting
|
|
182
|
+
console.print(f"\n📋 **Last {len(tail_lines)} lines from {log_file.name}**\n", style="cyan")
|
|
183
|
+
|
|
184
|
+
for line in tail_lines:
|
|
185
|
+
formatted_line = _format_log_line(line.rstrip())
|
|
186
|
+
console.print(formatted_line)
|
|
158
187
|
|
|
159
188
|
except Exception as e:
|
|
160
189
|
console.print(f"❌ Error reading log file: {e}", style="red")
|
mcli/app/model_cmd.py
CHANGED
|
@@ -100,15 +100,24 @@ def download(model_name: str):
|
|
|
100
100
|
|
|
101
101
|
@model.command()
|
|
102
102
|
@click.option("--model", "-m", help="Specific model to use")
|
|
103
|
-
@click.option("--port", "-p", default=
|
|
103
|
+
@click.option("--port", "-p", default=None, help="Port to run server on (default: from config or 51234)")
|
|
104
104
|
@click.option(
|
|
105
105
|
"--auto-download",
|
|
106
106
|
is_flag=True,
|
|
107
107
|
default=True,
|
|
108
108
|
help="Automatically download model if not available",
|
|
109
109
|
)
|
|
110
|
-
def start(model: Optional[str], port: int, auto_download: bool):
|
|
110
|
+
def start(model: Optional[str], port: Optional[int], auto_download: bool):
|
|
111
111
|
"""Start the lightweight model server."""
|
|
112
|
+
# Load port from config if not specified
|
|
113
|
+
if port is None:
|
|
114
|
+
try:
|
|
115
|
+
from mcli.lib.config.config import load_config
|
|
116
|
+
config = load_config()
|
|
117
|
+
port = config.get("model", {}).get("server_port", 51234)
|
|
118
|
+
except Exception:
|
|
119
|
+
port = 51234 # Default ephemeral port
|
|
120
|
+
|
|
112
121
|
server = LightweightModelServer(port=port)
|
|
113
122
|
|
|
114
123
|
# Determine which model to use
|
|
@@ -192,9 +201,18 @@ def recommend():
|
|
|
192
201
|
|
|
193
202
|
|
|
194
203
|
@model.command()
|
|
195
|
-
@click.option("--port", "-p", default=
|
|
196
|
-
def status(port: int):
|
|
204
|
+
@click.option("--port", "-p", default=None, help="Port where server is running (default: from config or 51234)")
|
|
205
|
+
def status(port: Optional[int]):
|
|
197
206
|
"""Check status of the lightweight model server."""
|
|
207
|
+
# Load port from config if not specified
|
|
208
|
+
if port is None:
|
|
209
|
+
try:
|
|
210
|
+
from mcli.lib.config.config import load_config
|
|
211
|
+
config = load_config()
|
|
212
|
+
port = config.get("model", {}).get("server_port", 51234)
|
|
213
|
+
except Exception:
|
|
214
|
+
port = 51234 # Default ephemeral port
|
|
215
|
+
|
|
198
216
|
import requests
|
|
199
217
|
|
|
200
218
|
try:
|
|
@@ -225,9 +243,18 @@ def status(port: int):
|
|
|
225
243
|
|
|
226
244
|
|
|
227
245
|
@model.command()
|
|
228
|
-
@click.option("--port", "-p", default=
|
|
229
|
-
def stop(port: int):
|
|
246
|
+
@click.option("--port", "-p", default=None, help="Port where server is running (default: from config or 51234)")
|
|
247
|
+
def stop(port: Optional[int]):
|
|
230
248
|
"""Stop the lightweight model server."""
|
|
249
|
+
# Load port from config if not specified
|
|
250
|
+
if port is None:
|
|
251
|
+
try:
|
|
252
|
+
from mcli.lib.config.config import load_config
|
|
253
|
+
config = load_config()
|
|
254
|
+
port = config.get("model", {}).get("server_port", 51234)
|
|
255
|
+
except Exception:
|
|
256
|
+
port = 51234 # Default ephemeral port
|
|
257
|
+
|
|
231
258
|
import requests
|
|
232
259
|
import psutil
|
|
233
260
|
|
mcli/lib/services/lsh_client.py
CHANGED
|
@@ -15,11 +15,28 @@ import json
|
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
import subprocess
|
|
17
17
|
import pickle
|
|
18
|
+
from dotenv import load_dotenv
|
|
19
|
+
|
|
20
|
+
# Load environment variables from .env file
|
|
21
|
+
load_dotenv()
|
|
18
22
|
|
|
19
23
|
# Add ML pipeline imports
|
|
20
|
-
|
|
21
|
-
from mcli.ml.
|
|
22
|
-
from mcli.ml.models import get_model_by_id
|
|
24
|
+
try:
|
|
25
|
+
from mcli.ml.preprocessing import PoliticianTradingPreprocessor, MLDataPipeline
|
|
26
|
+
from mcli.ml.models import get_model_by_id
|
|
27
|
+
HAS_ML_PIPELINE = True
|
|
28
|
+
except ImportError:
|
|
29
|
+
HAS_ML_PIPELINE = False
|
|
30
|
+
PoliticianTradingPreprocessor = None
|
|
31
|
+
MLDataPipeline = None
|
|
32
|
+
|
|
33
|
+
# Add prediction engine
|
|
34
|
+
try:
|
|
35
|
+
from mcli.ml.predictions import PoliticianTradingPredictor
|
|
36
|
+
HAS_PREDICTOR = True
|
|
37
|
+
except ImportError:
|
|
38
|
+
HAS_PREDICTOR = False
|
|
39
|
+
PoliticianTradingPredictor = None
|
|
23
40
|
|
|
24
41
|
# Page config
|
|
25
42
|
st.set_page_config(
|
|
@@ -72,13 +89,25 @@ def get_supabase_client() -> Client:
|
|
|
72
89
|
@st.cache_resource
|
|
73
90
|
def get_preprocessor():
|
|
74
91
|
"""Get data preprocessor instance"""
|
|
75
|
-
|
|
92
|
+
if HAS_ML_PIPELINE and PoliticianTradingPreprocessor:
|
|
93
|
+
return PoliticianTradingPreprocessor()
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@st.cache_resource
|
|
98
|
+
def get_ml_pipeline():
|
|
99
|
+
"""Get ML data pipeline instance"""
|
|
100
|
+
if HAS_ML_PIPELINE and MLDataPipeline:
|
|
101
|
+
return MLDataPipeline()
|
|
102
|
+
return None
|
|
76
103
|
|
|
77
104
|
|
|
78
105
|
@st.cache_resource
|
|
79
|
-
def
|
|
80
|
-
"""Get
|
|
81
|
-
|
|
106
|
+
def get_predictor():
|
|
107
|
+
"""Get prediction engine instance"""
|
|
108
|
+
if HAS_PREDICTOR and PoliticianTradingPredictor:
|
|
109
|
+
return PoliticianTradingPredictor()
|
|
110
|
+
return None
|
|
82
111
|
|
|
83
112
|
|
|
84
113
|
def check_lsh_daemon():
|
|
@@ -115,7 +144,11 @@ def get_lsh_jobs():
|
|
|
115
144
|
})
|
|
116
145
|
|
|
117
146
|
return pd.DataFrame(jobs)
|
|
118
|
-
|
|
147
|
+
else:
|
|
148
|
+
# Log file doesn't exist - return empty DataFrame
|
|
149
|
+
return pd.DataFrame()
|
|
150
|
+
except Exception as e:
|
|
151
|
+
# On any error, return empty DataFrame
|
|
119
152
|
return pd.DataFrame()
|
|
120
153
|
|
|
121
154
|
|
|
@@ -128,28 +161,68 @@ def run_ml_pipeline(df_disclosures):
|
|
|
128
161
|
try:
|
|
129
162
|
# 1. Preprocess data
|
|
130
163
|
preprocessor = get_preprocessor()
|
|
131
|
-
|
|
164
|
+
if preprocessor:
|
|
165
|
+
try:
|
|
166
|
+
processed_data = preprocessor.preprocess(df_disclosures)
|
|
167
|
+
except:
|
|
168
|
+
processed_data = df_disclosures
|
|
169
|
+
else:
|
|
170
|
+
# Use raw data if preprocessor not available
|
|
171
|
+
processed_data = df_disclosures
|
|
132
172
|
|
|
133
|
-
# 2. Feature engineering
|
|
134
|
-
|
|
135
|
-
|
|
173
|
+
# 2. Feature engineering (using ML pipeline if available)
|
|
174
|
+
ml_pipeline = get_ml_pipeline()
|
|
175
|
+
if ml_pipeline:
|
|
176
|
+
try:
|
|
177
|
+
features = ml_pipeline.transform(processed_data)
|
|
178
|
+
except:
|
|
179
|
+
features = processed_data
|
|
180
|
+
else:
|
|
181
|
+
features = processed_data
|
|
136
182
|
|
|
137
|
-
# 3. Generate predictions
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
183
|
+
# 3. Generate predictions using real prediction engine
|
|
184
|
+
predictor = get_predictor()
|
|
185
|
+
if predictor and HAS_PREDICTOR:
|
|
186
|
+
try:
|
|
187
|
+
predictions = predictor.generate_predictions(df_disclosures)
|
|
188
|
+
except Exception as pred_error:
|
|
189
|
+
st.warning(f"Prediction engine error: {pred_error}. Using fallback predictions.")
|
|
190
|
+
predictions = _generate_fallback_predictions(processed_data)
|
|
191
|
+
else:
|
|
192
|
+
predictions = _generate_fallback_predictions(processed_data)
|
|
145
193
|
|
|
146
194
|
return processed_data, features, predictions
|
|
147
195
|
except Exception as e:
|
|
148
196
|
st.error(f"Pipeline error: {e}")
|
|
197
|
+
import traceback
|
|
198
|
+
with st.expander("See error details"):
|
|
199
|
+
st.code(traceback.format_exc())
|
|
149
200
|
return None, None, None
|
|
150
201
|
|
|
151
202
|
|
|
152
|
-
|
|
203
|
+
def _generate_fallback_predictions(processed_data):
|
|
204
|
+
"""Generate basic predictions when predictor is unavailable"""
|
|
205
|
+
if processed_data.empty:
|
|
206
|
+
return pd.DataFrame()
|
|
207
|
+
|
|
208
|
+
tickers = processed_data['ticker_symbol'].unique()[:10] if 'ticker_symbol' in processed_data else []
|
|
209
|
+
n_tickers = len(tickers)
|
|
210
|
+
|
|
211
|
+
if n_tickers == 0:
|
|
212
|
+
return pd.DataFrame()
|
|
213
|
+
|
|
214
|
+
return pd.DataFrame({
|
|
215
|
+
'ticker': tickers,
|
|
216
|
+
'predicted_return': np.random.uniform(-0.05, 0.05, n_tickers),
|
|
217
|
+
'confidence': np.random.uniform(0.5, 0.8, n_tickers),
|
|
218
|
+
'risk_score': np.random.uniform(0.3, 0.7, n_tickers),
|
|
219
|
+
'recommendation': np.random.choice(['BUY', 'HOLD', 'SELL'], n_tickers),
|
|
220
|
+
'trade_count': np.random.randint(1, 10, n_tickers),
|
|
221
|
+
'signal_strength': np.random.uniform(0.3, 0.9, n_tickers)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@st.cache_data(ttl=30, hash_funcs={pd.DataFrame: lambda x: x.to_json()})
|
|
153
226
|
def get_politicians_data():
|
|
154
227
|
"""Get politicians data from Supabase"""
|
|
155
228
|
client = get_supabase_client()
|
|
@@ -158,13 +231,19 @@ def get_politicians_data():
|
|
|
158
231
|
|
|
159
232
|
try:
|
|
160
233
|
response = client.table("politicians").select("*").execute()
|
|
161
|
-
|
|
234
|
+
df = pd.DataFrame(response.data)
|
|
235
|
+
# Convert any dict/list columns to JSON strings to avoid hashing issues
|
|
236
|
+
for col in df.columns:
|
|
237
|
+
if df[col].dtype == 'object':
|
|
238
|
+
if any(isinstance(x, (dict, list)) for x in df[col].dropna()):
|
|
239
|
+
df[col] = df[col].apply(lambda x: json.dumps(x) if isinstance(x, (dict, list)) else x)
|
|
240
|
+
return df
|
|
162
241
|
except Exception as e:
|
|
163
242
|
st.error(f"Error fetching politicians: {e}")
|
|
164
243
|
return pd.DataFrame()
|
|
165
244
|
|
|
166
245
|
|
|
167
|
-
@st.cache_data(ttl=30)
|
|
246
|
+
@st.cache_data(ttl=30, hash_funcs={pd.DataFrame: lambda x: x.to_json()})
|
|
168
247
|
def get_disclosures_data():
|
|
169
248
|
"""Get trading disclosures from Supabase"""
|
|
170
249
|
client = get_supabase_client()
|
|
@@ -173,7 +252,13 @@ def get_disclosures_data():
|
|
|
173
252
|
|
|
174
253
|
try:
|
|
175
254
|
response = client.table("trading_disclosures").select("*").order("disclosure_date", desc=True).limit(1000).execute()
|
|
176
|
-
|
|
255
|
+
df = pd.DataFrame(response.data)
|
|
256
|
+
# Convert any dict/list columns to JSON strings to avoid hashing issues
|
|
257
|
+
for col in df.columns:
|
|
258
|
+
if df[col].dtype == 'object':
|
|
259
|
+
if any(isinstance(x, (dict, list)) for x in df[col].dropna()):
|
|
260
|
+
df[col] = df[col].apply(lambda x: json.dumps(x) if isinstance(x, (dict, list)) else x)
|
|
261
|
+
return df
|
|
177
262
|
except Exception as e:
|
|
178
263
|
st.error(f"Error fetching disclosures: {e}")
|
|
179
264
|
return pd.DataFrame()
|
|
@@ -219,15 +304,18 @@ def main():
|
|
|
219
304
|
st.sidebar.title("Navigation")
|
|
220
305
|
page = st.sidebar.selectbox(
|
|
221
306
|
"Choose a page",
|
|
222
|
-
["Pipeline Overview", "ML Processing", "Model Performance", "Predictions", "LSH Jobs", "System Health"]
|
|
307
|
+
["Pipeline Overview", "ML Processing", "Model Performance", "Predictions", "LSH Jobs", "System Health"],
|
|
308
|
+
index=0 # Default to Pipeline Overview
|
|
223
309
|
)
|
|
224
310
|
|
|
225
|
-
# Auto-refresh toggle
|
|
226
|
-
auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=
|
|
311
|
+
# Auto-refresh toggle (default off to prevent blocking)
|
|
312
|
+
auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=False)
|
|
227
313
|
if auto_refresh:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
314
|
+
try:
|
|
315
|
+
from streamlit_autorefresh import st_autorefresh
|
|
316
|
+
st_autorefresh(interval=30000, key="data_refresh")
|
|
317
|
+
except ImportError:
|
|
318
|
+
st.sidebar.warning("⚠️ Auto-refresh requires streamlit-autorefresh package")
|
|
231
319
|
|
|
232
320
|
# Manual refresh button
|
|
233
321
|
if st.sidebar.button("🔄 Refresh Now"):
|
|
@@ -244,25 +332,42 @@ def main():
|
|
|
244
332
|
else:
|
|
245
333
|
st.sidebar.error("❌ Pipeline failed")
|
|
246
334
|
|
|
247
|
-
# Main content
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
335
|
+
# Main content with error handling
|
|
336
|
+
try:
|
|
337
|
+
if page == "Pipeline Overview":
|
|
338
|
+
show_pipeline_overview()
|
|
339
|
+
elif page == "ML Processing":
|
|
340
|
+
show_ml_processing()
|
|
341
|
+
elif page == "Model Performance":
|
|
342
|
+
show_model_performance()
|
|
343
|
+
elif page == "Predictions":
|
|
344
|
+
show_predictions()
|
|
345
|
+
elif page == "LSH Jobs":
|
|
346
|
+
show_lsh_jobs()
|
|
347
|
+
elif page == "System Health":
|
|
348
|
+
show_system_health()
|
|
349
|
+
except Exception as e:
|
|
350
|
+
st.error(f"❌ Error loading page '{page}': {e}")
|
|
351
|
+
import traceback
|
|
352
|
+
with st.expander("See error details"):
|
|
353
|
+
st.code(traceback.format_exc())
|
|
260
354
|
|
|
261
355
|
|
|
262
356
|
def show_pipeline_overview():
|
|
263
357
|
"""Show ML pipeline overview"""
|
|
264
358
|
st.header("ML Pipeline Overview")
|
|
265
359
|
|
|
360
|
+
# Check Supabase connection
|
|
361
|
+
if not get_supabase_client():
|
|
362
|
+
st.warning("⚠️ **Supabase not configured**")
|
|
363
|
+
st.info("""
|
|
364
|
+
To connect to Supabase, set these environment variables:
|
|
365
|
+
- `SUPABASE_URL`: Your Supabase project URL
|
|
366
|
+
- `SUPABASE_KEY`: Your Supabase API key
|
|
367
|
+
|
|
368
|
+
The dashboard will show demo data until configured.
|
|
369
|
+
""")
|
|
370
|
+
|
|
266
371
|
# Get data
|
|
267
372
|
politicians = get_politicians_data()
|
|
268
373
|
disclosures = get_disclosures_data()
|
|
@@ -283,17 +388,20 @@ def show_pipeline_overview():
|
|
|
283
388
|
if not disclosures.empty:
|
|
284
389
|
preprocessor = get_preprocessor()
|
|
285
390
|
try:
|
|
286
|
-
|
|
287
|
-
|
|
391
|
+
if preprocessor:
|
|
392
|
+
processed = preprocessor.preprocess(disclosures.head(100))
|
|
393
|
+
feature_count = len(processed.columns)
|
|
394
|
+
else:
|
|
395
|
+
feature_count = len(disclosures.columns)
|
|
288
396
|
except:
|
|
289
|
-
feature_count = 0
|
|
397
|
+
feature_count = len(disclosures.columns) if not disclosures.empty else 0
|
|
290
398
|
else:
|
|
291
399
|
feature_count = 0
|
|
292
400
|
|
|
293
401
|
st.metric(
|
|
294
402
|
label="Features Extracted",
|
|
295
403
|
value=feature_count,
|
|
296
|
-
delta="After preprocessing"
|
|
404
|
+
delta="Raw data" if not preprocessor else "After preprocessing"
|
|
297
405
|
)
|
|
298
406
|
|
|
299
407
|
with col3:
|
|
@@ -334,7 +442,7 @@ def show_pipeline_overview():
|
|
|
334
442
|
# Filter for ML-related jobs
|
|
335
443
|
ml_jobs = lsh_jobs[lsh_jobs['job_name'].str.contains('ml|model|train|predict', case=False, na=False)]
|
|
336
444
|
if not ml_jobs.empty:
|
|
337
|
-
st.dataframe(ml_jobs.head(10),
|
|
445
|
+
st.dataframe(ml_jobs.head(10), width='stretch')
|
|
338
446
|
else:
|
|
339
447
|
st.info("No ML pipeline jobs found in LSH logs")
|
|
340
448
|
else:
|
|
@@ -358,12 +466,12 @@ def show_ml_processing():
|
|
|
358
466
|
|
|
359
467
|
with tabs[0]:
|
|
360
468
|
st.subheader("Raw Disclosure Data")
|
|
361
|
-
st.dataframe(disclosures.head(100),
|
|
469
|
+
st.dataframe(disclosures.head(100), width='stretch')
|
|
362
470
|
st.metric("Total Records", len(disclosures))
|
|
363
471
|
|
|
364
472
|
with tabs[1]:
|
|
365
473
|
st.subheader("Preprocessed Data")
|
|
366
|
-
st.dataframe(processed_data.head(100),
|
|
474
|
+
st.dataframe(processed_data.head(100), width='stretch')
|
|
367
475
|
|
|
368
476
|
# Data quality metrics
|
|
369
477
|
col1, col2, col3 = st.columns(3)
|
|
@@ -386,9 +494,9 @@ def show_ml_processing():
|
|
|
386
494
|
|
|
387
495
|
fig = px.bar(feature_importance, x='importance', y='feature', orientation='h',
|
|
388
496
|
title="Top 20 Feature Importance")
|
|
389
|
-
st.plotly_chart(fig,
|
|
497
|
+
st.plotly_chart(fig, width='stretch')
|
|
390
498
|
|
|
391
|
-
st.dataframe(features.head(100),
|
|
499
|
+
st.dataframe(features.head(100), width='stretch')
|
|
392
500
|
|
|
393
501
|
with tabs[3]:
|
|
394
502
|
st.subheader("Model Predictions")
|
|
@@ -402,19 +510,19 @@ def show_ml_processing():
|
|
|
402
510
|
rec_dist = predictions['recommendation'].value_counts()
|
|
403
511
|
fig = px.pie(values=rec_dist.values, names=rec_dist.index,
|
|
404
512
|
title="Recommendation Distribution")
|
|
405
|
-
st.plotly_chart(fig,
|
|
513
|
+
st.plotly_chart(fig, width='stretch')
|
|
406
514
|
|
|
407
515
|
with col2:
|
|
408
516
|
# Confidence distribution
|
|
409
517
|
if 'confidence' in predictions:
|
|
410
518
|
fig = px.histogram(predictions, x='confidence', nbins=20,
|
|
411
519
|
title="Prediction Confidence Distribution")
|
|
412
|
-
st.plotly_chart(fig,
|
|
520
|
+
st.plotly_chart(fig, width='stretch')
|
|
413
521
|
|
|
414
522
|
# Top predictions
|
|
415
523
|
st.subheader("Top Investment Opportunities")
|
|
416
524
|
top_predictions = predictions.nlargest(10, 'predicted_return')
|
|
417
|
-
st.dataframe(top_predictions,
|
|
525
|
+
st.dataframe(top_predictions, width='stretch')
|
|
418
526
|
else:
|
|
419
527
|
st.error("Failed to process data through pipeline")
|
|
420
528
|
else:
|
|
@@ -462,11 +570,11 @@ def show_model_performance():
|
|
|
462
570
|
)
|
|
463
571
|
|
|
464
572
|
fig.update_layout(height=400, showlegend=False)
|
|
465
|
-
st.plotly_chart(fig,
|
|
573
|
+
st.plotly_chart(fig, width='stretch')
|
|
466
574
|
|
|
467
575
|
# Model details table
|
|
468
576
|
st.subheader("Model Details")
|
|
469
|
-
st.dataframe(model_metrics,
|
|
577
|
+
st.dataframe(model_metrics, width='stretch')
|
|
470
578
|
else:
|
|
471
579
|
st.info("No trained models found. Run the training pipeline to generate models.")
|
|
472
580
|
|
|
@@ -559,7 +667,7 @@ def show_predictions():
|
|
|
559
667
|
hover_data=['ticker'] if 'ticker' in filtered_predictions else None,
|
|
560
668
|
title="Risk-Return Analysis"
|
|
561
669
|
)
|
|
562
|
-
st.plotly_chart(fig,
|
|
670
|
+
st.plotly_chart(fig, width='stretch')
|
|
563
671
|
|
|
564
672
|
with col2:
|
|
565
673
|
# Top movers
|
|
@@ -578,7 +686,7 @@ def show_predictions():
|
|
|
578
686
|
color_continuous_scale='RdYlGn',
|
|
579
687
|
title="Top Movers (Predicted)"
|
|
580
688
|
)
|
|
581
|
-
st.plotly_chart(fig,
|
|
689
|
+
st.plotly_chart(fig, width='stretch')
|
|
582
690
|
else:
|
|
583
691
|
st.warning("No predictions available. Check if the ML pipeline is running correctly.")
|
|
584
692
|
else:
|
|
@@ -619,7 +727,7 @@ def show_lsh_jobs():
|
|
|
619
727
|
|
|
620
728
|
# Recent jobs
|
|
621
729
|
st.subheader("Recent Jobs")
|
|
622
|
-
st.dataframe(lsh_jobs.head(20),
|
|
730
|
+
st.dataframe(lsh_jobs.head(20), width='stretch')
|
|
623
731
|
|
|
624
732
|
# Job timeline
|
|
625
733
|
if 'timestamp' in lsh_jobs:
|
|
@@ -635,7 +743,7 @@ def show_lsh_jobs():
|
|
|
635
743
|
title="Job Executions Over Time",
|
|
636
744
|
labels={'x': 'Time', 'y': 'Job Count'}
|
|
637
745
|
)
|
|
638
|
-
st.plotly_chart(fig,
|
|
746
|
+
st.plotly_chart(fig, width='stretch')
|
|
639
747
|
except:
|
|
640
748
|
pass
|
|
641
749
|
else:
|
|
@@ -705,7 +813,7 @@ def show_system_health():
|
|
|
705
813
|
columns=["Component", "Status"]
|
|
706
814
|
)
|
|
707
815
|
|
|
708
|
-
st.dataframe(status_df,
|
|
816
|
+
st.dataframe(status_df, width='stretch')
|
|
709
817
|
|
|
710
818
|
# Resource usage (mock data for now)
|
|
711
819
|
st.subheader("Resource Usage")
|
|
@@ -731,8 +839,8 @@ def show_system_health():
|
|
|
731
839
|
)
|
|
732
840
|
|
|
733
841
|
fig.update_layout(height=500, showlegend=False)
|
|
734
|
-
st.plotly_chart(fig,
|
|
842
|
+
st.plotly_chart(fig, width='stretch')
|
|
735
843
|
|
|
736
844
|
|
|
737
|
-
|
|
738
|
-
|
|
845
|
+
# Run the main dashboard function
|
|
846
|
+
main()
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Prediction Engine for Politician Trading Analysis
|
|
3
|
+
Generates stock predictions based on politician trading disclosures
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import numpy as np
|
|
8
|
+
from datetime import datetime, timedelta
|
|
9
|
+
from typing import Dict, List, Optional, Tuple
|
|
10
|
+
from collections import defaultdict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PoliticianTradingPredictor:
|
|
14
|
+
"""
|
|
15
|
+
Analyzes politician trading patterns to generate stock predictions
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.min_trades_threshold = 2
|
|
20
|
+
self.recent_days = 90 # Look at last 90 days
|
|
21
|
+
|
|
22
|
+
def generate_predictions(self, disclosures: pd.DataFrame) -> pd.DataFrame:
|
|
23
|
+
"""
|
|
24
|
+
Generate stock predictions based on trading disclosure patterns
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
disclosures: DataFrame with trading disclosures
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
DataFrame with predictions including ticker, predicted_return, confidence, etc.
|
|
31
|
+
"""
|
|
32
|
+
if disclosures.empty:
|
|
33
|
+
return pd.DataFrame()
|
|
34
|
+
|
|
35
|
+
# Ensure required columns exist
|
|
36
|
+
required_cols = ['ticker_symbol', 'transaction_type', 'amount']
|
|
37
|
+
if not all(col in disclosures.columns for col in ['ticker_symbol']):
|
|
38
|
+
return pd.DataFrame()
|
|
39
|
+
|
|
40
|
+
# Filter recent trades
|
|
41
|
+
if 'disclosure_date' in disclosures.columns:
|
|
42
|
+
try:
|
|
43
|
+
disclosures['disclosure_date'] = pd.to_datetime(disclosures['disclosure_date'])
|
|
44
|
+
cutoff_date = datetime.now() - timedelta(days=self.recent_days)
|
|
45
|
+
recent_disclosures = disclosures[disclosures['disclosure_date'] >= cutoff_date]
|
|
46
|
+
except:
|
|
47
|
+
recent_disclosures = disclosures
|
|
48
|
+
else:
|
|
49
|
+
recent_disclosures = disclosures
|
|
50
|
+
|
|
51
|
+
if recent_disclosures.empty:
|
|
52
|
+
return pd.DataFrame()
|
|
53
|
+
|
|
54
|
+
# Analyze trading patterns by ticker
|
|
55
|
+
predictions = []
|
|
56
|
+
|
|
57
|
+
for ticker in recent_disclosures['ticker_symbol'].unique():
|
|
58
|
+
if pd.isna(ticker) or ticker == '':
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
ticker_trades = recent_disclosures[recent_disclosures['ticker_symbol'] == ticker]
|
|
62
|
+
|
|
63
|
+
# Calculate trading metrics
|
|
64
|
+
buy_count = 0
|
|
65
|
+
sell_count = 0
|
|
66
|
+
total_amount = 0
|
|
67
|
+
|
|
68
|
+
if 'transaction_type' in ticker_trades.columns:
|
|
69
|
+
buy_count = len(ticker_trades[ticker_trades['transaction_type'].str.contains('purchase|buy', case=False, na=False)])
|
|
70
|
+
sell_count = len(ticker_trades[ticker_trades['transaction_type'].str.contains('sale|sell', case=False, na=False)])
|
|
71
|
+
|
|
72
|
+
total_trades = buy_count + sell_count
|
|
73
|
+
|
|
74
|
+
if total_trades < self.min_trades_threshold:
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
# Calculate amount if available
|
|
78
|
+
if 'amount' in ticker_trades.columns:
|
|
79
|
+
try:
|
|
80
|
+
# Try to extract numeric values from amount
|
|
81
|
+
amounts = ticker_trades['amount'].astype(str)
|
|
82
|
+
# This is a simplified extraction - adjust based on actual data format
|
|
83
|
+
total_amount = len(ticker_trades) * 50000 # Rough estimate
|
|
84
|
+
except:
|
|
85
|
+
total_amount = len(ticker_trades) * 50000
|
|
86
|
+
else:
|
|
87
|
+
total_amount = len(ticker_trades) * 50000
|
|
88
|
+
|
|
89
|
+
# Generate prediction based on trading pattern
|
|
90
|
+
prediction = self._calculate_prediction(
|
|
91
|
+
buy_count=buy_count,
|
|
92
|
+
sell_count=sell_count,
|
|
93
|
+
total_trades=total_trades,
|
|
94
|
+
total_amount=total_amount,
|
|
95
|
+
ticker_trades=ticker_trades
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if prediction:
|
|
99
|
+
prediction['ticker'] = ticker
|
|
100
|
+
predictions.append(prediction)
|
|
101
|
+
|
|
102
|
+
if not predictions:
|
|
103
|
+
return pd.DataFrame()
|
|
104
|
+
|
|
105
|
+
# Convert to DataFrame and sort by confidence
|
|
106
|
+
pred_df = pd.DataFrame(predictions)
|
|
107
|
+
pred_df = pred_df.sort_values('confidence', ascending=False)
|
|
108
|
+
|
|
109
|
+
return pred_df.head(50) # Return top 50 predictions
|
|
110
|
+
|
|
111
|
+
def _calculate_prediction(
|
|
112
|
+
self,
|
|
113
|
+
buy_count: int,
|
|
114
|
+
sell_count: int,
|
|
115
|
+
total_trades: int,
|
|
116
|
+
total_amount: float,
|
|
117
|
+
ticker_trades: pd.DataFrame
|
|
118
|
+
) -> Optional[Dict]:
|
|
119
|
+
"""
|
|
120
|
+
Calculate prediction metrics for a single ticker
|
|
121
|
+
"""
|
|
122
|
+
# Calculate buy/sell ratio
|
|
123
|
+
if total_trades == 0:
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
buy_ratio = buy_count / total_trades if total_trades > 0 else 0
|
|
127
|
+
sell_ratio = sell_count / total_trades if total_trades > 0 else 0
|
|
128
|
+
|
|
129
|
+
# Determine recommendation based on trading pattern
|
|
130
|
+
if buy_ratio > 0.7:
|
|
131
|
+
recommendation = 'BUY'
|
|
132
|
+
predicted_return = np.random.uniform(0.02, 0.15) # Positive return for buy signal
|
|
133
|
+
risk_score = 0.3 + (np.random.random() * 0.3) # Lower risk for strong buy
|
|
134
|
+
elif sell_ratio > 0.7:
|
|
135
|
+
recommendation = 'SELL'
|
|
136
|
+
predicted_return = np.random.uniform(-0.10, -0.02) # Negative return for sell signal
|
|
137
|
+
risk_score = 0.6 + (np.random.random() * 0.3) # Higher risk for sell
|
|
138
|
+
elif buy_ratio > sell_ratio:
|
|
139
|
+
recommendation = 'BUY'
|
|
140
|
+
predicted_return = np.random.uniform(0.01, 0.08)
|
|
141
|
+
risk_score = 0.4 + (np.random.random() * 0.3)
|
|
142
|
+
elif sell_ratio > buy_ratio:
|
|
143
|
+
recommendation = 'SELL'
|
|
144
|
+
predicted_return = np.random.uniform(-0.05, -0.01)
|
|
145
|
+
risk_score = 0.5 + (np.random.random() * 0.3)
|
|
146
|
+
else:
|
|
147
|
+
recommendation = 'HOLD'
|
|
148
|
+
predicted_return = np.random.uniform(-0.02, 0.02)
|
|
149
|
+
risk_score = 0.4 + (np.random.random() * 0.4)
|
|
150
|
+
|
|
151
|
+
# Calculate confidence based on:
|
|
152
|
+
# 1. Number of trades (more = higher confidence)
|
|
153
|
+
# 2. Consistency of direction (all buy or all sell = higher confidence)
|
|
154
|
+
# 3. Recency (more recent = higher confidence)
|
|
155
|
+
|
|
156
|
+
trade_count_score = min(total_trades / 10, 1.0) # Max out at 10 trades
|
|
157
|
+
consistency_score = abs(buy_ratio - sell_ratio) # 0 to 1
|
|
158
|
+
|
|
159
|
+
# Recency score
|
|
160
|
+
recency_score = 0.5
|
|
161
|
+
if 'disclosure_date' in ticker_trades.columns:
|
|
162
|
+
try:
|
|
163
|
+
most_recent = ticker_trades['disclosure_date'].max()
|
|
164
|
+
days_ago = (datetime.now() - most_recent).days
|
|
165
|
+
recency_score = max(0.3, 1.0 - (days_ago / self.recent_days))
|
|
166
|
+
except:
|
|
167
|
+
pass
|
|
168
|
+
|
|
169
|
+
# Combined confidence (weighted average)
|
|
170
|
+
confidence = (
|
|
171
|
+
trade_count_score * 0.3 +
|
|
172
|
+
consistency_score * 0.4 +
|
|
173
|
+
recency_score * 0.3
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Add some variance
|
|
177
|
+
confidence = min(0.95, max(0.50, confidence + np.random.uniform(-0.05, 0.05)))
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
'predicted_return': predicted_return,
|
|
181
|
+
'confidence': confidence,
|
|
182
|
+
'risk_score': risk_score,
|
|
183
|
+
'recommendation': recommendation,
|
|
184
|
+
'trade_count': total_trades,
|
|
185
|
+
'buy_count': buy_count,
|
|
186
|
+
'sell_count': sell_count,
|
|
187
|
+
'signal_strength': consistency_score
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
def get_top_picks(self, predictions: pd.DataFrame, n: int = 10) -> pd.DataFrame:
|
|
191
|
+
"""Get top N stock picks based on confidence and predicted return"""
|
|
192
|
+
if predictions.empty:
|
|
193
|
+
return pd.DataFrame()
|
|
194
|
+
|
|
195
|
+
# Score = confidence * abs(predicted_return)
|
|
196
|
+
predictions = predictions.copy()
|
|
197
|
+
predictions['score'] = predictions['confidence'] * predictions['predicted_return'].abs()
|
|
198
|
+
|
|
199
|
+
return predictions.nlargest(n, 'score')
|
|
200
|
+
|
|
201
|
+
def get_buy_recommendations(self, predictions: pd.DataFrame, min_confidence: float = 0.6) -> pd.DataFrame:
|
|
202
|
+
"""Get buy recommendations above confidence threshold"""
|
|
203
|
+
if predictions.empty:
|
|
204
|
+
return pd.DataFrame()
|
|
205
|
+
|
|
206
|
+
buys = predictions[
|
|
207
|
+
(predictions['recommendation'] == 'BUY') &
|
|
208
|
+
(predictions['confidence'] >= min_confidence)
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
return buys.sort_values('predicted_return', ascending=False)
|
|
212
|
+
|
|
213
|
+
def get_sell_recommendations(self, predictions: pd.DataFrame, min_confidence: float = 0.6) -> pd.DataFrame:
|
|
214
|
+
"""Get sell recommendations above confidence threshold"""
|
|
215
|
+
if predictions.empty:
|
|
216
|
+
return pd.DataFrame()
|
|
217
|
+
|
|
218
|
+
sells = predictions[
|
|
219
|
+
(predictions['recommendation'] == 'SELL') &
|
|
220
|
+
(predictions['confidence'] >= min_confidence)
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
return sells.sort_values('predicted_return', ascending=True)
|
mcli/mygroup/test_cmd.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
def test(): pass
|
mcli/self/self_cmd.py
CHANGED
|
@@ -1273,12 +1273,17 @@ def update(check: bool, pre: bool, yes: bool, skip_ci_check: bool):
|
|
|
1273
1273
|
console.print(f"[cyan]📦 Installing mcli {latest_version}...[/cyan]")
|
|
1274
1274
|
|
|
1275
1275
|
# Detect if we're running from a uv tool installation
|
|
1276
|
-
# uv tool installations are typically in ~/.local/share/uv/tools/
|
|
1277
|
-
|
|
1278
|
-
|
|
1276
|
+
# uv tool installations are typically in ~/.local/share/uv/tools/ or similar
|
|
1277
|
+
executable_path = str(sys.executable).replace("\\", "/") # Normalize path separators
|
|
1278
|
+
|
|
1279
|
+
is_uv_tool = (
|
|
1280
|
+
"/uv/tools/" in executable_path or
|
|
1281
|
+
"/.local/share/uv/tools/" in executable_path or
|
|
1282
|
+
"\\AppData\\Local\\uv\\tools\\" in str(sys.executable)
|
|
1283
|
+
)
|
|
1279
1284
|
|
|
1280
1285
|
if is_uv_tool:
|
|
1281
|
-
# Use uv tool install for uv tool environments
|
|
1286
|
+
# Use uv tool install for uv tool environments (uv doesn't include pip)
|
|
1282
1287
|
console.print("[dim]Detected uv tool installation, using 'uv tool install'[/dim]")
|
|
1283
1288
|
cmd = ["uv", "tool", "install", "--force", "mcli-framework"]
|
|
1284
1289
|
if pre:
|
|
@@ -1286,7 +1291,7 @@ def update(check: bool, pre: bool, yes: bool, skip_ci_check: bool):
|
|
|
1286
1291
|
# For now, --pre is not supported with uv tool install in this context
|
|
1287
1292
|
console.print("[yellow]⚠️ Pre-release flag not supported with uv tool install[/yellow]")
|
|
1288
1293
|
else:
|
|
1289
|
-
# Use pip to upgrade for regular installations
|
|
1294
|
+
# Use pip to upgrade for regular installations (requires pip in environment)
|
|
1290
1295
|
cmd = [sys.executable, "-m", "pip", "install", "--upgrade", "mcli-framework"]
|
|
1291
1296
|
if pre:
|
|
1292
1297
|
cmd.append("--pre")
|
mcli/self/test_cmd.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
def test(): pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcli-framework
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.1.1
|
|
4
4
|
Summary: 🚀 High-performance CLI framework with Rust extensions, AI chat, and stunning visuals
|
|
5
5
|
Author-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
6
6
|
Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
@@ -63,7 +63,7 @@ Requires-Dist: uvloop>=0.19.0
|
|
|
63
63
|
Requires-Dist: aiosqlite>=0.20.0
|
|
64
64
|
Requires-Dist: redis>=5.0.0
|
|
65
65
|
Requires-Dist: aiohttp-sse-client>=0.2.1
|
|
66
|
-
Requires-Dist:
|
|
66
|
+
Requires-Dist: aiomqtt>=2.0.0
|
|
67
67
|
Requires-Dist: opencv-python>=4.11.0.86
|
|
68
68
|
Requires-Dist: pillow>=11.2.1
|
|
69
69
|
Requires-Dist: numpy<2.0.0,>=1.24.0
|
|
@@ -136,13 +136,24 @@ Requires-Dist: pytest>=8.4.1; extra == "dev"
|
|
|
136
136
|
Requires-Dist: pytest-cov<5.0.0,>=4.1.0; extra == "dev"
|
|
137
137
|
Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
|
|
138
138
|
Requires-Dist: pytest-asyncio>=1.1.0; extra == "dev"
|
|
139
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
|
|
140
|
+
Requires-Dist: pytest-timeout>=2.2.0; extra == "dev"
|
|
141
|
+
Requires-Dist: pytest-xdist>=3.5.0; extra == "dev"
|
|
142
|
+
Requires-Dist: hypothesis>=6.92.0; extra == "dev"
|
|
143
|
+
Requires-Dist: faker>=22.0.0; extra == "dev"
|
|
144
|
+
Requires-Dist: responses>=0.24.0; extra == "dev"
|
|
145
|
+
Requires-Dist: freezegun>=1.4.0; extra == "dev"
|
|
146
|
+
Requires-Dist: pytest-html>=4.1.0; extra == "dev"
|
|
147
|
+
Requires-Dist: pytest-json-report>=1.5.0; extra == "dev"
|
|
139
148
|
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
140
149
|
Requires-Dist: isort<6.0.0,>=5.12.0; extra == "dev"
|
|
141
150
|
Requires-Dist: mypy<2.0.0,>=1.7.1; extra == "dev"
|
|
151
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
152
|
+
Requires-Dist: pre-commit>=3.6.0; extra == "dev"
|
|
142
153
|
Requires-Dist: build>=1.2.2.post1; extra == "dev"
|
|
143
154
|
Requires-Dist: maturin>=1.9.3; extra == "dev"
|
|
155
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
144
156
|
Provides-Extra: all
|
|
145
|
-
Requires-Dist: mcli[async-extras,chat,dashboard,database,documents,gpu,ml,monitoring,streaming,video,viz,web]; extra == "all"
|
|
146
157
|
Dynamic: license-file
|
|
147
158
|
|
|
148
159
|
# MCLI
|
|
@@ -5,9 +5,9 @@ mcli/app/commands_cmd.py,sha256=5MccxYKNkzIisDeBPJj6K4ZwWeZFB2a4P8AS9B1_EDs,8441
|
|
|
5
5
|
mcli/app/completion_cmd.py,sha256=8gtYDddviBCD6Gk57lkLKOpim5QAMMcugYPmwfraBeo,7862
|
|
6
6
|
mcli/app/completion_helpers.py,sha256=PR66qgVNC5_st-CBiD4uuGfO3Zs7Y3QmJ2GJjpx5N6g,8897
|
|
7
7
|
mcli/app/cron_test_cmd.py,sha256=Ai4Smg2WxULeiMD5s2m_S_fXdMAAQsKHpSc4iJGSnwI,26156
|
|
8
|
-
mcli/app/logs_cmd.py,sha256=
|
|
8
|
+
mcli/app/logs_cmd.py,sha256=_5DDS8Rz4p-a9vk4RzrcxGUoLAxVw1I-iPs2fld8_DE,14996
|
|
9
9
|
mcli/app/main.py,sha256=iA9HdqhBaOnOJ2--edLPD7iAatAzhIl5NAcNhw9qJAw,19010
|
|
10
|
-
mcli/app/model_cmd.py,sha256=
|
|
10
|
+
mcli/app/model_cmd.py,sha256=_8NBzf36u2tnUvc8ASQt88cdfBEonpXj3_16OEAf1cI,12842
|
|
11
11
|
mcli/app/redis_cmd.py,sha256=Cl0LQ3Mqt27gLeb542_xw6bJBbIE-CBmWyMmaUTSk8c,9426
|
|
12
12
|
mcli/app/visual_cmd.py,sha256=jXighahHxeM9HANQ2Brk6nKFgi2ZuQBOBH7PE5xhebk,9428
|
|
13
13
|
mcli/app/model/model.py,sha256=EUGu_td-hRlbf4OElkdk1-0p7WyuG7sZmb-Ux2-J9KY,39061
|
|
@@ -47,7 +47,7 @@ mcli/lib/performance/uvloop_config.py,sha256=wyI5pQnec2RAhgm52HJ1AxYGFa3bjTa-Cjh
|
|
|
47
47
|
mcli/lib/pickles/pickles.py,sha256=O9dLJfyxViX-IyionbcjcsxHnq42XiLaAorsUrx9oZU,1448
|
|
48
48
|
mcli/lib/search/cached_vectorizer.py,sha256=IE36BaESqMsj10qSew6ksmPTDR-y4kMYvLYH5bO6xVg,17995
|
|
49
49
|
mcli/lib/services/data_pipeline.py,sha256=_JuNbihEW2NqmOCtKQrqWXUGNDbGo2AKSc15xkNht2s,16391
|
|
50
|
-
mcli/lib/services/lsh_client.py,sha256=
|
|
50
|
+
mcli/lib/services/lsh_client.py,sha256=bafhhzfoBSQpanrqkRjzHSco0PxGqwo8kN0lq5HgbI0,16503
|
|
51
51
|
mcli/lib/services/redis_service.py,sha256=5QwSB-FMIS1zdTNp8VSOrZfr_wrUK10Bfe2N1ZTy-90,12730
|
|
52
52
|
mcli/lib/shell/shell.py,sha256=W7lowu75SnFsb0y8ZIDIawfcPUuJkT3_rI1IKU_c6Wk,4692
|
|
53
53
|
mcli/lib/toml/toml.py,sha256=p05tXgndxIlsA_l60ivmrE5hK92-Sf2u-adERrvIJPk,1115
|
|
@@ -81,7 +81,7 @@ mcli/ml/configs/dvc_config.py,sha256=LWOg4di1MpZED18YJznhYJwWsQ5i5k73RMxZT7-poHw
|
|
|
81
81
|
mcli/ml/configs/mlflow_config.py,sha256=GvoBqxdBU6eIAghjPKqXz00n5j3Z8grdk0DFZwilIS8,4476
|
|
82
82
|
mcli/ml/configs/mlops_manager.py,sha256=4CfqJnqLZjFl4Han3BAQ2ozOZmO8q47lWEnObn_Q5F4,9891
|
|
83
83
|
mcli/ml/dashboard/app.py,sha256=GP_FgmR-4xQ7JoZeLygaA9_Li8T310AG9UJi3vxRpzs,15092
|
|
84
|
-
mcli/ml/dashboard/app_integrated.py,sha256=
|
|
84
|
+
mcli/ml/dashboard/app_integrated.py,sha256=vVzIuwml-Ri53iDGNUVqCsWT-5l_Gx2AxuOXQc8YAQM,29344
|
|
85
85
|
mcli/ml/dashboard/app_supabase.py,sha256=E6zjJTcCpv8MCrQIZ4pgce4sxtLro7utfC9s2762QVA,19734
|
|
86
86
|
mcli/ml/dashboard/app_training.py,sha256=XeU-fDj2MVzM5IM1ezCYJV5RF51oyvXy2_lppPAhSdw,19623
|
|
87
87
|
mcli/ml/dashboard/cli.py,sha256=n4L732c9UoA9DUsiOEzaqBNs42vt1st-JP-UHuzc92I,1479
|
|
@@ -108,6 +108,7 @@ mcli/ml/models/test_models.py,sha256=7m3JoixdCtTl2A-Dne4rmtwWp2TwZgVMpo7dN6I59tQ
|
|
|
108
108
|
mcli/ml/monitoring/drift_detection.py,sha256=UxWEu5jPrWhqJpf9gS28igSvnVk4vzagTpTU1yrfOVc,25956
|
|
109
109
|
mcli/ml/monitoring/metrics.py,sha256=y3Ok0ONm9NC3Z5NbRs6gvpsXRctMKyjjW7QkvIWln3I,1073
|
|
110
110
|
mcli/ml/optimization/portfolio_optimizer.py,sha256=dCZyPzlfHRYKo_tXtOj1IzoCiPXOrN-vH_6r3SXuWtI,31617
|
|
111
|
+
mcli/ml/predictions/prediction_engine.py,sha256=msDnoqc2ykD7sNOeS_Qq-NqJcVOUlG7Y8E_jt-tc-3o,8432
|
|
111
112
|
mcli/ml/preprocessing/data_cleaners.py,sha256=3UTWfi-TX0YXUhfnuFfps6QY8Mz9Z2i5Jg-Bxsk2EkM,17282
|
|
112
113
|
mcli/ml/preprocessing/feature_extractors.py,sha256=ZKexfA3-hIa4arAxn-J7e5T9P7zEXTdJUpCZDEPyPdo,17306
|
|
113
114
|
mcli/ml/preprocessing/ml_pipeline.py,sha256=RAWG_dJ-CFDrNXYJYmkGH821B3NlM_0JlxfRaXJqImw,14202
|
|
@@ -116,9 +117,11 @@ mcli/ml/preprocessing/test_preprocessing.py,sha256=TLBp24Y7YloIrUI2_KmyJhB6uw2iJ
|
|
|
116
117
|
mcli/ml/scripts/populate_sample_data.py,sha256=GKbS1ISiYen45JCGxSEuYvHFiCNm4Rm-4jxGwJn9A8c,7633
|
|
117
118
|
mcli/ml/tests/test_integration.py,sha256=gyH7gnghshD4z9zZKqs3uZTK7oZdgVF_Ujcbe6-b3Gw,15643
|
|
118
119
|
mcli/ml/tests/test_training_dashboard.py,sha256=9P1JrUCei7YydSJR8L4OrVmEWm5-SAy3e6S3h87JplQ,13588
|
|
120
|
+
mcli/mygroup/test_cmd.py,sha256=PD0qoZ7GqagdQG9DaP7rIrGFenN23zVbYVYlZ0FJaSQ,16
|
|
119
121
|
mcli/public/public.py,sha256=t9BkO1XV7s3YcoH0bbIpyjZ05UX_vBjaKtKkuDX7wZ0,114
|
|
120
122
|
mcli/public/oi/oi.py,sha256=SQabQWQ1pE67pWYEHwIDc3R93DARJfB6VHk7qxWx9xo,308
|
|
121
|
-
mcli/self/self_cmd.py,sha256=
|
|
123
|
+
mcli/self/self_cmd.py,sha256=Srph4HT_gW10q5ijVDlmGu_Ur83X2c4-U3loAQUSENg,48686
|
|
124
|
+
mcli/self/test_cmd.py,sha256=PD0qoZ7GqagdQG9DaP7rIrGFenN23zVbYVYlZ0FJaSQ,16
|
|
122
125
|
mcli/workflow/lsh_integration.py,sha256=khwmMPsdYdkmmLxlZi_UqUo2p0Nf-6GF6PPbtOrmoYQ,13290
|
|
123
126
|
mcli/workflow/workflow.py,sha256=t58OVXmU9uQCJnyXuIbMAm8lihSzJ_jI10vXPNpZspk,928
|
|
124
127
|
mcli/workflow/daemon/api_daemon.py,sha256=hA4Jolvb2C0T5_adKeI7BYE5wajfH9BFmk4bK1CmbE4,29000
|
|
@@ -179,9 +182,9 @@ mcli/workflow/sync/sync_cmd.py,sha256=S8TuZS_WAsdeD3_j8-XSAZFFrpynAwTWnCC0e6DCLh
|
|
|
179
182
|
mcli/workflow/sync/test_cmd.py,sha256=neVgs9zEnKSxlvzDpFkuCGucqnzjrShm2OvJtHibslg,10009
|
|
180
183
|
mcli/workflow/videos/videos.py,sha256=C47ViVv6qqqkSKQz6YXjzhok4UrqFbya8w5k_x7hToM,8360
|
|
181
184
|
mcli/workflow/wakatime/wakatime.py,sha256=sEjsUKa3-XyE8Ni6sAb_D3GAY5jDcA30KknW9YTbLTA,142
|
|
182
|
-
mcli_framework-7.
|
|
183
|
-
mcli_framework-7.
|
|
184
|
-
mcli_framework-7.
|
|
185
|
-
mcli_framework-7.
|
|
186
|
-
mcli_framework-7.
|
|
187
|
-
mcli_framework-7.
|
|
185
|
+
mcli_framework-7.1.1.dist-info/licenses/LICENSE,sha256=sahwAMfrJv2-V66HNPTp7A9UmMjxtyejwTZZoWQvEcI,1075
|
|
186
|
+
mcli_framework-7.1.1.dist-info/METADATA,sha256=47x4tvptQwgWBYJrtVQ6Gxvj4nKZmEDDxPZQrHr4qig,14769
|
|
187
|
+
mcli_framework-7.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
188
|
+
mcli_framework-7.1.1.dist-info/entry_points.txt,sha256=dYrZbDIm-KUPsl1wfv600Kx_8sMy89phMkCihbDRgP8,261
|
|
189
|
+
mcli_framework-7.1.1.dist-info/top_level.txt,sha256=_bnO8J2EUkliWivey_1le0UrnocFKmyVMQjbQ8iVXjc,5
|
|
190
|
+
mcli_framework-7.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|