model-compose 0.3.5__tar.gz → 0.3.7__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 (215) hide show
  1. {model_compose-0.3.5/src/model_compose.egg-info → model_compose-0.3.7}/PKG-INFO +1 -1
  2. {model_compose-0.3.5 → model_compose-0.3.7}/pyproject.toml +1 -1
  3. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/cli/compose.py +7 -2
  4. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/base.py +12 -0
  5. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/context.py +6 -0
  6. model_compose-0.3.7/src/mindor/core/component/services/http_server.py +133 -0
  7. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/base.py +4 -3
  8. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/summarization.py +54 -27
  9. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_classification.py +2 -2
  10. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_embedding.py +2 -2
  11. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_generation.py +46 -23
  12. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/translation.py +55 -25
  13. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/shell.py +5 -14
  14. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/base.py +11 -9
  15. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runner/http_client.py +1 -1
  16. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runner/mcp_client.py +1 -1
  17. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/services/http_server.py +121 -18
  18. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/services/mcp_server.py +2 -4
  19. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/webui/gradio.py +15 -12
  20. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/webui/webui.py +8 -8
  21. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/listener/services/http_callback.py +2 -0
  22. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/runtime/env.py +10 -0
  23. model_compose-0.3.7/src/mindor/core/utils/shell.py +70 -0
  24. model_compose-0.3.7/src/mindor/core/utils/streamer.py +29 -0
  25. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/context.py +3 -0
  26. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/schema.py +6 -3
  27. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/workflow.py +3 -1
  28. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/http_client.py +18 -18
  29. model_compose-0.3.7/src/mindor/dsl/schema/action/impl/http_server.py +52 -0
  30. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/common.py +2 -2
  31. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +3 -1
  32. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +1 -1
  33. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +4 -0
  34. model_compose-0.3.7/src/mindor/dsl/schema/component/impl/http_server.py +35 -0
  35. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/common.py +3 -3
  36. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/http_server.py +2 -2
  37. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/mcp_server.py +2 -2
  38. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/common.py +2 -2
  39. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/common.py +1 -1
  40. {model_compose-0.3.5 → model_compose-0.3.7/src/model_compose.egg-info}/PKG-INFO +1 -1
  41. {model_compose-0.3.5 → model_compose-0.3.7}/src/model_compose.egg-info/SOURCES.txt +2 -0
  42. model_compose-0.3.5/src/mindor/core/component/services/http_server.py +0 -26
  43. model_compose-0.3.5/src/mindor/dsl/schema/action/impl/http_server.py +0 -8
  44. model_compose-0.3.5/src/mindor/dsl/schema/component/impl/http_server.py +0 -11
  45. {model_compose-0.3.5 → model_compose-0.3.7}/LICENSE +0 -0
  46. {model_compose-0.3.5 → model_compose-0.3.7}/README.md +0 -0
  47. {model_compose-0.3.5 → model_compose-0.3.7}/setup.cfg +0 -0
  48. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/__init__.py +0 -0
  49. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/cli/__init__.py +0 -0
  50. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/__init__.py +0 -0
  51. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/__init__.py +0 -0
  52. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/component.py +0 -0
  53. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/__init__.py +0 -0
  54. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/http_client.py +0 -0
  55. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/mcp_client.py +0 -0
  56. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/mcp_server.py +0 -0
  57. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/__init__.py +0 -0
  58. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/model.py +0 -0
  59. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  60. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/text_splitter.py +0 -0
  61. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/component/services/workflow.py +0 -0
  62. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/compose/__init__.py +0 -0
  63. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/compose/compose.py +0 -0
  64. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/compose/manager.py +0 -0
  65. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/__init__.py +0 -0
  66. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/controller.py +0 -0
  67. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runner/__init__.py +0 -0
  68. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runner/client.py +0 -0
  69. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runner/runner.py +0 -0
  70. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runtime/__init__.py +0 -0
  71. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  72. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
  73. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
  74. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/runtime/specs.py +0 -0
  75. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/services/__init__.py +0 -0
  76. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/controller/webui/__init__.py +0 -0
  77. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/__init__.py +0 -0
  78. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/base.py +0 -0
  79. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/gateway.py +0 -0
  80. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/services/__init__.py +0 -0
  81. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  82. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  83. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/listener/__init__.py +0 -0
  84. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/listener/base.py +0 -0
  85. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/listener/listener.py +0 -0
  86. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/listener/services/__init__.py +0 -0
  87. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/__init__.py +0 -0
  88. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/base.py +0 -0
  89. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/logger.py +0 -0
  90. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/logging.py +0 -0
  91. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/services/__init__.py +0 -0
  92. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/services/console.py +0 -0
  93. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/logger/services/file.py +0 -0
  94. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/runtime/__init__.py +0 -0
  95. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/runtime/docker/__init__.py +0 -0
  96. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/runtime/docker/docker.py +0 -0
  97. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/services/__init__.py +0 -0
  98. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/services/async_service.py +0 -0
  99. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/__init__.py +0 -0
  100. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/caching.py +0 -0
  101. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/http_client.py +0 -0
  102. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/http_request.py +0 -0
  103. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/http_status.py +0 -0
  104. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/image.py +0 -0
  105. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/mcp_client.py +0 -0
  106. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/renderers.py +0 -0
  107. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/resolvers.py +0 -0
  108. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/ssh_client.py +0 -0
  109. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/streaming.py +0 -0
  110. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/time.py +0 -0
  111. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/utils/workqueue.py +0 -0
  112. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/__init__.py +0 -0
  113. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/__init__.py +0 -0
  114. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/base.py +0 -0
  115. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/__init__.py +0 -0
  116. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/action.py +0 -0
  117. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/delay.py +0 -0
  118. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/if_.py +0 -0
  119. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/random_router.py +0 -0
  120. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/switch.py +0 -0
  121. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/core/workflow/job/job.py +0 -0
  122. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/__init__.py +0 -0
  123. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/loader.py +0 -0
  124. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/__init__.py +0 -0
  125. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/__init__.py +0 -0
  126. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/action.py +0 -0
  127. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  128. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  129. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  130. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
  131. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  132. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  133. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  134. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  135. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  136. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  137. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
  138. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  139. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/__init__.py +0 -0
  140. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/component.py +0 -0
  141. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  142. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/common.py +0 -0
  143. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
  144. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
  145. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -0
  146. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  147. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  148. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
  149. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -0
  150. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
  151. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -0
  152. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -0
  153. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -0
  154. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  155. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  156. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  157. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/text_splitter.py +0 -0
  158. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  159. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  160. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/compose.py +0 -0
  161. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  162. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/controller.py +0 -0
  163. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  164. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  165. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
  166. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
  167. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
  168. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
  169. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
  170. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/webui.py +0 -0
  171. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  172. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  173. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  174. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
  175. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  176. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  177. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/__init__.py +0 -0
  178. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/__init__.py +0 -0
  179. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/action.py +0 -0
  180. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/common.py +0 -0
  181. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
  182. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
  183. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
  184. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
  185. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/types.py +0 -0
  186. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/job/job.py +0 -0
  187. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  188. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  189. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
  190. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
  191. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  192. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/listener.py +0 -0
  193. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  194. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  195. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  196. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  197. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  198. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  199. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/logger.py +0 -0
  200. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  201. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  202. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  203. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  204. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  205. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  206. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  207. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/schema/workflow.py +0 -0
  208. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/utils/__init__.py +0 -0
  209. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/utils/annotation.py +0 -0
  210. {model_compose-0.3.5 → model_compose-0.3.7}/src/mindor/dsl/utils/enum.py +0 -0
  211. {model_compose-0.3.5 → model_compose-0.3.7}/src/model_compose.egg-info/dependency_links.txt +0 -0
  212. {model_compose-0.3.5 → model_compose-0.3.7}/src/model_compose.egg-info/entry_points.txt +0 -0
  213. {model_compose-0.3.5 → model_compose-0.3.7}/src/model_compose.egg-info/requires.txt +0 -0
  214. {model_compose-0.3.5 → model_compose-0.3.7}/src/model_compose.egg-info/top_level.txt +0 -0
  215. {model_compose-0.3.5 → model_compose-0.3.7}/tests/test_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: model-compose
3
- Version: 0.3.5
3
+ Version: 0.3.7
4
4
  Summary: model-compose: Declarative AI Model and Workflow Orchestrator
5
5
  Author-email: Hanyeol Cho <hanyeol.cho@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "model-compose"
3
- version = "0.3.5"
3
+ version = "0.3.7"
4
4
  description = "model-compose: Declarative AI Model and Workflow Orchestrator"
5
5
  authors = [
6
6
  { name = "Hanyeol Cho", email = "hanyeol.cho@gmail.com" }
@@ -4,14 +4,14 @@ from pathlib import Path
4
4
  import asyncio
5
5
 
6
6
  from mindor.dsl.loader import load_compose_config
7
- from mindor.core.runtime.env import load_env_files
7
+ from mindor.core.runtime.env import load_env_files, merge_env_data
8
8
  from mindor.core.compose import *
9
9
 
10
10
  @click.group()
11
11
  @click.option(
12
12
  "--file", "-f", "config_files", multiple=True,
13
13
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
14
- help="Compose configuration files"
14
+ help="Compose configuration files."
15
15
  )
16
16
  @click.pass_context
17
17
  def compose_command(ctx: click.Context, config_files: List[Path]) -> None:
@@ -44,6 +44,7 @@ def up_command(
44
44
  async def _async_command():
45
45
  try:
46
46
  env = load_env_files(".", env_files or [])
47
+ env = merge_env_data(env, env_data)
47
48
  config = load_compose_config(".", config_files, env)
48
49
  await launch_services(config, detach, verbose)
49
50
  except Exception as e:
@@ -73,6 +74,7 @@ def down_command(
73
74
  async def _async_command():
74
75
  try:
75
76
  env = load_env_files(".", env_files or [])
77
+ env = merge_env_data(env, env_data)
76
78
  config = load_compose_config(".", config_files, env)
77
79
  await terminate_services(config, verbose)
78
80
  except Exception as e:
@@ -102,6 +104,7 @@ def start_command(
102
104
  async def _async_command():
103
105
  try:
104
106
  env = load_env_files(".", env_files or [])
107
+ env = merge_env_data(env, env_data)
105
108
  config = load_compose_config(".", config_files, env)
106
109
  await start_services(config, verbose)
107
110
  except Exception as e:
@@ -131,6 +134,7 @@ def stop_command(
131
134
  async def _async_command():
132
135
  try:
133
136
  env = load_env_files(".", env_files or [])
137
+ env = merge_env_data(env, env_data)
134
138
  config = load_compose_config(".", config_files, env)
135
139
  await stop_services(config, verbose)
136
140
  except Exception as e:
@@ -176,6 +180,7 @@ def run_command(
176
180
  async def _async_command():
177
181
  try:
178
182
  env = load_env_files(".", env_files or [])
183
+ env = merge_env_data(env, env_data)
179
184
  config = load_compose_config(".", config_files, env)
180
185
  input = json.loads(input_json) if input_json else {}
181
186
  state = await run_workflow(config, workflow_id, input, output_path, verbose)
@@ -57,6 +57,12 @@ class ComponentService(AsyncService):
57
57
  if self.config.max_concurrent_count > 0:
58
58
  self.queue = WorkQueue(self.config.max_concurrent_count, self._run)
59
59
 
60
+ async def install(self) -> None:
61
+ await self._install()
62
+
63
+ async def build(self) -> None:
64
+ await self._build()
65
+
60
66
  async def run(self, action_id: Union[str, None], run_id: str, input: Dict[str, Any]) -> Dict[str, Any]:
61
67
  _, action = ActionResolver(self.config.actions).resolve(action_id)
62
68
  context = ComponentActionContext(run_id, input)
@@ -66,6 +72,12 @@ class ComponentService(AsyncService):
66
72
 
67
73
  return await self._run(action, context)
68
74
 
75
+ async def _install(self) -> None:
76
+ pass
77
+
78
+ async def _build(self) -> None:
79
+ pass
80
+
69
81
  async def _start(self) -> None:
70
82
  if self.queue:
71
83
  await self.queue.start()
@@ -19,17 +19,23 @@ class ComponentActionContext:
19
19
  async def _resolve_source(self, key: str, index: Optional[int]) -> Any:
20
20
  if key in self.sources:
21
21
  return self.sources[key][index] if index is not None else self.sources[key]
22
+
22
23
  if key == "input":
23
24
  return self.input
25
+
24
26
  if key == "context":
25
27
  return self.context
28
+
26
29
  if key.startswith("gateway:"):
27
30
  return self._resolve_gateway(key)
31
+
28
32
  raise KeyError(f"Unknown source: {key}")
29
33
 
30
34
  def _resolve_gateway(self, key: str) -> Any:
31
35
  _, port = key.split(":")
32
36
  gateway = find_gateway_by_port(int(port)) if port else None
37
+
33
38
  if gateway:
34
39
  return gateway.get_context()
40
+
35
41
  return None
@@ -0,0 +1,133 @@
1
+ from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Callable, Any
2
+ from abc import ABC, abstractmethod
3
+ from mindor.dsl.schema.component import HttpServerComponentConfig
4
+ from mindor.dsl.schema.action import ActionConfig, HttpServerActionConfig, HttpServerCompletionType, HttpServerCompletionConfig
5
+ from mindor.core.listener import HttpCallbackListener
6
+ from mindor.core.utils.http_client import HttpClient
7
+ from mindor.core.utils.http_status import is_status_code_matched
8
+ from mindor.core.utils.time import parse_duration
9
+ from mindor.core.utils.shell import run_command_streaming
10
+ from ..base import ComponentService, ComponentType, ComponentGlobalConfigs, register_component
11
+ from ..context import ComponentActionContext
12
+ from datetime import datetime, timezone
13
+ import asyncio, os
14
+
15
+ class HttpServerCompletion(ABC):
16
+ def __init__(self, config: HttpServerCompletionConfig):
17
+ self.config: HttpServerCompletionConfig = config
18
+
19
+ @abstractmethod
20
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
21
+ pass
22
+
23
+ class HttpServerPollingCompletion(HttpServerCompletion):
24
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
25
+ path = await context.render_variable(self.config.path)
26
+ method = await context.render_variable(self.config.method)
27
+ params = await context.render_variable(self.config.params)
28
+ body = await context.render_variable(self.config.body)
29
+ headers = await context.render_variable(self.config.headers)
30
+
31
+ interval = parse_duration((await context.render_variable(self.config.interval)) or 5.0)
32
+ timeout = parse_duration((await context.render_variable(self.config.timeout)) or 300.0)
33
+ deadline = datetime.now(timezone.utc) + timeout
34
+
35
+ await asyncio.sleep(interval.total_seconds())
36
+
37
+ while datetime.now(timezone.utc) < deadline:
38
+ response, status_code = await client.request(path or "", method, params, body, headers, raise_on_error=False)
39
+ context.register_source("result", response)
40
+
41
+ status = (await context.render_variable(self.config.status)) if self.config.status else None
42
+ if status:
43
+ if status in (self.config.success_when or []):
44
+ return response
45
+ if status in (self.config.fail_when or []):
46
+ raise RuntimeError(f"Polling failed: status '{status}' matched a failure condition.")
47
+ else: # use status code
48
+ if is_status_code_matched(status_code, self.config.success_when or []):
49
+ return response
50
+ if is_status_code_matched(status_code, self.config.fail_when or []):
51
+ raise RuntimeError(f"Polling failed: status code '{status_code}' matched a failure condition.")
52
+
53
+ await asyncio.sleep(interval.total_seconds())
54
+
55
+ raise TimeoutError(f"Polling timed out after {timeout}.")
56
+
57
+ class HttpServerCallbackCompletion(HttpServerCompletion):
58
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
59
+ callback_id = await context.render_variable(self.config.wait_for)
60
+ future: asyncio.Future = asyncio.get_running_loop().create_future()
61
+ HttpCallbackListener.register_pending_future(callback_id, future)
62
+
63
+ return await future
64
+
65
+ class HttpServerAction:
66
+ def __init__(self, config: HttpServerActionConfig):
67
+ self.config: HttpServerActionConfig = config
68
+ self.completion: HttpServerCompletion = None
69
+
70
+ if self.config.completion:
71
+ self._configure_completion()
72
+
73
+ def _configure_completion(self) -> None:
74
+ if self.config.completion.type == HttpServerCompletionType.POLLING:
75
+ self.completion = HttpServerPollingCompletion(self.config.completion)
76
+ return
77
+
78
+ if self.config.completion.type == HttpServerCompletionType.CALLBACK:
79
+ self.completion = HttpServerCallbackCompletion(self.config.completion)
80
+ return
81
+
82
+ raise ValueError(f"Unsupported http completion type: {self.config.completion.type}")
83
+
84
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
85
+ path = await context.render_variable(self.config.path)
86
+ method = await context.render_variable(self.config.method)
87
+ params = await context.render_variable(self.config.params)
88
+ body = await context.render_variable(self.config.body)
89
+ headers = await context.render_variable(self.config.headers)
90
+
91
+ response, result = await client.request(path or "", method, params, body, headers), None
92
+ context.register_source("response", response)
93
+
94
+ if self.completion:
95
+ result = await self.completion.run(context, client)
96
+ context.register_source("result", result)
97
+
98
+ return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else (result or response)
99
+
100
+ @register_component(ComponentType.HTTP_SERVER)
101
+ class HttpServerComponent(ComponentService):
102
+ def __init__(self, id: str, config: HttpServerComponentConfig, global_configs: ComponentGlobalConfigs, daemon: bool):
103
+ super().__init__(id, config, global_configs, daemon)
104
+
105
+ self.client: Optional[HttpClient] = None
106
+
107
+ async def _install(self) -> None:
108
+ if self.config.commands.install:
109
+ await run_command_streaming(self.config.commands.install, self.config.working_dir, self.config.env)
110
+
111
+ async def _build(self) -> None:
112
+ if self.config.commands.build:
113
+ await run_command_streaming(self.config.commands.build, self.config.working_dir, self.config.env)
114
+
115
+ async def _start(self) -> None:
116
+ base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
117
+ self.client = HttpClient(base_url, self.config.headers)
118
+ await super()._start()
119
+
120
+ async def _stop(self) -> None:
121
+ await super()._stop()
122
+ await self.client.close()
123
+ self.client = None
124
+
125
+ async def _serve(self) -> None:
126
+ if self.config.commands.start:
127
+ await run_command_streaming(self.config.commands.start, self.config.working_dir, self.config.env, block=False)
128
+
129
+ async def _shutdown(self) -> None:
130
+ pass
131
+
132
+ async def _run(self, action: ActionConfig, context: ComponentActionContext) -> Any:
133
+ return await HttpServerAction(action).run(context, self.client)
@@ -5,7 +5,6 @@ from mindor.dsl.schema.action import ModelActionConfig
5
5
  from mindor.core.services import AsyncService
6
6
  from ...context import ComponentActionContext
7
7
  from transformers import PreTrainedModel, PreTrainedTokenizer
8
- from threading import Thread
9
8
  import torch, asyncio
10
9
 
11
10
  class ModelTaskService(AsyncService):
@@ -16,13 +15,15 @@ class ModelTaskService(AsyncService):
16
15
  self.config: ModelComponentConfig = config
17
16
 
18
17
  async def run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
18
+ loop: asyncio.AbstractEventLoop = asyncio.get_running_loop()
19
+
19
20
  async def _run():
20
- return await self._run(action, context)
21
+ return await self._run(action, context, loop)
21
22
 
22
23
  return await self.run_in_thread(_run)
23
24
 
24
25
  @abstractmethod
25
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
26
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
26
27
  pass
27
28
 
28
29
  def _load_pretrained_model(self, extra_params: Optional[Dict[str, Any]] = None) -> PreTrainedModel:
@@ -1,12 +1,14 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
2
  from mindor.dsl.schema.component import ModelComponentConfig
3
3
  from mindor.dsl.schema.action import ModelActionConfig, SummarizationModelActionConfig
4
+ from mindor.core.utils.streamer import AsyncStreamer
4
5
  from mindor.core.logger import logging
5
6
  from ..base import ModelTaskService, ModelTaskType, register_model_task_service
6
7
  from ..base import ComponentActionContext
7
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin
8
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin, TextIteratorStreamer
9
+ from threading import Thread
8
10
  from torch import Tensor
9
- import torch
11
+ import torch, asyncio
10
12
 
11
13
  class SummarizationTaskAction:
12
14
  def __init__(self, config: SummarizationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
@@ -15,46 +17,71 @@ class SummarizationTaskAction:
15
17
  self.tokenizer: PreTrainedTokenizer = tokenizer
16
18
  self.device: torch.device = device
17
19
 
18
- async def run(self, context: ComponentActionContext) -> Any:
20
+ async def run(self, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
19
21
  text: Union[str, List[str]] = await context.render_variable(self.config.text)
20
22
 
21
23
  max_input_length = await context.render_variable(self.config.params.max_input_length)
22
24
  max_output_length = await context.render_variable(self.config.params.max_output_length)
23
25
  min_output_length = await context.render_variable(self.config.params.min_output_length)
24
26
  num_beams = await context.render_variable(self.config.params.num_beams)
25
- length_penalty = await context.render_variable(self.config.params.length_penalty)
26
- early_stopping = await context.render_variable(self.config.params.early_stopping)
27
+ length_penalty = await context.render_variable(self.config.params.length_penalty) if num_beams > 1 else None
28
+ early_stopping = await context.render_variable(self.config.params.early_stopping) if num_beams > 1 else False
27
29
  do_sample = await context.render_variable(self.config.params.do_sample)
30
+ top_k = await context.render_variable(self.config.params.top_k) if do_sample else None
31
+ top_p = await context.render_variable(self.config.params.top_p) if do_sample else None
28
32
  batch_size = await context.render_variable(self.config.params.batch_size)
33
+ stream = await context.render_variable(self.config.stream)
29
34
 
30
35
  texts: List[str] = [ text ] if isinstance(text, str) else text
31
36
  results = []
32
37
 
38
+ if stream and (batch_size != 1 or len(texts) != 1):
39
+ raise ValueError("Streaming mode only supports a single input text with batch size of 1.")
40
+
41
+ streamer = TextIteratorStreamer(self.tokenizer, skip_prompt=True, skip_special_tokens=True) if stream else None
33
42
  for index in range(0, len(texts), batch_size):
34
43
  batch_texts = texts[index:index + batch_size]
35
44
  inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
36
45
  inputs = { k: v.to(self.device) for k, v in inputs.items() }
37
46
 
38
- with torch.no_grad():
39
- outputs = self.model.generate(
40
- **inputs,
41
- max_length=max_output_length,
42
- min_length=min_output_length,
43
- num_beams=num_beams,
44
- length_penalty=length_penalty,
45
- early_stopping=early_stopping,
46
- do_sample=do_sample,
47
- pad_token_id=getattr(self.tokenizer, "pad_token_id", None),
48
- eos_token_id=getattr(self.tokenizer, "eos_token_id", None)
49
- )
50
-
51
- outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
52
- results.extend(outputs)
53
-
54
- result = results if len(results) > 1 else results[0]
55
- context.register_source("result", result)
56
-
57
- return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
47
+ def _generate():
48
+ with torch.no_grad():
49
+ outputs = self.model.generate(
50
+ **inputs,
51
+ max_length=max_output_length,
52
+ min_length=min_output_length,
53
+ num_beams=num_beams,
54
+ length_penalty=length_penalty,
55
+ early_stopping=early_stopping,
56
+ do_sample=do_sample,
57
+ top_k=top_k,
58
+ top_p=top_p,
59
+ pad_token_id=getattr(self.tokenizer, "pad_token_id", None),
60
+ eos_token_id=getattr(self.tokenizer, "eos_token_id", None),
61
+ streamer=streamer
62
+ )
63
+
64
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
65
+ results.extend(outputs)
66
+
67
+ if stream:
68
+ thread = Thread(target=_generate)
69
+ thread.start()
70
+ else:
71
+ _generate()
72
+
73
+ if stream:
74
+ async def _stream_generator():
75
+ async for result in AsyncStreamer(streamer, loop):
76
+ context.register_source("result", result)
77
+ yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
78
+
79
+ return _stream_generator()
80
+ else:
81
+ result = results if len(results) > 1 else results[0]
82
+ context.register_source("result", result)
83
+
84
+ return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
58
85
 
59
86
  @register_model_task_service(ModelTaskType.SUMMARIZATION)
60
87
  class SummarizationTaskService(ModelTaskService):
@@ -80,8 +107,8 @@ class SummarizationTaskService(ModelTaskService):
80
107
  self.tokenizer = None
81
108
  self.device = None
82
109
 
83
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
84
- return await SummarizationTaskAction(action, self.model, self.tokenizer, self.device).run(context)
110
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
111
+ return await SummarizationTaskAction(action, self.model, self.tokenizer, self.device).run(context, loop)
85
112
 
86
113
  def _get_model_class(self) -> Type[PreTrainedModel]:
87
114
  return AutoModelForSeq2SeqLM
@@ -8,7 +8,7 @@ from transformers import AutoModelForSequenceClassification, AutoTokenizer, PreT
8
8
  from transformers.modeling_outputs import SequenceClassifierOutput
9
9
  import torch.nn.functional as F
10
10
  from torch import Tensor
11
- import torch
11
+ import torch, asyncio
12
12
 
13
13
  class TextClassificationTaskAction:
14
14
  def __init__(self, config: TextClassificationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
@@ -80,7 +80,7 @@ class TextClassificationTaskService(ModelTaskService):
80
80
  self.tokenizer = None
81
81
  self.device = None
82
82
 
83
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
83
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
84
84
  return await TextClassificationTaskAction(action, self.model, self.tokenizer, self.device).run(context, self.config.labels)
85
85
 
86
86
  def _get_model_class(self) -> Type[PreTrainedModel]:
@@ -7,7 +7,7 @@ from ..base import ComponentActionContext
7
7
  from transformers import AutoModel, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer
8
8
  from transformers.modeling_outputs import BaseModelOutput
9
9
  from torch import Tensor
10
- import torch
10
+ import torch, asyncio
11
11
 
12
12
  class TextEmbeddingTaskAction:
13
13
  def __init__(self, config: TextEmbeddingModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
@@ -94,7 +94,7 @@ class TextEmbeddingTaskService(ModelTaskService):
94
94
  self.tokenizer = None
95
95
  self.device = None
96
96
 
97
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
97
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
98
98
  return await TextEmbeddingTaskAction(action, self.model, self.tokenizer, self.device).run(context)
99
99
 
100
100
  def _get_model_class(self) -> Type[PreTrainedModel]:
@@ -1,12 +1,14 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
2
  from mindor.dsl.schema.component import ModelComponentConfig
3
3
  from mindor.dsl.schema.action import ModelActionConfig, TextGenerationModelActionConfig
4
+ from mindor.core.utils.streamer import AsyncStreamer
4
5
  from mindor.core.logger import logging
5
6
  from ..base import ModelTaskService, ModelTaskType, register_model_task_service
6
7
  from ..base import ComponentActionContext
7
- from transformers import AutoModelForCausalLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin
8
+ from transformers import AutoModelForCausalLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin, TextIteratorStreamer
9
+ from threading import Thread
8
10
  from torch import Tensor
9
- import torch
11
+ import torch, asyncio
10
12
 
11
13
  class TextGenerationTaskAction:
12
14
  def __init__(self, config: TextGenerationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
@@ -15,7 +17,7 @@ class TextGenerationTaskAction:
15
17
  self.tokenizer: PreTrainedTokenizer = tokenizer
16
18
  self.device: torch.device = device
17
19
 
18
- async def run(self, context: ComponentActionContext) -> Any:
20
+ async def run(self, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
19
21
  prompt: Union[str, List[str]] = await context.render_variable(self.config.prompt)
20
22
 
21
23
  max_output_length = await context.render_variable(self.config.params.max_output_length)
@@ -24,33 +26,54 @@ class TextGenerationTaskAction:
24
26
  top_k = await context.render_variable(self.config.params.top_k)
25
27
  top_p = await context.render_variable(self.config.params.top_p)
26
28
  batch_size = await context.render_variable(self.config.params.batch_size)
29
+ stream = await context.render_variable(self.config.stream)
27
30
 
28
31
  prompts: List[str] = [ prompt ] if isinstance(prompt, str) else prompt
29
32
  results = []
30
33
 
34
+ if stream and (batch_size != 1 or len(prompts) != 1):
35
+ raise ValueError("Streaming mode only supports a single input prompt with batch size of 1.")
36
+
37
+ streamer = TextIteratorStreamer(self.tokenizer, skip_prompt=True, skip_special_tokens=True) if stream else None
31
38
  for index in range(0, len(prompts), batch_size):
32
39
  batch_prompts = prompts[index:index + batch_size]
33
40
  inputs: Dict[str, Tensor] = self.tokenizer(batch_prompts, return_tensors="pt", padding=True, truncation=True)
34
41
  inputs = { k: v.to(self.device) for k, v in inputs.items() }
35
42
 
36
- with torch.no_grad():
37
- outputs = self.model.generate(
38
- **inputs,
39
- max_new_tokens=max_output_length,
40
- num_return_sequences=num_return_sequences,
41
- temperature=temperature,
42
- top_k=top_k,
43
- top_p=top_p,
44
- do_sample=True
45
- )
46
-
47
- outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
48
- results.extend(outputs)
49
-
50
- result = results if len(results) > 1 else results[0]
51
- context.register_source("result", result)
52
-
53
- return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
43
+ def _generate():
44
+ with torch.no_grad():
45
+ outputs = self.model.generate(
46
+ **inputs,
47
+ max_new_tokens=max_output_length,
48
+ num_return_sequences=num_return_sequences,
49
+ temperature=temperature,
50
+ do_sample=True,
51
+ top_k=top_k,
52
+ top_p=top_p,
53
+ streamer=streamer
54
+ )
55
+
56
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
57
+ results.extend(outputs)
58
+
59
+ if stream:
60
+ thread = Thread(target=_generate)
61
+ thread.start()
62
+ else:
63
+ _generate()
64
+
65
+ if stream:
66
+ async def _stream_generator():
67
+ async for result in AsyncStreamer(streamer, loop):
68
+ context.register_source("result", result)
69
+ yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
70
+
71
+ return _stream_generator()
72
+ else:
73
+ result = results if len(results) > 1 else results[0]
74
+ context.register_source("result", result)
75
+
76
+ return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
54
77
 
55
78
  @register_model_task_service(ModelTaskType.TEXT_GENERATION)
56
79
  class TextGenerationTaskService(ModelTaskService):
@@ -76,8 +99,8 @@ class TextGenerationTaskService(ModelTaskService):
76
99
  self.tokenizer = None
77
100
  self.device = None
78
101
 
79
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
80
- return await TextGenerationTaskAction(action, self.model, self.tokenizer, self.device).run(context)
102
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
103
+ return await TextGenerationTaskAction(action, self.model, self.tokenizer, self.device).run(context, loop)
81
104
 
82
105
  def _get_model_class(self) -> Type[PreTrainedModel]:
83
106
  return AutoModelForCausalLM