weightslab 1.3.0__tar.gz → 1.3.2__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 (366) hide show
  1. {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/ci.yml +1 -1
  2. {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/release.yml +249 -53
  3. weightslab-1.3.2/CHANGELOG.md +1 -0
  4. {weightslab-1.3.0/weightslab.egg-info → weightslab-1.3.2}/PKG-INFO +15 -18
  5. {weightslab-1.3.0 → weightslab-1.3.2}/README.md +13 -16
  6. {weightslab-1.3.0 → weightslab-1.3.2}/agent_config.yaml +7 -1
  7. weightslab-1.3.2/docs/_static/custom.css +584 -0
  8. weightslab-1.3.2/docs/_static/examples-gallery.js +208 -0
  9. weightslab-1.3.2/docs/_static/github-stars.js +17 -0
  10. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/version-switcher.js +10 -11
  11. weightslab-1.3.2/docs/_static/wl-ribbon.js +49 -0
  12. weightslab-1.3.2/docs/_static/wl-topnav.js +89 -0
  13. weightslab-1.3.2/docs/_templates/sidebar/brand.html +21 -0
  14. weightslab-1.3.2/docs/agent.rst +650 -0
  15. {weightslab-1.3.0 → weightslab-1.3.2}/docs/conf.py +15 -5
  16. {weightslab-1.3.0 → weightslab-1.3.2}/docs/configuration.rst +398 -70
  17. {weightslab-1.3.0 → weightslab-1.3.2}/docs/data_exploration.rst +6 -0
  18. weightslab-1.3.2/docs/examples/index.rst +21 -0
  19. weightslab-1.3.2/docs/examples/lightning/classification.rst +119 -0
  20. weightslab-1.3.2/docs/examples/lightning/index.rst +19 -0
  21. weightslab-1.3.2/docs/examples/pytorch/classification.rst +161 -0
  22. weightslab-1.3.2/docs/examples/pytorch/clustering.rst +97 -0
  23. weightslab-1.3.2/docs/examples/pytorch/detection.rst +129 -0
  24. weightslab-1.3.2/docs/examples/pytorch/generation.rst +103 -0
  25. weightslab-1.3.2/docs/examples/pytorch/index.rst +23 -0
  26. weightslab-1.3.2/docs/examples/pytorch/segmentation.rst +116 -0
  27. weightslab-1.3.2/docs/examples/ultralytics/detection.rst +47 -0
  28. weightslab-1.3.2/docs/examples/ultralytics/index.rst +19 -0
  29. weightslab-1.3.2/docs/examples/usecases/index.rst +20 -0
  30. weightslab-1.3.2/docs/examples/usecases/lidar_detection.rst +126 -0
  31. weightslab-1.3.2/docs/examples/usecases/loss_shape_classification.rst +210 -0
  32. weightslab-1.3.2/docs/four_way_approach.rst +58 -0
  33. {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/audit_logger.rst +4 -0
  34. {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/grpc_functions.rst +0 -1
  35. {weightslab-1.3.0 → weightslab-1.3.2}/docs/index.rst +71 -16
  36. {weightslab-1.3.0 → weightslab-1.3.2}/docs/logger.rst +31 -0
  37. weightslab-1.3.2/docs/quickstart.rst +193 -0
  38. {weightslab-1.3.0 → weightslab-1.3.2}/docs/segmentation_usecase.rst +1 -1
  39. weightslab-1.3.2/docs/ultralytics.rst +224 -0
  40. weightslab-1.3.2/docs/usage/docker.rst +350 -0
  41. weightslab-1.3.2/docs/usage/good_practice.rst +211 -0
  42. weightslab-1.3.2/docs/usage/parameters.rst +528 -0
  43. weightslab-1.3.2/docs/usage.rst +18 -0
  44. weightslab-1.3.2/docs/user_commands.rst +440 -0
  45. {weightslab-1.3.0 → weightslab-1.3.2}/docs/user_functions.rst +437 -15
  46. {weightslab-1.3.0 → weightslab-1.3.2}/docs/weights_studio.rst +19 -41
  47. {weightslab-1.3.0 → weightslab-1.3.2}/pyproject.toml +23 -3
  48. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/__init__.py +1 -1
  49. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_logger_core.py +82 -0
  50. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_checkpoint_workflow.py +5 -1
  51. weightslab-1.3.2/tests/gRPC/test_grpc_histogram_categorical.py +265 -0
  52. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_cli.py +95 -1
  53. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_model_with_ops.py +1 -1
  54. weightslab-1.3.2/tests/trainer/services/test_agent_live_prompt_evaluation.py +1120 -0
  55. weightslab-1.3.2/tests/trainer/services/test_agent_model_and_safety_unit.py +1677 -0
  56. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_agent_prompt_unit.py +29 -1
  57. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_agent_service_unit.py +2 -2
  58. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/__init__.py +61 -8
  59. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/_version.py +3 -3
  60. weightslab-1.3.2/weightslab/art.py +164 -0
  61. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/cli.py +127 -3
  62. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/ledgers.py +14 -0
  63. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/logger.py +68 -0
  64. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/model_interface.py +18 -9
  65. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/optimizer_interface.py +1 -1
  66. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/checkpoint_manager.py +4 -4
  67. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/dataframe_manager.py +7 -3
  68. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/h5_dataframe_store.py +10 -2
  69. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/docker-compose.yml +1 -1
  70. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx-entrypoint.sh +0 -0
  71. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/test-deployment.sh +0 -0
  72. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/build-and-deploy.sh +8 -6
  73. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/generate-certs-auth-token.ps1 +0 -0
  74. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/generate-certs-auth-token.sh +0 -0
  75. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/utils/test-deployment.sh +0 -0
  76. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Lightning/ws-classification/main.py +1 -1
  77. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-classification/config.yaml +0 -1
  78. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-classification/main.py +3 -5
  79. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/main.py +8 -2
  80. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/README.md +102 -0
  81. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/config.yaml +50 -0
  82. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/main.py +340 -0
  83. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/criterions.py +361 -0
  84. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/data.py +226 -0
  85. weightslab-1.3.2/weightslab/examples/Usecases/ws-loss_shapes_classification_per_sample/utils/model.py +134 -0
  86. weightslab-1.3.2/weightslab/examples/__init__.py +6 -0
  87. weightslab-1.3.2/weightslab/examples/utils/__init__.py +1 -0
  88. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/modules/modules_with_ops.py +1 -1
  89. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service.proto +12 -2
  90. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service_pb2.py +66 -64
  91. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/security/cert_auth_manager.py +1 -1
  92. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/src.py +57 -29
  93. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/experiment_context.py +6 -2
  94. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent.py +827 -30
  95. weightslab-1.3.2/weightslab/trainer/services/agent/intent_prompt.py +843 -0
  96. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/data_service.py +817 -66
  97. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/experiment_service.py +3 -0
  98. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/model_service.py +12 -2
  99. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/trainer_tools.py +2 -0
  100. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/ui_docker_bridge.py +112 -16
  101. {weightslab-1.3.0 → weightslab-1.3.2/weightslab.egg-info}/PKG-INFO +15 -18
  102. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/SOURCES.txt +124 -97
  103. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/scm_file_list.json +124 -97
  104. weightslab-1.3.2/weightslab.egg-info/scm_version.json +8 -0
  105. weightslab-1.3.0/CHANGELOG.md +0 -1
  106. weightslab-1.3.0/docs/_static/custom.css +0 -143
  107. weightslab-1.3.0/docs/four_way_approach.rst +0 -29
  108. weightslab-1.3.0/docs/quickstart.rst +0 -191
  109. weightslab-1.3.0/weightslab/art.py +0 -58
  110. weightslab-1.3.0/weightslab/examples/Ultralytics/ws-detection/requirements.txt +0 -1
  111. weightslab-1.3.0/weightslab/tests/data/test_data_samples_with_ops.py +0 -783
  112. weightslab-1.3.0/weightslab/tests/data/test_data_service_metadata_copy.py +0 -97
  113. weightslab-1.3.0/weightslab/tests/data/test_data_utils_unit.py +0 -117
  114. weightslab-1.3.0/weightslab/tests/data/test_dataframe_manager_unit.py +0 -428
  115. weightslab-1.3.0/weightslab/tests/data/test_flush_pipeline.py +0 -276
  116. weightslab-1.3.0/weightslab/tests/data/test_h5_array_store.py +0 -216
  117. weightslab-1.3.0/weightslab/tests/data/test_h5_dataframe_store.py +0 -219
  118. weightslab-1.3.0/weightslab/tests/data/test_point_cloud_utils.py +0 -330
  119. weightslab-1.3.0/weightslab/trainer/services/agent/intent_prompt.py +0 -426
  120. weightslab-1.3.0/weightslab/trainer/services/utils/__init__.py +0 -0
  121. weightslab-1.3.0/weightslab.egg-info/scm_version.json +0 -8
  122. {weightslab-1.3.0 → weightslab-1.3.2}/.gitattributes +0 -0
  123. {weightslab-1.3.0 → weightslab-1.3.2}/.github/workflows/docs-pages.yml +0 -0
  124. {weightslab-1.3.0 → weightslab-1.3.2}/.gitignore +0 -0
  125. {weightslab-1.3.0 → weightslab-1.3.2}/AGENTS.md +0 -0
  126. {weightslab-1.3.0 → weightslab-1.3.2}/LICENSE +0 -0
  127. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/.gitkeep +0 -0
  128. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/favicon.png +0 -0
  129. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/logo-dark.png +0 -0
  130. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/logo-light.png +0 -0
  131. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_static/weights_studio_architecture.png +0 -0
  132. {weightslab-1.3.0 → weightslab-1.3.2}/docs/_templates/.gitkeep +0 -0
  133. {weightslab-1.3.0 → weightslab-1.3.2}/docs/grpc/index.rst +0 -0
  134. {weightslab-1.3.0 → weightslab-1.3.2}/docs/hyperparameters.rst +0 -0
  135. {weightslab-1.3.0 → weightslab-1.3.2}/docs/model_interaction.rst +0 -0
  136. {weightslab-1.3.0 → weightslab-1.3.2}/docs/pytorch_lightning.rst +0 -0
  137. {weightslab-1.3.0 → weightslab-1.3.2}/docs/requirements.txt +0 -0
  138. {weightslab-1.3.0 → weightslab-1.3.2}/docs/usecases.rst +0 -0
  139. {weightslab-1.3.0 → weightslab-1.3.2}/setup.cfg +0 -0
  140. {weightslab-1.3.0/weightslab → weightslab-1.3.2/tests}/backend/__init__.py +0 -0
  141. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_audit_logger.py +0 -0
  142. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_cli_additional_unit.py +0 -0
  143. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_compare_dataloaders.py +0 -0
  144. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_data_loader_interface.py +0 -0
  145. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_instance_signal_logger.py +0 -0
  146. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_ledgers.py +0 -0
  147. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_model_interface_unit.py +0 -0
  148. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_optimizer_interface.py +0 -0
  149. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_optimizer_interface_additional_unit.py +0 -0
  150. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_ui_docker_bridge.py +0 -0
  151. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_write_dataframe.py +0 -0
  152. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/backend/test_write_history.py +0 -0
  153. {weightslab-1.3.0/weightslab/baseline_models → weightslab-1.3.2/tests/chaos_monkeys_utests}/__init__.py +0 -0
  154. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/chaos_monkeys_utests/test_grpc_chaos_monkey_robustness.py +0 -0
  155. {weightslab-1.3.0/weightslab/baseline_models/pytorch → weightslab-1.3.2/tests/components}/__init__.py +0 -0
  156. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_experiment_hash_and_art.py +0 -0
  157. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/components/test_global_monitoring_unit.py +0 -0
  158. {weightslab-1.3.0/weightslab/data → weightslab-1.3.2/tests/gRPC}/__init__.py +0 -0
  159. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_get_point_cloud.py +0 -0
  160. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_grpc_tag_operations.py +0 -0
  161. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/gRPC/test_grpc_user_actions.py +0 -0
  162. {weightslab-1.3.0/weightslab/examples/PyTorch/ws-clustering/face → weightslab-1.3.2/tests/general}/__init__.py +0 -0
  163. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_auditor_mode.py +0 -0
  164. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_hyperparams.py +0 -0
  165. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_logger_snapshot_rotation.py +0 -0
  166. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_signals.py +0 -0
  167. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/general/test_signals_wrapping.py +0 -0
  168. {weightslab-1.3.0/weightslab/models → weightslab-1.3.2/tests/integrations}/__init__.py +0 -0
  169. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/test_pytorch_lightning_integration.py +0 -0
  170. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/ultralytics/ddp/ddp_ablation.py +0 -0
  171. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/integrations/ultralytics/ddp/ddp_test_suite.py +0 -0
  172. {weightslab-1.3.0/weightslab/modules → weightslab-1.3.2/tests/model}/__init__.py +0 -0
  173. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_constraint_generation.py +0 -0
  174. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_dependency_patterns.py +0 -0
  175. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_logger.py +0 -0
  176. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_model_with_ops_unit.py +0 -0
  177. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/model/test_tracking.py +0 -0
  178. {weightslab-1.3.0/weightslab/proto → weightslab-1.3.2/tests/modules}/__init__.py +0 -0
  179. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/modules/test_modules_with_ops.py +0 -0
  180. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/test_secure_docker.py +0 -0
  181. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/test_src_functions.py +0 -0
  182. {weightslab-1.3.0/weightslab/tests/backend → weightslab-1.3.2/tests/trainer}/__init__.py +0 -0
  183. {weightslab-1.3.0/weightslab/tests/chaos_monkeys_utests → weightslab-1.3.2/tests/trainer/services}/__init__.py +0 -0
  184. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_trainer_services_server.py +0 -0
  185. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/services/test_trainer_services_unit.py +0 -0
  186. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/trainer/test_trainer_tools.py +0 -0
  187. {weightslab-1.3.0/weightslab/tests/components → weightslab-1.3.2/tests/utils}/__init__.py +0 -0
  188. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_computational_graph_utils_unit.py +0 -0
  189. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_logs_unit.py +0 -0
  190. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_modules_dependencies_unit.py +0 -0
  191. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_plot_graph_render_unit.py +0 -0
  192. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_plot_graph_unit.py +0 -0
  193. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_shape_prop_unit.py +0 -0
  194. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/utils/test_utils_tools_unit.py +0 -0
  195. {weightslab-1.3.0/weightslab/tests/data → weightslab-1.3.2/tests/watchdog}/__init__.py +0 -0
  196. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/watchdog/test_lock_monitor.py +0 -0
  197. {weightslab-1.3.0/weightslab → weightslab-1.3.2}/tests/watchdog/test_watchdog.py +0 -0
  198. {weightslab-1.3.0/weightslab/tests/gRPC → weightslab-1.3.2/weightslab/backend}/__init__.py +0 -0
  199. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/audit_logger.py +0 -0
  200. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/backend/dataloader_interface.py +0 -0
  201. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/__init__.py +0 -0
  202. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/evaluation_controller.py +0 -0
  203. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/experiment_hash.py +0 -0
  204. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/global_monitoring.py +0 -0
  205. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/parallel_primitives.py +0 -0
  206. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/components/tracking.py +0 -0
  207. {weightslab-1.3.0/weightslab/tests/general → weightslab-1.3.2/weightslab/data}/__init__.py +0 -0
  208. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/array_proxy.py +0 -0
  209. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/data_samples_with_ops.py +0 -0
  210. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/data_utils.py +0 -0
  211. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/h5_array_store.py +0 -0
  212. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/point_cloud_utils.py +0 -0
  213. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/data/sample_stats.py +0 -0
  214. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/Dockerfile +0 -0
  215. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/.dockerignore +0 -0
  216. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/.env.example +0 -0
  217. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/DEPLOYMENT.md +0 -0
  218. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.base-path.conf copy.template +0 -0
  219. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.base-path.conf.template +0 -0
  220. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/docker/nginx.conf +0 -0
  221. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.downstream_plaintext.yaml +0 -0
  222. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.downstream_upstream_plaintext.yaml +0 -0
  223. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.upstream_plaintext.yaml +0 -0
  224. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/envoy/envoy.yaml +0 -0
  225. {weightslab-1.3.0/weightslab/ui → weightslab-1.3.2/weightslab/docker}/nginx.conf +0 -0
  226. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/README.md +0 -0
  227. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/Dockerfile +0 -0
  228. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/README.md +0 -0
  229. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/docker-compose.yml +0 -0
  230. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/docker_in_docker/entrypoint.sh +0 -0
  231. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/Dockerfile +0 -0
  232. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/README.md +0 -0
  233. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/docker-compose.yml +0 -0
  234. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/entrypoint.sh +0 -0
  235. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Docker_training/siblings_self_contained/ui-compose.yml +0 -0
  236. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Lightning/ws-classification/config.yaml +0 -0
  237. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/config.yaml +0 -0
  238. {weightslab-1.3.0/weightslab/tests/integrations → weightslab-1.3.2/weightslab/examples/PyTorch/ws-clustering/face}/__init__.py +0 -0
  239. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/data.py +0 -0
  240. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/model.py +0 -0
  241. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/signals.py +0 -0
  242. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/face/utils.py +0 -0
  243. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-clustering/main.py +0 -0
  244. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/README.md +0 -0
  245. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/config.yaml +0 -0
  246. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/main.py +0 -0
  247. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/criterions.py +0 -0
  248. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/data.py +0 -0
  249. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-detection/utils/model.py +0 -0
  250. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-generation/config.yaml +0 -0
  251. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-generation/main.py +0 -0
  252. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0000f77c-6257be58.jpg +0 -0
  253. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/000f8d37-d4c09a0f.jpg +0 -0
  254. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00a0f008-a315437f.jpg +0 -0
  255. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c12bd0-bb46e479.jpg +0 -0
  256. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00c29c52-f9524f1e.jpg +0 -0
  257. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00ce6f6d-50bbee62.jpg +0 -0
  258. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d1bafa-1b47b41c.jpg +0 -0
  259. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00d7268f-fd4487be.jpg +0 -0
  260. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/00f0dd0f-5e9c9557.jpg +0 -0
  261. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a0d7f4c-ac5c3c8f.jpg +0 -0
  262. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a1f4fce-f9cac880.jpg +0 -0
  263. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/train/0a3bb2d8-c195d91e.jpg +0 -0
  264. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1cac6a7-04e33135.jpg +0 -0
  265. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ceb32e-3f481b43.jpg +0 -0
  266. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d10d08-5b108225.jpg +0 -0
  267. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d22449-15fb948f.jpg +0 -0
  268. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1d7b3ac-5af8623b.jpg +0 -0
  269. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1dce572-c6a8cb5e.jpg +0 -0
  270. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e1a7b8-0aec80e8.jpg +0 -0
  271. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1e8ad72-c3c79240.jpg +0 -0
  272. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1ee702d-0ae1fc10.jpg +0 -0
  273. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b1f0efd9-37a14dda.jpg +0 -0
  274. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2a0648b-d8e126bc.jpg +0 -0
  275. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/images/val/b2b70230-bad4ff6e.jpg +0 -0
  276. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0000f77c-6257be58.png +0 -0
  277. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/000f8d37-d4c09a0f.png +0 -0
  278. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00a0f008-a315437f.png +0 -0
  279. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c12bd0-bb46e479.png +0 -0
  280. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00c29c52-f9524f1e.png +0 -0
  281. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00ce6f6d-50bbee62.png +0 -0
  282. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d1bafa-1b47b41c.png +0 -0
  283. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00d7268f-fd4487be.png +0 -0
  284. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/00f0dd0f-5e9c9557.png +0 -0
  285. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a0d7f4c-ac5c3c8f.png +0 -0
  286. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a1f4fce-f9cac880.png +0 -0
  287. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/train/0a3bb2d8-c195d91e.png +0 -0
  288. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1cac6a7-04e33135.png +0 -0
  289. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ceb32e-3f481b43.png +0 -0
  290. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d10d08-5b108225.png +0 -0
  291. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d22449-15fb948f.png +0 -0
  292. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1d7b3ac-5af8623b.png +0 -0
  293. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1dce572-c6a8cb5e.png +0 -0
  294. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e1a7b8-0aec80e8.png +0 -0
  295. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1e8ad72-c3c79240.png +0 -0
  296. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1ee702d-0ae1fc10.png +0 -0
  297. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b1f0efd9-37a14dda.png +0 -0
  298. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2a0648b-d8e126bc.png +0 -0
  299. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/BDD_subset/labels/val/b2b70230-bad4ff6e.png +0 -0
  300. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/config.yaml +0 -0
  301. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/criterions.py +0 -0
  302. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/data.py +0 -0
  303. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/PyTorch/ws-segmentation/utils/model.py +0 -0
  304. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Ultralytics/ws-detection/config.yaml +0 -0
  305. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Ultralytics/ws-detection/main.py +0 -0
  306. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/README.md +0 -0
  307. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/config.yaml +0 -0
  308. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/main.py +0 -0
  309. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/criterions.py +0 -0
  310. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/data.py +0 -0
  311. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-2d-lidar-detection/utils/model.py +0 -0
  312. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/README.md +0 -0
  313. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/config.yaml +0 -0
  314. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/main.py +0 -0
  315. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/criterions.py +0 -0
  316. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/data.py +0 -0
  317. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/kitti_download.py +0 -0
  318. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/examples/Usecases/ws-3d-lidar-detection/utils/model.py +0 -0
  319. {weightslab-1.3.0/weightslab/tests/model → weightslab-1.3.2/weightslab/examples/utils/baseline_models}/__init__.py +0 -0
  320. {weightslab-1.3.0/weightslab/tests/modules → weightslab-1.3.2/weightslab/examples/utils/baseline_models/pytorch}/__init__.py +0 -0
  321. {weightslab-1.3.0/weightslab → weightslab-1.3.2/weightslab/examples/utils}/baseline_models/pytorch/models.py +0 -0
  322. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/__init__.py +0 -0
  323. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/README.md +0 -0
  324. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/__init__.py +0 -0
  325. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/_utils.py +0 -0
  326. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/collate.py +0 -0
  327. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/dataset.py +0 -0
  328. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/signals.py +0 -0
  329. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/integrations/ultralytics/trainer.py +0 -0
  330. {weightslab-1.3.0/weightslab/tests/trainer → weightslab-1.3.2/weightslab/models}/__init__.py +0 -0
  331. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/models/model_with_ops.py +0 -0
  332. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/models/monkey_patcher.py +0 -0
  333. {weightslab-1.3.0/weightslab/tests/trainer/services → weightslab-1.3.2/weightslab/modules}/__init__.py +0 -0
  334. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/modules/neuron_ops.py +0 -0
  335. {weightslab-1.3.0/weightslab/tests/utils → weightslab-1.3.2/weightslab/proto}/__init__.py +0 -0
  336. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/proto/experiment_service_pb2_grpc.py +0 -0
  337. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/security/__init__.py +0 -0
  338. {weightslab-1.3.0/weightslab/tests/watchdog → weightslab-1.3.2/weightslab/trainer}/__init__.py +0 -0
  339. {weightslab-1.3.0/weightslab/trainer → weightslab-1.3.2/weightslab/trainer/services}/__init__.py +0 -0
  340. {weightslab-1.3.0/weightslab/trainer/services → weightslab-1.3.2/weightslab/trainer/services/agent}/__init__.py +0 -0
  341. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/agent.png +0 -0
  342. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/query_example.png +0 -0
  343. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent/agent_overview/schema.png +0 -0
  344. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/agent_service.py +0 -0
  345. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/data_image_utils.py +0 -0
  346. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/instance_merger.py +0 -0
  347. {weightslab-1.3.0/weightslab/trainer/services/agent → weightslab-1.3.2/weightslab/trainer/services/utils}/__init__.py +0 -0
  348. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/services/utils/tools.py +0 -0
  349. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/trainer/trainer_services.py +0 -0
  350. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/__init__.py +0 -0
  351. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/computational_graph.py +0 -0
  352. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/logs.py +0 -0
  353. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/modules_dependencies.py +0 -0
  354. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/plot_graph.py +0 -0
  355. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/shape_prop.py +0 -0
  356. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/telemetry.py +0 -0
  357. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/utils/tools.py +0 -0
  358. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/__init__.py +0 -0
  359. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/grpc_watchdog.py +0 -0
  360. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/lock_monitor.py +0 -0
  361. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/log_level.py +0 -0
  362. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab/watchdog/watchdog.py +0 -0
  363. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/dependency_links.txt +0 -0
  364. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/entry_points.txt +0 -0
  365. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/requires.txt +1 -1
  366. {weightslab-1.3.0 → weightslab-1.3.2}/weightslab.egg-info/top_level.txt +0 -0
@@ -221,7 +221,7 @@ jobs:
221
221
  run: |
222
222
  export WEIGHTSLAB_LOG_LEVEL="DEBUG"
223
223
  # A per-test timeout guards against any regression that hangs a test.
224
- python -m pytest ./weightslab/tests -v --timeout=300
224
+ python -m pytest ./tests -v --timeout=300
225
225
 
226
226
  build-and-publish-dev:
227
227
  # Only publish to TestPyPI when pushing to main (not on PRs or dev branch pushes).
@@ -16,6 +16,8 @@ jobs:
16
16
  if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
17
17
  outputs:
18
18
  is_main: ${{ steps.check.outputs.is_main }}
19
+ is_dev_release: ${{ steps.check.outputs.is_dev_release }}
20
+ should_run: ${{ steps.check.outputs.should_run }}
19
21
  steps:
20
22
  - uses: actions/checkout@v4
21
23
  with:
@@ -29,14 +31,32 @@ jobs:
29
31
  IS_ON_MAIN=$(git merge-base --is-ancestor "${TAG_COMMIT}" origin/main \
30
32
  && echo "true" || echo "false")
31
33
  echo "is_main=${IS_ON_MAIN}" >> $GITHUB_OUTPUT
32
- echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN}"
33
34
 
34
- # ── Shared: run tests before main publish only ───────────────────────────
35
+ # Dev pre-release: a tag NOT on main whose name contains 'dev'
36
+ # (e.g. v1.3.1-dev0). Runs the full pipeline up to the TestPyPI install
37
+ # tests + a GitHub pre-release, then STOPS before the production PyPI
38
+ # publish. A tag off main WITHOUT 'dev' triggers nothing (should_run=false),
39
+ # so accidental/non-dev tags on dev never release.
40
+ IS_DEV_RELEASE=false
41
+ if [ "${IS_ON_MAIN}" != "true" ] && [[ "${GITHUB_REF_NAME}" == *dev* ]]; then
42
+ IS_DEV_RELEASE=true
43
+ fi
44
+ echo "is_dev_release=${IS_DEV_RELEASE}" >> $GITHUB_OUTPUT
45
+
46
+ if [ "${IS_ON_MAIN}" = "true" ] || [ "${IS_DEV_RELEASE}" = "true" ]; then
47
+ SHOULD_RUN=true
48
+ else
49
+ SHOULD_RUN=false
50
+ fi
51
+ echo "should_run=${SHOULD_RUN}" >> $GITHUB_OUTPUT
52
+ echo "Tag: ${GITHUB_REF_NAME} commit: ${TAG_COMMIT} on_main: ${IS_ON_MAIN} dev_release: ${IS_DEV_RELEASE} should_run: ${SHOULD_RUN}"
53
+
54
+ # ── Shared: run tests before any publish (main or dev pre-release) ────────
35
55
  test:
36
56
  name: Run Tests Before Release
37
57
  needs: detect-target
38
58
  runs-on: ubuntu-latest
39
- if: ${{ needs.detect-target.outputs.is_main == 'true' }}
59
+ if: ${{ needs.detect-target.outputs.should_run == 'true' }}
40
60
  steps:
41
61
  - uses: actions/checkout@v4
42
62
 
@@ -57,8 +77,7 @@ jobs:
57
77
  run: |
58
78
  export WEIGHTSLAB_LOG_LEVEL="DEBUG"
59
79
  python -m pip install pytorch_lightning
60
- # python -m unittest discover -s ./weightslab/tests -p "test_*.py" -t . -v
61
- python -m pytest ./weightslab/tests -v --timeout=300
80
+ python -m unittest discover -s ./tests -p "test_*.py" -t . -v
62
81
 
63
82
  # ═══════════════════════════════════════════════════════════════════════════
64
83
  # DEV RELEASE — tag on dev branch, not yet merged to main
@@ -67,9 +86,9 @@ jobs:
67
86
 
68
87
  build-and-publish-dev-release:
69
88
  name: Build & Publish Dev Release (TestPyPI)
70
- needs: detect-target
89
+ needs: [detect-target,test]
71
90
  runs-on: ubuntu-latest
72
- if: ${{ needs.detect-target.outputs.is_main != 'true' }}
91
+ if: ${{ needs.detect-target.outputs.should_run == 'true' }}
73
92
  permissions:
74
93
  contents: read
75
94
  outputs:
@@ -188,9 +207,11 @@ jobs:
188
207
  print('installed version:', m.version('weightslab'))
189
208
  "
190
209
 
210
+ # Only for a dev pre-release tag (off main, name contains 'dev').
191
211
  create-dev-release:
192
212
  name: Create GitHub Pre-Release
193
- needs: [build-and-publish-dev-release, test-install-from-pip-dev-release]
213
+ needs: [detect-target, build-and-publish-dev-release, test-install-from-pip-dev-release]
214
+ if: ${{ needs.detect-target.outputs.is_dev_release == 'true' }}
194
215
  runs-on: ubuntu-latest
195
216
  permissions:
196
217
  contents: write
@@ -213,46 +234,107 @@ jobs:
213
234
  export VERSION_NO_V="${VERSION#v}"
214
235
  export PYPI_URL="https://test.pypi.org/project/weightslab/${VERSION_NO_V}/"
215
236
 
216
- PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${VERSION}$" | head -n 1 || true)
237
+ # Walk the actual commit graph for the nearest ancestor tag, rather
238
+ # than a lexicographic/semver sort across ALL tags. The old sort
239
+ # could pick an unrelated tag from a diverging branch — e.g. a
240
+ # "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
241
+ # sorted ABOVE it, making every real PR since v1.3.0 look "older"
242
+ # than that bogus previous-tag date and get silently filtered out
243
+ # (this is why past releases showed "no pull requests found").
244
+ PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
217
245
  if [ -n "$PREV_TAG" ]; then
218
- export PREV_TAG_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || echo "2020-01-01T00:00:00Z")
246
+ RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
247
+ # Normalize to UTC "Z" form so string comparison against GitHub's
248
+ # mergedAt (also UTC "Z") is valid regardless of the committer's
249
+ # local timezone offset.
250
+ export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
219
251
  export GIT_RANGE="${PREV_TAG}..HEAD"
220
252
  else
221
253
  export PREV_TAG_DATE="2020-01-01T00:00:00Z"
222
254
  export GIT_RANGE="HEAD"
223
255
  fi
224
256
 
225
- export COMMITS
226
- COMMITS=$(git log "${GIT_RANGE}" --no-merges --format="- %h %s" 2>/dev/null | head -25 || true)
227
- [ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
257
+ export COMMITS_RAW
258
+ COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
228
259
 
229
260
  export GIT_AUTHORS
230
261
  GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
231
262
 
263
+ # NOTE: deliberately NOT requesting --json commits here. With
264
+ # --limit 100 that expands into a GraphQL query requesting 100 PRs'
265
+ # worth of commit nodes, which reliably exceeds GitHub's 500,000
266
+ # node budget and makes `gh` print a plain-text GraphQL error
267
+ # instead of JSON — json.loads() below then fails, prs_data
268
+ # silently becomes [], and every release note says "no pull
269
+ # requests found" regardless of the date filter. Commits are
270
+ # fetched below, one lightweight call per PR, only for the small
271
+ # number of PRs that actually match this release.
232
272
  export PRS_JSON
233
273
  PRS_JSON=$(gh pr list --state merged --base "dev" --limit 100 \
234
- --json number,title,mergedAt,url,author,body,commits \
274
+ --json number,title,mergedAt,url,author,body \
235
275
  2>/dev/null || echo "[]")
236
276
 
237
277
  python3 << 'PYEOF'
238
- import os, json
278
+ import os, json, re, importlib.util, subprocess
239
279
  version = os.environ["VERSION"]
240
280
  pypi_url = os.environ["PYPI_URL"]
241
281
  prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
242
- commits = os.environ.get("COMMITS", "_(no commits found)_")
282
+ commits_raw = os.environ.get("COMMITS_RAW", "")
243
283
  git_authors = os.environ.get("GIT_AUTHORS", "")
244
284
  try:
245
285
  prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
246
286
  except Exception:
247
287
  prs_data = []
288
+
289
+ _README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
290
+
291
+ def _strip_pr_suffix(head):
292
+ return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
293
+
294
+ def _collapse_readme(entries):
295
+ """entries: list of (oid_or_None, head) tuples, in original order.
296
+ Collapse every bare "Update README[.md]" commit into a single
297
+ "Update README (n)" line at the position of its first occurrence —
298
+ these are near-duplicate housekeeping commits with no release signal."""
299
+ out, count, placeholder_idx = [], 0, None
300
+ for oid, head in entries:
301
+ if _README_RE.match(_strip_pr_suffix(head)):
302
+ count += 1
303
+ if placeholder_idx is None:
304
+ placeholder_idx = len(out)
305
+ out.append(None)
306
+ continue
307
+ out.append((oid, head))
308
+ if placeholder_idx is not None:
309
+ label = "Update README" if count == 1 else f"Update README ({count})"
310
+ out[placeholder_idx] = (None, label)
311
+ return out
312
+
313
+ def _format_entries(entries, indent=""):
314
+ return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
315
+
248
316
  def _pr_entry(pr):
249
- line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
250
317
  desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
251
- if desc:
252
- if len(desc) > 512:
253
- desc = desc[:509].rstrip() + "..."
254
- line += f"\n\n > {desc}"
255
- return line
318
+ if not desc:
319
+ desc = pr["title"]
320
+ if len(desc) > 512:
321
+ desc = desc[:509].rstrip() + "..."
322
+ return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
323
+
324
+ def _fetch_pr_commits(number):
325
+ # One lightweight call per matched PR (see the note above the
326
+ # PRS_JSON fetch for why this isn't batched into the list query).
327
+ try:
328
+ out = subprocess.run(
329
+ ["gh", "pr", "view", str(number), "--json", "commits"],
330
+ capture_output=True, text=True, timeout=30,
331
+ )
332
+ if out.returncode != 0:
333
+ return []
334
+ return json.loads(out.stdout).get("commits") or []
335
+ except Exception:
336
+ return []
337
+
256
338
  filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
257
339
  # "What's Changed precisely": list each merged PR's own developer commits,
258
340
  # NOT the squashed/merge/chore commits that land on the release branch
@@ -260,8 +342,8 @@ jobs:
260
342
  _seen_commits = set()
261
343
  _commit_blocks = []
262
344
  for pr in filtered:
263
- _commit_lines = []
264
- for c in (pr.get("commits") or []):
345
+ raw_entries = []
346
+ for c in _fetch_pr_commits(pr["number"]):
265
347
  oid = (c.get("oid") or "")[:7]
266
348
  head = (c.get("messageHeadline") or "").strip()
267
349
  if not head or head.startswith("Merge "):
@@ -270,13 +352,24 @@ jobs:
270
352
  if key in _seen_commits:
271
353
  continue
272
354
  _seen_commits.add(key)
273
- _commit_lines.append(f" - `{oid}` {head}")
274
- if _commit_lines:
355
+ raw_entries.append((oid, head))
356
+ commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
357
+ if commit_lines:
275
358
  _commit_blocks.append(
276
- f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(_commit_lines)
359
+ f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
277
360
  )
278
361
  # Fall back to the raw git log only when no PR commits are available.
279
- commits_section = "\n\n".join(_commit_blocks) if _commit_blocks else commits
362
+ if _commit_blocks:
363
+ commits_section = "\n\n".join(_commit_blocks)
364
+ else:
365
+ fallback_entries = []
366
+ for line in commits_raw.splitlines():
367
+ if "\t" not in line:
368
+ continue
369
+ oid, head = line.split("\t", 1)
370
+ fallback_entries.append((oid, head))
371
+ fallback_entries = _collapse_readme(fallback_entries)
372
+ commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
280
373
  if filtered:
281
374
  prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
282
375
  seen, clabels = set(), []
@@ -289,7 +382,23 @@ jobs:
289
382
  else:
290
383
  prs_lines = "_(no pull requests found since last release)_"
291
384
  contributors = git_authors or "_(no contributors found)_"
385
+
386
+ # CLI banner (weightslab/art.py), loaded as a standalone file so we
387
+ # don't pull in the full package (and its heavy optional deps) just
388
+ # to print a logo. ANSI color codes are stripped (Markdown can't render
389
+ # them); the box-drawing/ASCII art itself renders fine in a code fence.
390
+ banner_block = ""
391
+ try:
392
+ spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
393
+ wl_art = importlib.util.module_from_spec(spec)
394
+ spec.loader.exec_module(wl_art)
395
+ plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
396
+ banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
397
+ except Exception:
398
+ pass
399
+
292
400
  body = (
401
+ banner_block +
293
402
  "## **Weightslab**\n\n"
294
403
  "Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
295
404
  " | [Graybx](https://www.graybx.com/)\n\n"
@@ -309,7 +418,7 @@ jobs:
309
418
  "### Thank you!\n\n"
310
419
  f"{contributors}\n"
311
420
  )
312
- with open("RELEASE_NOTES.md", "w") as f:
421
+ with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
313
422
  f.write(body)
314
423
  PYEOF
315
424
 
@@ -331,8 +440,7 @@ jobs:
331
440
 
332
441
  build-and-publish-main:
333
442
  name: Build & Publish Main (PyPI)
334
- needs: [detect-target,test]
335
- # needs: [detect-target]
443
+ needs: [test-install-from-pip-dev-release, detect-target]
336
444
  runs-on: ubuntu-latest
337
445
  if: ${{ needs.detect-target.outputs.is_main == 'true' }}
338
446
  permissions:
@@ -446,7 +554,7 @@ jobs:
446
554
 
447
555
  create-main-release:
448
556
  name: Create GitHub Release
449
- needs: [build-and-publish-main, test-install-from-pip-main]
557
+ needs: [test-install-from-pip-main]
450
558
  runs-on: ubuntu-latest
451
559
  permissions:
452
560
  contents: write
@@ -469,46 +577,107 @@ jobs:
469
577
  export VERSION_NO_V="${VERSION#v}"
470
578
  export PYPI_URL="https://pypi.org/project/weightslab/${VERSION_NO_V}/"
471
579
 
472
- PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${VERSION}$" | head -n 1 || true)
580
+ # Walk the actual commit graph for the nearest ancestor tag, rather
581
+ # than a lexicographic/semver sort across ALL tags. The old sort
582
+ # could pick an unrelated tag from a diverging branch — e.g. a
583
+ # "v1.3.0-dev0" tag cut on dev after "v1.3.0" was tagged on main
584
+ # sorted ABOVE it, making every real PR since v1.3.0 look "older"
585
+ # than that bogus previous-tag date and get silently filtered out
586
+ # (this is why past releases showed "no pull requests found").
587
+ PREV_TAG=$(git describe --tags --abbrev=0 "${VERSION}^" 2>/dev/null || true)
473
588
  if [ -n "$PREV_TAG" ]; then
474
- export PREV_TAG_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || echo "2020-01-01T00:00:00Z")
589
+ RAW_DATE=$(git log -1 --format="%aI" "${PREV_TAG}" 2>/dev/null || true)
590
+ # Normalize to UTC "Z" form so string comparison against GitHub's
591
+ # mergedAt (also UTC "Z") is valid regardless of the committer's
592
+ # local timezone offset.
593
+ export PREV_TAG_DATE=$(date -u -d "${RAW_DATE:-2020-01-01}" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "2020-01-01T00:00:00Z")
475
594
  export GIT_RANGE="${PREV_TAG}..HEAD"
476
595
  else
477
596
  export PREV_TAG_DATE="2020-01-01T00:00:00Z"
478
597
  export GIT_RANGE="HEAD"
479
598
  fi
480
599
 
481
- export COMMITS
482
- COMMITS=$(git log "${GIT_RANGE}" --no-merges --format="- %h %s" 2>/dev/null | head -25 || true)
483
- [ -z "$COMMITS" ] && COMMITS="_(no commits found)_"
600
+ export COMMITS_RAW
601
+ COMMITS_RAW=$(git log "${GIT_RANGE}" --no-merges --format="%h%x09%s" 2>/dev/null | head -25 || true)
484
602
 
485
603
  export GIT_AUTHORS
486
604
  GIT_AUTHORS=$(git log "${GIT_RANGE}" --format="%an" 2>/dev/null | sort -u | sed 's/^/- /' | head -30 || true)
487
605
 
606
+ # NOTE: deliberately NOT requesting --json commits here. With
607
+ # --limit 100 that expands into a GraphQL query requesting 100 PRs'
608
+ # worth of commit nodes, which reliably exceeds GitHub's 500,000
609
+ # node budget and makes `gh` print a plain-text GraphQL error
610
+ # instead of JSON — json.loads() below then fails, prs_data
611
+ # silently becomes [], and every release note says "no pull
612
+ # requests found" regardless of the date filter. Commits are
613
+ # fetched below, one lightweight call per PR, only for the small
614
+ # number of PRs that actually match this release.
488
615
  export PRS_JSON
489
616
  PRS_JSON=$(gh pr list --state merged --base "main" --limit 100 \
490
- --json number,title,mergedAt,url,author,body,commits \
617
+ --json number,title,mergedAt,url,author,body \
491
618
  2>/dev/null || echo "[]")
492
619
 
493
620
  python3 << 'PYEOF'
494
- import os, json
621
+ import os, json, re, importlib.util, subprocess
495
622
  version = os.environ["VERSION"]
496
623
  pypi_url = os.environ["PYPI_URL"]
497
624
  prev_date = os.environ.get("PREV_TAG_DATE", "2020-01-01")
498
- commits = os.environ.get("COMMITS", "_(no commits found)_")
625
+ commits_raw = os.environ.get("COMMITS_RAW", "")
499
626
  git_authors = os.environ.get("GIT_AUTHORS", "")
500
627
  try:
501
628
  prs_data = json.loads(os.environ.get("PRS_JSON", "[]"))
502
629
  except Exception:
503
630
  prs_data = []
631
+
632
+ _README_RE = re.compile(r'^update\s+readme(\.md)?\s*$', re.IGNORECASE)
633
+
634
+ def _strip_pr_suffix(head):
635
+ return re.sub(r'\s*\(#\d+\)\s*$', '', head).strip()
636
+
637
+ def _collapse_readme(entries):
638
+ """entries: list of (oid_or_None, head) tuples, in original order.
639
+ Collapse every bare "Update README[.md]" commit into a single
640
+ "Update README (n)" line at the position of its first occurrence —
641
+ these are near-duplicate housekeeping commits with no release signal."""
642
+ out, count, placeholder_idx = [], 0, None
643
+ for oid, head in entries:
644
+ if _README_RE.match(_strip_pr_suffix(head)):
645
+ count += 1
646
+ if placeholder_idx is None:
647
+ placeholder_idx = len(out)
648
+ out.append(None)
649
+ continue
650
+ out.append((oid, head))
651
+ if placeholder_idx is not None:
652
+ label = "Update README" if count == 1 else f"Update README ({count})"
653
+ out[placeholder_idx] = (None, label)
654
+ return out
655
+
656
+ def _format_entries(entries, indent=""):
657
+ return [f"{indent}- `{oid}` {head}" if oid else f"{indent}- {head}" for oid, head in entries]
658
+
504
659
  def _pr_entry(pr):
505
- line = f"- [#{pr['number']}]({pr['url']}) {pr['title']} — {pr['mergedAt'][:10]}"
506
660
  desc = " ".join((pr.get("body") or "").split()) # collapse newlines/whitespace
507
- if desc:
508
- if len(desc) > 512:
509
- desc = desc[:509].rstrip() + "..."
510
- line += f"\n\n > {desc}"
511
- return line
661
+ if not desc:
662
+ desc = pr["title"]
663
+ if len(desc) > 512:
664
+ desc = desc[:509].rstrip() + "..."
665
+ return f"- [PR #{pr['number']}]({pr['url']}): {desc}"
666
+
667
+ def _fetch_pr_commits(number):
668
+ # One lightweight call per matched PR (see the note above the
669
+ # PRS_JSON fetch for why this isn't batched into the list query).
670
+ try:
671
+ out = subprocess.run(
672
+ ["gh", "pr", "view", str(number), "--json", "commits"],
673
+ capture_output=True, text=True, timeout=30,
674
+ )
675
+ if out.returncode != 0:
676
+ return []
677
+ return json.loads(out.stdout).get("commits") or []
678
+ except Exception:
679
+ return []
680
+
512
681
  filtered = [pr for pr in prs_data if pr.get("mergedAt", "") > prev_date]
513
682
  # "What's Changed precisely": list each merged PR's own developer commits,
514
683
  # NOT the squashed/merge/chore commits that land on the release branch
@@ -516,8 +685,8 @@ jobs:
516
685
  _seen_commits = set()
517
686
  _commit_blocks = []
518
687
  for pr in filtered:
519
- _commit_lines = []
520
- for c in (pr.get("commits") or []):
688
+ raw_entries = []
689
+ for c in _fetch_pr_commits(pr["number"]):
521
690
  oid = (c.get("oid") or "")[:7]
522
691
  head = (c.get("messageHeadline") or "").strip()
523
692
  if not head or head.startswith("Merge "):
@@ -526,13 +695,24 @@ jobs:
526
695
  if key in _seen_commits:
527
696
  continue
528
697
  _seen_commits.add(key)
529
- _commit_lines.append(f" - `{oid}` {head}")
530
- if _commit_lines:
698
+ raw_entries.append((oid, head))
699
+ commit_lines = _format_entries(_collapse_readme(raw_entries), indent=" ")
700
+ if commit_lines:
531
701
  _commit_blocks.append(
532
- f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(_commit_lines)
702
+ f"**[#{pr['number']}]({pr['url']}) {pr['title']}**\n" + "\n".join(commit_lines)
533
703
  )
534
704
  # Fall back to the raw git log only when no PR commits are available.
535
- commits_section = "\n\n".join(_commit_blocks) if _commit_blocks else commits
705
+ if _commit_blocks:
706
+ commits_section = "\n\n".join(_commit_blocks)
707
+ else:
708
+ fallback_entries = []
709
+ for line in commits_raw.splitlines():
710
+ if "\t" not in line:
711
+ continue
712
+ oid, head = line.split("\t", 1)
713
+ fallback_entries.append((oid, head))
714
+ fallback_entries = _collapse_readme(fallback_entries)
715
+ commits_section = "\n".join(_format_entries(fallback_entries)) if fallback_entries else "_(no commits found)_"
536
716
  if filtered:
537
717
  prs_lines = "\n".join(_pr_entry(pr) for pr in filtered)
538
718
  seen, clabels = set(), []
@@ -545,7 +725,23 @@ jobs:
545
725
  else:
546
726
  prs_lines = "_(no pull requests found since last release)_"
547
727
  contributors = git_authors or "_(no contributors found)_"
728
+
729
+ # CLI banner (weightslab/art.py), loaded as a standalone file so we
730
+ # don't pull in the full package (and its heavy optional deps) just
731
+ # to print a logo. ANSI color codes are stripped (Markdown can't render
732
+ # them); the box-drawing/ASCII art itself renders fine in a code fence.
733
+ banner_block = ""
734
+ try:
735
+ spec = importlib.util.spec_from_file_location("wl_art", "weightslab/art.py")
736
+ wl_art = importlib.util.module_from_spec(spec)
737
+ spec.loader.exec_module(wl_art)
738
+ plain_banner = re.sub(r'\x1b\[[0-9;]*m', '', wl_art._BANNER)
739
+ banner_block = f"```text\n{plain_banner.strip(chr(10))}\n```\n\n"
740
+ except Exception:
741
+ pass
742
+
548
743
  body = (
744
+ banner_block +
549
745
  "## **Weightslab**\n\n"
550
746
  "Follow us on [LinkedIn](https://www.linkedin.com/company/graybx-com/)"
551
747
  " | [Graybx](https://www.graybx.com/)\n\n"
@@ -565,7 +761,7 @@ jobs:
565
761
  "### Thank you!\n\n"
566
762
  f"{contributors}\n"
567
763
  )
568
- with open("RELEASE_NOTES.md", "w") as f:
764
+ with open("RELEASE_NOTES.md", "w", encoding="utf-8") as f:
569
765
  f.write(body)
570
766
  PYEOF
571
767
 
@@ -0,0 +1 @@
1
+ # Changelog - 2026-07-07 v1.3.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weightslab
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: Paving the way between black-box and white-box modeling.
5
5
  Author-email: Alexandru-Andrei Rotaru <alexandru@graybx.com>, Guillaue Pelluet <guillaue@graybx.com>
6
6
  License: BSD 2-clause
@@ -32,6 +32,7 @@ Requires-Dist: grpcio<2,>=1.80
32
32
  Requires-Dist: protobuf<7,>=4.25
33
33
  Requires-Dist: pydantic<3,>=2.7
34
34
  Requires-Dist: Pillow<12,>=10
35
+ Requires-Dist: graphviz<1,>=0.20
35
36
  Requires-Dist: onnx<=1.20,>=1.15
36
37
  Requires-Dist: tqdm<5,>=4.66
37
38
  Requires-Dist: python-dotenv<2,>=1
@@ -53,7 +54,6 @@ Requires-Dist: torchaudio<3,>=2.9; python_version >= "3.13" and extra == "utest"
53
54
  Requires-Dist: torchmetrics<2,>=1.3; extra == "utest"
54
55
  Requires-Dist: pytorch-lightning<3,>=2.2; extra == "utest"
55
56
  Requires-Dist: tensorboard<3,>=2.14; extra == "utest"
56
- Requires-Dist: graphviz<1,>=0.20; extra == "utest"
57
57
  Requires-Dist: pytest>=9.0.2; extra == "utest"
58
58
  Dynamic: license-file
59
59
 
@@ -67,8 +67,8 @@ Dynamic: license-file
67
67
  </a>
68
68
  </div>
69
69
  <div align="center">
70
- <h3>PyTorch Dataset Debugger Powered by Training Signals.</h3>
71
- <p>Pause training, mine live loss signals to surface mislabels, class imbalance & outliers,<br>then curate your image, video & LiDAR data without restarting.</p>
70
+ <h3>Trace training signals back to the exact samples causing them</h3>
71
+ <p>Pause training, mine live loss signals to surface mislabels, class imbalance & outliers,<br>then curate your image, video & LiDAR data, without restarting.</p>
72
72
  </div>
73
73
 
74
74
  </div>
@@ -81,11 +81,16 @@ Dynamic: license-file
81
81
 
82
82
  ## What it does
83
83
 
84
- WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets: images, video & LiDAR point clouds.
84
+ WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets: images, video & LiDAR point clouds.
85
+ Longer-term, we're building toward bringing dataset management, training, fine-tuning, and validation together in a single, unified workflow.
85
86
 
86
87
  <br>
87
-
88
- Most data problems are invisible until your model tells you: through loss spikes, poor generalization, or silent underperformance. WeightsLab connects those training signals back to the exact samples causing them
88
+ <div align="center">
89
+ <img src="https://github.com/GrayboxTech/assets/blob/main/GIF/weightslab_demo_bdd.gif" width="1280" alt="WeightsLab Studio demo" />
90
+ <!-- <sub><a href="https://youtu.be/GBBDDaJQLWk">▶ Watch full demo</a></sub> -->
91
+ </div>
92
+ <br>
93
+ Most data problems are invisible until your model tells you: through loss spikes, poor generalization, or silent underperformance. WeightsLab connects those training signals back to the exact samples causing them.
89
94
 
90
95
  **Wrap your training script with the SDK** to capture per-sample signals live.
91
96
  **Open Studio** to inspect, filter, and curate your dataset mid-training, without restarting.
@@ -93,20 +98,12 @@ Most data problems are invisible until your model tells you: through loss spikes
93
98
  - **Detect** - Surface mislabels, outliers & class imbalance using live loss signals
94
99
  - **Curate** - Discard bad samples, create data subsets, rebalance distributions
95
100
  - **Continue** - Resume training on your cleaned dataset, no restart required
96
-
97
- WeightsLab is an open-source PyTorch tool for dataset debugging, data quality monitoring, mislabel detection, and mid-training data curation for computer vision datasets (images, video & LiDAR point clouds).
98
-
99
- <br>
100
-
101
- → `give it a star ⭐` and join our [`early access ⏰`](https://grayboxtech.github.io/signup/)
102
-
103
101
  <br>
104
102
 
105
103
  ## Quickstart
106
104
 
107
105
  ![Python](https://img.shields.io/badge/Python-3.10--3.14-5865F2?style=flat&logo=python&logoColor=white)
108
106
  ![Docker Desktop](https://img.shields.io/badge/Docker_Desktop-v4-0db7ed?style=flat&logo=docker&logoColor=white)
109
- ![Docker Compose](https://img.shields.io/badge/Docker_Compose-v2-0db7ed?style=flat&logo=docker&logoColor=white)
110
107
 
111
108
  **1. Install**
112
109
  ```bash
@@ -162,8 +159,8 @@ For a detailed installation guide and advanced configuration &rarr; [Installatio
162
159
 
163
160
  2. **Wrap your parameters, model, optimizer, signals, and dataset:**
164
161
  ```python
165
- parameters = wl.watch_or_edit(parameters, flag='hp', ...) # ← WeightsLab monitors your parameters and lets you update them from the UI
166
- model = wl.watch_or_edit(parameters, flag='hp', ...) # ← WeightsLab monitors your model state
162
+ parameters = wl.watch_or_edit(parameters, flag='hp', ...) # ← WeightsLab monitors your parameters and lets you update them from the UI
163
+ model = wl.watch_or_edit(model, flag='model', ...) # ← WeightsLab monitors your model state
167
164
  optimizer = wl.watch_or_edit(optim.Adam(...), flag='opt', ...) # ← Tracks optimizer state and lets you update the learning rate from the UI
168
165
 
169
166
  train_criterion = wl.watch_or_edit(nn.CrossEntropyLoss(reduction="none"), flag='signal', name="train_loss/sample", per_sample=True, log=True) # ← Wrap and plot your signals on the UI
@@ -257,7 +254,7 @@ def main():
257
254
  # instance_id=[1, 2],
258
255
  )
259
256
 
260
- avg_loss = total_loss / len(dataloader)
257
+ avg_loss = total_loss / len(loader)
261
258
  print(f"Epoch {epoch+1}/5 - Loss: {avg_loss:.4f}")
262
259
 
263
260
  print("✅ Training complete!")