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
|
@@ -111,15 +111,25 @@ export function Pipelines() {
|
|
|
111
111
|
/>
|
|
112
112
|
) : (
|
|
113
113
|
<div className="h-full flex flex-col items-center justify-center text-center p-8 bg-slate-50/50 dark:bg-slate-900/50">
|
|
114
|
-
<div className="w-20 h-20 bg-primary-100 dark:
|
|
114
|
+
<div className="w-20 h-20 bg-gradient-to-br from-primary-100 to-primary-200 dark:from-primary-900/30 dark:to-primary-800/30 rounded-full flex items-center justify-center mb-6">
|
|
115
115
|
<Layers size={40} className="text-primary-500" />
|
|
116
116
|
</div>
|
|
117
117
|
<h2 className="text-2xl font-bold text-slate-900 dark:text-white mb-2">
|
|
118
118
|
Select a Pipeline
|
|
119
119
|
</h2>
|
|
120
|
-
<p className="text-slate-500 max-w-md">
|
|
120
|
+
<p className="text-slate-500 max-w-md mb-6">
|
|
121
121
|
Choose a pipeline from the sidebar to view execution history and statistics.
|
|
122
122
|
</p>
|
|
123
|
+
<div className="bg-slate-900 dark:bg-slate-950 rounded-lg p-4 max-w-md mx-auto text-left shadow-lg">
|
|
124
|
+
<p className="text-xs text-slate-400 mb-2">Define a pipeline in Python:</p>
|
|
125
|
+
<pre className="text-sm font-mono text-slate-300 overflow-x-auto">
|
|
126
|
+
<code>{`from flowyml import pipeline, step
|
|
127
|
+
|
|
128
|
+
@pipeline
|
|
129
|
+
def training_pipeline():
|
|
130
|
+
load_data() >> train_model()`}</code>
|
|
131
|
+
</pre>
|
|
132
|
+
</div>
|
|
123
133
|
</div>
|
|
124
134
|
)}
|
|
125
135
|
</div>
|
|
@@ -130,13 +130,26 @@ export function ProjectExperimentsList({ projectId }) {
|
|
|
130
130
|
</div>
|
|
131
131
|
)}
|
|
132
132
|
emptyState={
|
|
133
|
-
<div className="text-center py-12">
|
|
134
|
-
<div className="inline-flex items-center justify-center w-
|
|
135
|
-
<FlaskConical className="w-
|
|
133
|
+
<div className="text-center py-12 px-6">
|
|
134
|
+
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gradient-to-br from-purple-100 to-purple-200 dark:from-purple-900/30 dark:to-purple-800/30 mb-6">
|
|
135
|
+
<FlaskConical className="w-8 h-8 text-purple-500" />
|
|
136
136
|
</div>
|
|
137
|
-
<h3 className="text-
|
|
138
|
-
<p className="text-slate-500">
|
|
139
|
-
|
|
137
|
+
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2">No experiments yet</h3>
|
|
138
|
+
<p className="text-slate-500 max-w-md mx-auto mb-6">
|
|
139
|
+
Experiments help you organize and compare multiple pipeline runs. Create one using the SDK:
|
|
140
|
+
</p>
|
|
141
|
+
<div className="bg-slate-900 dark:bg-slate-950 rounded-lg p-4 max-w-md mx-auto text-left mb-6 shadow-lg">
|
|
142
|
+
<pre className="text-sm font-mono text-slate-300 overflow-x-auto">
|
|
143
|
+
<code>{`from flowyml import experiment
|
|
144
|
+
|
|
145
|
+
with experiment("my-experiment"):
|
|
146
|
+
pipeline.run(context={
|
|
147
|
+
"learning_rate": 0.01
|
|
148
|
+
})`}</code>
|
|
149
|
+
</pre>
|
|
150
|
+
</div>
|
|
151
|
+
<p className="text-xs text-slate-400">
|
|
152
|
+
All runs within an experiment block are automatically grouped and tracked together.
|
|
140
153
|
</p>
|
|
141
154
|
</div>
|
|
142
155
|
}
|
|
@@ -14,6 +14,8 @@ import { ProjectSelector } from '../../../components/ProjectSelector';
|
|
|
14
14
|
import { CodeSnippet } from '../../../components/ui/CodeSnippet';
|
|
15
15
|
import { TrainingMetricsPanel } from '../../../components/TrainingMetricsPanel';
|
|
16
16
|
import { TrainingHistoryChart } from '../../../components/TrainingHistoryChart';
|
|
17
|
+
import { RunMetaPanel } from '../../../components/RunMetaPanel';
|
|
18
|
+
import { useAIContext } from '../../../hooks/useAIContext';
|
|
17
19
|
|
|
18
20
|
export function RunDetails() {
|
|
19
21
|
const { runId } = useParams();
|
|
@@ -31,6 +33,15 @@ export function RunDetails() {
|
|
|
31
33
|
const [stepPanelExpanded, setStepPanelExpanded] = useState(false);
|
|
32
34
|
const [hasTrainingHistory, setHasTrainingHistory] = useState(false);
|
|
33
35
|
|
|
36
|
+
// Share run context with AI assistant
|
|
37
|
+
useAIContext({
|
|
38
|
+
pageType: 'run',
|
|
39
|
+
resourceId: runId,
|
|
40
|
+
includeLogs: true,
|
|
41
|
+
includeCode: true,
|
|
42
|
+
includeMetrics: true
|
|
43
|
+
});
|
|
44
|
+
|
|
34
45
|
const handleStopRun = async () => {
|
|
35
46
|
if (!confirm('Are you sure you want to stop this run?')) return;
|
|
36
47
|
|
|
@@ -231,12 +242,16 @@ export function RunDetails() {
|
|
|
231
242
|
/>
|
|
232
243
|
</div>
|
|
233
244
|
|
|
245
|
+
{/* Environment & Metadata Panel */}
|
|
246
|
+
<RunMetaPanel run={run} />
|
|
247
|
+
|
|
248
|
+
{/* Main Content - Dynamic Split View */}
|
|
249
|
+
|
|
234
250
|
{/* Main Content - Dynamic Split View */}
|
|
235
|
-
<div className={`grid gap-6 transition-all duration-300 ${
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}`}>
|
|
251
|
+
<div className={`grid gap-6 transition-all duration-300 ${stepPanelExpanded
|
|
252
|
+
? 'grid-cols-1 lg:grid-cols-2'
|
|
253
|
+
: 'grid-cols-1 lg:grid-cols-3'
|
|
254
|
+
}`}>
|
|
240
255
|
{/* DAG Visualization */}
|
|
241
256
|
<div className={stepPanelExpanded ? 'lg:col-span-1' : 'lg:col-span-2'}>
|
|
242
257
|
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-4 flex items-center gap-2">
|
|
@@ -278,7 +293,7 @@ export function RunDetails() {
|
|
|
278
293
|
found = artifacts.find(a =>
|
|
279
294
|
a.type === expectedType &&
|
|
280
295
|
(a.name.toLowerCase().includes(suffix.toLowerCase()) ||
|
|
281
|
-
|
|
296
|
+
suffix.toLowerCase().includes(a.name.toLowerCase().replace(/_/g, '')))
|
|
282
297
|
);
|
|
283
298
|
}
|
|
284
299
|
|
|
@@ -322,9 +337,8 @@ export function RunDetails() {
|
|
|
322
337
|
</div>
|
|
323
338
|
|
|
324
339
|
{selectedStepData ? (
|
|
325
|
-
<Card className={`overflow-hidden transition-all duration-300 ${
|
|
326
|
-
|
|
327
|
-
}`}>
|
|
340
|
+
<Card className={`overflow-hidden transition-all duration-300 ${stepPanelExpanded ? 'h-auto' : ''
|
|
341
|
+
}`}>
|
|
328
342
|
{/* Step Header */}
|
|
329
343
|
<div className="pb-4 border-b border-slate-100 dark:border-slate-700">
|
|
330
344
|
<div className="flex items-center justify-between">
|
|
@@ -385,9 +399,8 @@ export function RunDetails() {
|
|
|
385
399
|
</div>
|
|
386
400
|
|
|
387
401
|
{/* Tab Content - Larger when expanded */}
|
|
388
|
-
<div className={`mt-4 overflow-y-auto transition-all duration-300 ${
|
|
389
|
-
|
|
390
|
-
}`}>
|
|
402
|
+
<div className={`mt-4 overflow-y-auto transition-all duration-300 ${stepPanelExpanded ? 'max-h-[600px]' : 'max-h-[450px]'
|
|
403
|
+
}`}>
|
|
391
404
|
{activeTab === 'overview' && (
|
|
392
405
|
<OverviewTab
|
|
393
406
|
stepData={selectedStepData}
|
|
@@ -952,8 +965,8 @@ function ArtifactModal({ artifact, onClose }) {
|
|
|
952
965
|
<div className="flex gap-1 px-6 py-3 border-b border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-800/50">
|
|
953
966
|
<TabBtn active={activeTab === 'visualization'} onClick={() => setActiveTab('visualization')}>
|
|
954
967
|
{isModel ? <><LineChart size={14} /> Visualization</> :
|
|
955
|
-
|
|
956
|
-
|
|
968
|
+
isDataset ? <><BarChart2 size={14} /> Statistics</> :
|
|
969
|
+
<><Activity size={14} /> Metrics</>}
|
|
957
970
|
</TabBtn>
|
|
958
971
|
{displayableProps.length > 0 && (
|
|
959
972
|
<TabBtn active={activeTab === 'properties'} onClick={() => setActiveTab('properties')}>
|
|
@@ -1059,8 +1072,8 @@ function ArtifactModal({ artifact, onClose }) {
|
|
|
1059
1072
|
</span>
|
|
1060
1073
|
<span className="text-sm font-mono font-semibold text-slate-900 dark:text-white break-all">
|
|
1061
1074
|
{typeof value === 'object' ? JSON.stringify(value, null, 2) :
|
|
1062
|
-
|
|
1063
|
-
|
|
1075
|
+
typeof value === 'number' ? value.toLocaleString() :
|
|
1076
|
+
String(value)}
|
|
1064
1077
|
</span>
|
|
1065
1078
|
</div>
|
|
1066
1079
|
))}
|
|
@@ -1139,11 +1152,10 @@ function TabBtn({ active, onClick, children }) {
|
|
|
1139
1152
|
return (
|
|
1140
1153
|
<button
|
|
1141
1154
|
onClick={onClick}
|
|
1142
|
-
className={`flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all ${
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
}`}
|
|
1155
|
+
className={`flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all ${active
|
|
1156
|
+
? 'bg-white dark:bg-slate-700 text-slate-900 dark:text-white shadow-sm'
|
|
1157
|
+
: 'text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-white/50 dark:hover:bg-slate-700/50'
|
|
1158
|
+
}`}
|
|
1147
1159
|
>
|
|
1148
1160
|
{children}
|
|
1149
1161
|
</button>
|
|
@@ -1176,9 +1188,9 @@ function MetricDisplayCard({ name, value, index }) {
|
|
|
1176
1188
|
|
|
1177
1189
|
// Determine if this is a "good" metric (accuracy, score) or "bad" (loss, error)
|
|
1178
1190
|
const isLossLike = name.toLowerCase().includes('loss') ||
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1191
|
+
name.toLowerCase().includes('error') ||
|
|
1192
|
+
name.toLowerCase().includes('mse') ||
|
|
1193
|
+
name.toLowerCase().includes('mae');
|
|
1182
1194
|
|
|
1183
1195
|
return (
|
|
1184
1196
|
<motion.div
|
|
@@ -169,15 +169,21 @@ export function Runs() {
|
|
|
169
169
|
/>
|
|
170
170
|
) : (
|
|
171
171
|
<div className="h-full flex flex-col items-center justify-center text-center p-8 bg-slate-50/50 dark:bg-slate-900/50">
|
|
172
|
-
<div className="w-20 h-20 bg-blue-100 dark:
|
|
172
|
+
<div className="w-20 h-20 bg-gradient-to-br from-blue-100 to-blue-200 dark:from-blue-900/30 dark:to-blue-800/30 rounded-full flex items-center justify-center mb-6">
|
|
173
173
|
<PlayCircle size={40} className="text-blue-500" />
|
|
174
174
|
</div>
|
|
175
175
|
<h2 className="text-2xl font-bold text-slate-900 dark:text-white mb-2">
|
|
176
176
|
Select a Run
|
|
177
177
|
</h2>
|
|
178
|
-
<p className="text-slate-500 max-w-md">
|
|
178
|
+
<p className="text-slate-500 max-w-md mb-6">
|
|
179
179
|
Choose a run from the sidebar to view execution details, logs, and artifacts.
|
|
180
180
|
</p>
|
|
181
|
+
<div className="bg-slate-900 dark:bg-slate-950 rounded-lg p-4 max-w-md mx-auto text-left shadow-lg">
|
|
182
|
+
<p className="text-xs text-slate-400 mb-2">Run a pipeline from the CLI:</p>
|
|
183
|
+
<pre className="text-sm font-mono text-slate-300 overflow-x-auto">
|
|
184
|
+
<code>{`flowyml run my_pipeline`}</code>
|
|
185
|
+
</pre>
|
|
186
|
+
</div>
|
|
181
187
|
</div>
|
|
182
188
|
)}
|
|
183
189
|
</div>
|