model-compose 0.3.5__tar.gz → 0.3.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. {model_compose-0.3.5/src/model_compose.egg-info → model_compose-0.3.6}/PKG-INFO +1 -1
  2. {model_compose-0.3.5 → model_compose-0.3.6}/pyproject.toml +1 -1
  3. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/base.py +4 -3
  4. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/summarization.py +54 -27
  5. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/text_classification.py +2 -2
  6. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/text_embedding.py +2 -2
  7. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/text_generation.py +46 -23
  8. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/translation.py +55 -25
  9. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/services/http_server.py +41 -18
  10. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/webui/gradio.py +7 -4
  11. model_compose-0.3.6/src/mindor/core/utils/streamer.py +29 -0
  12. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/workflow.py +3 -1
  13. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/common.py +2 -2
  14. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +3 -1
  15. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +1 -1
  16. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +4 -0
  17. {model_compose-0.3.5 → model_compose-0.3.6/src/model_compose.egg-info}/PKG-INFO +1 -1
  18. {model_compose-0.3.5 → model_compose-0.3.6}/src/model_compose.egg-info/SOURCES.txt +1 -0
  19. {model_compose-0.3.5 → model_compose-0.3.6}/LICENSE +0 -0
  20. {model_compose-0.3.5 → model_compose-0.3.6}/README.md +0 -0
  21. {model_compose-0.3.5 → model_compose-0.3.6}/setup.cfg +0 -0
  22. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/__init__.py +0 -0
  23. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/cli/__init__.py +0 -0
  24. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/cli/compose.py +0 -0
  25. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/__init__.py +0 -0
  26. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/__init__.py +0 -0
  27. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/base.py +0 -0
  28. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/component.py +0 -0
  29. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/context.py +0 -0
  30. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/__init__.py +0 -0
  31. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/http_client.py +0 -0
  32. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/http_server.py +0 -0
  33. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/mcp_client.py +0 -0
  34. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/mcp_server.py +0 -0
  35. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/__init__.py +0 -0
  36. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/model.py +0 -0
  37. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  38. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/shell.py +0 -0
  39. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/text_splitter.py +0 -0
  40. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/component/services/workflow.py +0 -0
  41. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/compose/__init__.py +0 -0
  42. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/compose/compose.py +0 -0
  43. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/compose/manager.py +0 -0
  44. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/__init__.py +0 -0
  45. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/base.py +0 -0
  46. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/controller.py +0 -0
  47. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runner/__init__.py +0 -0
  48. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runner/client.py +0 -0
  49. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runner/http_client.py +0 -0
  50. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runner/mcp_client.py +0 -0
  51. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runner/runner.py +0 -0
  52. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runtime/__init__.py +0 -0
  53. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  54. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
  55. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
  56. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/runtime/specs.py +0 -0
  57. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/services/__init__.py +0 -0
  58. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/services/mcp_server.py +0 -0
  59. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/webui/__init__.py +0 -0
  60. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/controller/webui/webui.py +0 -0
  61. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/__init__.py +0 -0
  62. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/base.py +0 -0
  63. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/gateway.py +0 -0
  64. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/services/__init__.py +0 -0
  65. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  66. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  67. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/listener/__init__.py +0 -0
  68. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/listener/base.py +0 -0
  69. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/listener/listener.py +0 -0
  70. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/listener/services/__init__.py +0 -0
  71. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/listener/services/http_callback.py +0 -0
  72. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/__init__.py +0 -0
  73. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/base.py +0 -0
  74. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/logger.py +0 -0
  75. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/logging.py +0 -0
  76. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/services/__init__.py +0 -0
  77. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/services/console.py +0 -0
  78. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/logger/services/file.py +0 -0
  79. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/runtime/__init__.py +0 -0
  80. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/runtime/docker/__init__.py +0 -0
  81. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/runtime/docker/docker.py +0 -0
  82. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/runtime/env.py +0 -0
  83. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/services/__init__.py +0 -0
  84. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/services/async_service.py +0 -0
  85. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/__init__.py +0 -0
  86. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/caching.py +0 -0
  87. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/http_client.py +0 -0
  88. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/http_request.py +0 -0
  89. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/http_status.py +0 -0
  90. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/image.py +0 -0
  91. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/mcp_client.py +0 -0
  92. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/renderers.py +0 -0
  93. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/resolvers.py +0 -0
  94. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/ssh_client.py +0 -0
  95. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/streaming.py +0 -0
  96. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/time.py +0 -0
  97. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/utils/workqueue.py +0 -0
  98. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/__init__.py +0 -0
  99. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/context.py +0 -0
  100. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/__init__.py +0 -0
  101. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/base.py +0 -0
  102. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/__init__.py +0 -0
  103. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/action.py +0 -0
  104. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/delay.py +0 -0
  105. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/if_.py +0 -0
  106. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/random_router.py +0 -0
  107. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/impl/switch.py +0 -0
  108. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/job/job.py +0 -0
  109. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/core/workflow/schema.py +0 -0
  110. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/__init__.py +0 -0
  111. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/loader.py +0 -0
  112. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/__init__.py +0 -0
  113. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/__init__.py +0 -0
  114. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/action.py +0 -0
  115. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  116. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  117. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/http_client.py +0 -0
  118. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/http_server.py +0 -0
  119. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  120. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
  121. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  122. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  123. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  124. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  125. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  126. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  127. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
  128. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  129. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/__init__.py +0 -0
  130. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/component.py +0 -0
  131. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  132. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/common.py +0 -0
  133. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
  134. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/http_server.py +0 -0
  135. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
  136. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -0
  137. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  138. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  139. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
  140. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -0
  141. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
  142. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -0
  143. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -0
  144. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -0
  145. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  146. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  147. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  148. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/text_splitter.py +0 -0
  149. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  150. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  151. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/compose.py +0 -0
  152. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  153. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/controller.py +0 -0
  154. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  155. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
  156. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/impl/http_server.py +0 -0
  157. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/impl/mcp_server.py +0 -0
  158. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  159. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
  160. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
  161. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/impl/common.py +0 -0
  162. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
  163. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
  164. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
  165. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/controller/webui/webui.py +0 -0
  166. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  167. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  168. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  169. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/impl/common.py +0 -0
  170. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
  171. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  172. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  173. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/__init__.py +0 -0
  174. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/__init__.py +0 -0
  175. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/action.py +0 -0
  176. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/common.py +0 -0
  177. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
  178. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
  179. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
  180. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
  181. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/impl/types.py +0 -0
  182. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/job/job.py +0 -0
  183. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  184. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  185. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
  186. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
  187. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  188. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/listener/listener.py +0 -0
  189. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  190. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  191. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  192. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  193. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  194. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  195. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/logger/logger.py +0 -0
  196. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  197. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  198. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  199. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  200. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  201. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  202. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  203. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/schema/workflow.py +0 -0
  204. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/utils/__init__.py +0 -0
  205. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/utils/annotation.py +0 -0
  206. {model_compose-0.3.5 → model_compose-0.3.6}/src/mindor/dsl/utils/enum.py +0 -0
  207. {model_compose-0.3.5 → model_compose-0.3.6}/src/model_compose.egg-info/dependency_links.txt +0 -0
  208. {model_compose-0.3.5 → model_compose-0.3.6}/src/model_compose.egg-info/entry_points.txt +0 -0
  209. {model_compose-0.3.5 → model_compose-0.3.6}/src/model_compose.egg-info/requires.txt +0 -0
  210. {model_compose-0.3.5 → model_compose-0.3.6}/src/model_compose.egg-info/top_level.txt +0 -0
  211. {model_compose-0.3.5 → model_compose-0.3.6}/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.6
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.6"
4
4
  description = "model-compose: Declarative AI Model and Workflow Orchestrator"
5
5
  authors = [
6
6
  { name = "Hanyeol Cho", email = "hanyeol.cho@gmail.com" }
@@ -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
@@ -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, TranslationModelActionConfig
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 TranslationTaskAction:
12
14
  def __init__(self, config: TranslationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
@@ -15,43 +17,71 @@ class TranslationTaskAction:
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)
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
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
26
32
  batch_size = await context.render_variable(self.config.params.batch_size)
33
+ stream = await context.render_variable(self.config.stream)
27
34
 
28
35
  texts: List[str] = [ text ] if isinstance(text, str) else text
29
36
  results = []
30
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
31
42
  for index in range(0, len(texts), batch_size):
32
43
  batch_texts = texts[index:index + batch_size]
33
44
  inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
34
45
  inputs = { k: v.to(self.device) for k, v in inputs.items() }
35
46
 
36
- with torch.no_grad():
37
- outputs = self.model.generate(
38
- **inputs,
39
- max_length=max_output_length,
40
- min_length=min_output_length,
41
- num_beams=num_beams,
42
- length_penalty=length_penalty,
43
- do_sample=False,
44
- pad_token_id=getattr(self.tokenizer, "pad_token_id", None),
45
- eos_token_id=getattr(self.tokenizer, "eos_token_id", None)
46
- )
47
-
48
- outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
49
- results.extend(outputs)
50
-
51
- result = results if len(results) > 1 else results[0]
52
- context.register_source("result", result)
53
-
54
- 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
55
85
 
56
86
  @register_model_task_service(ModelTaskType.TRANSLATION)
57
87
  class TranslationTaskService(ModelTaskService):
@@ -77,8 +107,8 @@ class TranslationTaskService(ModelTaskService):
77
107
  self.tokenizer = None
78
108
  self.device = None
79
109
 
80
- async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
81
- return await TranslationTaskAction(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 TranslationTaskAction(action, self.model, self.tokenizer, self.device).run(context, loop)
82
112
 
83
113
  def _get_model_class(self) -> Type[PreTrainedModel]:
84
114
  return AutoModelForSeq2SeqLM
@@ -1,4 +1,5 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, AsyncIterator, Any
2
+ from types import AsyncGeneratorType
2
3
  from typing_extensions import Self
3
4
  from pydantic import BaseModel
4
5
  from mindor.dsl.schema.controller import HttpServerControllerConfig
@@ -15,7 +16,7 @@ from fastapi import FastAPI, APIRouter, Request, Body, HTTPException
15
16
  from fastapi.middleware.cors import CORSMiddleware
16
17
  from fastapi.responses import Response, JSONResponse, StreamingResponse
17
18
  from starlette.background import BackgroundTask
18
- import uvicorn
19
+ import uvicorn, json
19
20
 
20
21
  class WorkflowTaskRequestBody(BaseModel):
21
22
  workflow_id: Optional[str] = None
@@ -80,6 +81,9 @@ class HttpServerController(ControllerService):
80
81
  if body.output_only and not body.wait_for_completion:
81
82
  raise HTTPException(status_code=400, detail="output_only requires wait_for_completion=true.")
82
83
 
84
+ if not body.output_only and isinstance(state.output, (StreamResource, AsyncGeneratorType)):
85
+ raise HTTPException(status_code=400, detail="Streaming output is only allowed when output_only=true.")
86
+
83
87
  if body.output_only:
84
88
  return self._render_task_output(state)
85
89
 
@@ -95,6 +99,9 @@ class HttpServerController(ControllerService):
95
99
  if not state:
96
100
  raise HTTPException(status_code=404, detail="Task not found.")
97
101
 
102
+ if not output_only and isinstance(state.output, (StreamResource, AsyncGeneratorType)):
103
+ raise HTTPException(status_code=400, detail="Streaming output is only allowed when output_only=true.")
104
+
98
105
  if output_only:
99
106
  return self._render_task_output(state)
100
107
 
@@ -138,13 +145,44 @@ class HttpServerController(ControllerService):
138
145
  if state.status == TaskStatus.FAILED:
139
146
  raise HTTPException(status_code=500, detail=str(state.error))
140
147
 
148
+ if isinstance(state.output, AsyncGeneratorType):
149
+ return self._render_async_generator(state.output)
150
+
141
151
  if isinstance(state.output, HttpEventStreamResource):
142
152
  return self._render_event_stream_resource(state.output)
143
153
 
144
154
  if isinstance(state.output, StreamResource):
145
155
  return self._render_stream_resource(state.output)
146
-
156
+
147
157
  return JSONResponse(content=state.output)
158
+
159
+ def _render_async_generator(self, generator: AsyncGeneratorType) -> Response:
160
+ async def _event_generator() -> AsyncIterator[bytes]:
161
+ async for chunk in generator:
162
+ if not isinstance(chunk, str):
163
+ chunk = json.dumps()
164
+ yield b"data: " + chunk.encode("utf-8") + b"\n\n"
165
+
166
+ return StreamingResponse(
167
+ _event_generator(),
168
+ media_type="text/event-stream",
169
+ headers={ "Cache-Control": "no-cache" }
170
+ )
171
+
172
+ def _render_event_stream_resource(self, resource: HttpEventStreamResource) -> Response:
173
+ async def _event_generator() -> AsyncIterator[bytes]:
174
+ async for chunk in resource:
175
+ yield b"data: " + chunk + b"\n\n"
176
+
177
+ async def _close_stream():
178
+ await resource.close()
179
+
180
+ return StreamingResponse(
181
+ _event_generator(),
182
+ media_type="text/event-stream",
183
+ headers={ "Cache-Control": "no-cache" },
184
+ background=BackgroundTask(_close_stream)
185
+ )
148
186
 
149
187
  def _render_stream_resource(self, resource: StreamResource) -> Response:
150
188
  async def _close_stream():
@@ -156,7 +194,7 @@ class HttpServerController(ControllerService):
156
194
  headers=self._build_stream_resource_headers(resource),
157
195
  background=BackgroundTask(_close_stream)
158
196
  )
159
-
197
+
160
198
  def _build_stream_resource_headers(self, resource: StreamResource) -> Dict[str, str]:
161
199
  headers: Dict[str, str] = { "Cache-Control": "no-cache" }
162
200
 
@@ -165,18 +203,3 @@ class HttpServerController(ControllerService):
165
203
  headers["Content-Disposition"] = f'attachment; filename="{filename}"'
166
204
 
167
205
  return headers
168
-
169
- def _render_event_stream_resource(self, resource: HttpEventStreamResource) -> Response:
170
- async def _event_generator() -> AsyncIterator[bytes]:
171
- async for chunk in resource:
172
- yield b"data: " + chunk + b"\n\n"
173
-
174
- async def _close_stream():
175
- await resource.close()
176
-
177
- return StreamingResponse(
178
- _event_generator(),
179
- media_type="text/event-stream",
180
- headers={ "Cache-Control": "no-cache" },
181
- background=BackgroundTask(_close_stream)
182
- )
@@ -194,7 +194,7 @@ class GradioWebUIBuilder:
194
194
 
195
195
  async def _convert_output_value(self, value: Any, type: WorkflowVariableType, subtype: Optional[str], format: Optional[WorkflowVariableFormat], internal: bool) -> Any:
196
196
  if format == WorkflowVariableFormat.SSE_JSON:
197
- return await self._resolve_json_field_from_value(value, subtype, format)
197
+ return await self._resolve_json_field_from_bytes(value, subtype, format)
198
198
 
199
199
  if type in [ WorkflowVariableType.STRING, WorkflowVariableType.TEXT ]:
200
200
  return await self._convert_value_to_string(value, subtype, format)
@@ -210,13 +210,16 @@ class GradioWebUIBuilder:
210
210
  async def _convert_value_to_string(self, value: Any, subtype: Optional[str], format: Optional[WorkflowVariableFormat]) -> Optional[str]:
211
211
  if isinstance(value, (dict, list)):
212
212
  return json.dumps(value)
213
+
214
+ if isinstance(value, bytes):
215
+ return value.decode("utf-8", errors="replace")
213
216
 
214
217
  if value is not None:
215
218
  return str(value)
216
-
217
- return None
218
219
 
219
- async def _resolve_json_field_from_value(self, value: Any, subtype: Optional[str], format: Optional[WorkflowVariableFormat]) -> Optional[Any]:
220
+ return None
221
+
222
+ async def _resolve_json_field_from_bytes(self, value: Any, subtype: Optional[str], format: Optional[WorkflowVariableFormat]) -> Optional[Any]:
220
223
  try:
221
224
  return self.field_resolver.resolve(json.loads(value), subtype)
222
225
  except Exception:
@@ -0,0 +1,29 @@
1
+ from types import GeneratorType
2
+ from threading import Thread
3
+ import asyncio
4
+
5
+ class AsyncStreamer:
6
+ def __init__(self, generator: GeneratorType, loop: asyncio.AbstractEventLoop):
7
+ self.generator = generator
8
+ self.loop = loop
9
+ self._queue = asyncio.Queue()
10
+ self._end_of_stream = object()
11
+
12
+ self._start_stream_watcher()
13
+
14
+ def _start_stream_watcher(self):
15
+ def _run():
16
+ for chunk in self.generator:
17
+ asyncio.run_coroutine_threadsafe(self._queue.put(chunk), self.loop)
18
+ asyncio.run_coroutine_threadsafe(self._queue.put(self._end_of_stream), self.loop)
19
+
20
+ Thread(target=_run, daemon=True).start()
21
+
22
+ def __aiter__(self):
23
+ return self
24
+
25
+ async def __anext__(self):
26
+ chunk = await self._queue.get()
27
+ if chunk is self._end_of_stream:
28
+ raise StopAsyncIteration
29
+ return chunk
@@ -1,4 +1,5 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Callable, Any
2
+ from types import GeneratorType
2
3
  from mindor.dsl.schema.workflow import WorkflowConfig, JobConfig
3
4
  from mindor.dsl.schema.component import ComponentConfig
4
5
  from mindor.core.component import ComponentGlobalConfigs
@@ -142,7 +143,8 @@ class WorkflowRunner:
142
143
  del pending_jobs[completed_job_id]
143
144
  del scheduled_job_tasks[completed_job_id]
144
145
 
145
- logging.info("[task-%s] Workflow '%s' completed in %.2f seconds.", context.task_id, self.id, workflow_time_tracker.elapsed())
146
+ if not isinstance(output, GeneratorType):
147
+ logging.info("[task-%s] Workflow '%s' completed in %.2f seconds.", context.task_id, self.id, workflow_time_tracker.elapsed())
146
148
 
147
149
  return output
148
150
 
@@ -11,8 +11,8 @@ class CommonModelActionConfig(CommonActionConfig):
11
11
  mode: ModelTaskMode = Field(..., description="Mode for model task execution.")
12
12
 
13
13
  class CommonModelInferenceActionConfig(CommonModelActionConfig):
14
- mode: ModelTaskMode = Literal[ModelTaskMode.INFERENCE]
14
+ mode: ModelTaskMode = Field(default=ModelTaskMode.INFERENCE)
15
15
  stream: bool = Field(default=False, description="Whether to enable streaming responses for inference.")
16
16
 
17
17
  class CommonModelTrainingActionConfig(CommonModelActionConfig):
18
- mode: ModelTaskMode = Literal[ModelTaskMode.TRAINING]
18
+ mode: ModelTaskMode = Field(default=ModelTaskMode.TRAINING)
@@ -10,7 +10,9 @@ class SummarizationParamsConfig(BaseModel):
10
10
  num_beams: Union[int, str] = Field(default=4, description="Number of beams to use for beam search.")
11
11
  length_penalty: Union[float, str] = Field(default=2.0, description="Length penalty applied during beam search.")
12
12
  early_stopping: bool = Field(default=True, description="Whether to stop the beam search when all beams finish generating.")
13
- do_sample: bool = Field(default=True, description="Whether to use sampling.")
13
+ do_sample: bool = Field(default=True, description="Whether to use sampling to generate diverse summaries.")
14
+ top_k: Union[int, str] = Field(default=50, description="Top-K sampling; restricts sampling to the top K tokens.")
15
+ top_p: Union[float, str] = Field(default=1.0, description="Top-p (nucleus) sampling; restricts sampling to tokens with cumulative probability >= top_p.")
14
16
  batch_size: Union[int, str] = Field(default=32, description="Number of input texts to process in a single batch.")
15
17
 
16
18
  class SummarizationModelActionConfig(CommonModelInferenceActionConfig):