flowyml 1.7.2__py3-none-any.whl → 1.8.0__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.
- flowyml/assets/base.py +15 -0
- flowyml/assets/metrics.py +5 -0
- flowyml/cli/main.py +709 -0
- flowyml/cli/stack_cli.py +138 -25
- flowyml/core/__init__.py +17 -0
- flowyml/core/executor.py +161 -26
- flowyml/core/image_builder.py +129 -0
- flowyml/core/log_streamer.py +227 -0
- flowyml/core/orchestrator.py +22 -2
- flowyml/core/pipeline.py +34 -10
- flowyml/core/routing.py +558 -0
- flowyml/core/step.py +9 -1
- flowyml/core/step_grouping.py +49 -35
- flowyml/core/types.py +407 -0
- flowyml/monitoring/alerts.py +10 -0
- flowyml/monitoring/notifications.py +104 -25
- flowyml/monitoring/slack_blocks.py +323 -0
- flowyml/plugins/__init__.py +251 -0
- flowyml/plugins/alerters/__init__.py +1 -0
- flowyml/plugins/alerters/slack.py +168 -0
- flowyml/plugins/base.py +752 -0
- flowyml/plugins/config.py +478 -0
- flowyml/plugins/deployers/__init__.py +22 -0
- flowyml/plugins/deployers/gcp_cloud_run.py +200 -0
- flowyml/plugins/deployers/sagemaker.py +306 -0
- flowyml/plugins/deployers/vertex.py +290 -0
- flowyml/plugins/integration.py +369 -0
- flowyml/plugins/manager.py +510 -0
- flowyml/plugins/model_registries/__init__.py +22 -0
- flowyml/plugins/model_registries/mlflow.py +159 -0
- flowyml/plugins/model_registries/sagemaker.py +489 -0
- flowyml/plugins/model_registries/vertex.py +386 -0
- flowyml/plugins/orchestrators/__init__.py +13 -0
- flowyml/plugins/orchestrators/sagemaker.py +443 -0
- flowyml/plugins/orchestrators/vertex_ai.py +461 -0
- flowyml/plugins/registries/__init__.py +13 -0
- flowyml/plugins/registries/ecr.py +321 -0
- flowyml/plugins/registries/gcr.py +313 -0
- flowyml/plugins/registry.py +454 -0
- flowyml/plugins/stack.py +494 -0
- flowyml/plugins/stack_config.py +537 -0
- flowyml/plugins/stores/__init__.py +13 -0
- flowyml/plugins/stores/gcs.py +460 -0
- flowyml/plugins/stores/s3.py +453 -0
- flowyml/plugins/trackers/__init__.py +11 -0
- flowyml/plugins/trackers/mlflow.py +316 -0
- flowyml/plugins/validators/__init__.py +3 -0
- flowyml/plugins/validators/deepchecks.py +119 -0
- flowyml/registry/__init__.py +2 -1
- flowyml/registry/model_environment.py +109 -0
- flowyml/registry/model_registry.py +241 -96
- flowyml/serving/__init__.py +17 -0
- flowyml/serving/model_server.py +628 -0
- flowyml/stacks/__init__.py +60 -0
- flowyml/stacks/aws.py +93 -0
- flowyml/stacks/base.py +62 -0
- flowyml/stacks/components.py +12 -0
- flowyml/stacks/gcp.py +44 -9
- flowyml/stacks/plugins.py +115 -0
- flowyml/stacks/registry.py +2 -1
- flowyml/storage/sql.py +401 -12
- flowyml/tracking/experiment.py +8 -5
- flowyml/ui/backend/Dockerfile +87 -16
- flowyml/ui/backend/auth.py +12 -2
- flowyml/ui/backend/main.py +149 -5
- flowyml/ui/backend/routers/ai_context.py +226 -0
- flowyml/ui/backend/routers/assets.py +23 -4
- flowyml/ui/backend/routers/auth.py +96 -0
- flowyml/ui/backend/routers/deployments.py +660 -0
- flowyml/ui/backend/routers/model_explorer.py +597 -0
- flowyml/ui/backend/routers/plugins.py +103 -51
- flowyml/ui/backend/routers/projects.py +91 -8
- flowyml/ui/backend/routers/runs.py +20 -1
- flowyml/ui/backend/routers/schedules.py +22 -17
- flowyml/ui/backend/routers/templates.py +319 -0
- flowyml/ui/backend/routers/websocket.py +2 -2
- flowyml/ui/frontend/Dockerfile +55 -6
- flowyml/ui/frontend/dist/assets/index-B5AsPTSz.css +1 -0
- flowyml/ui/frontend/dist/assets/index-dFbZ8wD8.js +753 -0
- flowyml/ui/frontend/dist/index.html +2 -2
- flowyml/ui/frontend/dist/logo.png +0 -0
- flowyml/ui/frontend/nginx.conf +65 -4
- flowyml/ui/frontend/package-lock.json +1404 -74
- flowyml/ui/frontend/package.json +3 -0
- flowyml/ui/frontend/public/logo.png +0 -0
- flowyml/ui/frontend/src/App.jsx +10 -7
- flowyml/ui/frontend/src/app/auth/Login.jsx +90 -0
- flowyml/ui/frontend/src/app/dashboard/page.jsx +8 -8
- flowyml/ui/frontend/src/app/deployments/page.jsx +786 -0
- flowyml/ui/frontend/src/app/model-explorer/page.jsx +1031 -0
- flowyml/ui/frontend/src/app/pipelines/page.jsx +12 -2
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectExperimentsList.jsx +19 -6
- flowyml/ui/frontend/src/app/runs/[runId]/page.jsx +36 -24
- flowyml/ui/frontend/src/app/runs/page.jsx +8 -2
- flowyml/ui/frontend/src/app/settings/page.jsx +267 -253
- flowyml/ui/frontend/src/components/AssetDetailsPanel.jsx +29 -7
- flowyml/ui/frontend/src/components/Layout.jsx +6 -0
- flowyml/ui/frontend/src/components/PipelineGraph.jsx +79 -29
- flowyml/ui/frontend/src/components/RunDetailsPanel.jsx +36 -6
- flowyml/ui/frontend/src/components/RunMetaPanel.jsx +113 -0
- flowyml/ui/frontend/src/components/ai/AIAssistantButton.jsx +71 -0
- flowyml/ui/frontend/src/components/ai/AIAssistantPanel.jsx +420 -0
- flowyml/ui/frontend/src/components/header/Header.jsx +22 -0
- flowyml/ui/frontend/src/components/plugins/PluginManager.jsx +4 -4
- flowyml/ui/frontend/src/components/plugins/{ZenMLIntegration.jsx → StackImport.jsx} +38 -12
- flowyml/ui/frontend/src/components/sidebar/Sidebar.jsx +36 -13
- flowyml/ui/frontend/src/contexts/AIAssistantContext.jsx +245 -0
- flowyml/ui/frontend/src/contexts/AuthContext.jsx +108 -0
- flowyml/ui/frontend/src/hooks/useAIContext.js +156 -0
- flowyml/ui/frontend/src/hooks/useWebGPU.js +54 -0
- flowyml/ui/frontend/src/layouts/MainLayout.jsx +6 -0
- flowyml/ui/frontend/src/router/index.jsx +47 -20
- flowyml/ui/frontend/src/services/pluginService.js +3 -1
- flowyml/ui/server_manager.py +5 -5
- flowyml/ui/utils.py +157 -39
- flowyml/utils/config.py +37 -15
- flowyml/utils/model_introspection.py +123 -0
- flowyml/utils/observability.py +30 -0
- flowyml-1.8.0.dist-info/METADATA +174 -0
- {flowyml-1.7.2.dist-info → flowyml-1.8.0.dist-info}/RECORD +123 -65
- {flowyml-1.7.2.dist-info → flowyml-1.8.0.dist-info}/WHEEL +1 -1
- flowyml/ui/frontend/dist/assets/index-B40RsQDq.css +0 -1
- flowyml/ui/frontend/dist/assets/index-CjI0zKCn.js +0 -685
- flowyml-1.7.2.dist-info/METADATA +0 -477
- {flowyml-1.7.2.dist-info → flowyml-1.8.0.dist-info}/entry_points.txt +0 -0
- {flowyml-1.7.2.dist-info → flowyml-1.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""Slack Block Kit message builders for rich notifications.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for building professional-looking Slack messages
|
|
4
|
+
using Block Kit components.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _get_emoji(level: str) -> str:
|
|
12
|
+
"""Get emoji for notification level."""
|
|
13
|
+
return {
|
|
14
|
+
"info": "ℹ️",
|
|
15
|
+
"warning": "⚠️",
|
|
16
|
+
"error": "❌",
|
|
17
|
+
"success": "✅",
|
|
18
|
+
"critical": "🚨",
|
|
19
|
+
}.get(level, "📢")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _get_color(level: str) -> str:
|
|
23
|
+
"""Get color for notification level."""
|
|
24
|
+
return {
|
|
25
|
+
"info": "#36a64f",
|
|
26
|
+
"warning": "#ff9900",
|
|
27
|
+
"error": "#ff0000",
|
|
28
|
+
"success": "#2eb886",
|
|
29
|
+
"critical": "#8b0000",
|
|
30
|
+
}.get(level, "#cccccc")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def build_header_block(text: str, emoji: str = "") -> dict:
|
|
34
|
+
"""Build a header block."""
|
|
35
|
+
return {
|
|
36
|
+
"type": "header",
|
|
37
|
+
"text": {
|
|
38
|
+
"type": "plain_text",
|
|
39
|
+
"text": f"{emoji} {text}" if emoji else text,
|
|
40
|
+
"emoji": True,
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def build_section_block(text: str, accessory: dict | None = None) -> dict:
|
|
46
|
+
"""Build a section block with markdown text."""
|
|
47
|
+
block = {
|
|
48
|
+
"type": "section",
|
|
49
|
+
"text": {
|
|
50
|
+
"type": "mrkdwn",
|
|
51
|
+
"text": text,
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
if accessory:
|
|
55
|
+
block["accessory"] = accessory
|
|
56
|
+
return block
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def build_context_block(elements: list[str]) -> dict:
|
|
60
|
+
"""Build a context block with multiple text elements."""
|
|
61
|
+
return {
|
|
62
|
+
"type": "context",
|
|
63
|
+
"elements": [{"type": "mrkdwn", "text": el} for el in elements],
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def build_divider() -> dict:
|
|
68
|
+
"""Build a divider block."""
|
|
69
|
+
return {"type": "divider"}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def build_fields_section(fields: dict[str, Any]) -> dict:
|
|
73
|
+
"""Build a section with multiple fields."""
|
|
74
|
+
return {
|
|
75
|
+
"type": "section",
|
|
76
|
+
"fields": [{"type": "mrkdwn", "text": f"*{key}*\n{value}"} for key, value in fields.items()],
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def build_button_accessory(text: str, url: str, style: str = "primary") -> dict:
|
|
81
|
+
"""Build a button accessory."""
|
|
82
|
+
return {
|
|
83
|
+
"type": "button",
|
|
84
|
+
"text": {"type": "plain_text", "text": text, "emoji": True},
|
|
85
|
+
"url": url,
|
|
86
|
+
"style": style,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def build_pipeline_success_message(
|
|
91
|
+
pipeline_name: str,
|
|
92
|
+
run_id: str,
|
|
93
|
+
duration: float,
|
|
94
|
+
metrics: dict[str, float] | None = None,
|
|
95
|
+
ui_url: str | None = None,
|
|
96
|
+
) -> dict:
|
|
97
|
+
"""Build a rich message for pipeline success."""
|
|
98
|
+
emoji = _get_emoji("success")
|
|
99
|
+
|
|
100
|
+
blocks = [
|
|
101
|
+
build_header_block("Pipeline Completed Successfully", emoji),
|
|
102
|
+
build_section_block(f"*{pipeline_name}* finished in `{duration:.2f}s`"),
|
|
103
|
+
build_divider(),
|
|
104
|
+
build_fields_section(
|
|
105
|
+
{
|
|
106
|
+
"Run ID": f"`{run_id[:12]}...`",
|
|
107
|
+
"Duration": f"{duration:.2f} seconds",
|
|
108
|
+
"Status": "✅ Success",
|
|
109
|
+
"Completed": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
110
|
+
},
|
|
111
|
+
),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
if metrics:
|
|
115
|
+
metrics_text = "\n".join([f"• *{k}*: `{v:.4f}`" for k, v in metrics.items()])
|
|
116
|
+
blocks.append(build_section_block(f"*Metrics:*\n{metrics_text}"))
|
|
117
|
+
|
|
118
|
+
if ui_url:
|
|
119
|
+
blocks.append(
|
|
120
|
+
build_section_block(
|
|
121
|
+
"View run details in the FlowyML dashboard:",
|
|
122
|
+
accessory=build_button_accessory("View Run", f"{ui_url}/runs/{run_id}"),
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
blocks.append(
|
|
127
|
+
build_context_block([f"FlowyML | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"]),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
"attachments": [
|
|
132
|
+
{
|
|
133
|
+
"color": _get_color("success"),
|
|
134
|
+
"blocks": blocks,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def build_pipeline_failure_message(
|
|
141
|
+
pipeline_name: str,
|
|
142
|
+
run_id: str,
|
|
143
|
+
error: str,
|
|
144
|
+
step_name: str | None = None,
|
|
145
|
+
ui_url: str | None = None,
|
|
146
|
+
) -> dict:
|
|
147
|
+
"""Build a rich message for pipeline failure."""
|
|
148
|
+
emoji = _get_emoji("error")
|
|
149
|
+
|
|
150
|
+
blocks = [
|
|
151
|
+
build_header_block("Pipeline Failed", emoji),
|
|
152
|
+
build_section_block(f"*{pipeline_name}* encountered an error"),
|
|
153
|
+
build_divider(),
|
|
154
|
+
build_fields_section(
|
|
155
|
+
{
|
|
156
|
+
"Run ID": f"`{run_id[:12]}...`",
|
|
157
|
+
"Status": "❌ Failed",
|
|
158
|
+
"Failed At": step_name or "Unknown step",
|
|
159
|
+
"Time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
160
|
+
},
|
|
161
|
+
),
|
|
162
|
+
build_section_block(f"*Error:*\n```{error[:500]}```"),
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
if ui_url:
|
|
166
|
+
blocks.append(
|
|
167
|
+
build_section_block(
|
|
168
|
+
"Investigate the failure in the FlowyML dashboard:",
|
|
169
|
+
accessory=build_button_accessory("View Run", f"{ui_url}/runs/{run_id}", style="danger"),
|
|
170
|
+
),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
blocks.append(
|
|
174
|
+
build_context_block([f"FlowyML | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"]),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
"attachments": [
|
|
179
|
+
{
|
|
180
|
+
"color": _get_color("error"),
|
|
181
|
+
"blocks": blocks,
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def build_drift_warning_message(
|
|
188
|
+
feature: str,
|
|
189
|
+
psi: float,
|
|
190
|
+
threshold: float = 0.2,
|
|
191
|
+
model_name: str | None = None,
|
|
192
|
+
ui_url: str | None = None,
|
|
193
|
+
) -> dict:
|
|
194
|
+
"""Build a rich message for data drift detection."""
|
|
195
|
+
emoji = _get_emoji("warning")
|
|
196
|
+
severity = "High" if psi > 0.5 else "Medium" if psi > 0.25 else "Low"
|
|
197
|
+
|
|
198
|
+
blocks = [
|
|
199
|
+
build_header_block("Data Drift Detected", emoji),
|
|
200
|
+
build_section_block(
|
|
201
|
+
f"Drift detected in feature *{feature}*" + (f" for model *{model_name}*" if model_name else ""),
|
|
202
|
+
),
|
|
203
|
+
build_divider(),
|
|
204
|
+
build_fields_section(
|
|
205
|
+
{
|
|
206
|
+
"Feature": feature,
|
|
207
|
+
"PSI Score": f"`{psi:.4f}`",
|
|
208
|
+
"Threshold": f"`{threshold:.2f}`",
|
|
209
|
+
"Severity": f"{'🔴' if severity == 'High' else '🟡' if severity == 'Medium' else '🟢'} {severity}",
|
|
210
|
+
},
|
|
211
|
+
),
|
|
212
|
+
build_section_block(
|
|
213
|
+
"💡 *Recommended Actions:*\n"
|
|
214
|
+
"• Review recent data pipeline changes\n"
|
|
215
|
+
"• Check for upstream data quality issues\n"
|
|
216
|
+
"• Consider retraining the model if drift persists",
|
|
217
|
+
),
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
if ui_url:
|
|
221
|
+
blocks.append(
|
|
222
|
+
build_section_block(
|
|
223
|
+
"View drift analysis in the dashboard:",
|
|
224
|
+
accessory=build_button_accessory("View Analysis", f"{ui_url}/monitoring/drift"),
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
blocks.append(
|
|
229
|
+
build_context_block([f"FlowyML Monitoring | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"]),
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
"attachments": [
|
|
234
|
+
{
|
|
235
|
+
"color": _get_color("warning"),
|
|
236
|
+
"blocks": blocks,
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def build_model_promoted_message(
|
|
243
|
+
model_name: str,
|
|
244
|
+
version: str,
|
|
245
|
+
from_stage: str,
|
|
246
|
+
to_stage: str,
|
|
247
|
+
author: str | None = None,
|
|
248
|
+
metrics: dict[str, float] | None = None,
|
|
249
|
+
ui_url: str | None = None,
|
|
250
|
+
) -> dict:
|
|
251
|
+
"""Build a rich message for model promotion."""
|
|
252
|
+
emoji = "🚀" if to_stage == "production" else "📦"
|
|
253
|
+
|
|
254
|
+
blocks = [
|
|
255
|
+
build_header_block(f"Model Promoted to {to_stage.title()}", emoji),
|
|
256
|
+
build_section_block(f"*{model_name}* version `{version}` has been promoted"),
|
|
257
|
+
build_divider(),
|
|
258
|
+
build_fields_section(
|
|
259
|
+
{
|
|
260
|
+
"Model": model_name,
|
|
261
|
+
"Version": f"`{version}`",
|
|
262
|
+
"Transition": f"{from_stage} → *{to_stage}*",
|
|
263
|
+
"Promoted By": author or "System",
|
|
264
|
+
},
|
|
265
|
+
),
|
|
266
|
+
]
|
|
267
|
+
|
|
268
|
+
if metrics:
|
|
269
|
+
metrics_text = " | ".join([f"*{k}*: `{v:.4f}`" for k, v in metrics.items()])
|
|
270
|
+
blocks.append(build_context_block([f"Metrics: {metrics_text}"]))
|
|
271
|
+
|
|
272
|
+
if ui_url:
|
|
273
|
+
blocks.append(
|
|
274
|
+
build_section_block(
|
|
275
|
+
"View model in registry:",
|
|
276
|
+
accessory=build_button_accessory("View Model", f"{ui_url}/models/{model_name}"),
|
|
277
|
+
),
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
blocks.append(
|
|
281
|
+
build_context_block([f"FlowyML Registry | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"]),
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
"attachments": [
|
|
286
|
+
{
|
|
287
|
+
"color": _get_color("success") if to_stage == "production" else _get_color("info"),
|
|
288
|
+
"blocks": blocks,
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def build_simple_message(
|
|
295
|
+
title: str,
|
|
296
|
+
message: str,
|
|
297
|
+
level: str = "info",
|
|
298
|
+
metadata: dict[str, Any] | None = None,
|
|
299
|
+
) -> dict:
|
|
300
|
+
"""Build a simple notification message."""
|
|
301
|
+
emoji = _get_emoji(level)
|
|
302
|
+
|
|
303
|
+
blocks = [
|
|
304
|
+
build_header_block(title, emoji),
|
|
305
|
+
build_section_block(message),
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
if metadata:
|
|
309
|
+
blocks.append(build_divider())
|
|
310
|
+
blocks.append(build_fields_section(metadata))
|
|
311
|
+
|
|
312
|
+
blocks.append(
|
|
313
|
+
build_context_block([f"FlowyML | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"]),
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
"attachments": [
|
|
318
|
+
{
|
|
319
|
+
"color": _get_color(level),
|
|
320
|
+
"blocks": blocks,
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""FlowyML Native Plugin System.
|
|
2
|
+
|
|
3
|
+
A powerful, extensible plugin system that allows you to easily
|
|
4
|
+
integrate with external tools without requiring any framework dependencies.
|
|
5
|
+
|
|
6
|
+
Quick Start:
|
|
7
|
+
# Install a plugin (just installs the underlying packages)
|
|
8
|
+
from flowyml.plugins import install, load, get_plugin
|
|
9
|
+
|
|
10
|
+
install("mlflow") # Installs mlflow package directly
|
|
11
|
+
|
|
12
|
+
# Load and use
|
|
13
|
+
tracker = get_plugin("mlflow", tracking_uri="http://localhost:5000")
|
|
14
|
+
tracker.start_run("my_experiment")
|
|
15
|
+
tracker.log_metrics({"accuracy": 0.95})
|
|
16
|
+
tracker.end_run()
|
|
17
|
+
|
|
18
|
+
Config-Based Usage (Recommended):
|
|
19
|
+
# flowyml.yaml
|
|
20
|
+
plugins:
|
|
21
|
+
experiment_tracker:
|
|
22
|
+
type: mlflow
|
|
23
|
+
tracking_uri: http://localhost:5000
|
|
24
|
+
artifact_store:
|
|
25
|
+
type: gcs
|
|
26
|
+
bucket: my-ml-artifacts
|
|
27
|
+
|
|
28
|
+
# In code - just use, no setup needed
|
|
29
|
+
from flowyml.plugins.stack import (
|
|
30
|
+
start_run, log_metrics, save_artifact, save_model
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
start_run("my_training")
|
|
34
|
+
log_metrics({"accuracy": 0.95})
|
|
35
|
+
save_model(model, "models/classifier")
|
|
36
|
+
|
|
37
|
+
CLI Usage:
|
|
38
|
+
# List available plugins
|
|
39
|
+
flowyml plugin list
|
|
40
|
+
|
|
41
|
+
# Install a plugin
|
|
42
|
+
flowyml plugin install mlflow
|
|
43
|
+
|
|
44
|
+
# Initialize config
|
|
45
|
+
flowyml stack init --tracker mlflow --store gcs
|
|
46
|
+
|
|
47
|
+
Extending FlowyML:
|
|
48
|
+
Community plugins can register via Python entry points:
|
|
49
|
+
|
|
50
|
+
# In pyproject.toml
|
|
51
|
+
[project.entry-points."flowyml.plugins"]
|
|
52
|
+
my_tracker = "my_package.plugins:MyTracker"
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
# Base classes for creating plugins
|
|
56
|
+
from flowyml.plugins.base import (
|
|
57
|
+
BasePlugin,
|
|
58
|
+
PluginType,
|
|
59
|
+
PluginMetadata,
|
|
60
|
+
# Core plugin types
|
|
61
|
+
ExperimentTracker,
|
|
62
|
+
ArtifactStorePlugin,
|
|
63
|
+
OrchestratorPlugin,
|
|
64
|
+
ContainerRegistryPlugin,
|
|
65
|
+
FeatureStorePlugin,
|
|
66
|
+
DataValidatorPlugin,
|
|
67
|
+
ModelRegistryPlugin,
|
|
68
|
+
ModelDeployerPlugin,
|
|
69
|
+
AlerterPlugin,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Registry for discovering plugins
|
|
73
|
+
from flowyml.plugins.registry import (
|
|
74
|
+
PluginInfo,
|
|
75
|
+
PluginStatus,
|
|
76
|
+
PLUGIN_CATALOG,
|
|
77
|
+
get_plugin_info,
|
|
78
|
+
list_plugins,
|
|
79
|
+
list_plugin_names,
|
|
80
|
+
register_plugin,
|
|
81
|
+
unregister_plugin,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Manager for installing and loading plugins
|
|
85
|
+
from flowyml.plugins.manager import (
|
|
86
|
+
PluginManager,
|
|
87
|
+
get_manager,
|
|
88
|
+
install,
|
|
89
|
+
load,
|
|
90
|
+
get_plugin,
|
|
91
|
+
list_available,
|
|
92
|
+
list_installed,
|
|
93
|
+
is_installed,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Config-based plugin access
|
|
97
|
+
from flowyml.plugins.config import (
|
|
98
|
+
PluginConfig,
|
|
99
|
+
get_config,
|
|
100
|
+
reload_config,
|
|
101
|
+
get_tracker,
|
|
102
|
+
get_artifact_store,
|
|
103
|
+
get_orchestrator,
|
|
104
|
+
get_container_registry,
|
|
105
|
+
get_feature_store,
|
|
106
|
+
get_data_validator,
|
|
107
|
+
get_alerter,
|
|
108
|
+
generate_config_template,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Multi-stack configuration
|
|
112
|
+
from flowyml.plugins.stack_config import (
|
|
113
|
+
StackManager,
|
|
114
|
+
StackConfig,
|
|
115
|
+
ArtifactRoutingRule,
|
|
116
|
+
ArtifactRoutingConfig,
|
|
117
|
+
get_stack_manager,
|
|
118
|
+
get_active_stack,
|
|
119
|
+
list_stacks,
|
|
120
|
+
set_active_stack,
|
|
121
|
+
use_stack,
|
|
122
|
+
use_stack_decorator,
|
|
123
|
+
get_routing_for_type,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Unified stack interface (config-driven)
|
|
127
|
+
from flowyml.plugins.stack import (
|
|
128
|
+
# Experiment tracking
|
|
129
|
+
start_run,
|
|
130
|
+
end_run,
|
|
131
|
+
run,
|
|
132
|
+
log_params,
|
|
133
|
+
log_metrics,
|
|
134
|
+
log_artifact,
|
|
135
|
+
set_tag,
|
|
136
|
+
set_tags,
|
|
137
|
+
# Artifact storage
|
|
138
|
+
save_artifact,
|
|
139
|
+
load_artifact,
|
|
140
|
+
artifact_exists,
|
|
141
|
+
list_artifacts,
|
|
142
|
+
delete_artifact,
|
|
143
|
+
# Model management
|
|
144
|
+
save_model,
|
|
145
|
+
load_model,
|
|
146
|
+
# Container registry
|
|
147
|
+
push_image,
|
|
148
|
+
get_image_uri,
|
|
149
|
+
# Orchestration
|
|
150
|
+
run_pipeline,
|
|
151
|
+
# Alerts
|
|
152
|
+
send_alert,
|
|
153
|
+
# Stack info
|
|
154
|
+
show_stack,
|
|
155
|
+
validate_stack,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Pipeline integration
|
|
159
|
+
from flowyml.plugins.integration import (
|
|
160
|
+
StackContext,
|
|
161
|
+
run_with_stack,
|
|
162
|
+
tracked,
|
|
163
|
+
PipelinePluginIntegration,
|
|
164
|
+
get_integration,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
__all__ = [
|
|
168
|
+
# Base classes
|
|
169
|
+
"BasePlugin",
|
|
170
|
+
"PluginType",
|
|
171
|
+
"PluginMetadata",
|
|
172
|
+
"ExperimentTracker",
|
|
173
|
+
"ArtifactStorePlugin",
|
|
174
|
+
"OrchestratorPlugin",
|
|
175
|
+
"ContainerRegistryPlugin",
|
|
176
|
+
"FeatureStorePlugin",
|
|
177
|
+
"DataValidatorPlugin",
|
|
178
|
+
"ModelRegistryPlugin",
|
|
179
|
+
"ModelDeployerPlugin",
|
|
180
|
+
"AlerterPlugin",
|
|
181
|
+
# Registry
|
|
182
|
+
"PluginInfo",
|
|
183
|
+
"PluginStatus",
|
|
184
|
+
"PLUGIN_CATALOG",
|
|
185
|
+
"get_plugin_info",
|
|
186
|
+
"list_plugins",
|
|
187
|
+
"list_plugin_names",
|
|
188
|
+
"register_plugin",
|
|
189
|
+
"unregister_plugin",
|
|
190
|
+
# Manager
|
|
191
|
+
"PluginManager",
|
|
192
|
+
"get_manager",
|
|
193
|
+
"install",
|
|
194
|
+
"load",
|
|
195
|
+
"get_plugin",
|
|
196
|
+
"list_available",
|
|
197
|
+
"list_installed",
|
|
198
|
+
"is_installed",
|
|
199
|
+
# Config
|
|
200
|
+
"PluginConfig",
|
|
201
|
+
"get_config",
|
|
202
|
+
"reload_config",
|
|
203
|
+
"get_tracker",
|
|
204
|
+
"get_artifact_store",
|
|
205
|
+
"get_orchestrator",
|
|
206
|
+
"get_container_registry",
|
|
207
|
+
"get_feature_store",
|
|
208
|
+
"get_data_validator",
|
|
209
|
+
"get_alerter",
|
|
210
|
+
"generate_config_template",
|
|
211
|
+
# Stack (unified interface)
|
|
212
|
+
"start_run",
|
|
213
|
+
"end_run",
|
|
214
|
+
"run",
|
|
215
|
+
"log_params",
|
|
216
|
+
"log_metrics",
|
|
217
|
+
"log_artifact",
|
|
218
|
+
"set_tag",
|
|
219
|
+
"set_tags",
|
|
220
|
+
"save_artifact",
|
|
221
|
+
"load_artifact",
|
|
222
|
+
"artifact_exists",
|
|
223
|
+
"list_artifacts",
|
|
224
|
+
"delete_artifact",
|
|
225
|
+
"save_model",
|
|
226
|
+
"load_model",
|
|
227
|
+
"push_image",
|
|
228
|
+
"get_image_uri",
|
|
229
|
+
"run_pipeline",
|
|
230
|
+
"send_alert",
|
|
231
|
+
"show_stack",
|
|
232
|
+
"validate_stack",
|
|
233
|
+
# Integration
|
|
234
|
+
"StackContext",
|
|
235
|
+
"run_with_stack",
|
|
236
|
+
"tracked",
|
|
237
|
+
"PipelinePluginIntegration",
|
|
238
|
+
"get_integration",
|
|
239
|
+
# Multi-stack configuration
|
|
240
|
+
"StackManager",
|
|
241
|
+
"StackConfig",
|
|
242
|
+
"ArtifactRoutingRule",
|
|
243
|
+
"ArtifactRoutingConfig",
|
|
244
|
+
"get_stack_manager",
|
|
245
|
+
"get_active_stack",
|
|
246
|
+
"list_stacks",
|
|
247
|
+
"set_active_stack",
|
|
248
|
+
"use_stack",
|
|
249
|
+
"use_stack_decorator",
|
|
250
|
+
"get_routing_for_type",
|
|
251
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Alerter plugins for FlowyML."""
|