flowyml 1.1.0__tar.gz → 1.3.0__tar.gz
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-1.1.0 → flowyml-1.3.0}/LICENSE +1 -1
- {flowyml-1.1.0 → flowyml-1.3.0}/PKG-INFO +113 -12
- {flowyml-1.1.0 → flowyml-1.3.0}/README.md +108 -11
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/__init__.py +3 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/base.py +10 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/metrics.py +6 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/main.py +108 -2
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/run.py +9 -2
- flowyml-1.3.0/flowyml/core/execution_status.py +52 -0
- flowyml-1.3.0/flowyml/core/hooks.py +106 -0
- flowyml-1.3.0/flowyml/core/observability.py +210 -0
- flowyml-1.3.0/flowyml/core/orchestrator.py +274 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/pipeline.py +193 -231
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/project.py +34 -2
- flowyml-1.3.0/flowyml/core/remote_orchestrator.py +109 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/resources.py +22 -5
- flowyml-1.3.0/flowyml/core/retry_policy.py +80 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/step.py +18 -1
- flowyml-1.3.0/flowyml/core/submission_result.py +53 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/versioning.py +2 -2
- flowyml-1.3.0/flowyml/integrations/keras.py +207 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/alerts.py +2 -2
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/__init__.py +15 -0
- flowyml-1.3.0/flowyml/stacks/aws.py +599 -0
- flowyml-1.3.0/flowyml/stacks/azure.py +295 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/components.py +24 -2
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/gcp.py +158 -11
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/local.py +5 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/artifacts.py +15 -5
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/__init__.py +2 -0
- flowyml-1.3.0/flowyml/storage/materializers/cloudpickle.py +74 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/metadata.py +166 -5
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/main.py +41 -1
- flowyml-1.3.0/flowyml/ui/backend/routers/assets.py +386 -0
- flowyml-1.3.0/flowyml/ui/backend/routers/client.py +46 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/execution.py +13 -2
- flowyml-1.3.0/flowyml/ui/backend/routers/experiments.py +85 -0
- flowyml-1.3.0/flowyml/ui/backend/routers/metrics.py +213 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/pipelines.py +63 -7
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/projects.py +33 -7
- flowyml-1.3.0/flowyml/ui/backend/routers/runs.py +208 -0
- flowyml-1.3.0/flowyml/ui/frontend/dist/assets/index-DcYwrn2j.css +1 -0
- flowyml-1.3.0/flowyml/ui/frontend/dist/assets/index-Dlz_ygOL.js +592 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/dist/index.html +2 -2
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/App.jsx +4 -1
- flowyml-1.3.0/flowyml/ui/frontend/src/app/assets/page.jsx +427 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/dashboard/page.jsx +38 -7
- flowyml-1.3.0/flowyml/ui/frontend/src/app/experiments/page.jsx +107 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/observability/page.jsx +277 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/pipelines/page.jsx +131 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectArtifactsList.jsx +151 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectExperimentsList.jsx +145 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHeader.jsx +45 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHierarchy.jsx +467 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectMetricsPanel.jsx +253 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectPipelinesList.jsx +105 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRelations.jsx +189 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRunsList.jsx +136 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectTabs.jsx +95 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/app/projects/[projectId]/page.jsx +326 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/projects/page.jsx +13 -3
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/runs/[runId]/page.jsx +79 -10
- flowyml-1.3.0/flowyml/ui/frontend/src/app/runs/page.jsx +128 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/settings/page.jsx +1 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/tokens/page.jsx +62 -16
- flowyml-1.3.0/flowyml/ui/frontend/src/components/AssetDetailsPanel.jsx +373 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/AssetLineageGraph.jsx +291 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/AssetStatsDashboard.jsx +302 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/AssetTreeHierarchy.jsx +477 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/ExperimentDetailsPanel.jsx +227 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/NavigationTree.jsx +401 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/PipelineDetailsPanel.jsx +239 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/PipelineGraph.jsx +67 -3
- flowyml-1.3.0/flowyml/ui/frontend/src/components/ProjectSelector.jsx +115 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/components/RunDetailsPanel.jsx +298 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/header/Header.jsx +48 -1
- flowyml-1.3.0/flowyml/ui/frontend/src/components/plugins/ZenMLIntegration.jsx +106 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/sidebar/Sidebar.jsx +52 -26
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/DataView.jsx +35 -17
- flowyml-1.3.0/flowyml/ui/frontend/src/components/ui/ErrorBoundary.jsx +118 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/contexts/ProjectContext.jsx +2 -2
- flowyml-1.3.0/flowyml/ui/frontend/src/contexts/ToastContext.jsx +116 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/layouts/MainLayout.jsx +5 -1
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/router/index.jsx +4 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/utils/date.js +10 -0
- flowyml-1.3.0/flowyml/ui/frontend/src/utils/downloads.js +11 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/config.py +6 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/stack_config.py +45 -3
- {flowyml-1.1.0 → flowyml-1.3.0}/pyproject.toml +13 -4
- flowyml-1.1.0/flowyml/integrations/keras.py +0 -134
- flowyml-1.1.0/flowyml/ui/backend/routers/assets.py +0 -45
- flowyml-1.1.0/flowyml/ui/backend/routers/experiments.py +0 -49
- flowyml-1.1.0/flowyml/ui/backend/routers/runs.py +0 -66
- flowyml-1.1.0/flowyml/ui/frontend/dist/assets/index-DFNQnrUj.js +0 -448
- flowyml-1.1.0/flowyml/ui/frontend/dist/assets/index-pWI271rZ.css +0 -1
- flowyml-1.1.0/flowyml/ui/frontend/src/app/assets/page.jsx +0 -397
- flowyml-1.1.0/flowyml/ui/frontend/src/app/experiments/page.jsx +0 -360
- flowyml-1.1.0/flowyml/ui/frontend/src/app/pipelines/page.jsx +0 -454
- flowyml-1.1.0/flowyml/ui/frontend/src/app/runs/page.jsx +0 -470
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/artifact.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/dataset.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/featureset.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/model.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/registry.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/assets/report.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/experiment.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/init.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/stack_cli.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/cli/ui.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/advanced_cache.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/approval.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/cache.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/checkpoint.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/conditional.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/context.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/error_handling.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/executor.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/graph.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/parallel.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/scheduler.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/scheduler_config.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/step_grouping.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/core/templates.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/integrations/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/data.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/llm.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/monitor.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/monitoring/notifications.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/registry/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/registry/model_registry.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/registry/pipeline_registry.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/base.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/bridge.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/migration.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/plugin_config.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/plugins.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/stacks/registry.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/base.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/keras.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/numpy.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/pandas.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/pytorch.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/sklearn.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/storage/materializers/tensorflow.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/tracking/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/tracking/experiment.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/tracking/leaderboard.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/tracking/runs.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/Dockerfile +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/auth.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/leaderboard.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/notifications.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/plugins.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/schedules.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/backend/routers/traces.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/Dockerfile +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/README.md +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/index.html +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/nginx.conf +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/package-lock.json +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/package.json +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/postcss.config.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/experiments/[experimentId]/page.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/leaderboard/page.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/plugins/page.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/schedules/page.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/app/traces/page.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/Layout.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/plugins/AddPluginDialog.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/plugins/InstalledPlugins.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/plugins/PluginBrowser.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/plugins/PluginManager.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/Badge.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/Button.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/Card.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/CodeSnippet.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/CollapsibleCard.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/EmptyState.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/ExecutionStatus.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/KeyValue.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/components/ui/ProjectSelector.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/contexts/ThemeContext.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/index.css +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/main.jsx +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/services/pluginService.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/utils/api.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/src/utils/cn.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/tailwind.config.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/frontend/vite.config.js +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/ui/utils.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/__init__.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/debug.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/environment.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/git.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/logging.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/performance.py +0 -0
- {flowyml-1.1.0 → flowyml-1.3.0}/flowyml/utils/validation.py +0 -0
|
@@ -2,7 +2,7 @@ Apache License
|
|
|
2
2
|
Version 2.0, January 2004
|
|
3
3
|
http://www.apache.org/licenses/
|
|
4
4
|
|
|
5
|
-
Copyright 2024
|
|
5
|
+
Copyright 2024 UnicoLab.ai
|
|
6
6
|
|
|
7
7
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
8
|
you may not use this file except in compliance with the License.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowyml
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Next-Generation ML Pipeline Framework
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,16 +19,20 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
21
|
Provides-Extra: all
|
|
22
|
+
Provides-Extra: aws
|
|
23
|
+
Provides-Extra: azure
|
|
22
24
|
Provides-Extra: gcp
|
|
23
25
|
Provides-Extra: pytorch
|
|
24
26
|
Provides-Extra: sklearn
|
|
25
27
|
Provides-Extra: tensorflow
|
|
26
28
|
Provides-Extra: ui
|
|
27
29
|
Requires-Dist: click (>=8.0.0)
|
|
30
|
+
Requires-Dist: cloudpickle (>=2.0.0)
|
|
28
31
|
Requires-Dist: croniter (>=2.0.1,<3.0.0)
|
|
29
32
|
Requires-Dist: fastapi (>=0.122.0,<0.123.0) ; extra == "ui"
|
|
30
33
|
Requires-Dist: google-cloud-aiplatform (>=1.35.0) ; extra == "gcp" or extra == "all"
|
|
31
34
|
Requires-Dist: google-cloud-storage (>=2.10.0) ; extra == "gcp" or extra == "all"
|
|
35
|
+
Requires-Dist: httpx (>=0.24,<0.28)
|
|
32
36
|
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
|
33
37
|
Requires-Dist: numpy (>=1.20.0)
|
|
34
38
|
Requires-Dist: pandas (>=1.3.0)
|
|
@@ -66,21 +70,25 @@ Description-Content-Type: text/markdown
|
|
|
66
70
|
|
|
67
71
|
---
|
|
68
72
|
|
|
69
|
-
**
|
|
73
|
+
**FlowyML** is the comprehensive ML pipeline framework that combines the **simplicity of a Python script** with the **power of an enterprise MLOps platform**.
|
|
70
74
|
|
|
71
|
-
## 🚀 Why
|
|
75
|
+
## 🚀 Why FlowyML?
|
|
72
76
|
|
|
73
|
-
| Feature |
|
|
77
|
+
| Feature | FlowyML | Traditional Orchestrators |
|
|
74
78
|
|---------|---------|---------------------------|
|
|
75
79
|
| **Developer Experience** | 🐍 **Native Python** - No DSLs, no YAML hell. | 📜 Complex YAML or rigid DSLs. |
|
|
76
80
|
| **Context Awareness** | 🧠 **Auto-Injection** - Params are just function args. | 🔌 Manual wiring of every parameter. |
|
|
77
81
|
| **Caching** | ⚡ **Multi-Level** - Smart content-hashing & memoization. | 🐢 Basic file-timestamp checking. |
|
|
78
82
|
| **Asset Management** | 📦 **First-Class Assets** - Models & Datasets with lineage. | 📁 Generic file paths only. |
|
|
79
83
|
| **Architecture** | 🏗️ **Modular Stacks** - Local, Cloud, Hybrid. | 🔒 Vendor lock-in or complex setup. |
|
|
84
|
+
| **Deployment** | 🏢 **Local or Centralized** - Run locally or deploy as a company-wide hub. | 🧩 Fragmented or cloud-only. |
|
|
85
|
+
| **Flexibility** | 🔌 **Extensive Plugin Ecosystem** | Fixed integration with specific orchestrators or custom tools to be developed. |
|
|
86
|
+
| **Separation of Concerns** | **Steps Grouping, branching and conditions** | Handling only orchestrator logic and task execution oriented. |
|
|
87
|
+
| **Features Rich** | 🌟 **Built-in experiment tracking, model leaderboard, human-in-the-loop, notifications, scheduling** | Very limited or none extra features. |
|
|
80
88
|
|
|
81
89
|
## 🚀 Feature Showcase
|
|
82
90
|
|
|
83
|
-
|
|
91
|
+
FlowyML is a complete toolkit for building, debugging, and deploying ML applications.
|
|
84
92
|
|
|
85
93
|
### 1. Zero-Boilerplate Orchestration
|
|
86
94
|
Write pipelines as standard Python functions. No YAML, no DSLs.
|
|
@@ -110,18 +118,21 @@ def expensive_processing(data):
|
|
|
110
118
|
```
|
|
111
119
|
|
|
112
120
|
### 3. 🤖 LLM & GenAI Ready
|
|
113
|
-
Trace token usage, latency, and costs automatically.
|
|
121
|
+
Trace token usage, latency, and costs automatically with built-in observability.
|
|
114
122
|
|
|
115
123
|
```python
|
|
116
124
|
@step
|
|
117
125
|
@trace_llm(model="gpt-4", tags=["production"])
|
|
118
126
|
def generate_summary(text: str):
|
|
119
|
-
# flowyml automatically tracks
|
|
127
|
+
# flowyml automatically tracks:
|
|
128
|
+
# - Token usage (prompt/completion)
|
|
129
|
+
# - Cost estimation
|
|
130
|
+
# - Latency & Success/Failure rates
|
|
120
131
|
return openai.ChatCompletion.create(...)
|
|
121
132
|
```
|
|
122
133
|
|
|
123
|
-
### 4. ⚡ Efficient Step Grouping
|
|
124
|
-
Group related steps to run in the same container - reduce overhead, maintain clarity.
|
|
134
|
+
### 4. ⚡ Efficient Step Grouping & Separation of Concerns
|
|
135
|
+
Group related steps to run in the same container - reduce overhead, maintain clarity, and keep logic separate from configuration.
|
|
125
136
|
|
|
126
137
|
```python
|
|
127
138
|
# Run preprocessing steps in same container (shares resources)
|
|
@@ -238,12 +249,13 @@ pipeline.run(debug=True) # Pauses at breakpoint
|
|
|
238
249
|
```
|
|
239
250
|
|
|
240
251
|
### 13. 📦 First-Class Assets
|
|
241
|
-
|
|
252
|
+
Assets are not just files; they are first-class citizens with lineage, metadata, and versioning.
|
|
242
253
|
|
|
243
254
|
```python
|
|
244
255
|
from flowyml.core import Dataset, Model, Metrics, FeatureSet
|
|
245
256
|
|
|
246
|
-
|
|
257
|
+
# Assets track their producer, lineage, and metadata automatically
|
|
258
|
+
dataset = Dataset.create(data=df, name="training_data", metadata={"source": "s3"})
|
|
247
259
|
model = Model.create(artifact=trained_model, score=0.95)
|
|
248
260
|
metrics = Metrics.create(values={"accuracy": 0.95})
|
|
249
261
|
```
|
|
@@ -285,11 +297,80 @@ if drift['drift_detected']:
|
|
|
285
297
|
- **🔔 Notifications**: Slack/Email alerts.
|
|
286
298
|
- **🛡️ Circuit Breakers**: Stop cascading failures.
|
|
287
299
|
|
|
288
|
-
### 18.
|
|
300
|
+
### 18. 🏢 Centralized Hub & Docker
|
|
301
|
+
Ready for the enterprise. Run locally per project or deploy as a centralized entity for the company.
|
|
302
|
+
- **Docker Ready**: Backend and Frontend are fully dockerized.
|
|
303
|
+
- **Centralized Hub**: Share pipelines, artifacts, and experiments across the team.
|
|
304
|
+
- **Remote Execution**: Configure local clients to execute on the remote hub.
|
|
305
|
+
|
|
306
|
+
### 19. 🔌 Universal Integrations
|
|
289
307
|
- **ML Frameworks**: PyTorch, TensorFlow, Keras, Scikit-learn, HuggingFace.
|
|
290
308
|
- **Cloud Providers**: AWS, GCP, Azure (via plugins).
|
|
291
309
|
- **Tools**: MLflow, Weights & Biases, Great Expectations.
|
|
292
310
|
|
|
311
|
+
### 20. 📊 Automatic Training History Tracking
|
|
312
|
+
FlowyML automatically captures and visualizes your model training progress with zero manual intervention.
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
from flowyml.integrations.keras import FlowymlKerasCallback
|
|
316
|
+
|
|
317
|
+
# Just add the callback - that's it!
|
|
318
|
+
callback = FlowymlKerasCallback(
|
|
319
|
+
experiment_name="my-experiment",
|
|
320
|
+
project="my-project"
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
model.fit(
|
|
324
|
+
x_train, y_train,
|
|
325
|
+
validation_data=(x_val, y_val),
|
|
326
|
+
epochs=50,
|
|
327
|
+
callbacks=[callback] # Auto-tracks all metrics!
|
|
328
|
+
)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**What gets captured automatically:**
|
|
332
|
+
- ✅ Loss (train & validation) per epoch
|
|
333
|
+
- ✅ Accuracy (train & validation) per epoch
|
|
334
|
+
- ✅ All custom metrics (F1, precision, recall, etc.)
|
|
335
|
+
- ✅ Model architecture and parameters
|
|
336
|
+
- ✅ Interactive charts in the UI
|
|
337
|
+
|
|
338
|
+
**View beautiful training graphs in the UI:**
|
|
339
|
+
1. Navigate to your project's Structure tab
|
|
340
|
+
2. Click on any model artifact
|
|
341
|
+
3. See interactive loss/accuracy charts over epochs!
|
|
342
|
+
|
|
343
|
+
No external tools needed - all visualization built into FlowyML.
|
|
344
|
+
|
|
345
|
+
### 21. 📂 Project-Based Organization
|
|
346
|
+
Built-in multi-tenancy for managing multiple teams and initiatives.
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
from flowyml import Project
|
|
350
|
+
|
|
351
|
+
project = Project("recommendation_system")
|
|
352
|
+
pipeline = project.create_pipeline("training")
|
|
353
|
+
|
|
354
|
+
# All runs, artifacts, and metadata are automatically scoped to the project
|
|
355
|
+
runs = project.list_runs()
|
|
356
|
+
stats = project.get_stats()
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### 22. 📝 Pipeline Templates
|
|
360
|
+
Stop reinventing the wheel. Use pre-built templates for common ML patterns.
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
from flowyml.core.templates import create_from_template
|
|
364
|
+
|
|
365
|
+
# Create a standard training pipeline in one line
|
|
366
|
+
pipeline = create_from_template(
|
|
367
|
+
"ml_training",
|
|
368
|
+
data_loader=my_loader,
|
|
369
|
+
trainer=my_trainer,
|
|
370
|
+
evaluator=my_evaluator
|
|
371
|
+
)
|
|
372
|
+
```
|
|
373
|
+
|
|
293
374
|
## 📦 Installation
|
|
294
375
|
|
|
295
376
|
```bash
|
|
@@ -339,6 +420,26 @@ print(f"Run ID: {result.run_id}")
|
|
|
339
420
|
print(f"Model Score: {result.outputs['model'].score}")
|
|
340
421
|
```
|
|
341
422
|
|
|
423
|
+
### 23. 🌐 Pipeline Versioning
|
|
424
|
+
Git-like versioning for pipelines. Track changes, compare, rollback.
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
from flowyml import VersionedPipeline
|
|
428
|
+
|
|
429
|
+
pipeline = VersionedPipeline("training", version="v1.0.0")
|
|
430
|
+
pipeline.add_step(load_data)
|
|
431
|
+
pipeline.save_version()
|
|
432
|
+
|
|
433
|
+
# ... make changes ...
|
|
434
|
+
pipeline.version = "v1.1.0"
|
|
435
|
+
pipeline.save_version()
|
|
436
|
+
|
|
437
|
+
# Compare versions to see exactly what changed (steps, code, context)
|
|
438
|
+
diff = pipeline.compare_with("v1.0.0")
|
|
439
|
+
print(diff["modified_steps"]) # ['train_model']
|
|
440
|
+
print(diff["context_changes"]) # {'learning_rate': {'old': 0.01, 'new': 0.001}}
|
|
441
|
+
```
|
|
442
|
+
|
|
342
443
|
## 🖥️ The flowyml UI
|
|
343
444
|
|
|
344
445
|
Visualize your workflows, inspect artifacts, and monitor runs in real-time.
|
|
@@ -17,21 +17,25 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
**
|
|
20
|
+
**FlowyML** is the comprehensive ML pipeline framework that combines the **simplicity of a Python script** with the **power of an enterprise MLOps platform**.
|
|
21
21
|
|
|
22
|
-
## 🚀 Why
|
|
22
|
+
## 🚀 Why FlowyML?
|
|
23
23
|
|
|
24
|
-
| Feature |
|
|
24
|
+
| Feature | FlowyML | Traditional Orchestrators |
|
|
25
25
|
|---------|---------|---------------------------|
|
|
26
26
|
| **Developer Experience** | 🐍 **Native Python** - No DSLs, no YAML hell. | 📜 Complex YAML or rigid DSLs. |
|
|
27
27
|
| **Context Awareness** | 🧠 **Auto-Injection** - Params are just function args. | 🔌 Manual wiring of every parameter. |
|
|
28
28
|
| **Caching** | ⚡ **Multi-Level** - Smart content-hashing & memoization. | 🐢 Basic file-timestamp checking. |
|
|
29
29
|
| **Asset Management** | 📦 **First-Class Assets** - Models & Datasets with lineage. | 📁 Generic file paths only. |
|
|
30
30
|
| **Architecture** | 🏗️ **Modular Stacks** - Local, Cloud, Hybrid. | 🔒 Vendor lock-in or complex setup. |
|
|
31
|
+
| **Deployment** | 🏢 **Local or Centralized** - Run locally or deploy as a company-wide hub. | 🧩 Fragmented or cloud-only. |
|
|
32
|
+
| **Flexibility** | 🔌 **Extensive Plugin Ecosystem** | Fixed integration with specific orchestrators or custom tools to be developed. |
|
|
33
|
+
| **Separation of Concerns** | **Steps Grouping, branching and conditions** | Handling only orchestrator logic and task execution oriented. |
|
|
34
|
+
| **Features Rich** | 🌟 **Built-in experiment tracking, model leaderboard, human-in-the-loop, notifications, scheduling** | Very limited or none extra features. |
|
|
31
35
|
|
|
32
36
|
## 🚀 Feature Showcase
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
FlowyML is a complete toolkit for building, debugging, and deploying ML applications.
|
|
35
39
|
|
|
36
40
|
### 1. Zero-Boilerplate Orchestration
|
|
37
41
|
Write pipelines as standard Python functions. No YAML, no DSLs.
|
|
@@ -61,18 +65,21 @@ def expensive_processing(data):
|
|
|
61
65
|
```
|
|
62
66
|
|
|
63
67
|
### 3. 🤖 LLM & GenAI Ready
|
|
64
|
-
Trace token usage, latency, and costs automatically.
|
|
68
|
+
Trace token usage, latency, and costs automatically with built-in observability.
|
|
65
69
|
|
|
66
70
|
```python
|
|
67
71
|
@step
|
|
68
72
|
@trace_llm(model="gpt-4", tags=["production"])
|
|
69
73
|
def generate_summary(text: str):
|
|
70
|
-
# flowyml automatically tracks
|
|
74
|
+
# flowyml automatically tracks:
|
|
75
|
+
# - Token usage (prompt/completion)
|
|
76
|
+
# - Cost estimation
|
|
77
|
+
# - Latency & Success/Failure rates
|
|
71
78
|
return openai.ChatCompletion.create(...)
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
### 4. ⚡ Efficient Step Grouping
|
|
75
|
-
Group related steps to run in the same container - reduce overhead, maintain clarity.
|
|
81
|
+
### 4. ⚡ Efficient Step Grouping & Separation of Concerns
|
|
82
|
+
Group related steps to run in the same container - reduce overhead, maintain clarity, and keep logic separate from configuration.
|
|
76
83
|
|
|
77
84
|
```python
|
|
78
85
|
# Run preprocessing steps in same container (shares resources)
|
|
@@ -189,12 +196,13 @@ pipeline.run(debug=True) # Pauses at breakpoint
|
|
|
189
196
|
```
|
|
190
197
|
|
|
191
198
|
### 13. 📦 First-Class Assets
|
|
192
|
-
|
|
199
|
+
Assets are not just files; they are first-class citizens with lineage, metadata, and versioning.
|
|
193
200
|
|
|
194
201
|
```python
|
|
195
202
|
from flowyml.core import Dataset, Model, Metrics, FeatureSet
|
|
196
203
|
|
|
197
|
-
|
|
204
|
+
# Assets track their producer, lineage, and metadata automatically
|
|
205
|
+
dataset = Dataset.create(data=df, name="training_data", metadata={"source": "s3"})
|
|
198
206
|
model = Model.create(artifact=trained_model, score=0.95)
|
|
199
207
|
metrics = Metrics.create(values={"accuracy": 0.95})
|
|
200
208
|
```
|
|
@@ -236,11 +244,80 @@ if drift['drift_detected']:
|
|
|
236
244
|
- **🔔 Notifications**: Slack/Email alerts.
|
|
237
245
|
- **🛡️ Circuit Breakers**: Stop cascading failures.
|
|
238
246
|
|
|
239
|
-
### 18.
|
|
247
|
+
### 18. 🏢 Centralized Hub & Docker
|
|
248
|
+
Ready for the enterprise. Run locally per project or deploy as a centralized entity for the company.
|
|
249
|
+
- **Docker Ready**: Backend and Frontend are fully dockerized.
|
|
250
|
+
- **Centralized Hub**: Share pipelines, artifacts, and experiments across the team.
|
|
251
|
+
- **Remote Execution**: Configure local clients to execute on the remote hub.
|
|
252
|
+
|
|
253
|
+
### 19. 🔌 Universal Integrations
|
|
240
254
|
- **ML Frameworks**: PyTorch, TensorFlow, Keras, Scikit-learn, HuggingFace.
|
|
241
255
|
- **Cloud Providers**: AWS, GCP, Azure (via plugins).
|
|
242
256
|
- **Tools**: MLflow, Weights & Biases, Great Expectations.
|
|
243
257
|
|
|
258
|
+
### 20. 📊 Automatic Training History Tracking
|
|
259
|
+
FlowyML automatically captures and visualizes your model training progress with zero manual intervention.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from flowyml.integrations.keras import FlowymlKerasCallback
|
|
263
|
+
|
|
264
|
+
# Just add the callback - that's it!
|
|
265
|
+
callback = FlowymlKerasCallback(
|
|
266
|
+
experiment_name="my-experiment",
|
|
267
|
+
project="my-project"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
model.fit(
|
|
271
|
+
x_train, y_train,
|
|
272
|
+
validation_data=(x_val, y_val),
|
|
273
|
+
epochs=50,
|
|
274
|
+
callbacks=[callback] # Auto-tracks all metrics!
|
|
275
|
+
)
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**What gets captured automatically:**
|
|
279
|
+
- ✅ Loss (train & validation) per epoch
|
|
280
|
+
- ✅ Accuracy (train & validation) per epoch
|
|
281
|
+
- ✅ All custom metrics (F1, precision, recall, etc.)
|
|
282
|
+
- ✅ Model architecture and parameters
|
|
283
|
+
- ✅ Interactive charts in the UI
|
|
284
|
+
|
|
285
|
+
**View beautiful training graphs in the UI:**
|
|
286
|
+
1. Navigate to your project's Structure tab
|
|
287
|
+
2. Click on any model artifact
|
|
288
|
+
3. See interactive loss/accuracy charts over epochs!
|
|
289
|
+
|
|
290
|
+
No external tools needed - all visualization built into FlowyML.
|
|
291
|
+
|
|
292
|
+
### 21. 📂 Project-Based Organization
|
|
293
|
+
Built-in multi-tenancy for managing multiple teams and initiatives.
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
from flowyml import Project
|
|
297
|
+
|
|
298
|
+
project = Project("recommendation_system")
|
|
299
|
+
pipeline = project.create_pipeline("training")
|
|
300
|
+
|
|
301
|
+
# All runs, artifacts, and metadata are automatically scoped to the project
|
|
302
|
+
runs = project.list_runs()
|
|
303
|
+
stats = project.get_stats()
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 22. 📝 Pipeline Templates
|
|
307
|
+
Stop reinventing the wheel. Use pre-built templates for common ML patterns.
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
from flowyml.core.templates import create_from_template
|
|
311
|
+
|
|
312
|
+
# Create a standard training pipeline in one line
|
|
313
|
+
pipeline = create_from_template(
|
|
314
|
+
"ml_training",
|
|
315
|
+
data_loader=my_loader,
|
|
316
|
+
trainer=my_trainer,
|
|
317
|
+
evaluator=my_evaluator
|
|
318
|
+
)
|
|
319
|
+
```
|
|
320
|
+
|
|
244
321
|
## 📦 Installation
|
|
245
322
|
|
|
246
323
|
```bash
|
|
@@ -290,6 +367,26 @@ print(f"Run ID: {result.run_id}")
|
|
|
290
367
|
print(f"Model Score: {result.outputs['model'].score}")
|
|
291
368
|
```
|
|
292
369
|
|
|
370
|
+
### 23. 🌐 Pipeline Versioning
|
|
371
|
+
Git-like versioning for pipelines. Track changes, compare, rollback.
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
from flowyml import VersionedPipeline
|
|
375
|
+
|
|
376
|
+
pipeline = VersionedPipeline("training", version="v1.0.0")
|
|
377
|
+
pipeline.add_step(load_data)
|
|
378
|
+
pipeline.save_version()
|
|
379
|
+
|
|
380
|
+
# ... make changes ...
|
|
381
|
+
pipeline.version = "v1.1.0"
|
|
382
|
+
pipeline.save_version()
|
|
383
|
+
|
|
384
|
+
# Compare versions to see exactly what changed (steps, code, context)
|
|
385
|
+
diff = pipeline.compare_with("v1.0.0")
|
|
386
|
+
print(diff["modified_steps"]) # ['train_model']
|
|
387
|
+
print(diff["context_changes"]) # {'learning_rate': {'old': 0.01, 'new': 0.001}}
|
|
388
|
+
```
|
|
389
|
+
|
|
293
390
|
## 🖥️ The flowyml UI
|
|
294
391
|
|
|
295
392
|
Visualize your workflows, inspect artifacts, and monitor runs in real-time.
|
|
@@ -38,6 +38,7 @@ from flowyml.assets.registry import AssetRegistry
|
|
|
38
38
|
# Stack imports
|
|
39
39
|
from flowyml.stacks.base import Stack
|
|
40
40
|
from flowyml.stacks.local import LocalStack
|
|
41
|
+
from flowyml.stacks.components import ResourceConfig, DockerConfig
|
|
41
42
|
|
|
42
43
|
# Tracking imports
|
|
43
44
|
from flowyml.tracking.experiment import Experiment
|
|
@@ -140,6 +141,8 @@ __all__ = [
|
|
|
140
141
|
# Stacks
|
|
141
142
|
"Stack",
|
|
142
143
|
"LocalStack",
|
|
144
|
+
"ResourceConfig",
|
|
145
|
+
"DockerConfig",
|
|
143
146
|
# Tracking
|
|
144
147
|
"Experiment",
|
|
145
148
|
"Run",
|
|
@@ -77,6 +77,16 @@ class Asset:
|
|
|
77
77
|
if parent:
|
|
78
78
|
parent.children.append(self)
|
|
79
79
|
|
|
80
|
+
@property
|
|
81
|
+
def properties(self) -> dict[str, Any]:
|
|
82
|
+
"""Expose mutable properties stored in metadata."""
|
|
83
|
+
return self.metadata.properties
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def tags(self) -> dict[str, str]:
|
|
87
|
+
"""Expose mutable tags stored in metadata."""
|
|
88
|
+
return self.metadata.tags
|
|
89
|
+
|
|
80
90
|
@classmethod
|
|
81
91
|
def create(
|
|
82
92
|
cls,
|
|
@@ -89,7 +89,10 @@ class Metrics(Asset):
|
|
|
89
89
|
def create(
|
|
90
90
|
cls,
|
|
91
91
|
name: str | None = None,
|
|
92
|
+
version: str | None = None,
|
|
92
93
|
parent: Asset | None = None,
|
|
94
|
+
tags: dict[str, str] | None = None,
|
|
95
|
+
properties: dict[str, Any] | None = None,
|
|
93
96
|
**metrics,
|
|
94
97
|
) -> "Metrics":
|
|
95
98
|
"""Factory method to create metrics.
|
|
@@ -99,6 +102,9 @@ class Metrics(Asset):
|
|
|
99
102
|
"""
|
|
100
103
|
return cls(
|
|
101
104
|
name=name or "metrics",
|
|
105
|
+
version=version,
|
|
102
106
|
data=metrics,
|
|
103
107
|
parent=parent,
|
|
108
|
+
tags=tags,
|
|
109
|
+
properties=properties,
|
|
104
110
|
)
|
|
@@ -48,9 +48,11 @@ def init(name: str, template: str, directory: str) -> None:
|
|
|
48
48
|
@click.option("--stack", default="local", help="Stack to use for execution")
|
|
49
49
|
@click.option("--context", "-c", multiple=True, help="Context parameters (key=value)")
|
|
50
50
|
@click.option("--debug", is_flag=True, help="Enable debug mode")
|
|
51
|
-
|
|
51
|
+
@click.option("--retry", type=int, help="Number of retries for the pipeline")
|
|
52
|
+
def run(pipeline_name: str, stack: str, context: tuple, debug: bool, retry: int | None) -> None:
|
|
52
53
|
"""Run a pipeline."""
|
|
53
54
|
from flowyml.cli.run import run_pipeline
|
|
55
|
+
from flowyml.core.retry_policy import OrchestratorRetryPolicy
|
|
54
56
|
|
|
55
57
|
# Parse context parameters
|
|
56
58
|
ctx_params = {}
|
|
@@ -60,8 +62,13 @@ def run(pipeline_name: str, stack: str, context: tuple, debug: bool) -> None:
|
|
|
60
62
|
|
|
61
63
|
click.echo(f"Running pipeline '{pipeline_name}' on stack '{stack}'...")
|
|
62
64
|
|
|
65
|
+
kwargs = {}
|
|
66
|
+
if retry:
|
|
67
|
+
kwargs["retry_policy"] = OrchestratorRetryPolicy(max_attempts=retry)
|
|
68
|
+
click.echo(f" Retry policy enabled: max_attempts={retry}")
|
|
69
|
+
|
|
63
70
|
try:
|
|
64
|
-
result = run_pipeline(pipeline_name, stack, ctx_params, debug)
|
|
71
|
+
result = run_pipeline(pipeline_name, stack, ctx_params, debug, **kwargs)
|
|
65
72
|
click.echo("✓ Pipeline completed successfully")
|
|
66
73
|
click.echo(f" Run ID: {result.get('run_id', 'N/A')}")
|
|
67
74
|
click.echo(f" Duration: {result.get('duration', 'N/A')}")
|
|
@@ -70,6 +77,105 @@ def run(pipeline_name: str, stack: str, context: tuple, debug: bool) -> None:
|
|
|
70
77
|
raise click.Abort()
|
|
71
78
|
|
|
72
79
|
|
|
80
|
+
@cli.group()
|
|
81
|
+
def schedule() -> None:
|
|
82
|
+
"""Schedule management commands."""
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@schedule.command("create")
|
|
87
|
+
@click.argument("pipeline_name")
|
|
88
|
+
@click.argument("schedule_type", type=click.Choice(["cron", "interval", "daily", "hourly"]))
|
|
89
|
+
@click.argument("value")
|
|
90
|
+
@click.option("--stack", default="local", help="Stack to use for execution")
|
|
91
|
+
def create_schedule(pipeline_name: str, schedule_type: str, value: str, stack: str) -> None:
|
|
92
|
+
"""Create a new schedule for a pipeline.
|
|
93
|
+
|
|
94
|
+
VALUE format depends on SCHEDULE_TYPE:
|
|
95
|
+
- cron: "*/5 * * * *"
|
|
96
|
+
- interval: seconds (e.g. 60)
|
|
97
|
+
- daily: "HH:MM" (e.g. 14:30)
|
|
98
|
+
- hourly: minute (e.g. 30)
|
|
99
|
+
"""
|
|
100
|
+
from flowyml.core.scheduler import PipelineScheduler
|
|
101
|
+
from flowyml.cli.run import run_pipeline
|
|
102
|
+
|
|
103
|
+
# We need a callable for the scheduler.
|
|
104
|
+
# Since CLI is stateless, we wrap the run_pipeline command.
|
|
105
|
+
# Note: In a real distributed system, this would submit to a scheduler service.
|
|
106
|
+
# Here we are just registering it in the local scheduler DB.
|
|
107
|
+
|
|
108
|
+
# For now, we'll just use the scheduler API to register the definition
|
|
109
|
+
scheduler = PipelineScheduler()
|
|
110
|
+
|
|
111
|
+
# Define a wrapper that runs the pipeline via CLI logic
|
|
112
|
+
def job_func():
|
|
113
|
+
run_pipeline(pipeline_name, stack, {}, False)
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
if schedule_type == "cron":
|
|
117
|
+
scheduler.schedule_cron(pipeline_name, job_func, value)
|
|
118
|
+
elif schedule_type == "interval":
|
|
119
|
+
scheduler.schedule_interval(pipeline_name, job_func, seconds=int(value))
|
|
120
|
+
elif schedule_type == "daily":
|
|
121
|
+
if ":" in value:
|
|
122
|
+
h, m = map(int, value.split(":"))
|
|
123
|
+
scheduler.schedule_daily(pipeline_name, job_func, hour=h, minute=m)
|
|
124
|
+
else:
|
|
125
|
+
raise ValueError("Daily value must be HH:MM")
|
|
126
|
+
elif schedule_type == "hourly":
|
|
127
|
+
scheduler.schedule_hourly(pipeline_name, job_func, minute=int(value))
|
|
128
|
+
|
|
129
|
+
click.echo(f"✓ Schedule created for '{pipeline_name}' ({schedule_type}={value})")
|
|
130
|
+
click.echo(" Note: Ensure the scheduler service is running to execute this schedule.")
|
|
131
|
+
except Exception as e:
|
|
132
|
+
click.echo(f"✗ Error creating schedule: {e}", err=True)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@schedule.command("list")
|
|
136
|
+
def list_schedules() -> None:
|
|
137
|
+
"""List all active schedules."""
|
|
138
|
+
from flowyml.core.scheduler import PipelineScheduler
|
|
139
|
+
|
|
140
|
+
scheduler = PipelineScheduler()
|
|
141
|
+
jobs = scheduler.get_jobs()
|
|
142
|
+
|
|
143
|
+
if not jobs:
|
|
144
|
+
click.echo("No active schedules found.")
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
click.echo(f"Found {len(jobs)} schedules:\n")
|
|
148
|
+
for job in jobs:
|
|
149
|
+
click.echo(f" {job.id} - {job.name}")
|
|
150
|
+
click.echo(f" Next run: {job.next_run_time}")
|
|
151
|
+
click.echo()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@schedule.command("start")
|
|
155
|
+
def start_scheduler() -> None:
|
|
156
|
+
"""Start the scheduler service (blocking)."""
|
|
157
|
+
from flowyml.core.scheduler import PipelineScheduler
|
|
158
|
+
import time
|
|
159
|
+
|
|
160
|
+
click.echo("🚀 Starting Scheduler Service...")
|
|
161
|
+
scheduler = PipelineScheduler()
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
# In a real app, this would load definitions from DB and register them
|
|
165
|
+
# For now, it just runs the scheduler loop for existing in-memory jobs
|
|
166
|
+
# (which might be empty if we restarted).
|
|
167
|
+
# To make this persistent, we'd need to serialize job definitions to DB.
|
|
168
|
+
# The current Scheduler implementation supports SQLite persistence for job state,
|
|
169
|
+
# but we need to re-register jobs on startup.
|
|
170
|
+
|
|
171
|
+
click.echo(" Scheduler running. Press Ctrl+C to stop.")
|
|
172
|
+
while True:
|
|
173
|
+
scheduler.run_pending()
|
|
174
|
+
time.sleep(1)
|
|
175
|
+
except KeyboardInterrupt:
|
|
176
|
+
click.echo("\n🛑 Scheduler stopped.")
|
|
177
|
+
|
|
178
|
+
|
|
73
179
|
@cli.group()
|
|
74
180
|
def ui() -> None:
|
|
75
181
|
"""UI server commands."""
|
|
@@ -6,7 +6,13 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def run_pipeline(
|
|
9
|
+
def run_pipeline(
|
|
10
|
+
pipeline_name: str,
|
|
11
|
+
stack: str,
|
|
12
|
+
context_params: dict[str, Any],
|
|
13
|
+
debug: bool,
|
|
14
|
+
**kwargs,
|
|
15
|
+
) -> dict[str, Any]:
|
|
10
16
|
"""Run a pipeline by name.
|
|
11
17
|
|
|
12
18
|
Args:
|
|
@@ -14,6 +20,7 @@ def run_pipeline(pipeline_name: str, stack: str, context_params: dict[str, Any],
|
|
|
14
20
|
stack: Stack to use for execution
|
|
15
21
|
context_params: Context parameters to override
|
|
16
22
|
debug: Enable debug mode
|
|
23
|
+
**kwargs: Additional arguments passed to pipeline.run
|
|
17
24
|
|
|
18
25
|
Returns:
|
|
19
26
|
Dictionary with run results
|
|
@@ -65,7 +72,7 @@ def run_pipeline(pipeline_name: str, stack: str, context_params: dict[str, Any],
|
|
|
65
72
|
pipeline.set_stack(stack)
|
|
66
73
|
|
|
67
74
|
# Run pipeline
|
|
68
|
-
result = pipeline.run(debug=debug)
|
|
75
|
+
result = pipeline.run(debug=debug, **kwargs)
|
|
69
76
|
|
|
70
77
|
return {
|
|
71
78
|
"run_id": result.run_id,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Execution status tracking for pipeline runs."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ExecutionStatus(str, Enum):
|
|
7
|
+
"""Status of a pipeline or step execution."""
|
|
8
|
+
|
|
9
|
+
# Pre-execution states
|
|
10
|
+
INITIALIZING = "initializing"
|
|
11
|
+
PROVISIONING = "provisioning"
|
|
12
|
+
|
|
13
|
+
# Active execution states
|
|
14
|
+
RUNNING = "running"
|
|
15
|
+
|
|
16
|
+
# Terminal success states
|
|
17
|
+
COMPLETED = "completed"
|
|
18
|
+
CACHED = "cached"
|
|
19
|
+
|
|
20
|
+
# Terminal failure states
|
|
21
|
+
FAILED = "failed"
|
|
22
|
+
STOPPED = "stopped"
|
|
23
|
+
CANCELLED = "cancelled"
|
|
24
|
+
|
|
25
|
+
# Intermediate states
|
|
26
|
+
STOPPING = "stopping"
|
|
27
|
+
CANCELLING = "cancelling"
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def is_finished(self) -> bool:
|
|
31
|
+
"""Check if execution is in a terminal state."""
|
|
32
|
+
return self in {
|
|
33
|
+
ExecutionStatus.COMPLETED,
|
|
34
|
+
ExecutionStatus.CACHED,
|
|
35
|
+
ExecutionStatus.FAILED,
|
|
36
|
+
ExecutionStatus.STOPPED,
|
|
37
|
+
ExecutionStatus.CANCELLED,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def is_successful(self) -> bool:
|
|
42
|
+
"""Check if execution completed successfully."""
|
|
43
|
+
return self in {ExecutionStatus.COMPLETED, ExecutionStatus.CACHED}
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def is_failed(self) -> bool:
|
|
47
|
+
"""Check if execution failed."""
|
|
48
|
+
return self in {
|
|
49
|
+
ExecutionStatus.FAILED,
|
|
50
|
+
ExecutionStatus.STOPPED,
|
|
51
|
+
ExecutionStatus.CANCELLED,
|
|
52
|
+
}
|