lionagi 0.2.1__tar.gz → 0.2.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (262) hide show
  1. {lionagi-0.2.1 → lionagi-0.2.2}/PKG-INFO +5 -4
  2. {lionagi-0.2.1 → lionagi-0.2.2}/README.md +4 -3
  3. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/__init__.py +2 -1
  4. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/graph.py +10 -3
  5. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/node.py +5 -1
  6. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/report/base.py +1 -0
  7. lionagi-0.2.2/lionagi/core/work/work_edge.py +96 -0
  8. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/work_function.py +29 -6
  9. lionagi-0.2.2/lionagi/core/work/work_function_node.py +44 -0
  10. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/work_queue.py +20 -18
  11. lionagi-0.2.2/lionagi/core/work/work_task.py +155 -0
  12. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/worker.py +164 -39
  13. lionagi-0.2.2/lionagi/core/work/worker_engine.py +179 -0
  14. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/worklog.py +5 -3
  15. lionagi-0.2.2/lionagi/tests/test_core/generic/test_structure.py +193 -0
  16. lionagi-0.2.2/lionagi/tests/test_core/graph/__init__.py +0 -0
  17. lionagi-0.2.2/lionagi/tests/test_core/graph/test_graph.py +70 -0
  18. lionagi-0.2.2/lionagi/tests/test_core/graph/test_tree.py +75 -0
  19. lionagi-0.2.2/lionagi/tests/test_core/mail/__init__.py +0 -0
  20. lionagi-0.2.2/lionagi/tests/test_core/mail/test_mail.py +62 -0
  21. lionagi-0.2.2/lionagi/tests/test_core/test_structure/__init__.py +0 -0
  22. lionagi-0.2.2/lionagi/tests/test_core/test_structure/test_base_structure.py +196 -0
  23. lionagi-0.2.2/lionagi/tests/test_core/test_structure/test_graph.py +54 -0
  24. lionagi-0.2.2/lionagi/tests/test_core/test_structure/test_tree.py +48 -0
  25. lionagi-0.2.2/lionagi/version.py +1 -0
  26. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi.egg-info/PKG-INFO +5 -4
  27. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi.egg-info/SOURCES.txt +15 -1
  28. lionagi-0.2.1/lionagi/version.py +0 -1
  29. {lionagi-0.2.1 → lionagi-0.2.2}/LICENSE +0 -0
  30. {lionagi-0.2.1 → lionagi-0.2.2}/README.rst +0 -0
  31. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/__init__.py +0 -0
  32. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/_setting/__init__.py +0 -0
  33. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/_setting/_setting.py +0 -0
  34. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/__init__.py +0 -0
  35. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/function_calling.py +0 -0
  36. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/manual.py +0 -0
  37. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/node.py +0 -0
  38. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/tool.py +0 -0
  39. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/action/tool_manager.py +0 -0
  40. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/__init__.py +0 -0
  41. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/base_agent.py +0 -0
  42. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/eval/__init__.py +0 -0
  43. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/eval/evaluator.py +0 -0
  44. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/eval/vote.py +0 -0
  45. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/learn/__init__.py +0 -0
  46. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/learn/learner.py +0 -0
  47. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/plan/__init__.py +0 -0
  48. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/plan/plan.py +0 -0
  49. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/agent/plan/unit_template.py +0 -0
  50. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/__init__.py +0 -0
  51. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/_logger.py +0 -0
  52. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/abc/__init__.py +0 -0
  53. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/abc/component.py +0 -0
  54. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/abc/concepts.py +0 -0
  55. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/abc/exceptions.py +0 -0
  56. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/abc/util.py +0 -0
  57. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/exchange.py +0 -0
  58. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/flow.py +0 -0
  59. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/model.py +0 -0
  60. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/pile.py +0 -0
  61. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/progression.py +0 -0
  62. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/collections/util.py +0 -0
  63. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/director/__init__.py +0 -0
  64. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/director/direct.py +0 -0
  65. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/director/director.py +0 -0
  66. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/engine/__init__.py +0 -0
  67. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/engine/branch_engine.py +0 -0
  68. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/engine/instruction_map_engine.py +0 -0
  69. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/engine/sandbox_.py +0 -0
  70. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/engine/script_engine.py +0 -0
  71. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/executor/__init__.py +0 -0
  72. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/executor/base_executor.py +0 -0
  73. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/executor/graph_executor.py +0 -0
  74. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/executor/neo4j_executor.py +0 -0
  75. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/__init__.py +0 -0
  76. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/edge.py +0 -0
  77. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/edge_condition.py +0 -0
  78. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/hyperedge.py +0 -0
  79. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/tree.py +0 -0
  80. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/generic/tree_node.py +0 -0
  81. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/mail/__init__.py +0 -0
  82. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/mail/mail.py +0 -0
  83. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/mail/mail_manager.py +0 -0
  84. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/mail/package.py +0 -0
  85. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/mail/start_mail.py +0 -0
  86. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/__init__.py +0 -0
  87. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/action_request.py +0 -0
  88. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/action_response.py +0 -0
  89. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/assistant_response.py +0 -0
  90. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/instruction.py +0 -0
  91. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/message.py +0 -0
  92. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/system.py +0 -0
  93. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/message/util.py +0 -0
  94. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/report/__init__.py +0 -0
  95. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/report/form.py +0 -0
  96. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/report/report.py +0 -0
  97. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/report/util.py +0 -0
  98. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/__init__.py +0 -0
  99. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/_default.py +0 -0
  100. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/action.py +0 -0
  101. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/base.py +0 -0
  102. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/boolean.py +0 -0
  103. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/choice.py +0 -0
  104. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/mapping.py +0 -0
  105. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/number.py +0 -0
  106. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/rulebook.py +0 -0
  107. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/string.py +0 -0
  108. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/rule/util.py +0 -0
  109. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/session/__init__.py +0 -0
  110. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/session/branch.py +0 -0
  111. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/session/directive_mixin.py +0 -0
  112. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/session/session.py +0 -0
  113. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/structure/__init__.py +0 -0
  114. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/structure/chain.py +0 -0
  115. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/structure/forest.py +0 -0
  116. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/structure/graph.py +0 -0
  117. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/structure/tree.py +0 -0
  118. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/__init__.py +0 -0
  119. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/parallel_unit.py +0 -0
  120. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/__init__.py +0 -0
  121. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/action.py +0 -0
  122. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/base.py +0 -0
  123. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/plan.py +0 -0
  124. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/predict.py +0 -0
  125. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/score.py +0 -0
  126. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/template/select.py +0 -0
  127. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/unit.py +0 -0
  128. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/unit_form.py +0 -0
  129. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/unit_mixin.py +0 -0
  130. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/unit/util.py +0 -0
  131. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/validator/__init__.py +0 -0
  132. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/validator/validator.py +0 -0
  133. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/__init__.py +0 -0
  134. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/core/work/work.py +0 -0
  135. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/__init__.py +0 -0
  136. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/compressor/__init__.py +0 -0
  137. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/compressor/base.py +0 -0
  138. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/compressor/llm_compressor.py +0 -0
  139. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/compressor/llm_summarizer.py +0 -0
  140. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/compressor/util.py +0 -0
  141. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/__init__.py +0 -0
  142. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/parser/__init__.py +0 -0
  143. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/parser/base_parser.py +0 -0
  144. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/template/__init__.py +0 -0
  145. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/template/base_template.py +0 -0
  146. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/template/schema.py +0 -0
  147. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/directive/tokenizer.py +0 -0
  148. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/evaluator/__init__.py +0 -0
  149. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/evaluator/ast_evaluator.py +0 -0
  150. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/evaluator/base_evaluator.py +0 -0
  151. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/knowledge/__init__.py +0 -0
  152. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/knowledge/base.py +0 -0
  153. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/knowledge/graph.py +0 -0
  154. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/memory/__init__.py +0 -0
  155. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/strategies/__init__.py +0 -0
  156. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/experimental/strategies/base.py +0 -0
  157. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/__init__.py +0 -0
  158. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/__init__.py +0 -0
  159. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/autogen_/__init__.py +0 -0
  160. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/autogen_/autogen_.py +0 -0
  161. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/langchain_/__init__.py +0 -0
  162. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/langchain_/documents.py +0 -0
  163. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/langchain_/langchain_bridge.py +0 -0
  164. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/__init__.py +0 -0
  165. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/index.py +0 -0
  166. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +0 -0
  167. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/llama_pack.py +0 -0
  168. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/node_parser.py +0 -0
  169. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/reader.py +0 -0
  170. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/llamaindex_/textnode.py +0 -0
  171. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/pydantic_/__init__.py +0 -0
  172. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +0 -0
  173. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/transformers_/__init__.py +0 -0
  174. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/bridge/transformers_/install_.py +0 -0
  175. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/chunker/__init__.py +0 -0
  176. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/chunker/chunk.py +0 -0
  177. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/config/__init__.py +0 -0
  178. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/config/mlx_configs.py +0 -0
  179. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/config/oai_configs.py +0 -0
  180. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/config/ollama_configs.py +0 -0
  181. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/config/openrouter_configs.py +0 -0
  182. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/loader/__init__.py +0 -0
  183. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/loader/load.py +0 -0
  184. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/loader/load_util.py +0 -0
  185. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/__init__.py +0 -0
  186. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/_mapping.py +0 -0
  187. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/litellm.py +0 -0
  188. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/mistralai.py +0 -0
  189. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/mlx_service.py +0 -0
  190. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/oai.py +0 -0
  191. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/ollama.py +0 -0
  192. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/openrouter.py +0 -0
  193. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/services.py +0 -0
  194. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/provider/transformers.py +0 -0
  195. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/__init__.py +0 -0
  196. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/neo4j.py +0 -0
  197. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/storage_util.py +0 -0
  198. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/structure_excel.py +0 -0
  199. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/to_csv.py +0 -0
  200. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/integrations/storage/to_excel.py +0 -0
  201. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/__init__.py +0 -0
  202. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_api.py +0 -0
  203. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_async.py +0 -0
  204. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_context.py +0 -0
  205. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_convert.py +0 -0
  206. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_dataframe.py +0 -0
  207. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_func_call.py +0 -0
  208. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_image.py +0 -0
  209. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_knowledge_graph.py +0 -0
  210. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_nested.py +0 -0
  211. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_parse.py +0 -0
  212. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_queue.py +0 -0
  213. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_tokenize.py +0 -0
  214. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/ln_validate.py +0 -0
  215. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/special_tokens.py +0 -0
  216. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/libs/sys_util.py +0 -0
  217. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/__init__.py +0 -0
  218. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/__init__.py +0 -0
  219. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/add_feature.py +0 -0
  220. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/base_prompts.py +0 -0
  221. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/code_form.py +0 -0
  222. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/coder.py +0 -0
  223. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/coder/util.py +0 -0
  224. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/__init__.py +0 -0
  225. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/data_source/__init__.py +0 -0
  226. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/data_source/finhub_.py +0 -0
  227. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/data_source/google_.py +0 -0
  228. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/data_source/wiki_.py +0 -0
  229. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/lions/researcher/data_source/yfinance_.py +0 -0
  230. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/__init__.py +0 -0
  231. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/integrations/__init__.py +0 -0
  232. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/__init__.py +0 -0
  233. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_api.py +0 -0
  234. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_convert.py +0 -0
  235. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_field_validators.py +0 -0
  236. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_func_call.py +0 -0
  237. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_nested.py +0 -0
  238. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_parse.py +0 -0
  239. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_queue.py +0 -0
  240. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/libs/test_sys_util.py +0 -0
  241. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/__init__.py +0 -0
  242. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/__init__.py +0 -0
  243. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/test_component.py +0 -0
  244. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/test_exchange.py +0 -0
  245. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/test_flow.py +0 -0
  246. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/test_pile.py +0 -0
  247. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/collections/test_progression.py +0 -0
  248. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/generic/__init__.py +0 -0
  249. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/generic/test_edge.py +0 -0
  250. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/generic/test_graph.py +0 -0
  251. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/generic/test_node.py +0 -0
  252. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/generic/test_tree_node.py +0 -0
  253. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/test_branch.py +0 -0
  254. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/test_form.py +0 -0
  255. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/test_report.py +0 -0
  256. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi/tests/test_core/test_validator.py +0 -0
  257. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi.egg-info/dependency_links.txt +0 -0
  258. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi.egg-info/requires.txt +0 -0
  259. {lionagi-0.2.1 → lionagi-0.2.2}/lionagi.egg-info/top_level.txt +0 -0
  260. {lionagi-0.2.1 → lionagi-0.2.2}/pyproject.toml +0 -0
  261. {lionagi-0.2.1 → lionagi-0.2.2}/setup.cfg +0 -0
  262. {lionagi-0.2.1 → lionagi-0.2.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -226,13 +226,14 @@ Requires-Dist: pandas>=2.1.0
226
226
  ![PyPI - Version](https://img.shields.io/pypi/v/lionagi?labelColor=233476aa&color=231fc935) ![PyPI - Downloads](https://img.shields.io/pypi/dm/lionagi?color=blue)
227
227
 
228
228
 
229
- [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/xCkA5ErGmV)
229
+ [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/aqSJ2v46vu) | [Roadmap](https://trello.com/b/3seomsrI/lionagi)
230
230
 
231
231
 
232
232
  # Language InterOperable Network - LION
233
+ ### An AGentic Intelligence Operating System
233
234
 
234
235
  ```
235
- lionagi version 0.2.1
236
+ pip install lionagi==0.2.2
236
237
  ```
237
238
 
238
239
  **Powerful Intelligent Workflow Automation**
@@ -250,7 +251,7 @@ What goes inside of a LLM is more akin to a [black-box](https://pauldeepakraj-r.
250
251
 
251
252
  ### Community
252
253
 
253
- We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members [Join Our Discord](https://discord.gg/7RGWqpSxze)
254
+ We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members [Join Our Discord](https://discord.gg/aqSJ2v46vu)
254
255
 
255
256
  ### Citation
256
257
 
@@ -1,13 +1,14 @@
1
1
  ![PyPI - Version](https://img.shields.io/pypi/v/lionagi?labelColor=233476aa&color=231fc935) ![PyPI - Downloads](https://img.shields.io/pypi/dm/lionagi?color=blue)
2
2
 
3
3
 
4
- [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/xCkA5ErGmV)
4
+ [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/aqSJ2v46vu) | [Roadmap](https://trello.com/b/3seomsrI/lionagi)
5
5
 
6
6
 
7
7
  # Language InterOperable Network - LION
8
+ ### An AGentic Intelligence Operating System
8
9
 
9
10
  ```
10
- lionagi version 0.2.1
11
+ pip install lionagi==0.2.2
11
12
  ```
12
13
 
13
14
  **Powerful Intelligent Workflow Automation**
@@ -25,7 +26,7 @@ What goes inside of a LLM is more akin to a [black-box](https://pauldeepakraj-r.
25
26
 
26
27
  ### Community
27
28
 
28
- We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members [Join Our Discord](https://discord.gg/7RGWqpSxze)
29
+ We encourage contributions to LionAGI and invite you to enrich its features and capabilities. Engage with us and other community members [Join Our Discord](https://discord.gg/aqSJ2v46vu)
29
30
 
30
31
  ### Citation
31
32
 
@@ -27,7 +27,7 @@ from lionagi.core.action import func_to_tool
27
27
  from lionagi.core.report import Form, Report
28
28
  from lionagi.core.session.branch import Branch
29
29
  from lionagi.core.session.session import Session
30
- from lionagi.core.work.worker import work, Worker
30
+ from lionagi.core.work.worker import work, Worker, worklink
31
31
  from lionagi.integrations.provider.services import Services
32
32
  from lionagi.integrations.chunker.chunk import chunk
33
33
  from lionagi.integrations.loader.load import load
@@ -41,6 +41,7 @@ __all__ = [
41
41
  "pile",
42
42
  "iModel",
43
43
  "work",
44
+ "worklink",
44
45
  "Worker",
45
46
  "Branch",
46
47
  "Session",
@@ -44,6 +44,7 @@ class Graph(Node):
44
44
  condition: Condition | None = None,
45
45
  bundle=False,
46
46
  label=None,
47
+ edge_class=Edge,
47
48
  **kwargs,
48
49
  ):
49
50
  """Add an edge between two nodes in the graph."""
@@ -61,6 +62,7 @@ class Graph(Node):
61
62
  condition=condition,
62
63
  label=label,
63
64
  bundle=bundle,
65
+ edge_class=edge_class,
64
66
  **kwargs,
65
67
  )
66
68
 
@@ -184,19 +186,23 @@ class Graph(Node):
184
186
  node_info = node.to_dict()
185
187
  node_info.pop("ln_id")
186
188
  node_info.update({"class_name": node.class_name})
189
+ if hasattr(node, "name"):
190
+ node_info.update({"name": node.name})
187
191
  g.add_node(node.ln_id, **node_info)
188
192
 
189
193
  for _edge in self.internal_edges:
190
194
  edge_info = _edge.to_dict()
191
195
  edge_info.pop("ln_id")
192
196
  edge_info.update({"class_name": _edge.class_name})
197
+ if hasattr(_edge, "name"):
198
+ edge_info.update({"name": _edge.name})
193
199
  source_node_id = edge_info.pop("head")
194
200
  target_node_id = edge_info.pop("tail")
195
201
  g.add_edge(source_node_id, target_node_id, **edge_info)
196
202
 
197
203
  return g
198
204
 
199
- def display(self, **kwargs):
205
+ def display(self, node_label="class_name", edge_label="label", draw_kwargs={}, **kwargs):
200
206
  """Display the graph using NetworkX and Matplotlib."""
201
207
  from lionagi.libs import SysUtil
202
208
 
@@ -217,10 +223,11 @@ class Graph(Node):
217
223
  node_size=500,
218
224
  node_color="orange",
219
225
  alpha=0.9,
220
- labels=nx.get_node_attributes(g, "class_name"),
226
+ labels=nx.get_node_attributes(g, node_label),
227
+ **draw_kwargs
221
228
  )
222
229
 
223
- labels = nx.get_edge_attributes(g, "label")
230
+ labels = nx.get_edge_attributes(g, edge_label)
224
231
  labels = {k: v for k, v in labels.items() if v}
225
232
 
226
233
  if labels:
@@ -10,6 +10,7 @@ modifying, and removing edges, and querying related nodes and connections.
10
10
 
11
11
  from pydantic import Field
12
12
  from pandas import Series
13
+ from typing import Callable
13
14
 
14
15
  from lionagi.libs.ln_convert import to_list
15
16
 
@@ -122,6 +123,8 @@ class Node(Component, Relatable):
122
123
  condition: Condition | None = None,
123
124
  label: str | None = None,
124
125
  bundle: bool = False,
126
+ edge_class: Callable = Edge,
127
+ **kwargs
125
128
  ) -> None:
126
129
  """
127
130
  Establish directed relationship from this node to another.
@@ -141,12 +144,13 @@ class Node(Component, Relatable):
141
144
  f"Invalid value for direction: {direction}, " "must be 'in' or 'out'"
142
145
  )
143
146
 
144
- edge = Edge(
147
+ edge = edge_class(
145
148
  head=self if direction == "out" else node,
146
149
  tail=node if direction == "out" else self,
147
150
  condition=condition,
148
151
  bundle=bundle,
149
152
  label=label,
153
+ **kwargs
150
154
  )
151
155
 
152
156
  self.relations[direction].include(edge)
@@ -26,6 +26,7 @@ from typing import Any, List, Dict
26
26
  import contextlib
27
27
  from lionagi.core.collections.abc import Component, Field
28
28
  from ..collections.util import to_list_type
29
+ from lionagi.libs.ln_convert import to_str
29
30
 
30
31
 
31
32
  class BaseForm(Component):
@@ -0,0 +1,96 @@
1
+ from typing import Callable
2
+ from pydantic import Field, field_validator
3
+ import inspect
4
+
5
+ from lionagi.core.generic.edge import Edge
6
+ from lionagi.core.collections.abc.concepts import Progressable
7
+
8
+ from lionagi.core.work.worker import Worker
9
+
10
+
11
+ class WorkEdge(Edge, Progressable):
12
+ """
13
+ Represents a directed edge between work tasks, responsible for transforming
14
+ the result of one task into parameters for the next task.
15
+
16
+ Attributes:
17
+ convert_function (Callable): Function to transform the result of the previous
18
+ work into parameters for the next work. This function must be decorated
19
+ with the `worklink` decorator.
20
+ convert_function_kwargs (dict): Additional parameters for the convert_function
21
+ other than "from_work" and "from_result".
22
+ associated_worker (Worker): The worker to which this WorkEdge belongs.
23
+ """
24
+ convert_function: Callable = Field(
25
+ ...,
26
+ description="Function to transform the result of the previous work into parameters for the next work."
27
+ )
28
+
29
+ convert_function_kwargs: dict = Field(
30
+ {},
31
+ description="parameters for the worklink function other than \"from_work\" and \"from_result\""
32
+ )
33
+
34
+ associated_worker: Worker = Field(
35
+ ...,
36
+ description="The worker to which this WorkEdge belongs."
37
+ )
38
+
39
+ @field_validator("convert_function", mode="before")
40
+ def _validate_convert_funuction(cls, func):
41
+ """
42
+ Validates that the convert_function is decorated with the worklink decorator.
43
+
44
+ Args:
45
+ func (Callable): The function to validate.
46
+
47
+ Returns:
48
+ Callable: The validated function.
49
+
50
+ Raises:
51
+ ValueError: If the function is not decorated with the worklink decorator.
52
+ """
53
+ try:
54
+ getattr(func, "_worklink_decorator_params")
55
+ return func
56
+ except:
57
+ raise ValueError("convert_function must be a worklink decorated function")
58
+
59
+ @property
60
+ def name(self):
61
+ """
62
+ Returns the name of the convert_function.
63
+
64
+ Returns:
65
+ str: The name of the convert_function.
66
+ """
67
+ return self.convert_function.__name__
68
+
69
+ async def forward(self, task):
70
+ """
71
+ Transforms the result of the current work into parameters for the next work
72
+ and schedules the next work task.
73
+
74
+ Args:
75
+ task (Task): The task to process.
76
+
77
+ Returns:
78
+ Work: The next work task to be executed.
79
+
80
+ Raises:
81
+ StopIteration: If the task has no available steps left to proceed.
82
+ """
83
+ if task.available_steps == 0:
84
+ task.status_note = ("Task stopped proceeding further as all available steps have been used up, "
85
+ "but the task has not yet reached completion.")
86
+ return
87
+ func_signature = inspect.signature(self.convert_function)
88
+ kwargs = self.convert_function_kwargs.copy()
89
+ if "from_work" in func_signature.parameters:
90
+ kwargs = {"from_work": task.current_work} | kwargs
91
+ if "from_result" in func_signature.parameters:
92
+ kwargs = {"from_result": task.current_work.result} | kwargs
93
+
94
+ self.convert_function.auto_schedule = True
95
+ next_work = await self.convert_function(self=self.associated_worker, **kwargs)
96
+ return next_work
@@ -13,14 +13,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
+ import asyncio
16
17
  import logging
17
18
 
18
19
  from lionagi.libs.ln_func_call import rcall
19
- from lionagi.libs.ln_parse import ParseUtil
20
20
  from lionagi.core.work.worklog import WorkLog
21
21
 
22
- from lionagi.core.report.form import Form
23
-
24
22
 
25
23
  class WorkFunction:
26
24
  """
@@ -35,7 +33,7 @@ class WorkFunction:
35
33
  """
36
34
 
37
35
  def __init__(
38
- self, assignment, function, retry_kwargs=None, guidance=None, capacity=10
36
+ self, assignment, function, retry_kwargs=None, guidance=None, capacity=10, refresh_time=1
39
37
  ):
40
38
  """
41
39
  Initializes a WorkFunction instance.
@@ -47,12 +45,15 @@ class WorkFunction:
47
45
  Defaults to None.
48
46
  guidance (str, optional): The guidance or documentation for the function.
49
47
  Defaults to None.
50
- capacity (int, optional): The capacity of the work log. Defaults to 10.
48
+ capacity (int, optional): The capacity of the work queue batch processing.
49
+ Defaults to 10.
50
+ refresh_time (int, optional): The time interval to refresh the work log queue.
51
+ Defaults to 1.
51
52
  """
52
53
  self.assignment = assignment
53
54
  self.function = function
54
55
  self.retry_kwargs = retry_kwargs or {}
55
- self.worklog = WorkLog(capacity)
56
+ self.worklog = WorkLog(capacity, refresh_time=refresh_time)
56
57
  self.guidance = guidance or self.function.__doc__
57
58
 
58
59
  @property
@@ -65,6 +66,16 @@ class WorkFunction:
65
66
  """
66
67
  return self.function.__name__
67
68
 
69
+ @property
70
+ def execution_mode(self):
71
+ """
72
+ Gets the execution mode of the work function's queue.
73
+
74
+ Returns:
75
+ bool: The execution mode of the work function's queue.
76
+ """
77
+ return self.worklog.queue.execution_mode
78
+
68
79
  def is_progressable(self):
69
80
  """
70
81
  Checks if the work function is progressable.
@@ -99,3 +110,15 @@ class WorkFunction:
99
110
  Process the first capacity_size works in the work queue.
100
111
  """
101
112
  await self.worklog.queue.process()
113
+
114
+ async def execute(self):
115
+ """
116
+ Starts the execution of the work function's queue.
117
+ """
118
+ asyncio.create_task(self.worklog.queue.execute())
119
+
120
+ async def stop(self):
121
+ """
122
+ Stops the execution of the work function's queue.
123
+ """
124
+ await self.worklog.stop()
@@ -0,0 +1,44 @@
1
+ from pydantic import Field
2
+ import asyncio
3
+
4
+ from lionagi.core.generic.node import Node
5
+ from lionagi.core.work.work_function import WorkFunction
6
+ from lionagi.core.collections import Exchange
7
+ from lionagi.core.mail.mail import Mail
8
+
9
+
10
+ class WorkFunctionNode(WorkFunction, Node):
11
+ """
12
+ A class representing a work function node, combining the functionality
13
+ of a WorkFunction and a Node.
14
+
15
+ Attributes:
16
+ assignment (str): The assignment description of the work function.
17
+ function (Callable): The function to be performed.
18
+ retry_kwargs (dict): The retry arguments for the function.
19
+ guidance (str): The guidance or documentation for the function.
20
+ capacity (int): The capacity of the work queue batch processing.
21
+ refresh_time (int): The time interval to refresh the work log queue.
22
+ """
23
+
24
+ def __init__(self, assignment, function, retry_kwargs=None, guidance=None, capacity=10, refresh_time=1, **kwargs):
25
+ """
26
+ Initializes a WorkFunctionNode instance.
27
+
28
+ Args:
29
+ assignment (str): The assignment description of the work function.
30
+ function (Callable): The function to be performed.
31
+ retry_kwargs (dict, optional): The retry arguments for the function. Defaults to None.
32
+ guidance (str, optional): The guidance or documentation for the function. Defaults to None.
33
+ capacity (int, optional): The capacity of the work queue batch processing. Defaults to 10.
34
+ refresh_time (int, optional): The time interval to refresh the work log queue. Defaults to 1.
35
+ **kwargs: Additional keyword arguments for the Node initialization.
36
+ """
37
+ Node.__init__(self, **kwargs)
38
+ WorkFunction.__init__(self,
39
+ assignment=assignment,
40
+ function=function,
41
+ retry_kwargs=retry_kwargs,
42
+ guidance=guidance,
43
+ capacity=capacity,
44
+ refresh_time=refresh_time)
@@ -25,19 +25,33 @@ class WorkQueue:
25
25
  Attributes:
26
26
  capacity (int): The maximum number of tasks the queue can handle.
27
27
  queue (asyncio.Queue): The queue holding the tasks.
28
- _stop_event (asyncio.Event): Event to signal stopping `execute` of the queue.
28
+ _stop_event (asyncio.Event): Event to signal stopping the execution of the queue.
29
29
  available_capacity (int): The remaining number of tasks the queue can handle.
30
30
  execution_mode (bool): If `execute` is running.
31
+ refresh_time (int): The time interval between task processing.
31
32
  """
32
33
 
33
- def __init__(self, capacity=5):
34
+ def __init__(self, capacity=5, refresh_time=1):
35
+ """
36
+ Initializes a new instance of WorkQueue.
37
+
38
+ Args:
39
+ capacity (int): The maximum number of tasks the queue can handle.
40
+ refresh_time (int): The time interval between task processing.
41
+
42
+ Raises:
43
+ ValueError: If capacity is less than 0 or refresh_time is negative.
44
+ """
34
45
  if capacity < 0:
35
46
  raise ValueError("initial capacity must be >= 0")
47
+ if refresh_time < 0:
48
+ raise ValueError("refresh time for execution can not be negative")
36
49
  self.capacity = capacity
37
50
  self.queue = asyncio.Queue()
38
51
  self._stop_event = asyncio.Event()
39
52
  self.available_capacity = capacity
40
53
  self.execution_mode = False
54
+ self.refresh_time = refresh_time
41
55
 
42
56
  async def enqueue(self, work) -> None:
43
57
  """Enqueue a work item."""
@@ -60,20 +74,6 @@ class WorkQueue:
60
74
  """Return whether the queue has been stopped."""
61
75
  return self._stop_event.is_set()
62
76
 
63
- # async def process(self):
64
- # async def _parse_work(work):
65
- # async with self.semaphore:
66
- # await work.perform()
67
- #
68
- # tasks = set()
69
- # while self.queue.qsize() > 0:
70
- # next = await self.dequeue()
71
- # next.status = WorkStatus.IN_PROGRESS
72
- # task = asyncio.create_task(_parse_work(next))
73
- # tasks.add(task)
74
- #
75
- # await asyncio.wait(tasks)
76
-
77
77
  async def process(self) -> None:
78
78
  """Process the work items in the queue."""
79
79
  tasks = set()
@@ -88,7 +88,7 @@ class WorkQueue:
88
88
  await asyncio.wait(tasks)
89
89
  self.available_capacity = self.capacity
90
90
 
91
- async def execute(self, refresh_time=1):
91
+ async def execute(self):
92
92
  """
93
93
  Continuously executes the process method at a specified refresh interval.
94
94
 
@@ -97,7 +97,9 @@ class WorkQueue:
97
97
  successive calls to `process`. Defaults to 1.
98
98
  """
99
99
  self.execution_mode = True
100
+ self._stop_event.clear()
101
+
100
102
  while not self.stopped:
101
103
  await self.process()
102
- await asyncio.sleep(refresh_time)
104
+ await asyncio.sleep(self.refresh_time)
103
105
  self.execution_mode = False
@@ -0,0 +1,155 @@
1
+ import inspect
2
+ from typing import Any, Callable
3
+ from pydantic import Field, field_validator, model_validator
4
+
5
+ from lionagi.core.collections.abc.component import Component
6
+ from lionagi.core.work.work import WorkStatus, Work
7
+ from collections.abc import Coroutine
8
+
9
+
10
+ class WorkTask(Component):
11
+ """
12
+ A class representing a work task that can be processed in multiple steps.
13
+
14
+ Attributes:
15
+ name (str | None): The name of the task.
16
+ status (WorkStatus): The current status of the task.
17
+ status_note (str): A note for the task's current status.
18
+ work_history (list[Work]): A list of works processed in this task.
19
+ max_steps (int | None): The maximum number of works allowed in this task.
20
+ current_work (Work | None): The current work in progress.
21
+ post_processing (Callable | None): The post-processing function to be executed after the entire task is successfully completed.
22
+ """
23
+ name: str | None = Field(
24
+ None,
25
+ description="Name of the task"
26
+ )
27
+
28
+ status: WorkStatus = Field(
29
+ WorkStatus.PENDING,
30
+ description="The current status of the task"
31
+ )
32
+
33
+ status_note: str = Field(
34
+ None,
35
+ description="Note for tasks current status"
36
+ )
37
+
38
+ work_history: list[Work] = Field(
39
+ [],
40
+ description="List of works processed"
41
+ )
42
+
43
+ max_steps: int | None = Field(
44
+ 10,
45
+ description="Maximum number of works allowed"
46
+ )
47
+
48
+ current_work: Work | None = Field(
49
+ None,
50
+ description="The current work in progress"
51
+ )
52
+
53
+ post_processing: Callable | None = Field(
54
+ None,
55
+ description="The post-processing function to be executed after the entire task has been successfully completed."
56
+ )
57
+
58
+ @field_validator("max_steps", mode="before")
59
+ def _validate_max_steps(cls, value):
60
+ """
61
+ Validates that max_steps is a positive integer.
62
+
63
+ Args:
64
+ value (int): The value to validate.
65
+
66
+ Returns:
67
+ int: The validated value.
68
+
69
+ Raises:
70
+ ValueError: If value is not a positive integer.
71
+ """
72
+ if value <= 0:
73
+ raise ValueError("Invalid value: max_steps must be a positive integer.")
74
+ return value
75
+
76
+ @field_validator("post_processing", mode="before")
77
+ def _validate_prost_processing(cls, value):
78
+ """
79
+ Validates that post_processing is an asynchronous function.
80
+
81
+ Args:
82
+ value (Callable): The value to validate.
83
+
84
+ Returns:
85
+ Callable: The validated value.
86
+
87
+ Raises:
88
+ ValueError: If value is not an asynchronous function.
89
+ """
90
+ if value is not None and not inspect.iscoroutinefunction((value)):
91
+ raise ValueError("post_processing must be a async function")
92
+ return value
93
+
94
+ @property
95
+ def available_steps(self):
96
+ """
97
+ Calculates the number of available steps left in the task.
98
+
99
+ Returns:
100
+ int: The number of available steps.
101
+ """
102
+ return max(0, self.max_steps - len(self.work_history))
103
+
104
+ def clone(self):
105
+ """
106
+ Creates a clone of the current WorkTask instance.
107
+
108
+ Returns:
109
+ WorkTask: A new instance of WorkTask with the same attributes.
110
+ """
111
+ new_worktask = WorkTask(name=self.name, status=self.status, max_steps=self.max_steps, current_work=self.current_work)
112
+ for work in self.work_history:
113
+ new_worktask.work_history.append(work)
114
+ return new_worktask
115
+
116
+ async def process(self, current_func_node):
117
+ """
118
+ Processes the current work function node.
119
+
120
+ Args:
121
+ current_func_node (WorkFunctionNode): The current function node being processed.
122
+
123
+ Returns:
124
+ str | list[WorkTask]: Returns "COMPLETED", "FAILED", or a list of new WorkTask instances if there are next works to process.
125
+ """
126
+ if self.current_work.status == WorkStatus.FAILED:
127
+ self.status = WorkStatus.FAILED
128
+ self.status_note = f"Work {self.current_work.ln_id} failed. Error: {self.current_work.error}"
129
+ self.current_work = None
130
+ return "FAILED"
131
+ elif self.current_work.status == WorkStatus.COMPLETED:
132
+ next_works = []
133
+ if not current_func_node.relations["out"].is_empty():
134
+ for workedge in current_func_node.relations["out"]:
135
+ next_work = await workedge.forward(self)
136
+ if next_work is not None:
137
+ next_works.append(next_work)
138
+ if len(next_works) == 0:
139
+ self.current_work = None
140
+ self.status = WorkStatus.COMPLETED
141
+ if self.post_processing:
142
+ await self.post_processing(self)
143
+ return "COMPLETED"
144
+ else:
145
+ return_tasks = []
146
+ for i in reversed(range(len(next_works))):
147
+ if i == 0:
148
+ self.current_work = next_works[i]
149
+ self.work_history.append(next_works[i])
150
+ else:
151
+ clone_task = self.clone()
152
+ clone_task.current_work = next_works[i]
153
+ clone_task.work_history.append(next_works[i])
154
+ return_tasks.append(clone_task)
155
+ return return_tasks