flowyml 1.2.0__tar.gz → 1.4.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.
Files changed (211) hide show
  1. {flowyml-1.2.0 → flowyml-1.4.0}/LICENSE +1 -1
  2. {flowyml-1.2.0 → flowyml-1.4.0}/PKG-INFO +44 -4
  3. {flowyml-1.2.0 → flowyml-1.4.0}/README.md +37 -3
  4. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/__init__.py +3 -0
  5. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/base.py +10 -0
  6. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/metrics.py +6 -0
  7. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/main.py +108 -2
  8. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/run.py +9 -2
  9. flowyml-1.4.0/flowyml/core/execution_status.py +52 -0
  10. flowyml-1.4.0/flowyml/core/hooks.py +106 -0
  11. flowyml-1.4.0/flowyml/core/observability.py +210 -0
  12. flowyml-1.4.0/flowyml/core/orchestrator.py +274 -0
  13. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/pipeline.py +193 -231
  14. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/project.py +34 -2
  15. flowyml-1.4.0/flowyml/core/remote_orchestrator.py +109 -0
  16. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/resources.py +34 -17
  17. flowyml-1.4.0/flowyml/core/retry_policy.py +80 -0
  18. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/scheduler.py +9 -9
  19. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/scheduler_config.py +2 -3
  20. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/step.py +18 -1
  21. flowyml-1.4.0/flowyml/core/submission_result.py +53 -0
  22. flowyml-1.4.0/flowyml/integrations/keras.py +207 -0
  23. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/alerts.py +2 -2
  24. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/__init__.py +15 -0
  25. flowyml-1.4.0/flowyml/stacks/aws.py +599 -0
  26. flowyml-1.4.0/flowyml/stacks/azure.py +295 -0
  27. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/bridge.py +9 -9
  28. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/components.py +24 -2
  29. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/gcp.py +158 -11
  30. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/local.py +5 -0
  31. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/plugins.py +2 -2
  32. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/registry.py +21 -0
  33. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/artifacts.py +15 -5
  34. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/__init__.py +2 -0
  35. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/base.py +33 -0
  36. flowyml-1.4.0/flowyml/storage/materializers/cloudpickle.py +74 -0
  37. flowyml-1.4.0/flowyml/storage/metadata.py +53 -0
  38. flowyml-1.4.0/flowyml/storage/remote.py +590 -0
  39. flowyml-1.4.0/flowyml/storage/sql.py +911 -0
  40. flowyml-1.4.0/flowyml/ui/backend/dependencies.py +28 -0
  41. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/main.py +43 -80
  42. flowyml-1.4.0/flowyml/ui/backend/routers/assets.py +511 -0
  43. flowyml-1.4.0/flowyml/ui/backend/routers/client.py +46 -0
  44. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/execution.py +13 -2
  45. flowyml-1.4.0/flowyml/ui/backend/routers/experiments.py +132 -0
  46. flowyml-1.4.0/flowyml/ui/backend/routers/metrics.py +168 -0
  47. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/pipelines.py +77 -12
  48. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/projects.py +33 -7
  49. flowyml-1.4.0/flowyml/ui/backend/routers/runs.py +275 -0
  50. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/schedules.py +5 -21
  51. flowyml-1.4.0/flowyml/ui/backend/routers/stats.py +14 -0
  52. flowyml-1.4.0/flowyml/ui/backend/routers/traces.py +68 -0
  53. flowyml-1.4.0/flowyml/ui/frontend/dist/assets/index-DcYwrn2j.css +1 -0
  54. flowyml-1.4.0/flowyml/ui/frontend/dist/assets/index-Dlz_ygOL.js +592 -0
  55. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/dist/index.html +2 -2
  56. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/App.jsx +4 -1
  57. flowyml-1.4.0/flowyml/ui/frontend/src/app/assets/page.jsx +427 -0
  58. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/dashboard/page.jsx +38 -7
  59. flowyml-1.4.0/flowyml/ui/frontend/src/app/experiments/page.jsx +107 -0
  60. flowyml-1.4.0/flowyml/ui/frontend/src/app/observability/page.jsx +277 -0
  61. flowyml-1.4.0/flowyml/ui/frontend/src/app/pipelines/page.jsx +131 -0
  62. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectArtifactsList.jsx +151 -0
  63. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectExperimentsList.jsx +145 -0
  64. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHeader.jsx +45 -0
  65. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHierarchy.jsx +467 -0
  66. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectMetricsPanel.jsx +253 -0
  67. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectPipelinesList.jsx +105 -0
  68. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRelations.jsx +189 -0
  69. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRunsList.jsx +136 -0
  70. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectTabs.jsx +95 -0
  71. flowyml-1.4.0/flowyml/ui/frontend/src/app/projects/[projectId]/page.jsx +326 -0
  72. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/projects/page.jsx +13 -3
  73. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/runs/[runId]/page.jsx +79 -10
  74. flowyml-1.4.0/flowyml/ui/frontend/src/app/runs/page.jsx +128 -0
  75. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/settings/page.jsx +1 -0
  76. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/tokens/page.jsx +62 -16
  77. flowyml-1.4.0/flowyml/ui/frontend/src/components/AssetDetailsPanel.jsx +373 -0
  78. flowyml-1.4.0/flowyml/ui/frontend/src/components/AssetLineageGraph.jsx +291 -0
  79. flowyml-1.4.0/flowyml/ui/frontend/src/components/AssetStatsDashboard.jsx +302 -0
  80. flowyml-1.4.0/flowyml/ui/frontend/src/components/AssetTreeHierarchy.jsx +477 -0
  81. flowyml-1.4.0/flowyml/ui/frontend/src/components/ExperimentDetailsPanel.jsx +227 -0
  82. flowyml-1.4.0/flowyml/ui/frontend/src/components/NavigationTree.jsx +401 -0
  83. flowyml-1.4.0/flowyml/ui/frontend/src/components/PipelineDetailsPanel.jsx +239 -0
  84. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/PipelineGraph.jsx +67 -3
  85. flowyml-1.4.0/flowyml/ui/frontend/src/components/ProjectSelector.jsx +115 -0
  86. flowyml-1.4.0/flowyml/ui/frontend/src/components/RunDetailsPanel.jsx +298 -0
  87. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/header/Header.jsx +48 -1
  88. flowyml-1.4.0/flowyml/ui/frontend/src/components/plugins/ZenMLIntegration.jsx +106 -0
  89. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/sidebar/Sidebar.jsx +52 -26
  90. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/DataView.jsx +35 -17
  91. flowyml-1.4.0/flowyml/ui/frontend/src/components/ui/ErrorBoundary.jsx +118 -0
  92. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/contexts/ProjectContext.jsx +2 -2
  93. flowyml-1.4.0/flowyml/ui/frontend/src/contexts/ToastContext.jsx +116 -0
  94. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/layouts/MainLayout.jsx +5 -1
  95. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/router/index.jsx +4 -0
  96. flowyml-1.4.0/flowyml/ui/frontend/src/utils/date.js +10 -0
  97. flowyml-1.4.0/flowyml/ui/frontend/src/utils/downloads.js +11 -0
  98. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/config.py +6 -0
  99. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/stack_config.py +45 -3
  100. {flowyml-1.2.0 → flowyml-1.4.0}/pyproject.toml +11 -1
  101. flowyml-1.2.0/flowyml/integrations/keras.py +0 -134
  102. flowyml-1.2.0/flowyml/storage/metadata.py +0 -931
  103. flowyml-1.2.0/flowyml/ui/backend/routers/assets.py +0 -45
  104. flowyml-1.2.0/flowyml/ui/backend/routers/experiments.py +0 -49
  105. flowyml-1.2.0/flowyml/ui/backend/routers/runs.py +0 -66
  106. flowyml-1.2.0/flowyml/ui/backend/routers/traces.py +0 -84
  107. flowyml-1.2.0/flowyml/ui/frontend/dist/assets/index-DFNQnrUj.js +0 -448
  108. flowyml-1.2.0/flowyml/ui/frontend/dist/assets/index-pWI271rZ.css +0 -1
  109. flowyml-1.2.0/flowyml/ui/frontend/src/app/assets/page.jsx +0 -397
  110. flowyml-1.2.0/flowyml/ui/frontend/src/app/experiments/page.jsx +0 -360
  111. flowyml-1.2.0/flowyml/ui/frontend/src/app/pipelines/page.jsx +0 -454
  112. flowyml-1.2.0/flowyml/ui/frontend/src/app/runs/page.jsx +0 -470
  113. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/__init__.py +0 -0
  114. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/artifact.py +0 -0
  115. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/dataset.py +0 -0
  116. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/featureset.py +0 -0
  117. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/model.py +0 -0
  118. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/registry.py +0 -0
  119. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/assets/report.py +0 -0
  120. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/__init__.py +0 -0
  121. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/experiment.py +0 -0
  122. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/init.py +0 -0
  123. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/stack_cli.py +0 -0
  124. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/cli/ui.py +0 -0
  125. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/__init__.py +0 -0
  126. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/advanced_cache.py +0 -0
  127. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/approval.py +0 -0
  128. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/cache.py +0 -0
  129. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/checkpoint.py +0 -0
  130. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/conditional.py +0 -0
  131. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/context.py +0 -0
  132. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/error_handling.py +0 -0
  133. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/executor.py +0 -0
  134. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/graph.py +0 -0
  135. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/parallel.py +0 -0
  136. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/step_grouping.py +0 -0
  137. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/templates.py +0 -0
  138. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/core/versioning.py +0 -0
  139. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/integrations/__init__.py +0 -0
  140. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/__init__.py +0 -0
  141. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/data.py +0 -0
  142. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/llm.py +0 -0
  143. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/monitor.py +0 -0
  144. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/monitoring/notifications.py +0 -0
  145. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/registry/__init__.py +0 -0
  146. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/registry/model_registry.py +0 -0
  147. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/registry/pipeline_registry.py +0 -0
  148. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/base.py +0 -0
  149. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/migration.py +0 -0
  150. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/stacks/plugin_config.py +0 -0
  151. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/__init__.py +0 -0
  152. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/keras.py +0 -0
  153. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/numpy.py +0 -0
  154. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/pandas.py +0 -0
  155. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/pytorch.py +0 -0
  156. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/sklearn.py +0 -0
  157. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/storage/materializers/tensorflow.py +0 -0
  158. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/tracking/__init__.py +0 -0
  159. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/tracking/experiment.py +0 -0
  160. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/tracking/leaderboard.py +0 -0
  161. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/tracking/runs.py +0 -0
  162. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/__init__.py +0 -0
  163. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/Dockerfile +0 -0
  164. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/__init__.py +0 -0
  165. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/auth.py +0 -0
  166. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/__init__.py +0 -0
  167. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/leaderboard.py +0 -0
  168. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/notifications.py +0 -0
  169. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/backend/routers/plugins.py +0 -0
  170. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/Dockerfile +0 -0
  171. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/README.md +0 -0
  172. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/index.html +0 -0
  173. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/nginx.conf +0 -0
  174. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/package-lock.json +0 -0
  175. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/package.json +0 -0
  176. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/postcss.config.js +0 -0
  177. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/experiments/[experimentId]/page.jsx +0 -0
  178. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/leaderboard/page.jsx +0 -0
  179. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/plugins/page.jsx +0 -0
  180. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/schedules/page.jsx +0 -0
  181. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/app/traces/page.jsx +0 -0
  182. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/Layout.jsx +0 -0
  183. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/plugins/AddPluginDialog.jsx +0 -0
  184. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/plugins/InstalledPlugins.jsx +0 -0
  185. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/plugins/PluginBrowser.jsx +0 -0
  186. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/plugins/PluginManager.jsx +0 -0
  187. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/Badge.jsx +0 -0
  188. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/Button.jsx +0 -0
  189. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/Card.jsx +0 -0
  190. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/CodeSnippet.jsx +0 -0
  191. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/CollapsibleCard.jsx +0 -0
  192. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/EmptyState.jsx +0 -0
  193. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/ExecutionStatus.jsx +0 -0
  194. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/KeyValue.jsx +0 -0
  195. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/components/ui/ProjectSelector.jsx +0 -0
  196. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/contexts/ThemeContext.jsx +0 -0
  197. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/index.css +0 -0
  198. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/main.jsx +0 -0
  199. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/services/pluginService.js +0 -0
  200. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/utils/api.js +0 -0
  201. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/src/utils/cn.js +0 -0
  202. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/tailwind.config.js +0 -0
  203. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/frontend/vite.config.js +0 -0
  204. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/ui/utils.py +0 -0
  205. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/__init__.py +0 -0
  206. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/debug.py +0 -0
  207. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/environment.py +0 -0
  208. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/git.py +0 -0
  209. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/logging.py +0 -0
  210. {flowyml-1.2.0 → flowyml-1.4.0}/flowyml/utils/performance.py +0 -0
  211. {flowyml-1.2.0 → flowyml-1.4.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 Flowy Team
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.2.0
3
+ Version: 1.4.0
4
4
  Summary: Next-Generation ML Pipeline Framework
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -19,24 +19,30 @@ 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)
39
+ Requires-Dist: psycopg2-binary (>=2.9.0)
35
40
  Requires-Dist: pydantic (>=2.0.0)
36
41
  Requires-Dist: python-multipart (>=0.0.6) ; extra == "ui" or extra == "all"
37
42
  Requires-Dist: pytz (>=2024.1,<2025.0)
38
43
  Requires-Dist: pyyaml (>=6.0)
39
44
  Requires-Dist: scikit-learn (>=1.0.0) ; extra == "sklearn" or extra == "all"
45
+ Requires-Dist: sqlalchemy (>=2.0.0)
40
46
  Requires-Dist: tensorflow (>=2.12.0) ; extra == "tensorflow" or extra == "all"
41
47
  Requires-Dist: toml (>=0.10.2)
42
48
  Requires-Dist: torch (>=2.0.0) ; extra == "pytorch" or extra == "all"
@@ -304,7 +310,41 @@ Ready for the enterprise. Run locally per project or deploy as a centralized ent
304
310
  - **Cloud Providers**: AWS, GCP, Azure (via plugins).
305
311
  - **Tools**: MLflow, Weights & Biases, Great Expectations.
306
312
 
307
- ### 20. 📂 Project-Based Organization
313
+ ### 20. 📊 Automatic Training History Tracking
314
+ FlowyML automatically captures and visualizes your model training progress with zero manual intervention.
315
+
316
+ ```python
317
+ from flowyml.integrations.keras import FlowymlKerasCallback
318
+
319
+ # Just add the callback - that's it!
320
+ callback = FlowymlKerasCallback(
321
+ experiment_name="my-experiment",
322
+ project="my-project"
323
+ )
324
+
325
+ model.fit(
326
+ x_train, y_train,
327
+ validation_data=(x_val, y_val),
328
+ epochs=50,
329
+ callbacks=[callback] # Auto-tracks all metrics!
330
+ )
331
+ ```
332
+
333
+ **What gets captured automatically:**
334
+ - ✅ Loss (train & validation) per epoch
335
+ - ✅ Accuracy (train & validation) per epoch
336
+ - ✅ All custom metrics (F1, precision, recall, etc.)
337
+ - ✅ Model architecture and parameters
338
+ - ✅ Interactive charts in the UI
339
+
340
+ **View beautiful training graphs in the UI:**
341
+ 1. Navigate to your project's Structure tab
342
+ 2. Click on any model artifact
343
+ 3. See interactive loss/accuracy charts over epochs!
344
+
345
+ No external tools needed - all visualization built into FlowyML.
346
+
347
+ ### 21. 📂 Project-Based Organization
308
348
  Built-in multi-tenancy for managing multiple teams and initiatives.
309
349
 
310
350
  ```python
@@ -318,7 +358,7 @@ runs = project.list_runs()
318
358
  stats = project.get_stats()
319
359
  ```
320
360
 
321
- ### 21. 📝 Pipeline Templates
361
+ ### 22. 📝 Pipeline Templates
322
362
  Stop reinventing the wheel. Use pre-built templates for common ML patterns.
323
363
 
324
364
  ```python
@@ -382,7 +422,7 @@ print(f"Run ID: {result.run_id}")
382
422
  print(f"Model Score: {result.outputs['model'].score}")
383
423
  ```
384
424
 
385
- ### 16. 🌐 Pipeline Versioning
425
+ ### 23. 🌐 Pipeline Versioning
386
426
  Git-like versioning for pipelines. Track changes, compare, rollback.
387
427
 
388
428
  ```python
@@ -255,7 +255,41 @@ Ready for the enterprise. Run locally per project or deploy as a centralized ent
255
255
  - **Cloud Providers**: AWS, GCP, Azure (via plugins).
256
256
  - **Tools**: MLflow, Weights & Biases, Great Expectations.
257
257
 
258
- ### 20. 📂 Project-Based Organization
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
259
293
  Built-in multi-tenancy for managing multiple teams and initiatives.
260
294
 
261
295
  ```python
@@ -269,7 +303,7 @@ runs = project.list_runs()
269
303
  stats = project.get_stats()
270
304
  ```
271
305
 
272
- ### 21. 📝 Pipeline Templates
306
+ ### 22. 📝 Pipeline Templates
273
307
  Stop reinventing the wheel. Use pre-built templates for common ML patterns.
274
308
 
275
309
  ```python
@@ -333,7 +367,7 @@ print(f"Run ID: {result.run_id}")
333
367
  print(f"Model Score: {result.outputs['model'].score}")
334
368
  ```
335
369
 
336
- ### 16. 🌐 Pipeline Versioning
370
+ ### 23. 🌐 Pipeline Versioning
337
371
  Git-like versioning for pipelines. Track changes, compare, rollback.
338
372
 
339
373
  ```python
@@ -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
- def run(pipeline_name: str, stack: str, context: tuple, debug: bool) -> None:
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(pipeline_name: str, stack: str, context_params: dict[str, Any], debug: bool) -> dict[str, Any]:
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
+ }
@@ -0,0 +1,106 @@
1
+ """Lifecycle hooks for pipelines and steps."""
2
+
3
+ from typing import Any, TYPE_CHECKING
4
+ from collections.abc import Callable
5
+ from dataclasses import dataclass, field
6
+
7
+ if TYPE_CHECKING:
8
+ from flowyml.core.pipeline import Pipeline, PipelineResult
9
+ from flowyml.core.step import Step
10
+ from flowyml.core.executor import ExecutionResult
11
+
12
+
13
+ @dataclass
14
+ class HookRegistry:
15
+ """Registry for pipeline and step lifecycle hooks."""
16
+
17
+ # Pipeline-level hooks
18
+ on_pipeline_start: list[Callable[["Pipeline"], None]] = field(default_factory=list)
19
+ on_pipeline_end: list[Callable[["Pipeline", "PipelineResult"], None]] = field(default_factory=list)
20
+
21
+ # Step-level hooks
22
+ on_step_start: list[Callable[["Step", dict[str, Any]], None]] = field(default_factory=list)
23
+ on_step_end: list[Callable[["Step", "ExecutionResult"], None]] = field(default_factory=list)
24
+
25
+ def register_pipeline_start_hook(self, hook: Callable[["Pipeline"], None]) -> None:
26
+ """Register a hook to run at pipeline start."""
27
+ self.on_pipeline_start.append(hook)
28
+
29
+ def register_pipeline_end_hook(self, hook: Callable[["Pipeline", "PipelineResult"], None]) -> None:
30
+ """Register a hook to run at pipeline end."""
31
+ self.on_pipeline_end.append(hook)
32
+
33
+ def register_step_start_hook(self, hook: Callable[["Step", dict[str, Any]], None]) -> None:
34
+ """Register a hook to run before step execution."""
35
+ self.on_step_start.append(hook)
36
+
37
+ def register_step_end_hook(self, hook: Callable[["Step", "ExecutionResult"], None]) -> None:
38
+ """Register a hook to run after step execution."""
39
+ self.on_step_end.append(hook)
40
+
41
+ def run_pipeline_start_hooks(self, pipeline: "Pipeline") -> None:
42
+ """Execute all pipeline start hooks."""
43
+ for hook in self.on_pipeline_start:
44
+ try:
45
+ hook(pipeline)
46
+ except Exception as e:
47
+ print(f"Warning: Pipeline start hook failed: {e}")
48
+
49
+ def run_pipeline_end_hooks(self, pipeline: "Pipeline", result: "PipelineResult") -> None:
50
+ """Execute all pipeline end hooks."""
51
+ for hook in self.on_pipeline_end:
52
+ try:
53
+ hook(pipeline, result)
54
+ except Exception as e:
55
+ print(f"Warning: Pipeline end hook failed: {e}")
56
+
57
+ def run_step_start_hooks(self, step: "Step", inputs: dict[str, Any]) -> None:
58
+ """Execute all step start hooks."""
59
+ for hook in self.on_step_start:
60
+ try:
61
+ hook(step, inputs)
62
+ except Exception as e:
63
+ print(f"Warning: Step start hook failed: {e}")
64
+
65
+ def run_step_end_hooks(self, step: "Step", result: "ExecutionResult") -> None:
66
+ """Execute all step end hooks."""
67
+ for hook in self.on_step_end:
68
+ try:
69
+ hook(step, result)
70
+ except Exception as e:
71
+ print(f"Warning: Step end hook failed: {e}")
72
+
73
+
74
+ # Global hook registry
75
+ _global_hooks = HookRegistry()
76
+
77
+
78
+ def get_global_hooks() -> HookRegistry:
79
+ """Get the global hook registry."""
80
+ return _global_hooks
81
+
82
+
83
+ def on_pipeline_start(func: Callable[["Pipeline"], None]) -> Callable[["Pipeline"], None]:
84
+ """Decorator to register a pipeline start hook."""
85
+ _global_hooks.register_pipeline_start_hook(func)
86
+ return func
87
+
88
+
89
+ def on_pipeline_end(
90
+ func: Callable[["Pipeline", "PipelineResult"], None],
91
+ ) -> Callable[["Pipeline", "PipelineResult"], None]:
92
+ """Decorator to register a pipeline end hook."""
93
+ _global_hooks.register_pipeline_end_hook(func)
94
+ return func
95
+
96
+
97
+ def on_step_start(func: Callable[["Step", dict[str, Any]], None]) -> Callable[["Step", dict[str, Any]], None]:
98
+ """Decorator to register a step start hook."""
99
+ _global_hooks.register_step_start_hook(func)
100
+ return func
101
+
102
+
103
+ def on_step_end(func: Callable[["Step", "ExecutionResult"], None]) -> Callable[["Step", "ExecutionResult"], None]:
104
+ """Decorator to register a step end hook."""
105
+ _global_hooks.register_step_end_hook(func)
106
+ return func