flowcept 0.9.2__tar.gz → 0.9.3__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 (207) hide show
  1. {flowcept-0.9.2 → flowcept-0.9.3}/PKG-INFO +1 -1
  2. {flowcept-0.9.2 → flowcept-0.9.3}/docs/prov_capture.rst +4 -0
  3. flowcept-0.9.3/examples/convergence_loop_example.py +44 -0
  4. flowcept-0.9.3/examples/instrumented_loop_example.py +77 -0
  5. flowcept-0.9.3/examples/mqtt_example.py +101 -0
  6. {flowcept-0.9.2 → flowcept-0.9.3}/resources/sample_settings.yaml +1 -1
  7. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/flowcept_ctx_manager.py +10 -6
  8. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/gui/gui_utils.py +52 -1
  9. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/prompts/in_memory_query_prompts.py +36 -17
  10. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/tools/general_tools.py +1 -1
  11. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/tools/in_memory_queries/in_memory_queries_tools.py +19 -3
  12. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/task_data_preprocess.py +8 -2
  13. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/version.py +1 -1
  14. flowcept-0.9.2/examples/instrumented_loop_example.py +0 -19
  15. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/checks.yml +0 -0
  16. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/create-release-n-publish.yml +0 -0
  17. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-llm-tests.yml +0 -0
  18. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests-all-dbs.yml +0 -0
  19. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests-in-container.yml +0 -0
  20. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests-kafka.yml +0 -0
  21. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests-py313.yml +0 -0
  22. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests-simple.yml +0 -0
  23. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run-tests.yml +0 -0
  24. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/run_examples.sh +0 -0
  25. {flowcept-0.9.2 → flowcept-0.9.3}/.github/workflows/version_bumper.py +0 -0
  26. {flowcept-0.9.2 → flowcept-0.9.3}/.gitignore +0 -0
  27. {flowcept-0.9.2 → flowcept-0.9.3}/.readthedocs.yaml +0 -0
  28. {flowcept-0.9.2 → flowcept-0.9.3}/CONTRIBUTING.md +0 -0
  29. {flowcept-0.9.2 → flowcept-0.9.3}/LICENSE +0 -0
  30. {flowcept-0.9.2 → flowcept-0.9.3}/Makefile +0 -0
  31. {flowcept-0.9.2 → flowcept-0.9.3}/README.md +0 -0
  32. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/Dockerfile +0 -0
  33. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/compose-grafana.yml +0 -0
  34. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/compose-kafka.yml +0 -0
  35. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/compose-mofka.yml +0 -0
  36. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/compose-mongo.yml +0 -0
  37. {flowcept-0.9.2 → flowcept-0.9.3}/deployment/compose.yml +0 -0
  38. {flowcept-0.9.2 → flowcept-0.9.3}/docs/api-reference.rst +0 -0
  39. {flowcept-0.9.2 → flowcept-0.9.3}/docs/architecture.rst +0 -0
  40. {flowcept-0.9.2 → flowcept-0.9.3}/docs/cli-reference.rst +0 -0
  41. {flowcept-0.9.2 → flowcept-0.9.3}/docs/conf.py +0 -0
  42. {flowcept-0.9.2 → flowcept-0.9.3}/docs/contributing.rst +0 -0
  43. {flowcept-0.9.2 → flowcept-0.9.3}/docs/img/architecture-diagram.png +0 -0
  44. {flowcept-0.9.2 → flowcept-0.9.3}/docs/img/flowcept-logo-dark.png +0 -0
  45. {flowcept-0.9.2 → flowcept-0.9.3}/docs/img/flowcept-logo.png +0 -0
  46. {flowcept-0.9.2 → flowcept-0.9.3}/docs/index.rst +0 -0
  47. {flowcept-0.9.2 → flowcept-0.9.3}/docs/prov_storage.rst +0 -0
  48. {flowcept-0.9.2 → flowcept-0.9.3}/docs/quick_start.rst +0 -0
  49. {flowcept-0.9.2 → flowcept-0.9.3}/docs/schemas.rst +0 -0
  50. {flowcept-0.9.2 → flowcept-0.9.3}/docs/setup.rst +0 -0
  51. {flowcept-0.9.2 → flowcept-0.9.3}/docs/task_schema.rst +0 -0
  52. {flowcept-0.9.2 → flowcept-0.9.3}/docs/telemetry_capture.rst +0 -0
  53. {flowcept-0.9.2 → flowcept-0.9.3}/docs/workflow_schema.rst +0 -0
  54. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/a2a/README.md +0 -0
  55. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/a2a/agent1.py +0 -0
  56. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/a2a/agent2.py +0 -0
  57. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/aec_agent_context_manager.py +0 -0
  58. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/aec_agent_mock.py +0 -0
  59. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/aec_prompts.py +0 -0
  60. {flowcept-0.9.2 → flowcept-0.9.3}/examples/agents/opt_driver_mock.py +0 -0
  61. {flowcept-0.9.2 → flowcept-0.9.3}/examples/consumers/ping_pong_example.py +0 -0
  62. {flowcept-0.9.2 → flowcept-0.9.3}/examples/consumers/simple_consumer.py +0 -0
  63. {flowcept-0.9.2 → flowcept-0.9.3}/examples/consumers/simple_publisher.py +0 -0
  64. {flowcept-0.9.2 → flowcept-0.9.3}/examples/dask_example.py +0 -0
  65. {flowcept-0.9.2 → flowcept-0.9.3}/examples/distributed_consumer_example.py +0 -0
  66. {flowcept-0.9.2 → flowcept-0.9.3}/examples/instrumented_simple_example.py +0 -0
  67. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/README.md +0 -0
  68. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/custom_provenance_id_mapping.yaml +0 -0
  69. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/llm_dataprep.py +0 -0
  70. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/llm_main_example.py +0 -0
  71. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/llm_model.py +0 -0
  72. {flowcept-0.9.2 → flowcept-0.9.3}/examples/llm_complex/llm_test_runner.py +0 -0
  73. {flowcept-0.9.2 → flowcept-0.9.3}/examples/mlflow_example.py +0 -0
  74. {flowcept-0.9.2 → flowcept-0.9.3}/examples/single_layer_perceptron_example.py +0 -0
  75. {flowcept-0.9.2 → flowcept-0.9.3}/examples/start_here.py +0 -0
  76. {flowcept-0.9.2 → flowcept-0.9.3}/examples/tensorboard_example.py +0 -0
  77. {flowcept-0.9.2 → flowcept-0.9.3}/examples/unmanaged/main.py +0 -0
  78. {flowcept-0.9.2 → flowcept-0.9.3}/examples/unmanaged/simple_task.py +0 -0
  79. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/analytics.ipynb +0 -0
  80. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/dask.ipynb +0 -0
  81. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/dask_from_CLI.ipynb +0 -0
  82. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/mlflow.ipynb +0 -0
  83. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/reset_dask_nb_exec_counts.py +0 -0
  84. {flowcept-0.9.2 → flowcept-0.9.3}/notebooks/tensorboard.ipynb +0 -0
  85. {flowcept-0.9.2 → flowcept-0.9.3}/pyproject.toml +0 -0
  86. {flowcept-0.9.2 → flowcept-0.9.3}/resources/mofka/bedrock_setup.sh +0 -0
  87. {flowcept-0.9.2 → flowcept-0.9.3}/resources/mofka/consumer.py +0 -0
  88. {flowcept-0.9.2 → flowcept-0.9.3}/resources/mofka/mofka-requirements.yaml +0 -0
  89. {flowcept-0.9.2 → flowcept-0.9.3}/resources/mofka/mofka_config.json +0 -0
  90. {flowcept-0.9.2 → flowcept-0.9.3}/resources/simple_redis_consumer.py +0 -0
  91. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/__init__.py +0 -0
  92. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/__init__.py +0 -0
  93. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/agent_client.py +0 -0
  94. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/agents_utils.py +0 -0
  95. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/dynamic_schema_tracker.py +0 -0
  96. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/flowcept_agent.py +0 -0
  97. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/gui/__init__.py +0 -0
  98. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/gui/agent_gui.py +0 -0
  99. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/llms/__init__.py +0 -0
  100. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/llms/claude_gcp.py +0 -0
  101. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/llms/gemini25.py +0 -0
  102. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/prompts/__init__.py +0 -0
  103. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/prompts/general_prompts.py +0 -0
  104. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/tools/__init__.py +0 -0
  105. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/tools/in_memory_queries/__init__.py +0 -0
  106. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/agents/tools/in_memory_queries/pandas_agent_utils.py +0 -0
  107. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/analytics/__init__.py +0 -0
  108. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/analytics/analytics_utils.py +0 -0
  109. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/analytics/data_augmentation.py +0 -0
  110. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/analytics/plot.py +0 -0
  111. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/cli.py +0 -0
  112. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/__init__.py +0 -0
  113. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/autoflush_buffer.py +0 -0
  114. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/__init__.py +0 -0
  115. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/docdb_dao/__init__.py +0 -0
  116. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/docdb_dao/docdb_dao_base.py +0 -0
  117. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/docdb_dao/lmdb_dao.py +0 -0
  118. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/docdb_dao/mongodb_dao.py +0 -0
  119. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/keyvalue_dao.py +0 -0
  120. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/mq_dao/__init__.py +0 -0
  121. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/mq_dao/mq_dao_base.py +0 -0
  122. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/mq_dao/mq_dao_kafka.py +0 -0
  123. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/mq_dao/mq_dao_mofka.py +0 -0
  124. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/mq_dao/mq_dao_redis.py +0 -0
  125. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/daos/redis_conn.py +0 -0
  126. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_dataclasses/__init__.py +0 -0
  127. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_dataclasses/base_settings_dataclasses.py +0 -0
  128. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_dataclasses/task_object.py +0 -0
  129. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_dataclasses/telemetry.py +0 -0
  130. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_dataclasses/workflow_object.py +0 -0
  131. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/flowcept_logger.py +0 -0
  132. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/query_utils.py +0 -0
  133. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/settings_factory.py +0 -0
  134. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/utils.py +0 -0
  135. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/commons/vocabulary.py +0 -0
  136. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/configs.py +0 -0
  137. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_api/__init__.py +0 -0
  138. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_api/db_api.py +0 -0
  139. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_api/flowcept_controller.py +0 -0
  140. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_api/task_query_api.py +0 -0
  141. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_webserver/__init__.py +0 -0
  142. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_webserver/app.py +0 -0
  143. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_webserver/resources/__init__.py +0 -0
  144. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_webserver/resources/query_rsrc.py +0 -0
  145. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowcept_webserver/resources/task_messages_rsrc.py +0 -0
  146. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/__init__.py +0 -0
  147. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/__init__.py +0 -0
  148. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/base_interceptor.py +0 -0
  149. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/brokers/__init__.py +0 -0
  150. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/brokers/mqtt_interceptor.py +0 -0
  151. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/dask/__init__.py +0 -0
  152. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/dask/dask_dataclasses.py +0 -0
  153. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/dask/dask_interceptor.py +0 -0
  154. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/dask/dask_plugins.py +0 -0
  155. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/instrumentation_interceptor.py +0 -0
  156. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/interceptor_state_manager.py +0 -0
  157. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/mlflow/__init__.py +0 -0
  158. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/mlflow/interception_event_handler.py +0 -0
  159. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/mlflow/mlflow_dao.py +0 -0
  160. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/mlflow/mlflow_dataclasses.py +0 -0
  161. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/mlflow/mlflow_interceptor.py +0 -0
  162. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/tensorboard/__init__.py +0 -0
  163. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/tensorboard/tensorboard_dataclasses.py +0 -0
  164. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/adapters/tensorboard/tensorboard_interceptor.py +0 -0
  165. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/__init__.py +0 -0
  166. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/agent/__init__.py +0 -0
  167. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/agent/base_agent_context_manager.py +0 -0
  168. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/base_consumer.py +0 -0
  169. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/consumer_utils.py +0 -0
  170. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/consumers/document_inserter.py +0 -0
  171. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/flowceptor/telemetry_capture.py +0 -0
  172. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/__init__.py +0 -0
  173. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/flowcept_agent_task.py +0 -0
  174. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/flowcept_decorator.py +0 -0
  175. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/flowcept_loop.py +0 -0
  176. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/flowcept_task.py +0 -0
  177. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/flowcept_torch.py +0 -0
  178. {flowcept-0.9.2 → flowcept-0.9.3}/src/flowcept/instrumentation/task_capture.py +0 -0
  179. {flowcept-0.9.2 → flowcept-0.9.3}/tests/__init__.py +0 -0
  180. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/__init__.py +0 -0
  181. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/dask_test_utils.py +0 -0
  182. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_broker.py +0 -0
  183. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_dask.py +0 -0
  184. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_dask_with_context_mgmt.py +0 -0
  185. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_file_observer.py +0 -0
  186. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_mlflow.py +0 -0
  187. {flowcept-0.9.2 → flowcept-0.9.3}/tests/adapters/test_tensorboard.py +0 -0
  188. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/__init__.py +0 -0
  189. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/db_api_test.py +0 -0
  190. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/flowcept_api_test.py +0 -0
  191. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/sample_data.json +0 -0
  192. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/sample_data_with_telemetry_and_rai.json +0 -0
  193. {flowcept-0.9.2 → flowcept-0.9.3}/tests/api/task_query_api_test.py +0 -0
  194. {flowcept-0.9.2 → flowcept-0.9.3}/tests/doc_db_inserter/__init__.py +0 -0
  195. {flowcept-0.9.2 → flowcept-0.9.3}/tests/doc_db_inserter/doc_db_inserter_test.py +0 -0
  196. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/__init__.py +0 -0
  197. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/flowcept_explicit_tasks.py +0 -0
  198. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/flowcept_loop_test.py +0 -0
  199. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/flowcept_task_decorator_test.py +0 -0
  200. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/ml_tests/__init__.py +0 -0
  201. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/ml_tests/dl_trainer.py +0 -0
  202. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/ml_tests/ml_decorator_dask_test.py +0 -0
  203. {flowcept-0.9.2 → flowcept-0.9.3}/tests/instrumentation_tests/ml_tests/ml_decorator_test.py +0 -0
  204. {flowcept-0.9.2 → flowcept-0.9.3}/tests/misc_tests/__init__.py +0 -0
  205. {flowcept-0.9.2 → flowcept-0.9.3}/tests/misc_tests/log_test.py +0 -0
  206. {flowcept-0.9.2 → flowcept-0.9.3}/tests/misc_tests/singleton_test.py +0 -0
  207. {flowcept-0.9.2 → flowcept-0.9.3}/tests/misc_tests/telemetry_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowcept
3
- Version: 0.9.2
3
+ Version: 0.9.3
4
4
  Summary: Capture and query workflow provenance data using data observability
5
5
  Author: Oak Ridge National Laboratory
6
6
  License-Expression: MIT
@@ -25,6 +25,10 @@ Decorators
25
25
  --------------------------
26
26
 
27
27
  Use decorators to mark functions as **workflows** or **tasks** with almost no code changes.
28
+ If using the decorators, we expect that `instrumentation` is enabled in your settings file.
29
+ If it is not, the provenance capture will be simply ignored and the decorated function
30
+ will run as if without any Flowcept instrumentation.
31
+
28
32
 
29
33
  ``@flowcept`` (wrap a “main” function as a workflow)
30
34
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -0,0 +1,44 @@
1
+ from flowcept import Flowcept, FlowceptLoop
2
+
3
+ THRESHOLD = 0.05
4
+ MAX_ITERS = 50
5
+
6
+
7
+ def update_error(e: float) -> float:
8
+ """Dummy update rule that shrinks error each step."""
9
+ return e * 0.7 # replace with your real update
10
+
11
+
12
+ def finalize_loop(loop):
13
+ """Flush the last iteration so it’s captured even if we break early."""
14
+ if getattr(loop, "enabled", False) and getattr(loop, "_last_iteration_task", None) is not None:
15
+ try:
16
+ loop._end_iteration_task(loop._last_iteration_task) # uses FlowceptLoop internals
17
+ except Exception:
18
+ pass
19
+
20
+
21
+ # --- Convergence with FlowceptLoop ---
22
+ error = 1.0
23
+ loop = FlowceptLoop(
24
+ items=range(MAX_ITERS), # upper bound; we’ll break early on convergence
25
+ loop_name="convergence",
26
+ item_name="iter",
27
+ )
28
+
29
+ for it in loop:
30
+ # --- your loop body ---
31
+ error = update_error(error)
32
+ print(f"iter={it} error={error:.4f}")
33
+
34
+ # Record per-iteration outputs (only once per iteration)
35
+ loop.end_iter({
36
+ "iter": it,
37
+ "error": error,
38
+ "status": "converged" if error <= THRESHOLD else "continuing",
39
+ })
40
+
41
+ # Convergence check — emulate: while error > THRESHOLD: update error
42
+ if error <= THRESHOLD:
43
+ finalize_loop(loop) # ensure the last iteration is closed before breaking
44
+ break
@@ -0,0 +1,77 @@
1
+ import random
2
+ from time import sleep
3
+
4
+ from flowcept import Flowcept, FlowceptLoop
5
+
6
+ # EXAMPLE 1:
7
+
8
+
9
+ iterations = range(1, 5)
10
+
11
+ with Flowcept():
12
+
13
+ loop = FlowceptLoop(iterations) # See also: FlowceptLightweightLoop
14
+ for item in loop:
15
+ loss = random.random()
16
+ sleep(0.05)
17
+ print(item, loss)
18
+ # The following is optional, in case you want to capture values generated inside the loop.
19
+ loop.end_iter({"item": item, "loss": loss})
20
+
21
+ docs = Flowcept.db.get_tasks_from_current_workflow()
22
+ assert len(docs) == len(iterations)
23
+
24
+
25
+ # EXAMPLE 2: WHILE LOOP EXAMPLE
26
+ # The following code is equivalent to:
27
+ # while layer_for_control_update <= num_layers - 1:
28
+ # ... loop code ...
29
+ # layer_for_control_update += 1
30
+
31
+ layer_for_control_update = 2
32
+ num_layers = 6
33
+
34
+
35
+ def do_work(layer_ix: int) -> dict:
36
+ """Dummy per-iteration work that returns something to log."""
37
+ # simulate some computation
38
+ value = layer_ix * 10
39
+ return {"value": value}
40
+
41
+
42
+ # Wrap the loop with FlowceptLoop
43
+ iterations = range(layer_for_control_update, num_layers)
44
+
45
+ # You can create with_flowcept flags
46
+ with_flowcept = True
47
+
48
+ if with_flowcept:
49
+ loop = FlowceptLoop(
50
+ items=iterations,
51
+ loop_name="control_loop",
52
+ item_name="layer_ix",
53
+ # parent_task_id="optional-parent-id",
54
+ # workflow_id="optional-workflow-id",
55
+ )
56
+ iterations = loop
57
+
58
+
59
+ for layer_ix in iterations:
60
+ # Your loop body
61
+ result = do_work(layer_ix)
62
+ print(f"Processed layer {layer_ix}, result={result}")
63
+
64
+ if with_flowcept:
65
+ # Record per-iteration outputs
66
+ iterations.end_iter({
67
+ "layer_ix": layer_ix,
68
+ "status": "updated",
69
+ **result, # attach any metrics you computed
70
+ })
71
+
72
+ if with_flowcept:
73
+ docs = Flowcept.db.get_tasks_from_current_workflow()
74
+ assert len(docs) == len(iterations)
75
+
76
+
77
+ # EXAMPLE 3: WHILE LOOP EXAMPLE
@@ -0,0 +1,101 @@
1
+ # broker_minimal_example.py
2
+ import json
3
+ import time
4
+ import uuid
5
+ import paho.mqtt.client as mqtt
6
+
7
+ from flowcept import Flowcept
8
+ from flowcept.configs import settings
9
+
10
+
11
+ def configure_flowcept_for_mqtt():
12
+ """
13
+ Mirror your settings.yaml exactly under adapters.broker_mqtt so the
14
+ MQTTBrokerInterceptor picks it up via self.settings.
15
+ """
16
+ settings.setdefault("adapters", {})
17
+ settings["adapters"]["broker_mqtt"] = {
18
+ "kind": "broker",
19
+ "host": "localhost",
20
+ "port": 30011,
21
+ "protocol": "mqtt3.1.1",
22
+ "queues": ["#"],
23
+ "username": "postman",
24
+ "password": "p",
25
+ "qos": 2,
26
+ "task_subtype": "intersect_msg",
27
+ "tracked_keys": {
28
+ "used": "payload",
29
+ "generated": None, # ~ in YAML
30
+ "custom_metadata": ["headers", "msgId"],
31
+ "activity_id": "operationId",
32
+ "submitted_at": None,
33
+ "started_at": None,
34
+ "ended_at": None,
35
+ "registered_at": None,
36
+ },
37
+ }
38
+
39
+
40
+ def publish_one_message(
41
+ host="localhost",
42
+ port=30011,
43
+ username="postman",
44
+ password="p",
45
+ topic="flowcept/demo/test",
46
+ ):
47
+ """
48
+ Publish a single JSON payload with the fields your tracked_keys expect:
49
+ - payload -> mapped to Task.used
50
+ - headers, msgId -> copied into Task.custom_metadata
51
+ - operationId -> mapped to Task.activity_id
52
+ """
53
+ client = mqtt.Client(protocol=mqtt.MQTTv311)
54
+ client.username_pw_set(username, password)
55
+ client.connect(host, port, keepalive=60)
56
+
57
+ payload = {
58
+ "payload": {"greeting": "hello from mqtt"}, # becomes Task.used
59
+ "headers": {"x-source": "unit-test", "x-env": "local"},
60
+ "msgId": str(uuid.uuid4()),
61
+ "operationId": "op-xyz-123", # becomes Task.activity_id
62
+ # optional extras also okay
63
+ "status": "FINISHED",
64
+ }
65
+
66
+ client.publish(topic, json.dumps(payload), qos=2, retain=False)
67
+ client.disconnect()
68
+ return payload
69
+
70
+
71
+ def main():
72
+ # 1) Apply settings that match your YAML
73
+ configure_flowcept_for_mqtt()
74
+
75
+ # 2) Start Flowcept in context for the broker_mqtt adapter
76
+ with Flowcept("broker_mqtt"):
77
+ # 3) Start the interceptor (runs MQTT loop in a background thread)
78
+ # Give it a moment to connect/subscribe to "#"
79
+ time.sleep(1.0)
80
+
81
+ # 4) Publish one message
82
+ sent = publish_one_message()
83
+ print("Published:", sent)
84
+
85
+ # 5) Allow time for ingest
86
+ time.sleep(2.0)
87
+
88
+ # 6) (Optional) Query Flowcept DB for the ingested task
89
+ try:
90
+ # Query by nested field in used (payload.greeting)
91
+ tasks = Flowcept.db.query(filter={"used.greeting": "hello from mqtt"})
92
+ if tasks:
93
+ print("Ingested task example:\n", json.dumps(tasks[0], indent=2))
94
+ else:
95
+ print("No tasks found for filter used.greeting == 'hello from mqtt'")
96
+ except Exception as e:
97
+ print(f"DB query failed/skipped: {e}")
98
+
99
+
100
+ if __name__ == "__main__":
101
+ main()
@@ -1,4 +1,4 @@
1
- flowcept_version: 0.9.2 # Version of the Flowcept package. This setting file is compatible with this version.
1
+ flowcept_version: 0.9.3 # Version of the Flowcept package. This setting file is compatible with this version.
2
2
 
3
3
  project:
4
4
  debug: true # Toggle debug mode. This will add a property `debug: true` to all saved data, making it easier to retrieve/delete them later.
@@ -53,7 +53,7 @@ class FlowceptAgentContextManager(BaseAgentContextManager):
53
53
  Current application context holding task state and QA components.
54
54
  msgs_counter : int
55
55
  Counter tracking how many task messages have been processed.
56
- context_size : int
56
+ context_chunk_size : int
57
57
  Number of task messages to collect before triggering QA index building and LLM analysis.
58
58
  qa_manager : FlowceptQAManager
59
59
  Utility for constructing QA chains from task summaries.
@@ -64,7 +64,7 @@ class FlowceptAgentContextManager(BaseAgentContextManager):
64
64
  self.tracker_config = dict(max_examples=3, max_str_len=50)
65
65
  self.schema_tracker = DynamicSchemaTracker(**self.tracker_config)
66
66
  self.msgs_counter = 0
67
- self.context_size = 1
67
+ self.context_chunk_size = 1 # Should be in the settings
68
68
  super().__init__()
69
69
 
70
70
  def message_handler(self, msg_obj: Dict):
@@ -98,18 +98,22 @@ class FlowceptAgentContextManager(BaseAgentContextManager):
98
98
  if len(task_summary.get("tags", [])):
99
99
  self.context.critical_tasks.append(task_summary)
100
100
 
101
- if self.msgs_counter > 0 and self.msgs_counter % self.context_size == 0:
101
+ if self.msgs_counter > 0 and self.msgs_counter % self.context_chunk_size == 0:
102
102
  self.logger.debug(
103
- f"Going to add to index! {(self.msgs_counter - self.context_size, self.msgs_counter)}"
103
+ f"Going to add to index! {(self.msgs_counter - self.context_chunk_size, self.msgs_counter)}"
104
104
  )
105
105
  try:
106
106
  self.update_schema_and_add_to_df(
107
- tasks=self.context.task_summaries[self.msgs_counter - self.context_size : self.msgs_counter]
107
+ tasks=self.context.task_summaries[
108
+ self.msgs_counter - self.context_chunk_size : self.msgs_counter
109
+ ]
108
110
  )
109
111
  except Exception as e:
110
112
  self.logger.error(
111
113
  f"Could not add these tasks to buffer!\n"
112
- f"{self.context.task_summaries[self.msgs_counter - self.context_size : self.msgs_counter]}"
114
+ f"{
115
+ self.context.task_summaries[self.msgs_counter - self.context_chunk_size : self.msgs_counter]
116
+ }"
113
117
  )
114
118
  self.logger.exception(e)
115
119
 
@@ -1,3 +1,5 @@
1
+ import base64
2
+ import ast
1
3
  import io
2
4
  import json
3
5
 
@@ -122,6 +124,53 @@ def display_ai_msg_from_tool(tool_result: ToolResult):
122
124
  return agent_reply
123
125
 
124
126
 
127
+ def _sniff_mime(b: bytes) -> str:
128
+ if b.startswith(b"\x89PNG\r\n\x1a\n"):
129
+ return "image/png"
130
+ if b.startswith(b"\xff\xd8\xff"):
131
+ return "image/jpeg"
132
+ if b.startswith(b"GIF87a") or b.startswith(b"GIF89a"):
133
+ return "image/gif"
134
+ if b.startswith(b"BM"):
135
+ return "image/bmp"
136
+ if b.startswith(b"RIFF") and b[8:12] == b"WEBP":
137
+ return "image/webp"
138
+ return "application/octet-stream"
139
+
140
+
141
+ def ensure_data_uri(val):
142
+ r"""Accepts bytes/bytearray/memoryview or a repr like \"b'\\x89PNG...'\" and returns a data URL."""
143
+ if isinstance(val, str) and val.startswith("data:"):
144
+ return val
145
+ if isinstance(val, str) and val.startswith("b'"):
146
+ try:
147
+ val = ast.literal_eval(val) # turn repr into bytes
148
+ except Exception:
149
+ return None
150
+ if isinstance(val, memoryview):
151
+ val = val.tobytes()
152
+ if isinstance(val, bytearray):
153
+ val = bytes(val)
154
+ if isinstance(val, bytes):
155
+ mime = _sniff_mime(val)
156
+ return f"data:{mime};base64,{base64.b64encode(val).decode('ascii')}"
157
+ return val # path/URL, etc.
158
+
159
+
160
+ def _render_df(df: pd.DataFrame, image_width: int = 90, row_height: int = 90):
161
+ if "image" in df.columns:
162
+ df = df.copy()
163
+ df["image"] = df["image"].apply(ensure_data_uri)
164
+ st.dataframe(
165
+ df,
166
+ column_config={"image": st.column_config.ImageColumn("Preview", width=image_width)},
167
+ hide_index=True,
168
+ row_height=row_height, # make thumbnails visible
169
+ )
170
+ else:
171
+ st.dataframe(df, hide_index=True)
172
+
173
+
125
174
  def display_df_tool_response(tool_result: ToolResult):
126
175
  r"""
127
176
  Display the DataFrame contained in a ToolResult.
@@ -170,7 +219,8 @@ def display_df_tool_response(tool_result: ToolResult):
170
219
  df = pd.read_csv(io.StringIO(result_df_str))
171
220
  print("The result is a df")
172
221
  if not df.empty:
173
- st.dataframe(df, hide_index=False)
222
+ _render_df(df)
223
+
174
224
  print("Columns", str(df.columns))
175
225
  print("Number of columns", len(df.columns))
176
226
  else:
@@ -190,6 +240,7 @@ def display_df_tool_response(tool_result: ToolResult):
190
240
 
191
241
  if summary:
192
242
  st.markdown("📝 Summary:")
243
+ print(f"THIS IS THE SUMMARY\n{summary}")
193
244
  st.markdown(summary)
194
245
  elif summary_error:
195
246
  st.markdown(f"⚠️ Encountered this error when summarizing the result dataframe:\n```text\n{summary_error}")
@@ -15,6 +15,7 @@ COMMON_TASK_FIELDS = """
15
15
  | `ended_at` | datetime64[ns, UTC] | End time of a task. |
16
16
  | `subtype` | string | Subtype of a task. |
17
17
  | `tags` | List[str] | List of descriptive tags. |
18
+ | `image` | blob | Raw binary data related to an image. |
18
19
  | `telemetry_summary.duration_sec` | float | Task duration (seconds). |
19
20
  | `telemetry_summary.cpu.percent_all_diff` | float | Difference in overall CPU utilization percentage across all cores between task end and start.|
20
21
  | `telemetry_summary.cpu.user_time_diff` | float | Difference average per core CPU user time ( seconds ) between task start and end times.|
@@ -27,6 +28,17 @@ COMMON_TASK_FIELDS = """
27
28
  DF_FORM = "The user has a pandas DataFrame called `df`, created from flattened task objects using `pd.json_normalize`."
28
29
 
29
30
 
31
+ def get_example_values_prompt(example_values):
32
+ values_prompt = f"""
33
+ Now, this other dictionary below provides type (t), up to 3 example values (v), and, for lists, shape (s) and element type (et) for each field.
34
+ Field names do not include `used.` or `generated.` They represent the unprefixed form shared across roles. String values may be truncated if they exceed the length limit.
35
+ ```python
36
+ {example_values}
37
+ ```
38
+ """
39
+ return values_prompt
40
+
41
+
30
42
  def get_df_schema_prompt(dynamic_schema, example_values):
31
43
  schema_prompt = f"""
32
44
  ## DATAFRAME STRUCTURE
@@ -52,14 +64,7 @@ def get_df_schema_prompt(dynamic_schema, example_values):
52
64
  ---
53
65
  """
54
66
 
55
- values_prompt = f"""
56
- Now, this other dictionary below provides type (t), up to 3 example values (v), and, for lists, shape (s) and element type (et) for each field.
57
- Field names do not include `used.` or `generated.` They represent the unprefixed form shared across roles. String values may be truncated if they exceed the length limit.
58
- ```python
59
- {example_values}
60
- ```
61
- """
62
-
67
+ values_prompt = get_example_values_prompt(example_values)
63
68
  # values_prompt = ""
64
69
  prompt = schema_prompt + values_prompt
65
70
  return prompt
@@ -221,7 +226,7 @@ def generate_pandas_code_prompt(query: str, dynamic_schema, example_values):
221
226
  f"{JOB}"
222
227
  f"{DF_FORM}"
223
228
  f"{get_df_schema_prompt(dynamic_schema, example_values)}" # main tester
224
- # f"{QUERY_GUIDELINES}" # main tester
229
+ f"{QUERY_GUIDELINES}" # main tester
225
230
  f"{FEW_SHOTS}" # main tester
226
231
  f"{OUTPUT_FORMATTING}"
227
232
  "User Query:"
@@ -230,9 +235,16 @@ def generate_pandas_code_prompt(query: str, dynamic_schema, example_values):
230
235
  return prompt
231
236
 
232
237
 
233
- def dataframe_summarizer_context(code, reduced_df, query) -> str:
238
+ def dataframe_summarizer_context(code, reduced_df, dynamic_schema, example_values, query) -> str:
239
+ job = "You are a Workflow Provenance Specialist analyzing a DataFrame that was obtained to answer a query."
240
+
241
+ if "image" in reduced_df.columns:
242
+ reduced_df = reduced_df.drop(columns=["image"])
243
+
234
244
  prompt = f"""
235
- You are a Workflow Provenance Specialist analyzing a DataFrame that was obtained to answer a query. Given:
245
+ {job}
246
+
247
+ Given:
236
248
 
237
249
  **User Query**:
238
250
  {query}
@@ -240,19 +252,26 @@ def dataframe_summarizer_context(code, reduced_df, query) -> str:
240
252
  **Query_Code**:
241
253
  {code}
242
254
 
243
- **Reduced DataFrame** (rows sampled from full result):
255
+ **Reduced DataFrame `df` contents** (rows sampled from full result):
244
256
  {reduced_df}
245
257
 
246
- Your task is to:
247
- 1. Analyze the DataFrame values and columns for any meaningful or notable information.
248
- 2. Compare the query_code with the data content to understand what the result represents. THIS IS A REDUCED DATAFRAME, the original dataframe, used to answer the query, may be much bigger. IT IS ALREADY KNOWN! Do not need to restate this.
249
- 3. Provide a concise and direct answer to the user query. Your final response to the query should be within ```text .
258
+ **Original df (before reduction) had this schema:
259
+ {get_df_schema_prompt(dynamic_schema, example_values)}
260
+
261
+ Your task is to find a concise and direct answer as an English sentence to the user query.
262
+
263
+ Only if the answer to the query is complex, provide more explanation by:
264
+ 1. Analyzing the DataFrame values and columns for any meaningful or notable information.
265
+ 2. Comparing the query_code with the data content to understand what the result represents. THIS IS A REDUCED DATAFRAME, the original dataframe, used to answer the query, may be much bigger. IT IS ALREADY KNOWN! Do not need to restate this.
266
+ 3. If it makes sense, provide information beyond the recorded provenance, but state it clearly that you are inferring it.
267
+
268
+ In the end, conclude by giving your concise answer as follows: **Response**: <YOUR ANSWER>
250
269
 
251
270
  Note that the user should not know that this is a reduced dataframe.
252
-
253
271
  Keep your response short and focused.
254
272
 
255
273
  """
274
+
256
275
  return prompt
257
276
 
258
277
 
@@ -74,7 +74,7 @@ def prompt_handler(message: str) -> ToolResult:
74
74
  TextContent
75
75
  The AI response or routing feedback.
76
76
  """
77
- df_key_words = {"save", "result = df", "reset context"}
77
+ df_key_words = ["df", "save", "result = df", "reset context"]
78
78
  for key in df_key_words:
79
79
  if key in message:
80
80
  return run_df_query(llm=None, query=message, plot=False)
@@ -294,6 +294,8 @@ def generate_result_df(llm, query: str, dynamic_schema, example_values, df, atte
294
294
  >>> generate_result_df(llm, "bad query", schema, examples, df, attempt_fix=False)
295
295
  ToolResult(code=405, result="Failed to parse this as Python code: ...")
296
296
  """
297
+ if llm is None:
298
+ llm = build_llm_model()
297
299
  try:
298
300
  prompt = generate_pandas_code_prompt(query, dynamic_schema, example_values)
299
301
  response = llm(prompt)
@@ -351,7 +353,14 @@ def generate_result_df(llm, query: str, dynamic_schema, example_values, df, atte
351
353
  summary, summary_error = None, None
352
354
  if summarize:
353
355
  try:
354
- tool_result = summarize_result(llm, result_code, result_df, query)
356
+ tool_result = summarize_result(
357
+ llm,
358
+ result_code,
359
+ result_df,
360
+ query,
361
+ dynamic_schema,
362
+ example_values,
363
+ )
355
364
  if tool_result.is_success():
356
365
  return_code = 301
357
366
  summary = tool_result.result
@@ -570,7 +579,14 @@ def extract_or_fix_json_code(llm, raw_text) -> ToolResult:
570
579
 
571
580
 
572
581
  @mcp_flowcept.tool()
573
- def summarize_result(llm, code, result, query: str) -> ToolResult:
582
+ def summarize_result(
583
+ llm,
584
+ code,
585
+ result,
586
+ query: str,
587
+ dynamic_schema,
588
+ example_values,
589
+ ) -> ToolResult:
574
590
  """
575
591
  Summarize the pandas result with local reduction for large DataFrames.
576
592
  - For wide DataFrames, selects top columns based on variance and uniqueness.
@@ -578,7 +594,7 @@ def summarize_result(llm, code, result, query: str) -> ToolResult:
578
594
  - Constructs a detailed prompt for the LLM with original column context.
579
595
  """
580
596
  summarized_df = summarize_df(result, code)
581
- prompt = dataframe_summarizer_context(code, summarized_df, query)
597
+ prompt = dataframe_summarizer_context(code, summarized_df, dynamic_schema, example_values, query)
582
598
  try:
583
599
  response = llm(prompt)
584
600
  return ToolResult(code=201, result=response)
@@ -137,7 +137,6 @@ def summarize_task(task: Dict, thresholds: Dict = None, logger=None) -> Dict:
137
137
  "agent_id",
138
138
  "campaign_id",
139
139
  "subtype",
140
- "custom_metadata",
141
140
  ]:
142
141
  value = _safe_get(task, key)
143
142
  if value is not None:
@@ -146,7 +145,14 @@ def summarize_task(task: Dict, thresholds: Dict = None, logger=None) -> Dict:
146
145
  else:
147
146
  task_summary[key] = value
148
147
 
149
- # Special handling for timestamp field
148
+ # Adding image column if data is image. This is to handle special cases when there is an image associated to
149
+ # a provenance task.
150
+ if "data" in task:
151
+ if "custom_metadata" in task:
152
+ if "image" in task["custom_metadata"].get("mime_type", ""):
153
+ task_summary["image"] = task["data"]
154
+
155
+ # Special handling for timestamp field
150
156
  try:
151
157
  time_keys = ["started_at", "ended_at"]
152
158
  for time_key in time_keys:
@@ -4,4 +4,4 @@
4
4
  # The expected format is: <Major>.<Minor>.<Patch>
5
5
  # This file is supposed to be automatically modified by the CI Bot.
6
6
  # See .github/workflows/version_bumper.py
7
- __version__ = "0.9.2"
7
+ __version__ = "0.9.3"
@@ -1,19 +0,0 @@
1
- import random
2
- from time import sleep
3
-
4
- from flowcept import Flowcept, FlowceptLoop
5
-
6
- iterations = range(1, 5)
7
-
8
- with Flowcept():
9
-
10
- loop = FlowceptLoop(iterations) # See also: FlowceptLightweightLoop
11
- for item in loop:
12
- loss = random.random()
13
- sleep(0.05)
14
- print(item, loss)
15
- # The following is optional, in case you want to capture values generated inside the loop.
16
- loop.end_iter({"item": item, "loss": loss})
17
-
18
- docs = Flowcept.db.get_tasks_from_current_workflow()
19
- assert len(docs) == len(iterations)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes