model-compose 0.3.1__tar.gz → 0.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. {model_compose-0.3.1/src/model_compose.egg-info → model_compose-0.3.3}/PKG-INFO +41 -2
  2. {model_compose-0.3.1 → model_compose-0.3.3}/README.md +40 -1
  3. {model_compose-0.3.1 → model_compose-0.3.3}/pyproject.toml +1 -1
  4. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/cli/compose.py +10 -10
  5. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/context.py +1 -1
  6. model_compose-0.3.3/src/mindor/core/component/services/model/base.py +102 -0
  7. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/model.py +1 -1
  8. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/summarization.py +18 -6
  9. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/text_classification.py +18 -6
  10. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/text_embedding.py +18 -7
  11. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/text_generation.py +18 -6
  12. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/translation.py +19 -7
  13. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/base.py +1 -1
  14. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runtime/docker/context/Dockerfile +1 -0
  15. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runtime/docker/docker.py +27 -8
  16. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runtime/specs.py +6 -0
  17. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/services/http_server.py +20 -1
  18. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/webui/gradio.py +52 -10
  19. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/webui/webui.py +13 -2
  20. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/listener/services/http_callback.py +1 -1
  21. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/http_client.py +34 -1
  22. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/image.py +1 -1
  23. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/mcp_client.py +6 -6
  24. model_compose-0.3.1/src/mindor/core/utils/renderer.py → model_compose-0.3.3/src/mindor/core/utils/renderers.py +6 -26
  25. model_compose-0.3.3/src/mindor/core/utils/resolvers.py +29 -0
  26. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/context.py +1 -1
  27. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/impl/__init__.py +1 -0
  28. model_compose-0.3.3/src/mindor/core/workflow/job/impl/random_router.py +37 -0
  29. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +2 -2
  30. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +2 -2
  31. model_compose-0.3.3/src/mindor/dsl/schema/component/impl/common.py +13 -0
  32. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/http_client.py +3 -3
  33. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/http_server.py +3 -3
  34. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/mcp_client.py +2 -2
  35. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/mcp_server.py +1 -1
  36. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/common.py +23 -1
  37. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +1 -1
  38. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +1 -1
  39. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +1 -1
  40. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +1 -1
  41. model_compose-0.3.3/src/mindor/dsl/schema/controller/impl/common.py +28 -0
  42. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/impl/http_server.py +4 -4
  43. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/impl/mcp_server.py +3 -3
  44. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/__init__.py +1 -0
  45. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/impl/__init__.py +4 -0
  46. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/impl/common.py +13 -0
  47. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +9 -0
  48. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/impl/gradio.py +6 -0
  49. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/impl/static.py +7 -0
  50. model_compose-0.3.3/src/mindor/dsl/schema/controller/webui/webui.py +13 -0
  51. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/impl/common.py +2 -2
  52. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +1 -1
  53. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/__init__.py +1 -0
  54. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/delay.py +1 -1
  55. model_compose-0.3.3/src/mindor/dsl/schema/job/impl/random_router.py +21 -0
  56. model_compose-0.3.3/src/mindor/dsl/schema/job/impl/types.py +8 -0
  57. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/job.py +2 -1
  58. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/impl/common.py +2 -2
  59. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/impl/http_callback.py +7 -7
  60. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/workflow.py +16 -7
  61. {model_compose-0.3.1 → model_compose-0.3.3/src/model_compose.egg-info}/PKG-INFO +41 -2
  62. {model_compose-0.3.1 → model_compose-0.3.3}/src/model_compose.egg-info/SOURCES.txt +12 -3
  63. model_compose-0.3.1/src/mindor/core/component/services/model/base.py +0 -28
  64. model_compose-0.3.1/src/mindor/dsl/schema/component/impl/common.py +0 -13
  65. model_compose-0.3.1/src/mindor/dsl/schema/controller/impl/common.py +0 -21
  66. model_compose-0.3.1/src/mindor/dsl/schema/controller/impl/webui.py +0 -11
  67. model_compose-0.3.1/src/mindor/dsl/schema/job/impl/types.py +0 -7
  68. {model_compose-0.3.1 → model_compose-0.3.3}/LICENSE +0 -0
  69. {model_compose-0.3.1 → model_compose-0.3.3}/setup.cfg +0 -0
  70. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/__init__.py +0 -0
  71. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/cli/__init__.py +0 -0
  72. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/__init__.py +0 -0
  73. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/__init__.py +0 -0
  74. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/base.py +0 -0
  75. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/component.py +0 -0
  76. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/__init__.py +0 -0
  77. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/http_client.py +0 -0
  78. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/http_server.py +0 -0
  79. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/mcp_client.py +0 -0
  80. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/mcp_server.py +0 -0
  81. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/__init__.py +0 -0
  82. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  83. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/shell.py +0 -0
  84. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/component/services/workflow.py +0 -0
  85. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/compose/__init__.py +0 -0
  86. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/compose/compose.py +0 -0
  87. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/compose/manager.py +0 -0
  88. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/__init__.py +0 -0
  89. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/controller.py +0 -0
  90. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runner/__init__.py +0 -0
  91. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runner/client.py +0 -0
  92. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runner/http_client.py +0 -0
  93. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runner/mcp_client.py +0 -0
  94. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runner/runner.py +0 -0
  95. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runtime/__init__.py +0 -0
  96. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  97. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/services/__init__.py +0 -0
  98. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/services/mcp_server.py +0 -0
  99. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/controller/webui/__init__.py +0 -0
  100. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/__init__.py +0 -0
  101. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/base.py +0 -0
  102. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/gateway.py +0 -0
  103. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/services/__init__.py +0 -0
  104. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  105. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  106. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/listener/__init__.py +0 -0
  107. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/listener/base.py +0 -0
  108. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/listener/listener.py +0 -0
  109. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/listener/services/__init__.py +0 -0
  110. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/__init__.py +0 -0
  111. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/base.py +0 -0
  112. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/logger.py +0 -0
  113. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/logging.py +0 -0
  114. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/services/__init__.py +0 -0
  115. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/services/console.py +0 -0
  116. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/logger/services/file.py +0 -0
  117. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/runtime/__init__.py +0 -0
  118. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/runtime/docker/__init__.py +0 -0
  119. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/runtime/docker/docker.py +0 -0
  120. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/runtime/env.py +0 -0
  121. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/services/__init__.py +0 -0
  122. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/services/async_service.py +0 -0
  123. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/__init__.py +0 -0
  124. /model_compose-0.3.1/src/mindor/core/utils/expiring.py → /model_compose-0.3.3/src/mindor/core/utils/caching.py +0 -0
  125. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/http_request.py +0 -0
  126. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/http_status.py +0 -0
  127. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/ssh_client.py +0 -0
  128. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/streaming.py +0 -0
  129. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/time.py +0 -0
  130. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/utils/workqueue.py +0 -0
  131. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/__init__.py +0 -0
  132. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/__init__.py +0 -0
  133. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/base.py +0 -0
  134. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/impl/action.py +0 -0
  135. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/impl/delay.py +0 -0
  136. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/impl/if_.py +0 -0
  137. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/impl/switch.py +0 -0
  138. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/job/job.py +0 -0
  139. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/schema.py +0 -0
  140. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/core/workflow/workflow.py +0 -0
  141. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/__init__.py +0 -0
  142. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/loader.py +0 -0
  143. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/__init__.py +0 -0
  144. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/__init__.py +0 -0
  145. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/action.py +0 -0
  146. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  147. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  148. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/http_client.py +0 -0
  149. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/http_server.py +0 -0
  150. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  151. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
  152. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  153. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  154. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
  155. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  156. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  157. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
  158. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  159. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  160. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  161. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/__init__.py +0 -0
  162. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/component.py +0 -0
  163. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  164. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  165. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  166. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
  167. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  168. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  169. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  170. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  171. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  172. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/compose.py +0 -0
  173. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  174. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/controller.py +0 -0
  175. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  176. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  177. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  178. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  179. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  180. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  181. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  182. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/__init__.py +0 -0
  183. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/action.py +0 -0
  184. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/common.py +0 -0
  185. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
  186. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
  187. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  188. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  189. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  190. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/listener/listener.py +0 -0
  191. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  192. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  193. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  194. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  195. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  196. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  197. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/logger/logger.py +0 -0
  198. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  199. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  200. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  201. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  202. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  203. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  204. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  205. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/utils/__init__.py +0 -0
  206. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/utils/annotation.py +0 -0
  207. {model_compose-0.3.1 → model_compose-0.3.3}/src/mindor/dsl/utils/enum.py +0 -0
  208. {model_compose-0.3.1 → model_compose-0.3.3}/src/model_compose.egg-info/dependency_links.txt +0 -0
  209. {model_compose-0.3.1 → model_compose-0.3.3}/src/model_compose.egg-info/entry_points.txt +0 -0
  210. {model_compose-0.3.1 → model_compose-0.3.3}/src/model_compose.egg-info/requires.txt +0 -0
  211. {model_compose-0.3.1 → model_compose-0.3.3}/src/model_compose.egg-info/top_level.txt +0 -0
  212. {model_compose-0.3.1 → model_compose-0.3.3}/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.1
3
+ Version: 0.3.3
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
@@ -248,7 +248,46 @@ Once enabled, the Web UI will be available at:
248
248
  ```
249
249
  http://localhost:8081
250
250
  ```
251
- > By default, the Web UI is powered by [Gradio](https://www.gradio.app), but support for other drivers may be added in the future.
251
+
252
+ ## 🎨 Custom Web UI
253
+ You can fully customize the Web UI experience by specifying a different driver or serving your own frontend.
254
+
255
+ By default, `model-compose` uses [Gradio](https://www.gradio.app) as the interactive UI. However, if you prefer to use your own static frontend (e.g., a custom React/Vite app), you can switch to the `static` driver.
256
+
257
+ Here’s how you can do it:
258
+
259
+ ```
260
+ controller:
261
+ type: http-server
262
+ port: 8080
263
+ webui:
264
+ driver: static
265
+ static_dir: webui
266
+ port: 8081
267
+ ```
268
+ Your frontend should be a prebuilt static site (e.g., using `vite build`, `next export`, or `react-scripts` build) and placed in the specified `static_dir`.
269
+ Make sure `index.html` exists in that directory.
270
+
271
+ #### 📁 Example Directory Structure
272
+ ```
273
+ project/
274
+ ├── model-compose.yml
275
+ ├── webui/
276
+ │ ├── index.html
277
+ │ ├── assets/
278
+ │ └── ...
279
+ ```
280
+
281
+ #### 🔧 Notes
282
+ * Ensure the `static_dir` path is relative to the project root or an absolute path.
283
+ * You can use environment variables inside `model-compose.yml` to make this path configurable.
284
+
285
+ Support for additional drivers (e.g., `dynamic`) may be added in future versions.
286
+
287
+ Once configured, the Web UI will be available at:
288
+ ```
289
+ http://localhost:8081
290
+ ```
252
291
 
253
292
  ---
254
293
  ## 🛰 MCP Server Support
@@ -219,7 +219,46 @@ Once enabled, the Web UI will be available at:
219
219
  ```
220
220
  http://localhost:8081
221
221
  ```
222
- > By default, the Web UI is powered by [Gradio](https://www.gradio.app), but support for other drivers may be added in the future.
222
+
223
+ ## 🎨 Custom Web UI
224
+ You can fully customize the Web UI experience by specifying a different driver or serving your own frontend.
225
+
226
+ By default, `model-compose` uses [Gradio](https://www.gradio.app) as the interactive UI. However, if you prefer to use your own static frontend (e.g., a custom React/Vite app), you can switch to the `static` driver.
227
+
228
+ Here’s how you can do it:
229
+
230
+ ```
231
+ controller:
232
+ type: http-server
233
+ port: 8080
234
+ webui:
235
+ driver: static
236
+ static_dir: webui
237
+ port: 8081
238
+ ```
239
+ Your frontend should be a prebuilt static site (e.g., using `vite build`, `next export`, or `react-scripts` build) and placed in the specified `static_dir`.
240
+ Make sure `index.html` exists in that directory.
241
+
242
+ #### 📁 Example Directory Structure
243
+ ```
244
+ project/
245
+ ├── model-compose.yml
246
+ ├── webui/
247
+ │ ├── index.html
248
+ │ ├── assets/
249
+ │ └── ...
250
+ ```
251
+
252
+ #### 🔧 Notes
253
+ * Ensure the `static_dir` path is relative to the project root or an absolute path.
254
+ * You can use environment variables inside `model-compose.yml` to make this path configurable.
255
+
256
+ Support for additional drivers (e.g., `dynamic`) may be added in future versions.
257
+
258
+ Once configured, the Web UI will be available at:
259
+ ```
260
+ http://localhost:8081
261
+ ```
223
262
 
224
263
  ---
225
264
  ## 🛰 MCP Server Support
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "model-compose"
3
- version = "0.3.1"
3
+ version = "0.3.3"
4
4
  description = "model-compose: Declarative AI Model and Workflow Orchestrator"
5
5
  authors = [
6
6
  { name = "Hanyeol Cho", email = "hanyeol.cho@gmail.com" }
@@ -11,7 +11,7 @@ from mindor.core.compose import *
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:
@@ -25,11 +25,11 @@ def compose_command(ctx: click.Context, config_files: List[Path]) -> None:
25
25
  "--env-file", "env_files", multiple=True,
26
26
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
27
27
  required=False,
28
- help="Path to a .env file containing environment variables.",
28
+ help="Path to a .env file containing environment variables."
29
29
  )
30
30
  @click.option(
31
31
  "--env", "-e", "env_data", multiple=True,
32
- help="Environment variable in the form KEY=VALUE. Repeatable.",
32
+ help="Environment variable in the form KEY=VALUE. Repeatable."
33
33
  )
34
34
  @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output.")
35
35
  @click.pass_context
@@ -55,11 +55,11 @@ def up_command(
55
55
  "--env-file", "env_files", multiple=True,
56
56
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
57
57
  required=False,
58
- help="Path to a .env file containing environment variables.",
58
+ help="Path to a .env file containing environment variables."
59
59
  )
60
60
  @click.option(
61
61
  "--env", "-e", "env_data", multiple=True,
62
- help="Environment variable in the form KEY=VALUE. Repeatable.",
62
+ help="Environment variable in the form KEY=VALUE. Repeatable."
63
63
  )
64
64
  @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output.")
65
65
  @click.pass_context
@@ -84,7 +84,7 @@ def down_command(
84
84
  "--env-file", "env_files", multiple=True,
85
85
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
86
86
  required=False,
87
- help="Path to a .env file containing environment variables.",
87
+ help="Path to a .env file containing environment variables."
88
88
  )
89
89
  @click.option(
90
90
  "--env", "-e", "env_data", multiple=True,
@@ -113,11 +113,11 @@ def start_command(
113
113
  "--env-file", "env_files", multiple=True,
114
114
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
115
115
  required=False,
116
- help="Path to a .env file containing environment variables.",
116
+ help="Path to a .env file containing environment variables."
117
117
  )
118
118
  @click.option(
119
119
  "--env", "-e", "env_data", multiple=True,
120
- help="Environment variable in the form KEY=VALUE. Repeatable.",
120
+ help="Environment variable in the form KEY=VALUE. Repeatable."
121
121
  )
122
122
  @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output.")
123
123
  @click.pass_context
@@ -149,11 +149,11 @@ def stop_command(
149
149
  "--env-file", "env_files", multiple=True,
150
150
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
151
151
  required=False,
152
- help="Path to a .env file containing environment variables.",
152
+ help="Path to a .env file containing environment variables."
153
153
  )
154
154
  @click.option(
155
155
  "--env", "-e", "env_data", multiple=True,
156
- help="Environment variable in the form KEY=VALUE. Repeatable.",
156
+ help="Environment variable in the form KEY=VALUE. Repeatable."
157
157
  )
158
158
  @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output.")
159
159
  @click.pass_context
@@ -1,5 +1,5 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
- from mindor.core.utils.renderer import VariableRenderer
2
+ from mindor.core.utils.renderers import VariableRenderer
3
3
  from mindor.core.gateway import find_gateway_by_port
4
4
 
5
5
  class ComponentActionContext:
@@ -0,0 +1,102 @@
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 ModelComponentConfig, ModelTaskType, DeviceMode
4
+ from mindor.dsl.schema.action import ModelActionConfig
5
+ from mindor.core.services import AsyncService
6
+ from ...context import ComponentActionContext
7
+ from transformers import PreTrainedModel, PreTrainedTokenizer
8
+ import torch
9
+
10
+ class ModelTaskService(AsyncService):
11
+ def __init__(self, id: str, config: ModelComponentConfig, daemon: bool):
12
+ super().__init__(daemon)
13
+
14
+ self.id: str = id
15
+ self.config: ModelComponentConfig = config
16
+
17
+ async def run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
18
+ return await self._run(action, context)
19
+
20
+ @abstractmethod
21
+ async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
22
+ pass
23
+
24
+ def _load_pretrained_model(self, extra_params: Optional[Dict[str, Any]] = None) -> PreTrainedModel:
25
+ params = self._get_common_model_params()
26
+
27
+ if extra_params:
28
+ params.update(extra_params)
29
+
30
+ model = self._get_model_class().from_pretrained(self.config.model, **params)
31
+
32
+ if self.config.device_mode == DeviceMode.SINGLE:
33
+ model = model.to(torch.device(self.config.device))
34
+
35
+ return model
36
+
37
+ def _get_common_model_params(self) -> Dict[str, Any]:
38
+ params: Dict[str, Any] = {}
39
+
40
+ if self.config.device_mode != DeviceMode.SINGLE:
41
+ params["device_map"] = self.config.device_mode.value
42
+
43
+ if self.config.precision is not None:
44
+ params["torch_dtype"] = getattr(torch, self.config.precision.value)
45
+
46
+ if self.config.low_cpu_mem_usage:
47
+ params["low_cpu_mem_usage"] = True
48
+
49
+ if self.config.revision:
50
+ params["revision"] = self.config.revision
51
+
52
+ if self.config.cache_dir:
53
+ params["cache_dir"] = self.config.cache_dir
54
+
55
+ if self.config.local_files_only:
56
+ params["local_files_only"] = True
57
+
58
+ return params
59
+
60
+ def _load_pretrained_tokenizer(self, extra_params: Optional[Dict[str, Any]] = None) -> PreTrainedTokenizer:
61
+ params = self._get_common_tokenizer_params()
62
+
63
+ if extra_params:
64
+ params.update(extra_params)
65
+
66
+ return self._get_tokenizer_class().from_pretrained(self.config.model, **params)
67
+
68
+ def _get_common_tokenizer_params(self) -> Dict[str, Any]:
69
+ params: Dict[str, Any] = {}
70
+
71
+ if not self.config.fast_tokenizer:
72
+ params["use_fast"] = False
73
+
74
+ if self.config.revision:
75
+ params["revision"] = self.config.revision
76
+
77
+ if self.config.cache_dir:
78
+ params["cache_dir"] = self.config.cache_dir
79
+
80
+ if self.config.local_files_only:
81
+ params["local_files_only"] = True
82
+
83
+ return params
84
+
85
+ def _get_model_device(self, model: PreTrainedModel) -> torch.device:
86
+ return next(model.parameters()).device
87
+
88
+ @abstractmethod
89
+ def _get_model_class(self) -> Type[PreTrainedModel]:
90
+ pass
91
+
92
+ @abstractmethod
93
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
94
+ pass
95
+
96
+ def register_model_task_service(type: ModelTaskType):
97
+ def decorator(cls: Type[ModelTaskService]) -> Type[ModelTaskService]:
98
+ ModelTaskServiceRegistry[type] = cls
99
+ return cls
100
+ return decorator
101
+
102
+ ModelTaskServiceRegistry: Dict[ModelTaskType, Type[ModelTaskService]] = {}
@@ -25,7 +25,7 @@ class ModelComponent(ComponentService):
25
25
  from . import tasks
26
26
  return ModelTaskServiceRegistry[type](self.id, self.config, self.daemon)
27
27
  except KeyError:
28
- raise ValueError(f"Unsupported component type: {type}")
28
+ raise ValueError(f"Unsupported model task type: {type}")
29
29
 
30
30
  async def _serve(self) -> None:
31
31
  await self.task_service.start()
@@ -5,13 +5,15 @@ from mindor.core.logger import logging
5
5
  from ..base import ModelTaskService, ModelTaskType, register_model_task_service
6
6
  from ..base import ComponentActionContext
7
7
  from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin
8
+ from torch import Tensor
8
9
  import torch
9
10
 
10
11
  class SummarizationTaskAction:
11
- def __init__(self, config: SummarizationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer):
12
+ def __init__(self, config: SummarizationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
12
13
  self.config: SummarizationModelActionConfig = config
13
14
  self.model: Union[PreTrainedModel, GenerationMixin] = model
14
15
  self.tokenizer: PreTrainedTokenizer = tokenizer
16
+ self.device: torch.device = device
15
17
 
16
18
  async def run(self, context: ComponentActionContext) -> Any:
17
19
  text: Union[str, List[str]] = await context.render_variable(self.config.text)
@@ -30,7 +32,8 @@ class SummarizationTaskAction:
30
32
 
31
33
  for index in range(0, len(texts), batch_size):
32
34
  batch_texts = texts[index:index + batch_size]
33
- inputs = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True).to(self.model.device)
35
+ inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
36
+ inputs = { k: v.to(self.device) for k, v in inputs.items() }
34
37
 
35
38
  with torch.no_grad():
36
39
  outputs = self.model.generate(
@@ -60,12 +63,14 @@ class SummarizationTaskService(ModelTaskService):
60
63
 
61
64
  self.model: Optional[Union[PreTrainedModel, GenerationMixin]] = None
62
65
  self.tokenizer: Optional[PreTrainedTokenizer] = None
66
+ self.device: Optional[torch.device] = None
63
67
 
64
68
  async def _serve(self) -> None:
65
69
  try:
66
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.config.model).to(torch.device(self.config.device))
67
- self.tokenizer = AutoTokenizer.from_pretrained(self.config.model, use_fast=self.config.fast_tokenizer)
68
- logging.info(f"Model and tokenizer loaded successfully on device '{self.config.device}': {self.config.model}")
70
+ self.model = self._load_pretrained_model()
71
+ self.tokenizer = self._load_pretrained_tokenizer()
72
+ self.device = self._get_model_device(self.model)
73
+ logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
69
74
  except Exception as e:
70
75
  logging.error(f"Failed to load model '{self.config.model}': {e}")
71
76
  raise
@@ -73,6 +78,13 @@ class SummarizationTaskService(ModelTaskService):
73
78
  async def _shutdown(self) -> None:
74
79
  self.model = None
75
80
  self.tokenizer = None
81
+ self.device = None
76
82
 
77
83
  async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
78
- return await SummarizationTaskAction(action, self.model, self.tokenizer).run(context)
84
+ return await SummarizationTaskAction(action, self.model, self.tokenizer, self.device).run(context)
85
+
86
+ def _get_model_class(self) -> Type[PreTrainedModel]:
87
+ return AutoModelForSeq2SeqLM
88
+
89
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
90
+ return AutoTokenizer
@@ -7,13 +7,15 @@ from ..base import ComponentActionContext
7
7
  from transformers import AutoModelForSequenceClassification, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer
8
8
  from transformers.modeling_outputs import SequenceClassifierOutput
9
9
  import torch.nn.functional as F
10
+ from torch import Tensor
10
11
  import torch
11
12
 
12
13
  class TextClassificationTaskAction:
13
- def __init__(self, config: TextClassificationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer):
14
+ def __init__(self, config: TextClassificationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
14
15
  self.config: TextClassificationModelActionConfig = config
15
16
  self.model: PreTrainedModel = model
16
17
  self.tokenizer: PreTrainedTokenizer = tokenizer
18
+ self.device: torch.device = device
17
19
 
18
20
  async def run(self, context: ComponentActionContext, labels: Optional[List[str]]) -> Any:
19
21
  text: Union[str, List[str]] = await context.render_variable(self.config.text)
@@ -26,7 +28,8 @@ class TextClassificationTaskAction:
26
28
 
27
29
  for index in range(0, len(texts), batch_size):
28
30
  batch_texts = texts[index:index + batch_size]
29
- inputs = self.tokenizer(batch_texts, return_tensors="pt", padding=True, truncation=True).to(self.model.device)
31
+ inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", padding=True, truncation=True)
32
+ inputs = { k: v.to(self.device) for k, v in inputs.items() }
30
33
 
31
34
  with torch.no_grad():
32
35
  outputs: SequenceClassifierOutput = self.model(**inputs)
@@ -60,12 +63,14 @@ class TextClassificationTaskService(ModelTaskService):
60
63
 
61
64
  self.model: Optional[PreTrainedModel] = None
62
65
  self.tokenizer: Optional[PreTrainedTokenizer] = None
66
+ self.device: Optional[torch.device] = None
63
67
 
64
68
  async def _serve(self) -> None:
65
69
  try:
66
- self.model = AutoModelForSequenceClassification.from_pretrained(self.config.model).to(torch.device(self.config.device))
67
- self.tokenizer = AutoTokenizer.from_pretrained(self.config.model, use_fast=self.config.fast_tokenizer)
68
- logging.info(f"Model and tokenizer loaded successfully on device '{self.config.device}': {self.config.model}")
70
+ self.model = self._load_pretrained_model()
71
+ self.tokenizer = self._load_pretrained_tokenizer()
72
+ self.device = self._get_model_device(self.model)
73
+ logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
69
74
  except Exception as e:
70
75
  logging.error(f"Failed to load model '{self.config.model}': {e}")
71
76
  raise
@@ -73,6 +78,13 @@ class TextClassificationTaskService(ModelTaskService):
73
78
  async def _shutdown(self) -> None:
74
79
  self.model = None
75
80
  self.tokenizer = None
81
+ self.device = None
76
82
 
77
83
  async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
78
- return await TextClassificationTaskAction(action, self.model, self.tokenizer).run(context, self.config.labels)
84
+ return await TextClassificationTaskAction(action, self.model, self.tokenizer, self.device).run(context, self.config.labels)
85
+
86
+ def _get_model_class(self) -> Type[PreTrainedModel]:
87
+ return AutoModelForSequenceClassification
88
+
89
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
90
+ return AutoTokenizer
@@ -10,10 +10,11 @@ from torch import Tensor
10
10
  import torch
11
11
 
12
12
  class TextEmbeddingTaskAction:
13
- def __init__(self, config: TextEmbeddingModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer):
13
+ def __init__(self, config: TextEmbeddingModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
14
14
  self.config: TextEmbeddingModelActionConfig = config
15
15
  self.model: PreTrainedModel = model
16
16
  self.tokenizer: PreTrainedTokenizer = tokenizer
17
+ self.device: torch.device = device
17
18
 
18
19
  async def run(self, context: ComponentActionContext) -> Any:
19
20
  text: Union[str, List[str]] = await context.render_variable(self.config.text)
@@ -28,13 +29,14 @@ class TextEmbeddingTaskAction:
28
29
 
29
30
  for index in range(0, len(texts), batch_size):
30
31
  batch_texts = texts[index:index + batch_size]
31
- inputs = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True).to(self.model.device)
32
- attention_mask: Tensor = inputs.get("attention_mask", None)
32
+ inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
33
+ inputs = { k: v.to(self.device) for k, v in inputs.items() }
33
34
 
34
35
  with torch.no_grad():
35
36
  outputs: BaseModelOutput = self.model(**inputs)
36
37
  last_hidden_state = outputs.last_hidden_state # (batch_size, seq_len, hidden_size)
37
38
 
39
+ attention_mask = inputs.get("attention_mask", None)
38
40
  embeddings = self._pool_hidden_state(last_hidden_state, attention_mask, pooling)
39
41
 
40
42
  if normalize:
@@ -75,12 +77,14 @@ class TextEmbeddingTaskService(ModelTaskService):
75
77
 
76
78
  self.model: Optional[PreTrainedModel] = None
77
79
  self.tokenizer: Optional[PreTrainedTokenizer] = None
80
+ self.device: Optional[torch.device] = None
78
81
 
79
82
  async def _serve(self) -> None:
80
83
  try:
81
- self.model = AutoModel.from_pretrained(self.config.model).to(torch.device(self.config.device))
82
- self.tokenizer = AutoTokenizer.from_pretrained(self.config.model, use_fast=self.config.fast_tokenizer)
83
- logging.info(f"Model and tokenizer loaded successfully on device '{self.config.device}': {self.config.model}")
84
+ self.model = self._load_pretrained_model()
85
+ self.tokenizer = self._load_pretrained_tokenizer()
86
+ self.device = self._get_model_device(self.model)
87
+ logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
84
88
  except Exception as e:
85
89
  logging.error(f"Failed to load model '{self.config.model}': {e}")
86
90
  raise
@@ -88,6 +92,13 @@ class TextEmbeddingTaskService(ModelTaskService):
88
92
  async def _shutdown(self) -> None:
89
93
  self.model = None
90
94
  self.tokenizer = None
95
+ self.device = None
91
96
 
92
97
  async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
93
- return await TextEmbeddingTaskAction(action, self.model, self.tokenizer).run(context)
98
+ return await TextEmbeddingTaskAction(action, self.model, self.tokenizer, self.device).run(context)
99
+
100
+ def _get_model_class(self) -> Type[PreTrainedModel]:
101
+ return AutoModel
102
+
103
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
104
+ return AutoTokenizer
@@ -5,13 +5,15 @@ from mindor.core.logger import logging
5
5
  from ..base import ModelTaskService, ModelTaskType, register_model_task_service
6
6
  from ..base import ComponentActionContext
7
7
  from transformers import AutoModelForCausalLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin
8
+ from torch import Tensor
8
9
  import torch
9
10
 
10
11
  class TextGenerationTaskAction:
11
- def __init__(self, config: TextGenerationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer):
12
+ def __init__(self, config: TextGenerationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
12
13
  self.config: TextGenerationModelActionConfig = config
13
14
  self.model: Union[PreTrainedModel, GenerationMixin] = model
14
15
  self.tokenizer: PreTrainedTokenizer = tokenizer
16
+ self.device: torch.device = device
15
17
 
16
18
  async def run(self, context: ComponentActionContext) -> Any:
17
19
  prompt: Union[str, List[str]] = await context.render_variable(self.config.prompt)
@@ -28,7 +30,8 @@ class TextGenerationTaskAction:
28
30
 
29
31
  for index in range(0, len(prompts), batch_size):
30
32
  batch_prompts = prompts[index:index + batch_size]
31
- inputs = self.tokenizer(batch_prompts, return_tensors="pt").to(self.model.device)
33
+ inputs: Dict[str, Tensor] = self.tokenizer(batch_prompts, return_tensors="pt", padding=True, truncation=True)
34
+ inputs = { k: v.to(self.device) for k, v in inputs.items() }
32
35
 
33
36
  with torch.no_grad():
34
37
  outputs = self.model.generate(
@@ -56,12 +59,14 @@ class TextGenerationTaskService(ModelTaskService):
56
59
 
57
60
  self.model: Optional[Union[PreTrainedModel, GenerationMixin]] = None
58
61
  self.tokenizer: Optional[PreTrainedTokenizer] = None
62
+ self.device: Optional[torch.device] = None
59
63
 
60
64
  async def _serve(self) -> None:
61
65
  try:
62
- self.model = AutoModelForCausalLM.from_pretrained(self.config.model).to(torch.device(self.config.device))
63
- self.tokenizer = AutoTokenizer.from_pretrained(self.config.model, use_fast=self.config.fast_tokenizer)
64
- logging.info(f"Model and tokenizer loaded successfully on device '{self.config.device}': {self.config.model}")
66
+ self.model = self._load_pretrained_model()
67
+ self.tokenizer = self._load_pretrained_tokenizer()
68
+ self.device = self._get_model_device(self.model)
69
+ logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
65
70
  except Exception as e:
66
71
  logging.error(f"Failed to load model '{self.config.model}': {e}")
67
72
  raise
@@ -69,6 +74,13 @@ class TextGenerationTaskService(ModelTaskService):
69
74
  async def _shutdown(self) -> None:
70
75
  self.model = None
71
76
  self.tokenizer = None
77
+ self.device = None
72
78
 
73
79
  async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
74
- return await TextGenerationTaskAction(action, self.model, self.tokenizer).run(context)
80
+ return await TextGenerationTaskAction(action, self.model, self.tokenizer, self.device).run(context)
81
+
82
+ def _get_model_class(self) -> Type[PreTrainedModel]:
83
+ return AutoModelForCausalLM
84
+
85
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
86
+ return AutoTokenizer
@@ -5,13 +5,15 @@ from mindor.core.logger import logging
5
5
  from ..base import ModelTaskService, ModelTaskType, register_model_task_service
6
6
  from ..base import ComponentActionContext
7
7
  from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer, GenerationMixin
8
+ from torch import Tensor
8
9
  import torch
9
10
 
10
11
  class TranslationTaskAction:
11
- def __init__(self, config: TranslationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer):
12
+ def __init__(self, config: TranslationModelActionConfig, model: Union[PreTrainedModel, GenerationMixin], tokenizer: PreTrainedTokenizer, device: torch.device):
12
13
  self.config: TranslationModelActionConfig = config
13
14
  self.model: Union[PreTrainedModel, GenerationMixin] = model
14
15
  self.tokenizer: PreTrainedTokenizer = tokenizer
16
+ self.device: torch.device = device
15
17
 
16
18
  async def run(self, context: ComponentActionContext) -> Any:
17
19
  text: Union[str, List[str]] = await context.render_variable(self.config.text)
@@ -28,8 +30,9 @@ class TranslationTaskAction:
28
30
 
29
31
  for index in range(0, len(texts), batch_size):
30
32
  batch_texts = texts[index:index + batch_size]
31
- inputs = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True).to(self.model.device)
32
-
33
+ inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
34
+ inputs = { k: v.to(self.device) for k, v in inputs.items() }
35
+
33
36
  with torch.no_grad():
34
37
  outputs = self.model.generate(
35
38
  **inputs,
@@ -57,12 +60,14 @@ class TranslationTaskService(ModelTaskService):
57
60
 
58
61
  self.model: Optional[Union[PreTrainedModel, GenerationMixin]] = None
59
62
  self.tokenizer: Optional[PreTrainedTokenizer] = None
63
+ self.device: Optional[torch.device] = None
60
64
 
61
65
  async def _serve(self) -> None:
62
66
  try:
63
- self.model = AutoModelForSeq2SeqLM.from_pretrained(self.config.model).to(torch.device(self.config.device))
64
- self.tokenizer = AutoTokenizer.from_pretrained(self.config.model, use_fast=self.config.fast_tokenizer)
65
- logging.info(f"Model and tokenizer loaded successfully on device '{self.config.device}': {self.config.model}")
67
+ self.model = self._load_pretrained_model()
68
+ self.tokenizer = self._load_pretrained_tokenizer()
69
+ self.device = self._get_model_device(self.model)
70
+ logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
66
71
  except Exception as e:
67
72
  logging.error(f"Failed to load model '{self.config.model}': {e}")
68
73
  raise
@@ -70,6 +75,13 @@ class TranslationTaskService(ModelTaskService):
70
75
  async def _shutdown(self) -> None:
71
76
  self.model = None
72
77
  self.tokenizer = None
78
+ self.device = None
73
79
 
74
80
  async def _run(self, action: ModelActionConfig, context: ComponentActionContext) -> Any:
75
- return await TranslationTaskAction(action, self.model, self.tokenizer).run(context)
81
+ return await TranslationTaskAction(action, self.model, self.tokenizer, self.device).run(context)
82
+
83
+ def _get_model_class(self) -> Type[PreTrainedModel]:
84
+ return AutoModelForSeq2SeqLM
85
+
86
+ def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
87
+ return AutoTokenizer
@@ -17,7 +17,7 @@ from mindor.core.workflow import Workflow, WorkflowResolver, create_workflow
17
17
  from mindor.core.logger import LoggerService, create_logger
18
18
  from mindor.core.controller.webui import ControllerWebUI
19
19
  from mindor.core.utils.workqueue import WorkQueue
20
- from mindor.core.utils.expiring import ExpiringDict
20
+ from mindor.core.utils.caching import ExpiringDict
21
21
  from .runtime.specs import ControllerRuntimeSpecs
22
22
  from .runtime.docker import DockerRuntimeLauncher
23
23
  from threading import Lock
@@ -37,6 +37,7 @@ COPY requirements.txt .
37
37
  RUN pip install --no-cache-dir -r requirements.txt
38
38
 
39
39
  COPY src .
40
+ COPY webui ./webui
40
41
  COPY model-compose.yml .
41
42
 
42
43
  CMD [ "python", "-m", "mindor.cli.compose", "up" ]