model-compose 0.3.9__tar.gz → 0.3.11__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.9 → model_compose-0.3.11}/PKG-INFO +7 -7
- {model_compose-0.3.9 → model_compose-0.3.11}/README.md +6 -6
- {model_compose-0.3.9 → model_compose-0.3.11}/pyproject.toml +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/base.py +13 -12
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/component.py +9 -8
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/context.py +9 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/http_server.py +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/base.py +35 -12
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/tasks/__init__.py +1 -0
- model_compose-0.3.11/src/mindor/core/component/services/model/tasks/image_to_text.py +155 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/tasks/summarization.py +12 -10
- model_compose-0.3.11/src/mindor/core/component/services/model/tasks/text_classification.py +121 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/tasks/text_embedding.py +55 -22
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/tasks/text_generation.py +12 -10
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/tasks/translation.py +12 -10
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/base.py +5 -5
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/controller.py +2 -2
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runner/http_client.py +2 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runner/mcp_client.py +1 -15
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/specs.py +9 -11
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/services/http_server.py +24 -29
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/services/mcp_server.py +6 -4
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/webui/gradio.py +5 -5
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/webui/webui.py +8 -6
- model_compose-0.3.11/src/mindor/core/gateway/services/http_tunnel.py +82 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/listener/services/http_callback.py +5 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/http_client.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/image.py +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/renderers.py +43 -9
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/streaming.py +9 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/context.py +6 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/__init__.py +2 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/delay.py +4 -4
- model_compose-0.3.11/src/mindor/core/workflow/job/impl/filter.py +13 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/if_.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/random_router.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/switch.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/schema.py +24 -24
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/workflow.py +11 -10
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/action.py +1 -1
- model_compose-0.3.11/src/mindor/dsl/schema/action/impl/common.py +7 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/http_client.py +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/http_server.py +1 -1
- {model_compose-0.3.9/src/mindor/dsl/schema/component → model_compose-0.3.11/src/mindor/dsl/schema/action}/impl/model/impl/__init__.py +1 -0
- model_compose-0.3.11/src/mindor/dsl/schema/action/impl/model/impl/image_to_text.py +12 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/model.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/common.py +2 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/http_client.py +7 -7
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/http_server.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/mcp_client.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/mcp_server.py +3 -3
- {model_compose-0.3.9/src/mindor/dsl/schema/action → model_compose-0.3.11/src/mindor/dsl/schema/component}/impl/model/impl/__init__.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/model/impl/common.py +1 -9
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/image_to_text.py +27 -0
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +17 -0
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +17 -0
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +17 -0
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +17 -0
- model_compose-0.3.11/src/mindor/dsl/schema/component/impl/model/impl/translation.py +17 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/model/impl/types.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/model/model.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/shell.py +4 -4
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/text_splitter.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/workflow.py +3 -3
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/compose.py +5 -5
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/webui.py +0 -1
- model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/__init__.py +1 -0
- model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/http_tunnel.py +11 -0
- model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/__init__.py +3 -0
- model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/cloudflare.py +7 -0
- model_compose-0.3.9/src/mindor/dsl/schema/gateway/impl/http_tunnel.py → model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/common.py +5 -4
- model_compose-0.3.11/src/mindor/dsl/schema/gateway/impl/http_tunnel/impl/ngrok.py +7 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +2 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/__init__.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/common.py +2 -1
- model_compose-0.3.11/src/mindor/dsl/schema/job/impl/filter.py +8 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/if_.py +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/switch.py +1 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/types.py +1 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/job.py +2 -1
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/impl/http_callback.py +6 -6
- model_compose-0.3.11/src/mindor/dsl/schema/transport/ssh.py +33 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/workflow.py +13 -12
- model_compose-0.3.11/src/mindor/dsl/utils/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/PKG-INFO +7 -7
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/SOURCES.txt +13 -1
- model_compose-0.3.9/src/mindor/core/component/services/model/tasks/text_classification.py +0 -90
- model_compose-0.3.9/src/mindor/core/gateway/services/http_tunnel.py +0 -32
- model_compose-0.3.9/src/mindor/dsl/schema/action/impl/common.py +0 -6
- model_compose-0.3.9/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -9
- model_compose-0.3.9/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -9
- model_compose-0.3.9/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -9
- model_compose-0.3.9/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -9
- model_compose-0.3.9/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -9
- {model_compose-0.3.9 → model_compose-0.3.11}/LICENSE +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/setup.cfg +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/cli/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/cli/compose.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/http_client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/mcp_client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/mcp_server.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/model/model.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/shell.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/text_splitter.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/component/services/workflow.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/compose/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/compose/compose.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/compose/manager.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runner/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runner/client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runner/runner.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/native/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/runtime/native/native.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/controller/webui/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/gateway/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/gateway/base.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/gateway/gateway.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/gateway/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/listener/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/listener/base.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/listener/listener.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/listener/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/base.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/logger.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/logging.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/services/console.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/logger/services/file.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/runtime/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/runtime/docker/docker.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/runtime/env.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/services/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/services/async_service.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/caching.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/http_request.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/http_status.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/mcp_client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/resolvers.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/shell.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/ssh_client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/streamer.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/time.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/utils/workqueue.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/base.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/impl/action.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/core/workflow/job/job.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/loader.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/component.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/component/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/controller.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/impl/http_server.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/impl/mcp_server.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/action.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/listener/listener.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/logger/logger.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
- {model_compose-0.3.9/src/mindor/dsl/utils → model_compose-0.3.11/src/mindor/dsl/schema/transport}/__init__.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/utils/annotation.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/mindor/dsl/utils/enum.py +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/dependency_links.txt +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/entry_points.txt +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/requires.txt +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/src/model_compose.egg-info/top_level.txt +0 -0
- {model_compose-0.3.9 → model_compose-0.3.11}/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.
|
|
3
|
+
Version: 0.3.11
|
|
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
|
|
@@ -165,7 +165,7 @@ controller:
|
|
|
165
165
|
port: 8081
|
|
166
166
|
|
|
167
167
|
components:
|
|
168
|
-
chatgpt
|
|
168
|
+
- id: chatgpt
|
|
169
169
|
type: http-client
|
|
170
170
|
base_url: https://api.openai.com/v1
|
|
171
171
|
path: /chat/completions
|
|
@@ -182,10 +182,10 @@ components:
|
|
|
182
182
|
quote: ${response.choices[0].message.content}
|
|
183
183
|
|
|
184
184
|
workflows:
|
|
185
|
-
generate-quote
|
|
185
|
+
- id: generate-quote
|
|
186
186
|
default: true
|
|
187
187
|
jobs:
|
|
188
|
-
get-quote
|
|
188
|
+
- id: get-quote
|
|
189
189
|
component: chatgpt
|
|
190
190
|
```
|
|
191
191
|
|
|
@@ -302,7 +302,7 @@ controller:
|
|
|
302
302
|
base_path: /mcp
|
|
303
303
|
|
|
304
304
|
components:
|
|
305
|
-
chatgpt
|
|
305
|
+
- id: chatgpt
|
|
306
306
|
type: http-client
|
|
307
307
|
base_url: https://api.openai.com/v1
|
|
308
308
|
path: /chat/completions
|
|
@@ -319,10 +319,10 @@ components:
|
|
|
319
319
|
quote: ${response.choices[0].message.content}
|
|
320
320
|
|
|
321
321
|
workflows:
|
|
322
|
-
generate-quote
|
|
322
|
+
- id: generate-quote
|
|
323
323
|
default: true
|
|
324
324
|
jobs:
|
|
325
|
-
get-quote
|
|
325
|
+
- id: get-quote
|
|
326
326
|
component: chatgpt
|
|
327
327
|
```
|
|
328
328
|
This configuration launches the controller as an **MCP server**, which listens on port 8080 and exposes your workflows over a **JSON-RPC API**.
|
|
@@ -136,7 +136,7 @@ controller:
|
|
|
136
136
|
port: 8081
|
|
137
137
|
|
|
138
138
|
components:
|
|
139
|
-
chatgpt
|
|
139
|
+
- id: chatgpt
|
|
140
140
|
type: http-client
|
|
141
141
|
base_url: https://api.openai.com/v1
|
|
142
142
|
path: /chat/completions
|
|
@@ -153,10 +153,10 @@ components:
|
|
|
153
153
|
quote: ${response.choices[0].message.content}
|
|
154
154
|
|
|
155
155
|
workflows:
|
|
156
|
-
generate-quote
|
|
156
|
+
- id: generate-quote
|
|
157
157
|
default: true
|
|
158
158
|
jobs:
|
|
159
|
-
get-quote
|
|
159
|
+
- id: get-quote
|
|
160
160
|
component: chatgpt
|
|
161
161
|
```
|
|
162
162
|
|
|
@@ -273,7 +273,7 @@ controller:
|
|
|
273
273
|
base_path: /mcp
|
|
274
274
|
|
|
275
275
|
components:
|
|
276
|
-
chatgpt
|
|
276
|
+
- id: chatgpt
|
|
277
277
|
type: http-client
|
|
278
278
|
base_url: https://api.openai.com/v1
|
|
279
279
|
path: /chat/completions
|
|
@@ -290,10 +290,10 @@ components:
|
|
|
290
290
|
quote: ${response.choices[0].message.content}
|
|
291
291
|
|
|
292
292
|
workflows:
|
|
293
|
-
generate-quote
|
|
293
|
+
- id: generate-quote
|
|
294
294
|
default: true
|
|
295
295
|
jobs:
|
|
296
|
-
get-quote
|
|
296
|
+
- id: get-quote
|
|
297
297
|
component: chatgpt
|
|
298
298
|
```
|
|
299
299
|
This configuration launches the controller as an **MCP server**, which listens on port 8080 and exposes your workflows over a **JSON-RPC API**.
|
|
@@ -10,40 +10,41 @@ from mindor.core.utils.workqueue import WorkQueue
|
|
|
10
10
|
from .context import ComponentActionContext
|
|
11
11
|
|
|
12
12
|
class ActionResolver:
|
|
13
|
-
def __init__(self, actions:
|
|
14
|
-
self.actions = actions
|
|
13
|
+
def __init__(self, actions: List[ActionConfig]):
|
|
14
|
+
self.actions: List[ActionConfig] = actions
|
|
15
15
|
|
|
16
16
|
def resolve(self, action_id: Optional[str]) -> Tuple[str, ActionConfig]:
|
|
17
17
|
action_id = action_id or self._find_default_id(self.actions)
|
|
18
|
+
action = next((action for action in self.actions if action.id == action_id), None)
|
|
18
19
|
|
|
19
|
-
if
|
|
20
|
+
if action is None:
|
|
20
21
|
raise ValueError(f"Action not found: {action_id}")
|
|
21
22
|
|
|
22
|
-
return action_id,
|
|
23
|
+
return action_id, action
|
|
23
24
|
|
|
24
|
-
def _find_default_id(self, actions:
|
|
25
|
-
default_ids = [
|
|
25
|
+
def _find_default_id(self, actions: List[ActionConfig]) -> str:
|
|
26
|
+
default_ids = [ action.id for action in actions if action.default or action.id == "__default__" ]
|
|
26
27
|
|
|
27
28
|
if len(default_ids) > 1:
|
|
28
29
|
raise ValueError("Multiple actions have default: true")
|
|
29
30
|
|
|
30
|
-
if not default_ids
|
|
31
|
+
if not default_ids:
|
|
31
32
|
raise ValueError("No default action defined.")
|
|
32
33
|
|
|
33
|
-
return default_ids[0]
|
|
34
|
+
return default_ids[0]
|
|
34
35
|
|
|
35
36
|
class ComponentGlobalConfigs:
|
|
36
37
|
def __init__(
|
|
37
38
|
self,
|
|
38
|
-
components:
|
|
39
|
+
components: List[ComponentConfig],
|
|
39
40
|
listeners: List[ListenerConfig],
|
|
40
41
|
gateways: List[GatewayConfig],
|
|
41
|
-
workflows:
|
|
42
|
+
workflows: List[WorkflowConfig]
|
|
42
43
|
):
|
|
43
|
-
self.components:
|
|
44
|
+
self.components: List[ComponentConfig] = components
|
|
44
45
|
self.listeners: List[ListenerConfig] = listeners
|
|
45
46
|
self.gateways: List[GatewayConfig] = gateways
|
|
46
|
-
self.workflows:
|
|
47
|
+
self.workflows: List[WorkflowConfig] = workflows
|
|
47
48
|
|
|
48
49
|
class ComponentService(AsyncService):
|
|
49
50
|
def __init__(self, id: str, config: ComponentConfig, global_configs: ComponentGlobalConfigs, daemon: bool):
|
|
@@ -5,27 +5,28 @@ from .base import ComponentService, ComponentGlobalConfigs, ComponentRegistry
|
|
|
5
5
|
ComponentInstances: Dict[str, ComponentService] = {}
|
|
6
6
|
|
|
7
7
|
class ComponentResolver:
|
|
8
|
-
def __init__(self, components:
|
|
9
|
-
self.components:
|
|
8
|
+
def __init__(self, components: List[ComponentConfig]):
|
|
9
|
+
self.components: List[ComponentConfig] = components
|
|
10
10
|
|
|
11
11
|
def resolve(self, component_id: Optional[str]) -> Tuple[str, ComponentConfig]:
|
|
12
12
|
component_id = component_id or self._find_default_id(self.components)
|
|
13
|
+
component = next((component for component in self.components if component.id == component_id), None)
|
|
13
14
|
|
|
14
|
-
if
|
|
15
|
+
if component is None:
|
|
15
16
|
raise ValueError(f"Component not found: {component_id}")
|
|
16
17
|
|
|
17
|
-
return component_id,
|
|
18
|
+
return component_id, component
|
|
18
19
|
|
|
19
|
-
def _find_default_id(self, components:
|
|
20
|
-
default_ids = [
|
|
20
|
+
def _find_default_id(self, components: List[ComponentConfig]) -> str:
|
|
21
|
+
default_ids = [ component.id for component in components if component.default or component.id == "__default__" ]
|
|
21
22
|
|
|
22
23
|
if len(default_ids) > 1:
|
|
23
24
|
raise ValueError("Multiple components have default: true")
|
|
24
25
|
|
|
25
|
-
if not default_ids
|
|
26
|
+
if not default_ids:
|
|
26
27
|
raise ValueError("No default component defined.")
|
|
27
28
|
|
|
28
|
-
return default_ids[0]
|
|
29
|
+
return default_ids[0]
|
|
29
30
|
|
|
30
31
|
def create_component(id: str, config: ComponentConfig, global_configs: ComponentGlobalConfigs, daemon: bool) -> ComponentService:
|
|
31
32
|
try:
|
|
@@ -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
|
-
async def render_variable(self,
|
|
17
|
-
return await self.renderer.render(
|
|
16
|
+
async def render_variable(self, value: Any, ignore_files: bool = False) -> Any:
|
|
17
|
+
return await self.renderer.render(value, ignore_files)
|
|
18
|
+
|
|
19
|
+
async def render_image(self, value: Any) -> Any:
|
|
20
|
+
return await ImageValueRenderer().render(await self.render_variable(value))
|
|
21
|
+
|
|
22
|
+
def contains_variable_reference(self, key: str, value: Any) -> bool:
|
|
23
|
+
return self.renderer.contains_reference(key, 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.9 → model_compose-0.3.11}/src/mindor/core/component/services/http_server.py
RENAMED
|
@@ -56,7 +56,7 @@ class HttpServerPollingCompletion(HttpServerCompletion):
|
|
|
56
56
|
|
|
57
57
|
class HttpServerCallbackCompletion(HttpServerCompletion):
|
|
58
58
|
async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
|
|
59
|
-
callback_id = await context.render_variable(self.config.wait_for)
|
|
59
|
+
callback_id = await context.render_variable(self.config.wait_for) if self.config.wait_for else "__default__"
|
|
60
60
|
future: asyncio.Future = asyncio.get_running_loop().create_future()
|
|
61
61
|
HttpCallbackListener.register_pending_future(callback_id, future)
|
|
62
62
|
|
{model_compose-0.3.9 → model_compose-0.3.11}/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,121 @@
|
|
|
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.logger import logging
|
|
5
|
+
from ..base import ModelTaskService, ModelTaskType, register_model_task_service
|
|
6
|
+
from ..base import ComponentActionContext
|
|
7
|
+
from transformers import AutoModelForSequenceClassification, AutoTokenizer, PreTrainedModel, PreTrainedTokenizer
|
|
8
|
+
from transformers.modeling_outputs import SequenceClassifierOutput
|
|
9
|
+
import torch.nn.functional as F
|
|
10
|
+
from torch import Tensor
|
|
11
|
+
import torch, asyncio
|
|
12
|
+
|
|
13
|
+
class TextClassificationTaskAction:
|
|
14
|
+
def __init__(self, config: TextClassificationModelActionConfig, model: PreTrainedModel, tokenizer: PreTrainedTokenizer, device: torch.device):
|
|
15
|
+
self.config: TextClassificationModelActionConfig = config
|
|
16
|
+
self.model: PreTrainedModel = model
|
|
17
|
+
self.tokenizer: PreTrainedTokenizer = tokenizer
|
|
18
|
+
self.device: torch.device = device
|
|
19
|
+
|
|
20
|
+
async def run(self, context: ComponentActionContext, labels: Optional[List[str]]) -> Any:
|
|
21
|
+
text: Union[str, List[str]] = await context.render_variable(self.config.text)
|
|
22
|
+
|
|
23
|
+
return_probabilities = await context.render_variable(self.config.params.return_probabilities)
|
|
24
|
+
batch_size = await context.render_variable(self.config.params.batch_size)
|
|
25
|
+
stream = await context.render_variable(self.config.stream)
|
|
26
|
+
|
|
27
|
+
is_single_input: bool = True if not isinstance(text, list) else False
|
|
28
|
+
is_output_array_mode: bool = context.contains_variable_reference("result[]", self.config.output)
|
|
29
|
+
texts: List[str] = [ text ] if is_single_input else text
|
|
30
|
+
results = []
|
|
31
|
+
|
|
32
|
+
async def _predict():
|
|
33
|
+
for index in range(0, len(texts), batch_size):
|
|
34
|
+
batch_texts = texts[index:index + batch_size]
|
|
35
|
+
inputs: Dict[str, Tensor] = self.tokenizer(batch_texts, return_tensors="pt", padding=True, truncation=True)
|
|
36
|
+
inputs = { k: v.to(self.device) for k, v in inputs.items() }
|
|
37
|
+
|
|
38
|
+
with torch.inference_mode():
|
|
39
|
+
outputs: SequenceClassifierOutput = self.model(**inputs)
|
|
40
|
+
logits = outputs.logits # shape: (batch_size, num_classes)
|
|
41
|
+
predictions = []
|
|
42
|
+
|
|
43
|
+
if return_probabilities:
|
|
44
|
+
probs = F.softmax(logits, dim=-1).cpu()
|
|
45
|
+
for prob in probs:
|
|
46
|
+
predicted_index = torch.argmax(prob).item()
|
|
47
|
+
predictions.append({
|
|
48
|
+
"label": labels[predicted_index] if labels else predicted_index,
|
|
49
|
+
"probabilities": prob.tolist()
|
|
50
|
+
})
|
|
51
|
+
else:
|
|
52
|
+
predicted_indices = torch.argmax(logits, dim=-1).tolist()
|
|
53
|
+
for predicted_index in predicted_indices:
|
|
54
|
+
predictions.append(labels[predicted_index] if labels else predicted_index)
|
|
55
|
+
|
|
56
|
+
if self.config.output and is_output_array_mode:
|
|
57
|
+
rendered_outputs = []
|
|
58
|
+
for prediction in predictions:
|
|
59
|
+
context.register_source("result[]", prediction)
|
|
60
|
+
output = await context.render_variable(self.config.output, ignore_files=True)
|
|
61
|
+
rendered_outputs.append(output)
|
|
62
|
+
yield rendered_outputs
|
|
63
|
+
else:
|
|
64
|
+
yield predictions
|
|
65
|
+
|
|
66
|
+
if stream:
|
|
67
|
+
async def _stream_generator():
|
|
68
|
+
async for predictions in _predict():
|
|
69
|
+
if not is_output_array_mode:
|
|
70
|
+
for prediction in predictions:
|
|
71
|
+
context.register_source("result", prediction)
|
|
72
|
+
yield (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
73
|
+
else:
|
|
74
|
+
for prediction in predictions:
|
|
75
|
+
yield prediction
|
|
76
|
+
|
|
77
|
+
return _stream_generator()
|
|
78
|
+
else:
|
|
79
|
+
async for predictions in _predict():
|
|
80
|
+
results.extend(predictions)
|
|
81
|
+
|
|
82
|
+
if not is_output_array_mode:
|
|
83
|
+
result = results[0] if is_single_input else results
|
|
84
|
+
context.register_source("result", result)
|
|
85
|
+
|
|
86
|
+
return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
|
|
87
|
+
else:
|
|
88
|
+
return results
|
|
89
|
+
|
|
90
|
+
@register_model_task_service(ModelTaskType.TEXT_CLASSIFICATION)
|
|
91
|
+
class TextClassificationTaskService(ModelTaskService):
|
|
92
|
+
def __init__(self, id: str, config: ModelComponentConfig, daemon: bool):
|
|
93
|
+
super().__init__(id, config, daemon)
|
|
94
|
+
|
|
95
|
+
self.model: Optional[PreTrainedModel] = None
|
|
96
|
+
self.tokenizer: Optional[PreTrainedTokenizer] = None
|
|
97
|
+
self.device: Optional[torch.device] = None
|
|
98
|
+
|
|
99
|
+
async def _serve(self) -> None:
|
|
100
|
+
try:
|
|
101
|
+
self.model = self._load_pretrained_model()
|
|
102
|
+
self.tokenizer = self._load_pretrained_tokenizer()
|
|
103
|
+
self.device = self._get_model_device(self.model)
|
|
104
|
+
logging.info(f"Model and tokenizer loaded successfully on device '{self.device}': {self.config.model}")
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logging.error(f"Failed to load model '{self.config.model}': {e}")
|
|
107
|
+
raise
|
|
108
|
+
|
|
109
|
+
async def _shutdown(self) -> None:
|
|
110
|
+
self.model = None
|
|
111
|
+
self.tokenizer = None
|
|
112
|
+
self.device = None
|
|
113
|
+
|
|
114
|
+
async def _run(self, action: ModelActionConfig, context: ComponentActionContext, loop: asyncio.AbstractEventLoop) -> Any:
|
|
115
|
+
return await TextClassificationTaskAction(action, self.model, self.tokenizer, self.device).run(context, self.config.labels)
|
|
116
|
+
|
|
117
|
+
def _get_model_class(self) -> Type[PreTrainedModel]:
|
|
118
|
+
return AutoModelForSequenceClassification
|
|
119
|
+
|
|
120
|
+
def _get_tokenizer_class(self) -> Type[PreTrainedTokenizer]:
|
|
121
|
+
return AutoTokenizer
|