model-compose 0.3.8__tar.gz → 0.3.10__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.
- {model_compose-0.3.8 → model_compose-0.3.10}/PKG-INFO +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/pyproject.toml +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/context.py +9 -3
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/http_server.py +11 -9
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/mcp_server.py +11 -9
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/base.py +35 -12
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/tasks/__init__.py +1 -0
- model_compose-0.3.10/src/mindor/core/component/services/model/tasks/image_to_text.py +155 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/tasks/summarization.py +12 -10
- model_compose-0.3.10/src/mindor/core/component/services/model/tasks/text_classification.py +122 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/tasks/text_embedding.py +56 -22
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/tasks/text_generation.py +12 -10
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/tasks/translation.py +12 -10
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/shell.py +11 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runner/http_client.py +2 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runner/mcp_client.py +1 -15
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/services/http_server.py +22 -27
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/services/mcp_server.py +4 -2
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/webui/gradio.py +5 -5
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/webui/webui.py +6 -4
- model_compose-0.3.10/src/mindor/core/gateway/services/http_tunnel.py +82 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/listener/services/http_callback.py +4 -2
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/http_client.py +3 -3
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/image.py +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/renderers.py +44 -9
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/streaming.py +9 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/context.py +6 -3
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/schema.py +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/action.py +1 -1
- {model_compose-0.3.8/src/mindor/dsl/schema/component → model_compose-0.3.10/src/mindor/dsl/schema/action}/impl/model/impl/__init__.py +1 -0
- model_compose-0.3.10/src/mindor/dsl/schema/action/impl/model/impl/image_to_text.py +12 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/model.py +1 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/http_server.py +26 -17
- model_compose-0.3.10/src/mindor/dsl/schema/component/impl/mcp_server.py +51 -0
- {model_compose-0.3.8/src/mindor/dsl/schema/action → model_compose-0.3.10/src/mindor/dsl/schema/component}/impl/model/impl/__init__.py +1 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -8
- model_compose-0.3.10/src/mindor/dsl/schema/component/impl/model/impl/image_to_text.py +27 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +8 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +8 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +8 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +8 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +8 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/impl/types.py +1 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/model.py +1 -0
- model_compose-0.3.10/src/mindor/dsl/schema/component/impl/shell.py +49 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/text_splitter.py +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/workflow.py +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/webui.py +0 -1
- model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/__init__.py +1 -0
- model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/http_tunnel.py +11 -0
- model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/__init__.py +3 -0
- model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/cloudflare.py +7 -0
- model_compose-0.3.8/src/mindor/dsl/schema/gateway/impl/http_tunnel.py → model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/common.py +5 -4
- model_compose-0.3.10/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/ngrok.py +7 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +2 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/impl/http_callback.py +4 -4
- model_compose-0.3.10/src/mindor/dsl/schema/transport/ssh.py +33 -0
- model_compose-0.3.10/src/mindor/dsl/utils/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/PKG-INFO +1 -1
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/SOURCES.txt +11 -1
- model_compose-0.3.8/src/mindor/core/component/services/model/tasks/text_classification.py +0 -90
- model_compose-0.3.8/src/mindor/core/gateway/services/http_tunnel.py +0 -32
- model_compose-0.3.8/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -27
- model_compose-0.3.8/src/mindor/dsl/schema/component/impl/shell.py +0 -19
- {model_compose-0.3.8 → model_compose-0.3.10}/LICENSE +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/README.md +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/setup.cfg +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/cli/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/cli/compose.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/component.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/http_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/mcp_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/model.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/text_splitter.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/workflow.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/compose/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/compose/compose.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/compose/manager.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/controller.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runner/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runner/client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runner/runner.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/native/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/native/native.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/runtime/specs.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/controller/webui/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/gateway/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/gateway/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/gateway/gateway.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/gateway/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/listener/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/listener/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/listener/listener.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/listener/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/logger.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/logging.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/services/console.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/logger/services/file.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/runtime/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/runtime/docker/docker.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/runtime/env.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/services/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/services/async_service.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/caching.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/http_request.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/http_status.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/mcp_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/resolvers.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/shell.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/ssh_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/streamer.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/time.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/utils/workqueue.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/base.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/action.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/delay.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/if_.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/random_router.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/impl/switch.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/job/job.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/workflow/workflow.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/loader.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/http_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/http_server.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/component.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/component/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/compose.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/controller.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/impl/http_server.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/impl/mcp_server.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/action.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/job/job.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/listener/listener.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/logger/logger.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
- {model_compose-0.3.8/src/mindor/dsl/utils → model_compose-0.3.10/src/mindor/dsl/schema/transport}/__init__.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/schema/workflow.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/utils/annotation.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/dsl/utils/enum.py +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/dependency_links.txt +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/entry_points.txt +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/requires.txt +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/src/model_compose.egg-info/top_level.txt +0 -0
- {model_compose-0.3.8 → model_compose-0.3.10}/tests/test_cli.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from mindor.core.utils.renderers import VariableRenderer
|
|
2
|
+
from mindor.core.utils.renderers import VariableRenderer, ImageValueRenderer
|
|
3
3
|
from mindor.core.gateway import find_gateway_by_port
|
|
4
4
|
|
|
5
5
|
class ComponentActionContext:
|
|
@@ -13,8 +13,14 @@ class ComponentActionContext:
|
|
|
13
13
|
def register_source(self, key: str, source: Any) -> None:
|
|
14
14
|
self.sources[key] = source
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
return
|
|
16
|
+
def has_reference(self, key: str, value: Any) -> bool:
|
|
17
|
+
return self.renderer.has_reference(key, value)
|
|
18
|
+
|
|
19
|
+
async def render_variable(self, value: Any, ignore_files: bool = False) -> Any:
|
|
20
|
+
return await self.renderer.render(value, ignore_files)
|
|
21
|
+
|
|
22
|
+
async def render_image(self, value: Any) -> Any:
|
|
23
|
+
return await ImageValueRenderer().render(await self.render_variable(value))
|
|
18
24
|
|
|
19
25
|
async def _resolve_source(self, key: str, index: Optional[int]) -> Any:
|
|
20
26
|
if key in self.sources:
|
{model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/http_server.py
RENAMED
|
@@ -105,16 +105,18 @@ class HttpServerComponent(ComponentService):
|
|
|
105
105
|
self.client: Optional[HttpClient] = None
|
|
106
106
|
|
|
107
107
|
async def _setup(self) -> None:
|
|
108
|
-
if self.config.
|
|
109
|
-
for command in self.config.
|
|
110
|
-
await run_command_streaming(command, self.config.working_dir, self.config.env)
|
|
108
|
+
if self.config.manage.scripts.install:
|
|
109
|
+
for command in self.config.manage.scripts.install:
|
|
110
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
111
111
|
|
|
112
|
-
if self.config.
|
|
113
|
-
for command in self.config.
|
|
114
|
-
await run_command_streaming(command, self.config.working_dir, self.config.env)
|
|
112
|
+
if self.config.manage.scripts.build:
|
|
113
|
+
for command in self.config.manage.scripts.build:
|
|
114
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
115
115
|
|
|
116
116
|
async def _teardown(self):
|
|
117
|
-
|
|
117
|
+
if self.config.manage.scripts.clean:
|
|
118
|
+
for command in self.config.manage.scripts.clean:
|
|
119
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
118
120
|
|
|
119
121
|
async def _start(self) -> None:
|
|
120
122
|
base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
|
|
@@ -127,8 +129,8 @@ class HttpServerComponent(ComponentService):
|
|
|
127
129
|
self.client = None
|
|
128
130
|
|
|
129
131
|
async def _serve(self) -> None:
|
|
130
|
-
if self.config.
|
|
131
|
-
await run_command_streaming(self.config.
|
|
132
|
+
if self.config.manage.scripts.start:
|
|
133
|
+
await run_command_streaming(self.config.manage.scripts.start, self.config.manage.working_dir, self.config.manage.env, block=False)
|
|
132
134
|
|
|
133
135
|
async def _shutdown(self) -> None:
|
|
134
136
|
pass
|
{model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/mcp_server.py
RENAMED
|
@@ -36,16 +36,18 @@ class McpServerComponent(ComponentService):
|
|
|
36
36
|
self.client: Optional[McpClient] = None
|
|
37
37
|
|
|
38
38
|
async def _setup(self) -> None:
|
|
39
|
-
if self.config.
|
|
40
|
-
for command in self.config.
|
|
41
|
-
await run_command_streaming(command, self.config.working_dir, self.config.env)
|
|
39
|
+
if self.config.manage.scripts.install:
|
|
40
|
+
for command in self.config.manage.scripts.install:
|
|
41
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
42
42
|
|
|
43
|
-
if self.config.
|
|
44
|
-
for command in self.config.
|
|
45
|
-
await run_command_streaming(command, self.config.working_dir, self.config.env)
|
|
43
|
+
if self.config.manage.scripts.build:
|
|
44
|
+
for command in self.config.manage.scripts.build:
|
|
45
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
46
46
|
|
|
47
47
|
async def _teardown(self):
|
|
48
|
-
|
|
48
|
+
if self.config.manage.scripts.clean:
|
|
49
|
+
for command in self.config.manage.scripts.clean:
|
|
50
|
+
await run_command_streaming(command, self.config.manage.working_dir, self.config.manage.env)
|
|
49
51
|
|
|
50
52
|
async def _start(self) -> None:
|
|
51
53
|
base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
|
|
@@ -58,8 +60,8 @@ class McpServerComponent(ComponentService):
|
|
|
58
60
|
self.client = None
|
|
59
61
|
|
|
60
62
|
async def _serve(self) -> None:
|
|
61
|
-
if self.config.
|
|
62
|
-
await run_command_streaming(self.config.
|
|
63
|
+
if self.config.manage.scripts.start:
|
|
64
|
+
await run_command_streaming(self.config.manage.scripts.start, self.config.manage.working_dir, self.config.manage.env, block=False)
|
|
63
65
|
|
|
64
66
|
async def _shutdown(self) -> None:
|
|
65
67
|
pass
|
{model_compose-0.3.8 → model_compose-0.3.10}/src/mindor/core/component/services/model/base.py
RENAMED
|
@@ -4,7 +4,7 @@ from mindor.dsl.schema.component import ModelComponentConfig, ModelTaskType, Dev
|
|
|
4
4
|
from mindor.dsl.schema.action import ModelActionConfig
|
|
5
5
|
from mindor.core.services import AsyncService
|
|
6
6
|
from ...context import ComponentActionContext
|
|
7
|
-
from transformers import PreTrainedModel, PreTrainedTokenizer
|
|
7
|
+
from transformers import PreTrainedModel, PreTrainedTokenizer, ProcessorMixin
|
|
8
8
|
import torch, asyncio
|
|
9
9
|
|
|
10
10
|
class ModelTaskService(AsyncService):
|
|
@@ -41,7 +41,7 @@ class ModelTaskService(AsyncService):
|
|
|
41
41
|
|
|
42
42
|
def _get_common_model_params(self) -> Dict[str, Any]:
|
|
43
43
|
params: Dict[str, Any] = {}
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
if self.config.device_mode != DeviceMode.SINGLE:
|
|
46
46
|
params["device_map"] = self.config.device_mode.value
|
|
47
47
|
|
|
@@ -61,7 +61,10 @@ class ModelTaskService(AsyncService):
|
|
|
61
61
|
params["local_files_only"] = True
|
|
62
62
|
|
|
63
63
|
return params
|
|
64
|
-
|
|
64
|
+
|
|
65
|
+
def _get_model_class(self) -> Type[PreTrainedModel]:
|
|
66
|
+
raise NotImplementedError("Model class loader not implemented.")
|
|
67
|
+
|
|
65
68
|
def _load_pretrained_tokenizer(self, extra_params: Optional[Dict[str, Any]] = None) -> PreTrainedTokenizer:
|
|
66
69
|
params = self._get_common_tokenizer_params()
|
|
67
70
|
|
|
@@ -86,17 +89,37 @@ class ModelTaskService(AsyncService):
|
|
|
86
89
|
params["local_files_only"] = True
|
|
87
90
|
|
|
88
91
|
return params
|
|
89
|
-
|
|
90
|
-
def _get_model_device(self, model: PreTrainedModel) -> torch.device:
|
|
91
|
-
return next(model.parameters()).device
|
|
92
92
|
|
|
93
|
-
@abstractmethod
|
|
94
|
-
def _get_model_class(self) -> Type[PreTrainedModel]:
|
|
95
|
-
pass
|
|
96
|
-
|
|
97
|
-
@abstractmethod
|
|
98
93
|
def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
|
|
99
|
-
|
|
94
|
+
raise NotImplementedError("Tokenizer class loader not implemented.")
|
|
95
|
+
|
|
96
|
+
def _load_pretrained_processor(self, extra_params: Optional[Dict[str, Any]] = None) -> ProcessorMixin:
|
|
97
|
+
params = self._get_common_processor_params()
|
|
98
|
+
|
|
99
|
+
if extra_params:
|
|
100
|
+
params.update(extra_params)
|
|
101
|
+
|
|
102
|
+
return self._get_processor_class().from_pretrained(self.config.model, **params)
|
|
103
|
+
|
|
104
|
+
def _get_common_processor_params(self) -> Dict[str, Any]:
|
|
105
|
+
params: Dict[str, Any] = {}
|
|
106
|
+
|
|
107
|
+
if self.config.revision:
|
|
108
|
+
params["revision"] = self.config.revision
|
|
109
|
+
|
|
110
|
+
if self.config.cache_dir:
|
|
111
|
+
params["cache_dir"] = self.config.cache_dir
|
|
112
|
+
|
|
113
|
+
if self.config.local_files_only:
|
|
114
|
+
params["local_files_only"] = True
|
|
115
|
+
|
|
116
|
+
return params
|
|
117
|
+
|
|
118
|
+
def _get_processor_class(self) -> Type[ProcessorMixin]:
|
|
119
|
+
raise NotImplementedError("Processor class loader not implemented.")
|
|
120
|
+
|
|
121
|
+
def _get_model_device(self, model: PreTrainedModel) -> torch.device:
|
|
122
|
+
return next(model.parameters()).device
|
|
100
123
|
|
|
101
124
|
def register_model_task_service(type: ModelTaskType):
|
|
102
125
|
def decorator(cls: Type[ModelTaskService]) -> Type[ModelTaskService]:
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Protocol, Any
|
|
2
|
+
from mindor.dsl.schema.component import ModelComponentConfig, ImageToTextModelArchitecture
|
|
3
|
+
from mindor.dsl.schema.action import ModelActionConfig, ImageToTextModelActionConfig
|
|
4
|
+
from mindor.core.utils.streamer import AsyncStreamer
|
|
5
|
+
from mindor.core.logger import logging
|
|
6
|
+
from ..base import ModelTaskService, ModelTaskType, register_model_task_service
|
|
7
|
+
from ..base import ComponentActionContext
|
|
8
|
+
from transformers import PreTrainedModel, PreTrainedTokenizer, ProcessorMixin, GenerationMixin, TextIteratorStreamer
|
|
9
|
+
from PIL import Image as PILImage
|
|
10
|
+
from threading import Thread
|
|
11
|
+
from torch import Tensor
|
|
12
|
+
import torch, asyncio
|
|
13
|
+
|
|
14
|
+
class WithTokenizer(Protocol):
|
|
15
|
+
tokenizer: PreTrainedTokenizer
|
|
16
|
+
|
|
17
|
+
class ImageToTextTaskAction:
|
|
18
|
+
def __init__(self, config: ImageToTextModelActionConfig, model: PreTrainedModel, processor: ProcessorMixin, device: torch.device):
|
|
19
|
+
self.config: ImageToTextModelActionConfig = config
|
|
20
|
+
self.model: Union[PreTrainedModel, GenerationMixin] = model
|
|
21
|
+
self.processor: Union[ProcessorMixin, WithTokenizer] = processor
|
|
22
|
+
self.device: torch.device = device
|
|
23
|
+
|
|
24
|
+
async def run(self, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
|
|
25
|
+
image: Union[PILImage.Image, List[PILImage.Image]] = await context.render_image(self.config.image)
|
|
26
|
+
prompt: Optional[Union[str, List[str]]] = await context.render_variable(self.config.prompt)
|
|
27
|
+
|
|
28
|
+
batch_size = await context.render_variable(self.config.params.batch_size)
|
|
29
|
+
stream = await context.render_variable(self.config.stream)
|
|
30
|
+
|
|
31
|
+
is_single_input: bool = True if not isinstance(images, list) else False
|
|
32
|
+
images: List[PILImage.Image] = [ image ] if is_single_input else image
|
|
33
|
+
prompts: Optional[List[str]] = [ prompt ] if is_single_input else prompt
|
|
34
|
+
results = []
|
|
35
|
+
|
|
36
|
+
if stream and (batch_size != 1 or len(images) != 1):
|
|
37
|
+
raise ValueError("Streaming mode only supports a single input image with batch size of 1.")
|
|
38
|
+
|
|
39
|
+
streamer = TextIteratorStreamer(self.processor.tokenizer, skip_prompt=True, skip_special_tokens=True) if stream else None
|
|
40
|
+
for index in range(0, len(images), batch_size):
|
|
41
|
+
batch_images = images[index:index + batch_size]
|
|
42
|
+
batch_prompts = prompts[index:index + batch_size] if prompts else None
|
|
43
|
+
|
|
44
|
+
inputs: Tensor = self.processor(images=batch_images, text=batch_prompts, return_tensors="pt")
|
|
45
|
+
inputs = inputs.to(self.device)
|
|
46
|
+
|
|
47
|
+
def _generate():
|
|
48
|
+
with torch.inference_mode():
|
|
49
|
+
outputs = self.model.generate(
|
|
50
|
+
**inputs,
|
|
51
|
+
streamer=streamer
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
outputs = self.processor.tokenizer.batch_decode(outputs, skip_special_tokens=True)
|
|
55
|
+
results.extend(outputs)
|
|
56
|
+
|
|
57
|
+
if stream:
|
|
58
|
+
thread = Thread(target=_generate)
|
|
59
|
+
thread.start()
|
|
60
|
+
else:
|
|
61
|
+
_generate()
|
|
62
|
+
|
|
63
|
+
if stream:
|
|
64
|
+
async def _stream_generator():
|
|
65
|
+
async for chunk in AsyncStreamer(streamer, loop):
|
|
66
|
+
context.register_source("result", chunk)
|
|
67
|
+
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else chunk
|
|
68
|
+
|
|
69
|
+
return _stream_generator()
|
|
70
|
+
else:
|
|
71
|
+
result = results[0] if is_single_input else results
|
|
72
|
+
context.register_source("result", result)
|
|
73
|
+
|
|
74
|
+
return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
75
|
+
|
|
76
|
+
@register_model_task_service(ModelTaskType.IMAGE_TO_TEXT)
|
|
77
|
+
class ImageToTextTaskService(ModelTaskService):
|
|
78
|
+
def __init__(self, id: str, config: ModelComponentConfig, daemon: bool):
|
|
79
|
+
super().__init__(id, config, daemon)
|
|
80
|
+
|
|
81
|
+
self.model: Optional[Union[PreTrainedModel, GenerationMixin]] = None
|
|
82
|
+
self.processor: Optional[ProcessorMixin] = None
|
|
83
|
+
self.device: Optional[torch.device] = None
|
|
84
|
+
|
|
85
|
+
async def _serve(self) -> None:
|
|
86
|
+
try:
|
|
87
|
+
self.model = self._load_pretrained_model()
|
|
88
|
+
self.processor = self._load_pretrained_processor()
|
|
89
|
+
self.device = self._get_model_device(self.model)
|
|
90
|
+
logging.info(f"Model and processor loaded successfully on device '{self.device}': {self.config.model}")
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logging.error(f"Failed to load model '{self.config.model}': {e}")
|
|
93
|
+
raise
|
|
94
|
+
|
|
95
|
+
async def _shutdown(self) -> None:
|
|
96
|
+
self.model = None
|
|
97
|
+
self.processor = None
|
|
98
|
+
self.device = None
|
|
99
|
+
|
|
100
|
+
async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
|
|
101
|
+
return await ImageToTextTaskAction(action, self.model, self.processor, self.device).run(context, loop)
|
|
102
|
+
|
|
103
|
+
def _get_model_class(self) -> Type[PreTrainedModel]:
|
|
104
|
+
if self.config.architecture == ImageToTextModelArchitecture.BLIP:
|
|
105
|
+
from transformers import BlipForConditionalGeneration
|
|
106
|
+
return BlipForConditionalGeneration
|
|
107
|
+
|
|
108
|
+
if self.config.architecture == ImageToTextModelArchitecture.BLIP2:
|
|
109
|
+
from transformers import Blip2ForConditionalGeneration
|
|
110
|
+
return Blip2ForConditionalGeneration
|
|
111
|
+
|
|
112
|
+
if self.config.architecture == ImageToTextModelArchitecture.GIT:
|
|
113
|
+
from transformers import GitForCausalLM
|
|
114
|
+
return GitForCausalLM
|
|
115
|
+
|
|
116
|
+
if self.config.architecture == ImageToTextModelArchitecture.PIX2STRUCT:
|
|
117
|
+
from transformers import Pix2StructForConditionalGeneration
|
|
118
|
+
return Pix2StructForConditionalGeneration
|
|
119
|
+
|
|
120
|
+
if self.config.architecture == ImageToTextModelArchitecture.DONUT:
|
|
121
|
+
from transformers import VisionEncoderDecoderModel # Donut uses this
|
|
122
|
+
return VisionEncoderDecoderModel
|
|
123
|
+
|
|
124
|
+
if self.config.architecture == ImageToTextModelArchitecture.KOSMOS2:
|
|
125
|
+
from transformers import Kosmos2ForConditionalGeneration
|
|
126
|
+
return Kosmos2ForConditionalGeneration
|
|
127
|
+
|
|
128
|
+
raise ValueError(f"Unknown architecture: {self.config.architecture}")
|
|
129
|
+
|
|
130
|
+
def _get_processor_class(self) -> Type[ProcessorMixin]:
|
|
131
|
+
if self.config.architecture == ImageToTextModelArchitecture.BLIP:
|
|
132
|
+
from transformers import BlipProcessor
|
|
133
|
+
return BlipProcessor
|
|
134
|
+
|
|
135
|
+
if self.config.architecture == ImageToTextModelArchitecture.BLIP2:
|
|
136
|
+
from transformers import Blip2Processor
|
|
137
|
+
return Blip2Processor
|
|
138
|
+
|
|
139
|
+
if self.config.architecture == ImageToTextModelArchitecture.GIT:
|
|
140
|
+
from transformers import GitProcessor
|
|
141
|
+
return GitProcessor
|
|
142
|
+
|
|
143
|
+
if self.config.architecture == ImageToTextModelArchitecture.PIX2STRUCT:
|
|
144
|
+
from transformers import Pix2StructProcessor
|
|
145
|
+
return Pix2StructProcessor
|
|
146
|
+
|
|
147
|
+
if self.config.architecture == ImageToTextModelArchitecture.DONUT:
|
|
148
|
+
from transformers import DonutProcessor
|
|
149
|
+
return DonutProcessor
|
|
150
|
+
|
|
151
|
+
if self.config.architecture == ImageToTextModelArchitecture.KOSMOS2:
|
|
152
|
+
from transformers import Kosmos2Processor
|
|
153
|
+
return Kosmos2Processor
|
|
154
|
+
|
|
155
|
+
raise ValueError(f"Unknown architecture: {self.config.architecture}")
|
|
@@ -11,7 +11,7 @@ from torch import Tensor
|
|
|
11
11
|
import torch, asyncio
|
|
12
12
|
|
|
13
13
|
class SummarizationTaskAction:
|
|
14
|
-
def __init__(self, config: SummarizationModelActionConfig, model:
|
|
14
|
+
def __init__(self, config: SummarizationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
|
|
15
15
|
self.config: SummarizationModelActionConfig = config
|
|
16
16
|
self.model: Union[PreTrainedModel, GenerationMixin] = model
|
|
17
17
|
self.tokenizer: PreTrainedTokenizer = tokenizer
|
|
@@ -32,7 +32,8 @@ class SummarizationTaskAction:
|
|
|
32
32
|
batch_size = await context.render_variable(self.config.params.batch_size)
|
|
33
33
|
stream = await context.render_variable(self.config.stream)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
is_single_input: bool = True if not isinstance(text, list) else False
|
|
36
|
+
texts: List[str] = [ text ] if is_single_input else text
|
|
36
37
|
results = []
|
|
37
38
|
|
|
38
39
|
if stream and (batch_size != 1 or len(texts) != 1):
|
|
@@ -45,7 +46,7 @@ class SummarizationTaskAction:
|
|
|
45
46
|
inputs = { k: v.to(self.device) for k, v in inputs.items() }
|
|
46
47
|
|
|
47
48
|
def _generate():
|
|
48
|
-
with torch.
|
|
49
|
+
with torch.inference_mode():
|
|
49
50
|
outputs = self.model.generate(
|
|
50
51
|
**inputs,
|
|
51
52
|
max_length=max_output_length,
|
|
@@ -61,8 +62,9 @@ class SummarizationTaskAction:
|
|
|
61
62
|
streamer=streamer
|
|
62
63
|
)
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
if not stream:
|
|
66
|
+
outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
|
|
67
|
+
results.extend(outputs)
|
|
66
68
|
|
|
67
69
|
if stream:
|
|
68
70
|
thread = Thread(target=_generate)
|
|
@@ -70,15 +72,15 @@ class SummarizationTaskAction:
|
|
|
70
72
|
else:
|
|
71
73
|
_generate()
|
|
72
74
|
|
|
73
|
-
if stream:
|
|
75
|
+
if stream:
|
|
74
76
|
async def _stream_generator():
|
|
75
|
-
async for
|
|
76
|
-
context.register_source("result",
|
|
77
|
-
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else
|
|
77
|
+
async for chunk in AsyncStreamer(streamer, loop):
|
|
78
|
+
context.register_source("result", chunk)
|
|
79
|
+
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else chunk
|
|
78
80
|
|
|
79
81
|
return _stream_generator()
|
|
80
82
|
else:
|
|
81
|
-
result = results if
|
|
83
|
+
result = results[0] if is_single_input else results
|
|
82
84
|
context.register_source("result", result)
|
|
83
85
|
|
|
84
86
|
return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from mindor.dsl.schema.component import ModelComponentConfig
|
|
3
|
+
from mindor.dsl.schema.action import ModelActionConfig, TextClassificationModelActionConfig
|
|
4
|
+
from mindor.core.utils.streamer import AsyncStreamer
|
|
5
|
+
from mindor.core.logger import logging
|
|
6
|
+
from ..base import ModelTaskService, ModelTaskType, register_model_task_service
|
|
7
|
+
from ..base import ComponentActionContext
|
|
8
|
+
from transformers import AutoModelForSequenceClassification, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer
|
|
9
|
+
from transformers.modeling_outputs import SequenceClassifierOutput
|
|
10
|
+
import torch.nn.functional as F
|
|
11
|
+
from torch import Tensor
|
|
12
|
+
import torch, asyncio
|
|
13
|
+
|
|
14
|
+
class TextClassificationTaskAction:
|
|
15
|
+
def __init__(self, config: TextClassificationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
|
|
16
|
+
self.config: TextClassificationModelActionConfig = config
|
|
17
|
+
self.model: PreTrainedModel = model
|
|
18
|
+
self.tokenizer: PreTrainedTokenizer = tokenizer
|
|
19
|
+
self.device: torch.device = device
|
|
20
|
+
|
|
21
|
+
async def run(self, context: ComponentActionContext, labels: Optional[List[str]]) -> Any:
|
|
22
|
+
text: Union[str, List[str]] = await context.render_variable(self.config.text)
|
|
23
|
+
|
|
24
|
+
return_probabilities = await context.render_variable(self.config.params.return_probabilities)
|
|
25
|
+
batch_size = await context.render_variable(self.config.params.batch_size)
|
|
26
|
+
stream = await context.render_variable(self.config.stream)
|
|
27
|
+
|
|
28
|
+
is_single_input: bool = True if not isinstance(text, list) else False
|
|
29
|
+
has_iterable_result: bool = context.has_reference("result[]", self.config.output)
|
|
30
|
+
texts: List[str] = [ text ] if is_single_input else text
|
|
31
|
+
results = []
|
|
32
|
+
|
|
33
|
+
async def _predict():
|
|
34
|
+
for index in range(0, len(texts), batch_size):
|
|
35
|
+
batch_texts = texts[index:index + batch_size]
|
|
36
|
+
inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", padding=True, truncation=True)
|
|
37
|
+
inputs = { k: v.to(self.device) for k, v in inputs.items() }
|
|
38
|
+
|
|
39
|
+
with torch.inference_mode():
|
|
40
|
+
outputs: SequenceClassifierOutput = self.model(**inputs)
|
|
41
|
+
logits = outputs.logits # shape: (batch_size, num_classes)
|
|
42
|
+
predictions = []
|
|
43
|
+
|
|
44
|
+
if return_probabilities:
|
|
45
|
+
probs = F.softmax(logits, dim=-1).cpu()
|
|
46
|
+
for prob in probs:
|
|
47
|
+
predicted_index = torch.argmax(prob).item()
|
|
48
|
+
predictions.append({
|
|
49
|
+
"label": labels[predicted_index] if labels else predicted_index,
|
|
50
|
+
"probabilities": prob.tolist()
|
|
51
|
+
})
|
|
52
|
+
else:
|
|
53
|
+
predicted_indices = torch.argmax(logits, dim=-1).tolist()
|
|
54
|
+
for predicted_index in predicted_indices:
|
|
55
|
+
predictions.append(labels[predicted_index] if labels else predicted_index)
|
|
56
|
+
|
|
57
|
+
if self.config.output and has_iterable_result:
|
|
58
|
+
rendered_outputs = []
|
|
59
|
+
for prediction in predictions:
|
|
60
|
+
context.register_source("result[]", prediction)
|
|
61
|
+
output = await context.render_variable(self.config.output, ignore_files=True)
|
|
62
|
+
rendered_outputs.append(output)
|
|
63
|
+
yield rendered_outputs
|
|
64
|
+
else:
|
|
65
|
+
yield predictions
|
|
66
|
+
|
|
67
|
+
if stream:
|
|
68
|
+
async def _stream_generator():
|
|
69
|
+
async for predictions in _predict():
|
|
70
|
+
if not has_iterable_result:
|
|
71
|
+
for prediction in predictions:
|
|
72
|
+
context.register_source("result", prediction)
|
|
73
|
+
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
74
|
+
else:
|
|
75
|
+
for prediction in predictions:
|
|
76
|
+
yield prediction
|
|
77
|
+
|
|
78
|
+
return _stream_generator()
|
|
79
|
+
else:
|
|
80
|
+
async for predictions in _predict():
|
|
81
|
+
results.extend(predictions)
|
|
82
|
+
|
|
83
|
+
if not has_iterable_result:
|
|
84
|
+
result = results[0] if is_single_input else results
|
|
85
|
+
context.register_source("result", result)
|
|
86
|
+
|
|
87
|
+
return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
88
|
+
else:
|
|
89
|
+
return results
|
|
90
|
+
|
|
91
|
+
@register_model_task_service(ModelTaskType.TEXT_CLASSIFICATION)
|
|
92
|
+
class TextClassificationTaskService(ModelTaskService):
|
|
93
|
+
def __init__(self, id: str, config: ModelComponentConfig, daemon: bool):
|
|
94
|
+
super().__init__(id, config, daemon)
|
|
95
|
+
|
|
96
|
+
self.model: Optional[PreTrainedModel] = None
|
|
97
|
+
self.tokenizer: Optional[PreTrainedTokenizer] = None
|
|
98
|
+
self.device: Optional[torch.device] = None
|
|
99
|
+
|
|
100
|
+
async def _serve(self) -> None:
|
|
101
|
+
try:
|
|
102
|
+
self.model = self._load_pretrained_model()
|
|
103
|
+
self.tokenizer = self._load_pretrained_tokenizer()
|
|
104
|
+
self.device = self._get_model_device(self.model)
|
|
105
|
+
logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logging.error(f"Failed to load model '{self.config.model}': {e}")
|
|
108
|
+
raise
|
|
109
|
+
|
|
110
|
+
async def _shutdown(self) -> None:
|
|
111
|
+
self.model = None
|
|
112
|
+
self.tokenizer = None
|
|
113
|
+
self.device = None
|
|
114
|
+
|
|
115
|
+
async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
|
|
116
|
+
return await TextClassificationTaskAction(action, self.model, self.tokenizer, self.device).run(context, self.config.labels)
|
|
117
|
+
|
|
118
|
+
def _get_model_class(self) -> Type[PreTrainedModel]:
|
|
119
|
+
return AutoModelForSequenceClassification
|
|
120
|
+
|
|
121
|
+
def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
|
|
122
|
+
return AutoTokenizer
|
|
@@ -1,6 +1,7 @@
|
|
|
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, TextEmbeddingModelActionConfig
|
|
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
|
|
@@ -23,31 +24,64 @@ class TextEmbeddingTaskAction:
|
|
|
23
24
|
pooling = await context.render_variable(self.config.params.pooling)
|
|
24
25
|
normalize = await context.render_variable(self.config.params.normalize)
|
|
25
26
|
batch_size = await context.render_variable(self.config.params.batch_size)
|
|
27
|
+
stream = await context.render_variable(self.config.stream)
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
is_single_input: bool = True if not isinstance(text, list) else False
|
|
30
|
+
has_iterable_result: bool = context.has_reference("result[]", self.config.output)
|
|
31
|
+
texts: List[str] = [ text ] if is_single_input else text
|
|
28
32
|
results = []
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
34
|
+
async def _embed():
|
|
35
|
+
for index in range(0, len(texts), batch_size):
|
|
36
|
+
batch_texts = texts[index:index + batch_size]
|
|
37
|
+
inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", max_length=max_input_length, padding=True, truncation=True)
|
|
38
|
+
inputs = { k: v.to(self.device) for k, v in inputs.items() }
|
|
39
|
+
|
|
40
|
+
with torch.inference_mode():
|
|
41
|
+
outputs: BaseModelOutput = self.model(**inputs)
|
|
42
|
+
last_hidden_state = outputs.last_hidden_state # (batch_size, seq_len, hidden_size)
|
|
43
|
+
|
|
44
|
+
attention_mask = inputs.get("attention_mask", None)
|
|
45
|
+
embeddings = self._pool_hidden_state(last_hidden_state, attention_mask, pooling)
|
|
46
|
+
|
|
47
|
+
if normalize:
|
|
48
|
+
embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1, eps=1e-12)
|
|
49
|
+
|
|
50
|
+
embeddings = embeddings.cpu().tolist()
|
|
51
|
+
|
|
52
|
+
if self.config.output and has_iterable_result:
|
|
53
|
+
rendered_outputs = []
|
|
54
|
+
for embedding in embeddings:
|
|
55
|
+
context.register_source("result[]", embedding)
|
|
56
|
+
output = await context.render_variable(self.config.output, ignore_files=True)
|
|
57
|
+
rendered_outputs.append(output)
|
|
58
|
+
yield rendered_outputs
|
|
59
|
+
else:
|
|
60
|
+
yield embeddings
|
|
61
|
+
|
|
62
|
+
if stream:
|
|
63
|
+
async def _stream_generator():
|
|
64
|
+
async for embeddings in _embed():
|
|
65
|
+
if not has_iterable_result:
|
|
66
|
+
for embedding in embeddings:
|
|
67
|
+
context.register_source("result", embedding)
|
|
68
|
+
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
69
|
+
else:
|
|
70
|
+
for embedding in embeddings:
|
|
71
|
+
yield embedding
|
|
72
|
+
|
|
73
|
+
return _stream_generator()
|
|
74
|
+
else:
|
|
75
|
+
async for embeddings in _embed():
|
|
76
|
+
results.extend(embeddings)
|
|
77
|
+
|
|
78
|
+
if not has_iterable_result:
|
|
79
|
+
result = results[0] if is_single_input else results
|
|
80
|
+
context.register_source("result", result)
|
|
81
|
+
|
|
82
|
+
return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
83
|
+
else:
|
|
84
|
+
return results
|
|
51
85
|
|
|
52
86
|
def _pool_hidden_state(self, last_hidden_state: Tensor, attention_mask: Optional[Tensor], pooling: str) -> Tensor:
|
|
53
87
|
if pooling == "mean":
|