truss 0.10.0rc1__py3-none-any.whl → 0.60.0__py3-none-any.whl
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.
Potentially problematic release.
This version of truss might be problematic. Click here for more details.
- truss/__init__.py +10 -3
- truss/api/__init__.py +123 -0
- truss/api/definitions.py +51 -0
- truss/base/constants.py +116 -0
- truss/base/custom_types.py +29 -0
- truss/{errors.py → base/errors.py} +4 -0
- truss/base/trt_llm_config.py +310 -0
- truss/{truss_config.py → base/truss_config.py} +344 -31
- truss/{truss_spec.py → base/truss_spec.py} +20 -6
- truss/{validation.py → base/validation.py} +60 -11
- truss/cli/cli.py +841 -88
- truss/{remote → cli}/remote_cli.py +2 -7
- truss/contexts/docker_build_setup.py +67 -0
- truss/contexts/image_builder/cache_warmer.py +2 -8
- truss/contexts/image_builder/image_builder.py +1 -1
- truss/contexts/image_builder/serving_image_builder.py +292 -46
- truss/contexts/image_builder/util.py +1 -3
- truss/contexts/local_loader/docker_build_emulator.py +58 -0
- truss/contexts/local_loader/load_model_local.py +2 -2
- truss/contexts/local_loader/truss_module_loader.py +1 -1
- truss/contexts/local_loader/utils.py +1 -1
- truss/local/local_config.py +2 -6
- truss/local/local_config_handler.py +20 -5
- truss/patch/__init__.py +1 -0
- truss/patch/hash.py +4 -70
- truss/patch/signature.py +4 -16
- truss/patch/truss_dir_patch_applier.py +3 -78
- truss/remote/baseten/api.py +308 -23
- truss/remote/baseten/auth.py +3 -3
- truss/remote/baseten/core.py +257 -50
- truss/remote/baseten/custom_types.py +44 -0
- truss/remote/baseten/error.py +4 -0
- truss/remote/baseten/remote.py +369 -118
- truss/remote/baseten/service.py +118 -11
- truss/remote/baseten/utils/status.py +29 -0
- truss/remote/baseten/utils/tar.py +34 -22
- truss/remote/baseten/utils/transfer.py +36 -23
- truss/remote/remote_factory.py +14 -5
- truss/remote/truss_remote.py +72 -45
- truss/templates/base.Dockerfile.jinja +18 -16
- truss/templates/cache.Dockerfile.jinja +3 -3
- truss/{server → templates/control}/control/application.py +14 -35
- truss/{server → templates/control}/control/endpoints.py +39 -9
- truss/{server/control/patch/types.py → templates/control/control/helpers/custom_types.py} +13 -52
- truss/{server → templates/control}/control/helpers/inference_server_controller.py +4 -8
- truss/{server → templates/control}/control/helpers/inference_server_process_controller.py +2 -4
- truss/{server → templates/control}/control/helpers/inference_server_starter.py +5 -10
- truss/{server/control → templates/control/control/helpers}/truss_patch/model_code_patch_applier.py +8 -6
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/model_container_patch_applier.py +18 -26
- truss/templates/control/control/helpers/truss_patch/requirement_name_identifier.py +66 -0
- truss/{server → templates/control}/control/server.py +11 -6
- truss/templates/control/requirements.txt +9 -0
- truss/templates/custom_python_dx/my_model.py +28 -0
- truss/templates/docker_server/proxy.conf.jinja +42 -0
- truss/templates/docker_server/supervisord.conf.jinja +27 -0
- truss/templates/docker_server_requirements.txt +1 -0
- truss/templates/server/common/errors.py +231 -0
- truss/{server → templates/server}/common/patches/whisper/patch.py +1 -0
- truss/{server/common/patches/__init__.py → templates/server/common/patches.py} +1 -3
- truss/{server → templates/server}/common/retry.py +1 -0
- truss/{server → templates/server}/common/schema.py +11 -9
- truss/templates/server/common/tracing.py +157 -0
- truss/templates/server/main.py +9 -0
- truss/templates/server/model_wrapper.py +961 -0
- truss/templates/server/requirements.txt +21 -0
- truss/templates/server/truss_server.py +447 -0
- truss/templates/server.Dockerfile.jinja +62 -14
- truss/templates/shared/dynamic_config_resolver.py +28 -0
- truss/templates/shared/lazy_data_resolver.py +164 -0
- truss/templates/shared/log_config.py +125 -0
- truss/{server → templates}/shared/secrets_resolver.py +1 -2
- truss/{server → templates}/shared/serialization.py +31 -9
- truss/{server → templates}/shared/util.py +3 -13
- truss/templates/trtllm-audio/model/model.py +49 -0
- truss/templates/trtllm-audio/packages/sigint_patch.py +14 -0
- truss/templates/trtllm-audio/packages/whisper_trt/__init__.py +215 -0
- truss/templates/trtllm-audio/packages/whisper_trt/assets.py +25 -0
- truss/templates/trtllm-audio/packages/whisper_trt/batching.py +52 -0
- truss/templates/trtllm-audio/packages/whisper_trt/custom_types.py +26 -0
- truss/templates/trtllm-audio/packages/whisper_trt/modeling.py +184 -0
- truss/templates/trtllm-audio/packages/whisper_trt/tokenizer.py +185 -0
- truss/templates/trtllm-audio/packages/whisper_trt/utils.py +245 -0
- truss/templates/trtllm-briton/src/extension.py +64 -0
- truss/tests/conftest.py +302 -94
- truss/tests/contexts/image_builder/test_serving_image_builder.py +74 -31
- truss/tests/contexts/local_loader/test_load_local.py +2 -2
- truss/tests/contexts/local_loader/test_truss_module_finder.py +1 -1
- truss/tests/patch/test_calc_patch.py +439 -127
- truss/tests/patch/test_dir_signature.py +3 -12
- truss/tests/patch/test_hash.py +1 -1
- truss/tests/patch/test_signature.py +1 -1
- truss/tests/patch/test_truss_dir_patch_applier.py +23 -11
- truss/tests/patch/test_types.py +2 -2
- truss/tests/remote/baseten/test_api.py +153 -58
- truss/tests/remote/baseten/test_auth.py +2 -1
- truss/tests/remote/baseten/test_core.py +160 -12
- truss/tests/remote/baseten/test_remote.py +489 -77
- truss/tests/remote/baseten/test_service.py +55 -0
- truss/tests/remote/test_remote_factory.py +16 -18
- truss/tests/remote/test_truss_remote.py +26 -17
- truss/tests/templates/control/control/helpers/test_context_managers.py +11 -0
- truss/tests/templates/control/control/helpers/test_model_container_patch_applier.py +184 -0
- truss/tests/templates/control/control/helpers/test_requirement_name_identifier.py +89 -0
- truss/tests/{server → templates/control}/control/test_server.py +79 -24
- truss/tests/{server → templates/control}/control/test_server_integration.py +24 -16
- truss/tests/templates/core/server/test_dynamic_config_resolver.py +108 -0
- truss/tests/templates/core/server/test_lazy_data_resolver.py +329 -0
- truss/tests/templates/core/server/test_lazy_data_resolver_v2.py +79 -0
- truss/tests/{server → templates}/core/server/test_secrets_resolver.py +1 -1
- truss/tests/{server → templates/server}/common/test_retry.py +3 -3
- truss/tests/templates/server/test_model_wrapper.py +248 -0
- truss/tests/{server → templates/server}/test_schema.py +3 -5
- truss/tests/{server/core/server/common → templates/server}/test_truss_server.py +8 -5
- truss/tests/test_build.py +9 -52
- truss/tests/test_config.py +336 -77
- truss/tests/test_context_builder_image.py +3 -11
- truss/tests/test_control_truss_patching.py +7 -12
- truss/tests/test_custom_server.py +38 -0
- truss/tests/test_data/context_builder_image_test/test.py +3 -0
- truss/tests/test_data/happy.ipynb +56 -0
- truss/tests/test_data/model_load_failure_test/config.yaml +2 -0
- truss/tests/test_data/model_load_failure_test/model/__init__.py +0 -0
- truss/tests/test_data/patch_ping_test_server/__init__.py +0 -0
- truss/{test_data → tests/test_data}/patch_ping_test_server/app.py +3 -9
- truss/{test_data → tests/test_data}/server.Dockerfile +20 -21
- truss/tests/test_data/server_conformance_test_truss/__init__.py +0 -0
- truss/tests/test_data/server_conformance_test_truss/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/server_conformance_test_truss/model/model.py +1 -3
- truss/tests/test_data/test_async_truss/__init__.py +0 -0
- truss/tests/test_data/test_async_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_basic_truss/__init__.py +0 -0
- truss/tests/test_data/test_basic_truss/config.yaml +16 -0
- truss/tests/test_data/test_basic_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_build_commands/__init__.py +0 -0
- truss/tests/test_data/test_build_commands/config.yaml +13 -0
- truss/tests/test_data/test_build_commands/model/__init__.py +0 -0
- truss/{test_data/test_streaming_async_generator_truss → tests/test_data/test_build_commands}/model/model.py +2 -3
- truss/tests/test_data/test_build_commands_failure/__init__.py +0 -0
- truss/tests/test_data/test_build_commands_failure/config.yaml +14 -0
- truss/tests/test_data/test_build_commands_failure/model/__init__.py +0 -0
- truss/tests/test_data/test_build_commands_failure/model/model.py +17 -0
- truss/tests/test_data/test_concurrency_truss/__init__.py +0 -0
- truss/tests/test_data/test_concurrency_truss/config.yaml +4 -0
- truss/tests/test_data/test_concurrency_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/config.yaml +20 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/Dockerfile +17 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/README.md +10 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/VERSION +1 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/__init__.py +0 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/app.py +19 -0
- truss/tests/test_data/test_custom_server_truss/test_docker_image/build_upload_new_image.sh +6 -0
- truss/tests/test_data/test_openai/__init__.py +0 -0
- truss/{test_data/test_basic_truss → tests/test_data/test_openai}/config.yaml +1 -2
- truss/tests/test_data/test_openai/model/__init__.py +0 -0
- truss/tests/test_data/test_openai/model/model.py +15 -0
- truss/tests/test_data/test_pyantic_v1/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v1/model/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v1/model/model.py +28 -0
- truss/tests/test_data/test_pyantic_v1/requirements.txt +1 -0
- truss/tests/test_data/test_pyantic_v2/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v2/config.yaml +13 -0
- truss/tests/test_data/test_pyantic_v2/model/__init__.py +0 -0
- truss/tests/test_data/test_pyantic_v2/model/model.py +30 -0
- truss/tests/test_data/test_pyantic_v2/requirements.txt +1 -0
- truss/tests/test_data/test_requirements_file_truss/__init__.py +0 -0
- truss/tests/test_data/test_requirements_file_truss/config.yaml +13 -0
- truss/tests/test_data/test_requirements_file_truss/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/test_requirements_file_truss/model/model.py +1 -0
- truss/tests/test_data/test_streaming_async_generator_truss/__init__.py +0 -0
- truss/tests/test_data/test_streaming_async_generator_truss/config.yaml +4 -0
- truss/tests/test_data/test_streaming_async_generator_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_async_generator_truss/model/model.py +7 -0
- truss/tests/test_data/test_streaming_read_timeout/__init__.py +0 -0
- truss/tests/test_data/test_streaming_read_timeout/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss/config.yaml +4 -0
- truss/tests/test_data/test_streaming_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/test_streaming_truss_with_error/model/model.py +3 -11
- truss/tests/test_data/test_streaming_truss_with_error/packages/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_1.py +5 -0
- truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_2.py +2 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/config.yaml +43 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/model/__init__.py +0 -0
- truss/tests/test_data/test_streaming_truss_with_tracing/model/model.py +65 -0
- truss/tests/test_data/test_trt_llm_truss/__init__.py +0 -0
- truss/tests/test_data/test_trt_llm_truss/config.yaml +15 -0
- truss/tests/test_data/test_trt_llm_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_trt_llm_truss/model/model.py +15 -0
- truss/tests/test_data/test_truss/__init__.py +0 -0
- truss/tests/test_data/test_truss/config.yaml +4 -0
- truss/tests/test_data/test_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_truss/model/dummy +0 -0
- truss/tests/test_data/test_truss/packages/__init__.py +0 -0
- truss/tests/test_data/test_truss/packages/test_package/__init__.py +0 -0
- truss/tests/test_data/test_truss_server_caching_truss/__init__.py +0 -0
- truss/tests/test_data/test_truss_server_caching_truss/model/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/config.yaml +4 -0
- truss/tests/test_data/test_truss_with_error/model/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/model/model.py +8 -0
- truss/tests/test_data/test_truss_with_error/packages/__init__.py +0 -0
- truss/tests/test_data/test_truss_with_error/packages/helpers_1.py +5 -0
- truss/tests/test_data/test_truss_with_error/packages/helpers_2.py +2 -0
- truss/tests/test_docker.py +2 -1
- truss/tests/test_model_inference.py +1340 -292
- truss/tests/test_model_schema.py +33 -26
- truss/tests/test_testing_utilities_for_other_tests.py +50 -5
- truss/tests/test_truss_gatherer.py +3 -5
- truss/tests/test_truss_handle.py +62 -59
- truss/tests/test_util.py +2 -1
- truss/tests/test_validation.py +15 -13
- truss/tests/trt_llm/test_trt_llm_config.py +41 -0
- truss/tests/trt_llm/test_validation.py +91 -0
- truss/tests/util/test_config_checks.py +40 -0
- truss/tests/util/test_env_vars.py +14 -0
- truss/tests/util/test_path.py +10 -23
- truss/trt_llm/config_checks.py +43 -0
- truss/trt_llm/validation.py +42 -0
- truss/truss_handle/__init__.py +0 -0
- truss/truss_handle/build.py +122 -0
- truss/{decorators.py → truss_handle/decorators.py} +1 -1
- truss/truss_handle/patch/__init__.py +0 -0
- truss/{patch → truss_handle/patch}/calc_patch.py +146 -92
- truss/{types.py → truss_handle/patch/custom_types.py} +35 -27
- truss/{patch → truss_handle/patch}/dir_signature.py +1 -1
- truss/truss_handle/patch/hash.py +71 -0
- truss/{patch → truss_handle/patch}/local_truss_patch_applier.py +6 -4
- truss/truss_handle/patch/signature.py +22 -0
- truss/truss_handle/patch/truss_dir_patch_applier.py +87 -0
- truss/{readme_generator.py → truss_handle/readme_generator.py} +3 -2
- truss/{truss_gatherer.py → truss_handle/truss_gatherer.py} +3 -2
- truss/{truss_handle.py → truss_handle/truss_handle.py} +174 -78
- truss/util/.truss_ignore +3 -0
- truss/{docker.py → util/docker.py} +6 -2
- truss/util/download.py +6 -15
- truss/util/env_vars.py +41 -0
- truss/util/log_utils.py +52 -0
- truss/util/path.py +20 -20
- truss/util/requirements.py +11 -0
- {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/METADATA +18 -16
- truss-0.60.0.dist-info/RECORD +324 -0
- {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/WHEEL +1 -1
- truss-0.60.0.dist-info/entry_points.txt +4 -0
- truss_chains/__init__.py +71 -0
- truss_chains/definitions.py +756 -0
- truss_chains/deployment/__init__.py +0 -0
- truss_chains/deployment/code_gen.py +816 -0
- truss_chains/deployment/deployment_client.py +871 -0
- truss_chains/framework.py +1480 -0
- truss_chains/public_api.py +231 -0
- truss_chains/py.typed +0 -0
- truss_chains/pydantic_numpy.py +131 -0
- truss_chains/reference_code/reference_chainlet.py +34 -0
- truss_chains/reference_code/reference_model.py +10 -0
- truss_chains/remote_chainlet/__init__.py +0 -0
- truss_chains/remote_chainlet/model_skeleton.py +60 -0
- truss_chains/remote_chainlet/stub.py +380 -0
- truss_chains/remote_chainlet/utils.py +332 -0
- truss_chains/streaming.py +378 -0
- truss_chains/utils.py +178 -0
- CODE_OF_CONDUCT.md +0 -131
- CONTRIBUTING.md +0 -48
- README.md +0 -137
- context_builder.Dockerfile +0 -24
- truss/blob/blob_backend.py +0 -10
- truss/blob/blob_backend_registry.py +0 -23
- truss/blob/http_public_blob_backend.py +0 -23
- truss/build/__init__.py +0 -2
- truss/build/build.py +0 -143
- truss/build/configure.py +0 -63
- truss/cli/__init__.py +0 -2
- truss/cli/console.py +0 -5
- truss/cli/create.py +0 -5
- truss/config/trt_llm.py +0 -81
- truss/constants.py +0 -61
- truss/model_inference.py +0 -123
- truss/patch/types.py +0 -30
- truss/pytest.ini +0 -7
- truss/server/common/errors.py +0 -100
- truss/server/common/termination_handler_middleware.py +0 -64
- truss/server/common/truss_server.py +0 -389
- truss/server/control/patch/model_code_patch_applier.py +0 -46
- truss/server/control/patch/requirement_name_identifier.py +0 -17
- truss/server/inference_server.py +0 -29
- truss/server/model_wrapper.py +0 -434
- truss/server/shared/logging.py +0 -81
- truss/templates/trtllm/model/model.py +0 -97
- truss/templates/trtllm/packages/build_engine_utils.py +0 -34
- truss/templates/trtllm/packages/constants.py +0 -11
- truss/templates/trtllm/packages/schema.py +0 -216
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/ensemble/config.pbtxt +0 -246
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/1/model.py +0 -181
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/config.pbtxt +0 -64
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/1/model.py +0 -260
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/config.pbtxt +0 -99
- truss/templates/trtllm/packages/tensorrt_llm_model_repository/tensorrt_llm/config.pbtxt +0 -208
- truss/templates/trtllm/packages/triton_client.py +0 -150
- truss/templates/trtllm/packages/utils.py +0 -43
- truss/test_data/context_builder_image_test/test.py +0 -4
- truss/test_data/happy.ipynb +0 -54
- truss/test_data/model_load_failure_test/config.yaml +0 -2
- truss/test_data/test_concurrency_truss/config.yaml +0 -2
- truss/test_data/test_streaming_async_generator_truss/config.yaml +0 -2
- truss/test_data/test_streaming_truss/config.yaml +0 -3
- truss/test_data/test_truss/config.yaml +0 -2
- truss/tests/server/common/test_termination_handler_middleware.py +0 -93
- truss/tests/server/control/test_model_container_patch_applier.py +0 -203
- truss/tests/server/core/server/common/test_util.py +0 -19
- truss/tests/server/test_model_wrapper.py +0 -87
- truss/util/data_structures.py +0 -16
- truss-0.10.0rc1.dist-info/RECORD +0 -216
- truss-0.10.0rc1.dist-info/entry_points.txt +0 -3
- truss/{server/shared → base}/__init__.py +0 -0
- truss/{server → templates/control}/control/helpers/context_managers.py +0 -0
- truss/{server/control → templates/control/control/helpers}/errors.py +0 -0
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/__init__.py +0 -0
- truss/{server/control/patch → templates/control/control/helpers/truss_patch}/system_packages.py +0 -0
- truss/{test_data/annotated_types_truss/model → templates/server}/__init__.py +0 -0
- truss/{server → templates/server}/common/__init__.py +0 -0
- truss/{test_data/gcs_fix/model → templates/shared}/__init__.py +0 -0
- truss/templates/{trtllm → trtllm-briton}/README.md +0 -0
- truss/{test_data/server_conformance_test_truss/model → tests/test_data}/__init__.py +0 -0
- truss/{test_data/test_basic_truss/model → tests/test_data/annotated_types_truss}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/annotated_types_truss/config.yaml +0 -0
- truss/{test_data/test_requirements_file_truss → tests/test_data/annotated_types_truss}/model/__init__.py +0 -0
- truss/{test_data → tests/test_data}/annotated_types_truss/model/model.py +0 -0
- truss/{test_data → tests/test_data}/auto-mpg.data +0 -0
- truss/{test_data → tests/test_data}/context_builder_image_test/Dockerfile +0 -0
- truss/{test_data/test_truss/model → tests/test_data/context_builder_image_test}/__init__.py +0 -0
- truss/{test_data/test_truss_server_caching_truss/model → tests/test_data/gcs_fix}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/gcs_fix/config.yaml +0 -0
- truss/tests/{local → test_data/gcs_fix/model}/__init__.py +0 -0
- truss/{test_data → tests/test_data}/gcs_fix/model/model.py +0 -0
- truss/{test_data/test_truss/model/dummy → tests/test_data/model_load_failure_test/__init__.py} +0 -0
- truss/{test_data → tests/test_data}/model_load_failure_test/model/model.py +0 -0
- truss/{test_data → tests/test_data}/pima-indians-diabetes.csv +0 -0
- truss/{test_data → tests/test_data}/readme_int_example.md +0 -0
- truss/{test_data → tests/test_data}/readme_no_example.md +0 -0
- truss/{test_data → tests/test_data}/readme_str_example.md +0 -0
- truss/{test_data → tests/test_data}/server_conformance_test_truss/config.yaml +0 -0
- truss/{test_data → tests/test_data}/test_async_truss/config.yaml +0 -0
- truss/{test_data → tests/test_data}/test_async_truss/model/model.py +3 -3
- /truss/{test_data → tests/test_data}/test_basic_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_concurrency_truss/model/model.py +0 -0
- /truss/{test_data/test_requirements_file_truss → tests/test_data/test_pyantic_v1}/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_requirements_file_truss/requirements.txt +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_read_timeout/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_read_timeout/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_streaming_truss_with_error/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss/examples.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss/model/model.py +0 -0
- /truss/{test_data → tests/test_data}/test_truss/packages/test_package/test.py +0 -0
- /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/config.yaml +0 -0
- /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/model/model.py +0 -0
- /truss/{patch → truss_handle/patch}/constants.py +0 -0
- /truss/{notebook.py → util/notebook.py} +0 -0
- {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/LICENSE +0 -0
|
@@ -23,9 +23,7 @@ def inquire_remote_config() -> RemoteConfig:
|
|
|
23
23
|
# can do so manually in the .trussrc file.
|
|
24
24
|
remote_url = "https://app.baseten.co"
|
|
25
25
|
api_key = inquirer.secret(
|
|
26
|
-
message="🤫 Quietly paste your API_KEY:",
|
|
27
|
-
qmark="",
|
|
28
|
-
validate=NonEmptyValidator(),
|
|
26
|
+
message="🤫 Quietly paste your API_KEY:", qmark="", validate=NonEmptyValidator()
|
|
29
27
|
).execute()
|
|
30
28
|
|
|
31
29
|
return RemoteConfig(
|
|
@@ -56,7 +54,4 @@ def inquire_remote_name(available_remotes: List[str]) -> str:
|
|
|
56
54
|
|
|
57
55
|
|
|
58
56
|
def inquire_model_name() -> str:
|
|
59
|
-
return inquirer.text(
|
|
60
|
-
"📦 Name this model:",
|
|
61
|
-
qmark="",
|
|
62
|
-
).execute()
|
|
57
|
+
return inquirer.text("📦 Name this model:", qmark="").execute()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import pathlib
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from truss.patch.hash import directory_content_hash
|
|
9
|
+
from truss.patch.truss_dir_patch_applier import TrussDirPatchApplier
|
|
10
|
+
from truss.templates.control.control.helpers.custom_types import Patch
|
|
11
|
+
from truss.truss_handle import truss_handle
|
|
12
|
+
from truss.truss_handle.patch import signature
|
|
13
|
+
|
|
14
|
+
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
|
|
15
|
+
|
|
16
|
+
working_dir = pathlib.Path("/")
|
|
17
|
+
|
|
18
|
+
TRUSS_SRC_DIR = working_dir / "build/model_scaffold"
|
|
19
|
+
TRUSS_HASH_FILE = working_dir / "scaffold/truss_hash"
|
|
20
|
+
TRUSS_SIGNATURE_FILE = working_dir / "scaffold/truss_signature"
|
|
21
|
+
TRUSS_BUILD_CONTEXT_DIR = working_dir / "build/context"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.command()
|
|
25
|
+
@click.option("--truss_type", required=True)
|
|
26
|
+
def docker_build_setup(truss_type: str) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Prepares source and asset files in a build directory (build context), on which a
|
|
29
|
+
docker build command can be run.
|
|
30
|
+
|
|
31
|
+
This is to be run for remote builds on baseten.
|
|
32
|
+
Local builds use `TrussHandle.build_serving_docker_image`.
|
|
33
|
+
"""
|
|
34
|
+
logging.info("Loading truss")
|
|
35
|
+
tr = truss_handle.TrussHandle(TRUSS_SRC_DIR)
|
|
36
|
+
logging.info("Truss is loaded")
|
|
37
|
+
|
|
38
|
+
if patches_dir := os.environ.get("PATCHES_DIR"):
|
|
39
|
+
logging.info("Applying patches")
|
|
40
|
+
logger = logging.getLogger("patch_applier")
|
|
41
|
+
patch_applier = TrussDirPatchApplier(TRUSS_SRC_DIR, logger)
|
|
42
|
+
patches = json.loads(pathlib.Path(patches_dir).read_text())
|
|
43
|
+
patch_applier([Patch.from_dict(patch) for patch in patches])
|
|
44
|
+
|
|
45
|
+
# Important to do this before making changes to truss, we want
|
|
46
|
+
# to capture hash of original truss.
|
|
47
|
+
logging.info("Recording truss hash")
|
|
48
|
+
TRUSS_HASH_FILE.write_text(directory_content_hash(TRUSS_SRC_DIR))
|
|
49
|
+
|
|
50
|
+
logging.info("Recording truss signature.")
|
|
51
|
+
sign = signature.calc_truss_signature(TRUSS_SRC_DIR)
|
|
52
|
+
TRUSS_SIGNATURE_FILE.write_text(json.dumps(sign.to_dict()))
|
|
53
|
+
|
|
54
|
+
if truss_type == "server_control":
|
|
55
|
+
tr.live_reload(enable=True)
|
|
56
|
+
else:
|
|
57
|
+
tr.live_reload(enable=False)
|
|
58
|
+
|
|
59
|
+
# check if we have a hf_secret
|
|
60
|
+
tr.docker_build_setup(
|
|
61
|
+
TRUSS_BUILD_CONTEXT_DIR, use_hf_secret="HUGGING_FACE_HUB_TOKEN" in os.environ
|
|
62
|
+
)
|
|
63
|
+
print("Docker build context is set up for the truss.")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
docker_build_setup()
|
|
@@ -25,11 +25,7 @@ def _b10cp_path() -> Optional[str]:
|
|
|
25
25
|
return os.environ.get(B10CP_PATH_TRUSS_ENV_VAR_NAME)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def _download_from_url_using_b10cp(
|
|
29
|
-
b10cp_path: str,
|
|
30
|
-
url: str,
|
|
31
|
-
download_to: Path,
|
|
32
|
-
):
|
|
28
|
+
def _download_from_url_using_b10cp(b10cp_path: str, url: str, download_to: Path):
|
|
33
29
|
return subprocess.Popen(
|
|
34
30
|
[
|
|
35
31
|
b10cp_path,
|
|
@@ -157,9 +153,7 @@ class GCSFile(RepositoryFile):
|
|
|
157
153
|
|
|
158
154
|
if is_private:
|
|
159
155
|
url = blob.generate_signed_url(
|
|
160
|
-
version="v4",
|
|
161
|
-
expiration=datetime.timedelta(minutes=15),
|
|
162
|
-
method="GET",
|
|
156
|
+
version="v4", expiration=datetime.timedelta(minutes=15), method="GET"
|
|
163
157
|
)
|
|
164
158
|
else:
|
|
165
159
|
base_url = "https://storage.googleapis.com"
|
|
@@ -6,24 +6,51 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Any, Dict, List, Optional, Tuple, Type
|
|
7
7
|
|
|
8
8
|
import boto3
|
|
9
|
+
import yaml
|
|
9
10
|
from botocore import UNSIGNED
|
|
10
11
|
from botocore.client import Config
|
|
11
12
|
from google.cloud import storage
|
|
12
13
|
from huggingface_hub import get_hf_file_metadata, hf_hub_url, list_repo_files
|
|
13
14
|
from huggingface_hub.utils import filter_repo_objects
|
|
14
|
-
from truss.
|
|
15
|
+
from truss.base import constants
|
|
16
|
+
from truss.base.constants import (
|
|
17
|
+
BASE_SERVER_REQUIREMENTS_TXT_FILENAME,
|
|
15
18
|
BASE_TRTLLM_REQUIREMENTS,
|
|
19
|
+
BEI_MAX_CONCURRENCY_TARGET_REQUESTS,
|
|
20
|
+
BEI_REQUIRED_MAX_NUM_TOKENS,
|
|
21
|
+
BEI_TRTLLM_BASE_IMAGE,
|
|
22
|
+
BEI_TRTLLM_CLIENT_BATCH_SIZE,
|
|
23
|
+
BEI_TRTLLM_PYTHON_EXECUTABLE,
|
|
24
|
+
CHAINS_CODE_DIR,
|
|
25
|
+
CONTROL_SERVER_CODE_DIR,
|
|
26
|
+
DOCKER_SERVER_TEMPLATES_DIR,
|
|
16
27
|
FILENAME_CONSTANTS_MAP,
|
|
28
|
+
MAX_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE,
|
|
29
|
+
MIN_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE,
|
|
17
30
|
MODEL_DOCKERFILE_NAME,
|
|
18
31
|
REQUIREMENTS_TXT_FILENAME,
|
|
32
|
+
SERVER_CODE_DIR,
|
|
19
33
|
SERVER_DOCKERFILE_TEMPLATE_NAME,
|
|
34
|
+
SERVER_REQUIREMENTS_TXT_FILENAME,
|
|
35
|
+
SHARED_SERVING_AND_TRAINING_CODE_DIR,
|
|
36
|
+
SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
|
|
20
37
|
SYSTEM_PACKAGES_TXT_FILENAME,
|
|
21
38
|
TEMPLATES_DIR,
|
|
22
39
|
TRTLLM_BASE_IMAGE,
|
|
40
|
+
TRTLLM_PREDICT_CONCURRENCY,
|
|
41
|
+
TRTLLM_PYTHON_EXECUTABLE,
|
|
23
42
|
TRTLLM_TRUSS_DIR,
|
|
24
|
-
|
|
43
|
+
TRUSSLESS_MAX_PAYLOAD_SIZE,
|
|
25
44
|
USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME,
|
|
26
45
|
)
|
|
46
|
+
from truss.base.trt_llm_config import TRTLLMConfiguration, TrussTRTLLMModel
|
|
47
|
+
from truss.base.truss_config import (
|
|
48
|
+
DEFAULT_BUNDLED_PACKAGES_DIR,
|
|
49
|
+
BaseImage,
|
|
50
|
+
DockerServer,
|
|
51
|
+
TrussConfig,
|
|
52
|
+
)
|
|
53
|
+
from truss.base.truss_spec import TrussSpec
|
|
27
54
|
from truss.contexts.image_builder.cache_warmer import (
|
|
28
55
|
AWSCredentials,
|
|
29
56
|
parse_s3_credentials_file,
|
|
@@ -37,9 +64,7 @@ from truss.contexts.image_builder.util import (
|
|
|
37
64
|
truss_base_image_tag,
|
|
38
65
|
)
|
|
39
66
|
from truss.contexts.truss_context import TrussContext
|
|
40
|
-
from truss.patch.hash import directory_content_hash
|
|
41
|
-
from truss.truss_config import BaseImage, ModelServer, TrussConfig
|
|
42
|
-
from truss.truss_spec import TrussSpec
|
|
67
|
+
from truss.truss_handle.patch.hash import directory_content_hash
|
|
43
68
|
from truss.util.jinja import read_template_from_fs
|
|
44
69
|
from truss.util.path import (
|
|
45
70
|
build_truss_target_directory,
|
|
@@ -48,12 +73,16 @@ from truss.util.path import (
|
|
|
48
73
|
load_trussignore_patterns,
|
|
49
74
|
)
|
|
50
75
|
|
|
76
|
+
BUILD_SERVER_DIR_NAME = "server"
|
|
77
|
+
BUILD_CONTROL_SERVER_DIR_NAME = "control"
|
|
78
|
+
BUILD_SERVER_EXTENSIONS_PATH = "extensions"
|
|
79
|
+
BUILD_CHAINS_DIR_NAME = "truss_chains"
|
|
80
|
+
|
|
51
81
|
CONFIG_FILE = "config.yaml"
|
|
52
82
|
USER_TRUSS_IGNORE_FILE = ".truss_ignore"
|
|
53
83
|
GCS_CREDENTIALS = "service_account.json"
|
|
54
84
|
S3_CREDENTIALS = "s3_credentials.json"
|
|
55
85
|
|
|
56
|
-
HF_ACCESS_TOKEN_SECRET_NAME = "hf_access_token"
|
|
57
86
|
HF_ACCESS_TOKEN_FILE_NAME = "hf-access-token"
|
|
58
87
|
|
|
59
88
|
CLOUD_BUCKET_CACHE = Path("/app/model_cache/")
|
|
@@ -131,7 +160,7 @@ class GCSCache(RemoteCache):
|
|
|
131
160
|
|
|
132
161
|
|
|
133
162
|
class S3Cache(RemoteCache):
|
|
134
|
-
def list_files(self, revision=None):
|
|
163
|
+
def list_files(self, revision=None) -> List[str]:
|
|
135
164
|
s3_credentials_file = self.data_dir / S3_CREDENTIALS
|
|
136
165
|
|
|
137
166
|
if s3_credentials_file.exists():
|
|
@@ -279,6 +308,49 @@ def update_config_and_gather_files(
|
|
|
279
308
|
return get_files_to_cache(config, truss_dir, build_dir)
|
|
280
309
|
|
|
281
310
|
|
|
311
|
+
def generate_docker_server_nginx_config(build_dir, config):
|
|
312
|
+
nginx_template = read_template_from_fs(
|
|
313
|
+
DOCKER_SERVER_TEMPLATES_DIR, "proxy.conf.jinja"
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
assert config.docker_server.predict_endpoint is not None, (
|
|
317
|
+
"docker_server.predict_endpoint is required to use custom server"
|
|
318
|
+
)
|
|
319
|
+
assert config.docker_server.server_port is not None, (
|
|
320
|
+
"docker_server.server_port is required to use custom server"
|
|
321
|
+
)
|
|
322
|
+
assert config.docker_server.readiness_endpoint is not None, (
|
|
323
|
+
"docker_server.readiness_endpoint is required to use custom server"
|
|
324
|
+
)
|
|
325
|
+
assert config.docker_server.liveness_endpoint is not None, (
|
|
326
|
+
"docker_server.liveness_endpoint is required to use custom server"
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
nginx_content = nginx_template.render(
|
|
330
|
+
server_endpoint=config.docker_server.predict_endpoint,
|
|
331
|
+
readiness_endpoint=config.docker_server.readiness_endpoint,
|
|
332
|
+
liveness_endpoint=config.docker_server.liveness_endpoint,
|
|
333
|
+
server_port=config.docker_server.server_port,
|
|
334
|
+
client_max_body_size=TRUSSLESS_MAX_PAYLOAD_SIZE,
|
|
335
|
+
)
|
|
336
|
+
nginx_filepath = build_dir / "proxy.conf"
|
|
337
|
+
nginx_filepath.write_text(nginx_content)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def generate_docker_server_supervisord_config(build_dir, config):
|
|
341
|
+
supervisord_template = read_template_from_fs(
|
|
342
|
+
DOCKER_SERVER_TEMPLATES_DIR, "supervisord.conf.jinja"
|
|
343
|
+
)
|
|
344
|
+
assert config.docker_server.start_command is not None, (
|
|
345
|
+
"docker_server.start_command is required to use custom server"
|
|
346
|
+
)
|
|
347
|
+
supervisord_contents = supervisord_template.render(
|
|
348
|
+
start_command=config.docker_server.start_command
|
|
349
|
+
)
|
|
350
|
+
supervisord_filepath = build_dir / "supervisord.conf"
|
|
351
|
+
supervisord_filepath.write_text(supervisord_contents)
|
|
352
|
+
|
|
353
|
+
|
|
282
354
|
class ServingImageBuilderContext(TrussContext):
|
|
283
355
|
@staticmethod
|
|
284
356
|
def run(truss_dir: Path):
|
|
@@ -294,6 +366,99 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
294
366
|
def default_tag(self):
|
|
295
367
|
return f"{self._spec.model_framework_name}-model:latest"
|
|
296
368
|
|
|
369
|
+
def _copy_into_build_dir(
|
|
370
|
+
self, from_path: Path, build_dir: Path, path_in_build_dir: str
|
|
371
|
+
):
|
|
372
|
+
copy_tree_or_file(from_path, build_dir / path_in_build_dir) # type: ignore[operator]
|
|
373
|
+
|
|
374
|
+
def prepare_trtllm_bei_encoder_build_dir(self, build_dir: Path):
|
|
375
|
+
"""prepares the build directory for a trtllm ENCODER model to launch a Baseten Embeddings Inference (BEI) server"""
|
|
376
|
+
config = self._spec.config
|
|
377
|
+
assert (
|
|
378
|
+
config.trt_llm
|
|
379
|
+
and config.trt_llm.build
|
|
380
|
+
and config.trt_llm.build.base_model == TrussTRTLLMModel.ENCODER
|
|
381
|
+
), (
|
|
382
|
+
"prepare_trtllm_bei_encoder_build_dir should only be called for ENCODER tensorrt-llm model"
|
|
383
|
+
)
|
|
384
|
+
# TRTLLM has performance degradation with batch size >> 32, so we limit the runtime settings
|
|
385
|
+
# runtime batch size may not be higher than what the build settings of the model allow
|
|
386
|
+
# to 32 even if the engine.rank0 allows for higher batch_size
|
|
387
|
+
runtime_max_batch_size = min(config.trt_llm.build.max_batch_size, 32)
|
|
388
|
+
# make sure the user gets good performance, enforcing max_num_tokens here and in engine-builder
|
|
389
|
+
runtime_max_batch_tokens = max(
|
|
390
|
+
config.trt_llm.build.max_num_tokens, BEI_REQUIRED_MAX_NUM_TOKENS
|
|
391
|
+
)
|
|
392
|
+
port = 7997
|
|
393
|
+
start_command = " ".join(
|
|
394
|
+
[
|
|
395
|
+
"truss-transfer-cli && text-embeddings-router",
|
|
396
|
+
f"--port {port}",
|
|
397
|
+
# assert the max_batch_size is within trt-engine limits
|
|
398
|
+
f"--max-batch-requests {runtime_max_batch_size}",
|
|
399
|
+
# assert the max_num_tokens is within trt-engine limits
|
|
400
|
+
f"--max-batch-tokens {runtime_max_batch_tokens}",
|
|
401
|
+
# how many sentences can be in a single json payload.
|
|
402
|
+
# limited default to improve request based autoscaling.
|
|
403
|
+
f"--max-client-batch-size {BEI_TRTLLM_CLIENT_BATCH_SIZE}",
|
|
404
|
+
# how many concurrent requests can be handled by the server until 429 is returned.
|
|
405
|
+
# limited by https://docs.baseten.co/performance/concurrency#concurrency-target
|
|
406
|
+
# 2048 is a safe max value for the server
|
|
407
|
+
f"--max-concurrent-requests {BEI_MAX_CONCURRENCY_TARGET_REQUESTS}",
|
|
408
|
+
]
|
|
409
|
+
)
|
|
410
|
+
self._spec.config.docker_server = DockerServer(
|
|
411
|
+
start_command=f"/bin/sh -c '{start_command}'",
|
|
412
|
+
server_port=port,
|
|
413
|
+
predict_endpoint="/v1/embeddings",
|
|
414
|
+
readiness_endpoint="/health",
|
|
415
|
+
liveness_endpoint="/health",
|
|
416
|
+
)
|
|
417
|
+
copy_tree_path(DOCKER_SERVER_TEMPLATES_DIR, build_dir, ignore_patterns=[])
|
|
418
|
+
|
|
419
|
+
config.base_image = BaseImage(
|
|
420
|
+
image=BEI_TRTLLM_BASE_IMAGE,
|
|
421
|
+
python_executable_path=BEI_TRTLLM_PYTHON_EXECUTABLE,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
def prepare_trtllm_decoder_build_dir(self, build_dir: Path):
|
|
425
|
+
"""prepares the build directory for a trtllm decoder-like models to launch BRITON server"""
|
|
426
|
+
config = self._spec.config
|
|
427
|
+
assert (
|
|
428
|
+
config.trt_llm
|
|
429
|
+
and config.trt_llm.build
|
|
430
|
+
and config.trt_llm.build.base_model != TrussTRTLLMModel.ENCODER
|
|
431
|
+
), (
|
|
432
|
+
"prepare_trtllm_decoder_build_dir should only be called for decoder tensorrt-llm model"
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
# trt_llm is treated as an extension at model run time.
|
|
436
|
+
self._copy_into_build_dir(
|
|
437
|
+
TRTLLM_TRUSS_DIR / "src",
|
|
438
|
+
build_dir,
|
|
439
|
+
f"{BUILD_SERVER_DIR_NAME}/{BUILD_SERVER_EXTENSIONS_PATH}/trt_llm",
|
|
440
|
+
)
|
|
441
|
+
# TODO(pankaj) Do this differently. This is not ideal, user
|
|
442
|
+
# supplied code in bundled packages can conflict with those from
|
|
443
|
+
# the trtllm extension. We don't want to put this in the build
|
|
444
|
+
# directory directly either because of chances of conflict there
|
|
445
|
+
# as well and the noise it can create there. We need to find a
|
|
446
|
+
# new place that's made available in model's pythonpath. This is
|
|
447
|
+
# a bigger lift and feels overkill right now. Worth revisiting
|
|
448
|
+
# if we come across cases of actual conflicts.
|
|
449
|
+
self._copy_into_build_dir(
|
|
450
|
+
TRTLLM_TRUSS_DIR / DEFAULT_BUNDLED_PACKAGES_DIR,
|
|
451
|
+
build_dir,
|
|
452
|
+
DEFAULT_BUNDLED_PACKAGES_DIR,
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
config.runtime.predict_concurrency = TRTLLM_PREDICT_CONCURRENCY
|
|
456
|
+
|
|
457
|
+
config.base_image = BaseImage(
|
|
458
|
+
image=TRTLLM_BASE_IMAGE, python_executable_path=TRTLLM_PYTHON_EXECUTABLE
|
|
459
|
+
)
|
|
460
|
+
config.requirements.extend(BASE_TRTLLM_REQUIREMENTS)
|
|
461
|
+
|
|
297
462
|
def prepare_image_build_dir(
|
|
298
463
|
self, build_dir: Optional[Path] = None, use_hf_secret: bool = False
|
|
299
464
|
):
|
|
@@ -310,17 +475,6 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
310
475
|
|
|
311
476
|
data_dir = build_dir / config.data_dir # type: ignore[operator]
|
|
312
477
|
|
|
313
|
-
def copy_into_build_dir(from_path: Path, path_in_build_dir: str):
|
|
314
|
-
# using default ignore patterns ignores the `build` dir in truss
|
|
315
|
-
copy_tree_or_file(from_path, build_dir / path_in_build_dir, ignore_files=False) # type: ignore[operator]
|
|
316
|
-
|
|
317
|
-
# Copy truss package from the context builder image to build dir
|
|
318
|
-
copy_into_build_dir(TRUSS_PACKAGE_DIR, "truss/")
|
|
319
|
-
copy_into_build_dir(
|
|
320
|
-
TRUSS_PACKAGE_DIR.parent / "pyproject.toml", "./pyproject.toml"
|
|
321
|
-
)
|
|
322
|
-
copy_into_build_dir(TRUSS_PACKAGE_DIR.parent / "README.md", "./README.md")
|
|
323
|
-
|
|
324
478
|
truss_ignore_patterns = []
|
|
325
479
|
if (truss_dir / USER_TRUSS_IGNORE_FILE).exists():
|
|
326
480
|
truss_ignore_patterns = load_trussignore_patterns(
|
|
@@ -329,36 +483,37 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
329
483
|
|
|
330
484
|
# Copy over truss
|
|
331
485
|
copy_tree_path(truss_dir, build_dir, ignore_patterns=truss_ignore_patterns)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
config.base_image = BaseImage(
|
|
349
|
-
image=TRTLLM_BASE_IMAGE, python_executable_path="/usr/bin/python3"
|
|
486
|
+
if (
|
|
487
|
+
isinstance(config.trt_llm, TRTLLMConfiguration)
|
|
488
|
+
and config.trt_llm.build is not None
|
|
489
|
+
):
|
|
490
|
+
if config.trt_llm.build.base_model == TrussTRTLLMModel.ENCODER:
|
|
491
|
+
# Run the specific encoder build
|
|
492
|
+
self.prepare_trtllm_bei_encoder_build_dir(build_dir=build_dir)
|
|
493
|
+
else:
|
|
494
|
+
self.prepare_trtllm_decoder_build_dir(build_dir=build_dir)
|
|
495
|
+
|
|
496
|
+
if config.docker_server is not None:
|
|
497
|
+
self._copy_into_build_dir(
|
|
498
|
+
TEMPLATES_DIR / "docker_server_requirements.txt",
|
|
499
|
+
build_dir,
|
|
500
|
+
"docker_server_requirements.txt",
|
|
350
501
|
)
|
|
351
|
-
|
|
502
|
+
|
|
503
|
+
generate_docker_server_nginx_config(build_dir, config)
|
|
504
|
+
|
|
505
|
+
generate_docker_server_supervisord_config(build_dir, config)
|
|
506
|
+
|
|
507
|
+
# Override config.yml
|
|
508
|
+
with (build_dir / CONFIG_FILE).open("w") as config_file:
|
|
509
|
+
yaml.dump(config.to_dict(verbose=True), config_file)
|
|
352
510
|
|
|
353
511
|
external_data_files: list = []
|
|
354
512
|
data_dir = Path("/app/data/")
|
|
355
513
|
if self._spec.external_data is not None:
|
|
356
514
|
for ext_file in self._spec.external_data.items:
|
|
357
515
|
external_data_files.append(
|
|
358
|
-
(
|
|
359
|
-
ext_file.url,
|
|
360
|
-
(data_dir / ext_file.local_data_path).resolve(),
|
|
361
|
-
)
|
|
516
|
+
(ext_file.url, (data_dir / ext_file.local_data_path).resolve())
|
|
362
517
|
)
|
|
363
518
|
|
|
364
519
|
# Download from HuggingFace
|
|
@@ -366,12 +521,74 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
366
521
|
config, truss_dir, build_dir
|
|
367
522
|
)
|
|
368
523
|
|
|
369
|
-
|
|
370
|
-
|
|
524
|
+
# Copy inference server code
|
|
525
|
+
self._copy_into_build_dir(SERVER_CODE_DIR, build_dir, BUILD_SERVER_DIR_NAME)
|
|
526
|
+
self._copy_into_build_dir(
|
|
527
|
+
SHARED_SERVING_AND_TRAINING_CODE_DIR,
|
|
528
|
+
build_dir,
|
|
529
|
+
BUILD_SERVER_DIR_NAME + "/" + SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Copy control server code
|
|
533
|
+
if config.live_reload:
|
|
534
|
+
self._copy_into_build_dir(
|
|
535
|
+
CONTROL_SERVER_CODE_DIR, build_dir, BUILD_CONTROL_SERVER_DIR_NAME
|
|
536
|
+
)
|
|
537
|
+
self._copy_into_build_dir(
|
|
538
|
+
SHARED_SERVING_AND_TRAINING_CODE_DIR,
|
|
539
|
+
build_dir,
|
|
540
|
+
BUILD_CONTROL_SERVER_DIR_NAME
|
|
541
|
+
+ "/control/"
|
|
542
|
+
+ SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
if config.use_local_chains_src:
|
|
546
|
+
self._copy_into_build_dir(CHAINS_CODE_DIR, build_dir, BUILD_CHAINS_DIR_NAME)
|
|
547
|
+
|
|
548
|
+
# Copy base TrussServer requirements if supplied custom base image
|
|
549
|
+
base_truss_server_reqs_filepath = SERVER_CODE_DIR / REQUIREMENTS_TXT_FILENAME
|
|
550
|
+
if config.base_image:
|
|
551
|
+
self._copy_into_build_dir(
|
|
552
|
+
base_truss_server_reqs_filepath,
|
|
553
|
+
build_dir,
|
|
554
|
+
BASE_SERVER_REQUIREMENTS_TXT_FILENAME,
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
# Copy model framework specific requirements file
|
|
558
|
+
server_reqs_filepath = (
|
|
559
|
+
TEMPLATES_DIR / model_framework_name / REQUIREMENTS_TXT_FILENAME
|
|
371
560
|
)
|
|
561
|
+
should_install_server_requirements = file_is_not_empty(server_reqs_filepath)
|
|
562
|
+
if should_install_server_requirements:
|
|
563
|
+
self._copy_into_build_dir(
|
|
564
|
+
server_reqs_filepath, build_dir, SERVER_REQUIREMENTS_TXT_FILENAME
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
with open(base_truss_server_reqs_filepath, "r") as f:
|
|
568
|
+
base_server_requirements = f.read()
|
|
569
|
+
|
|
570
|
+
if config.docker_server:
|
|
571
|
+
# when docker server is enabled, no need to install truss requirements
|
|
572
|
+
# only install user-provided python requirements
|
|
573
|
+
user_provided_python_requirements = spec.requirements_txt
|
|
574
|
+
else:
|
|
575
|
+
# If the user has provided python requirements,
|
|
576
|
+
# append the truss server requirements, so that any conflicts
|
|
577
|
+
# are detected and cause a build failure. If there are no
|
|
578
|
+
# requirements provided, we just pass an empty string,
|
|
579
|
+
# as there's no need to install anything.
|
|
580
|
+
# TODO (BT-10217): above reasoning leads to inconsistencies. To get consistent
|
|
581
|
+
# images tentatively add server requirements always. This whole point needs
|
|
582
|
+
# more thought and potentially a re-design.
|
|
583
|
+
user_provided_python_requirements = (
|
|
584
|
+
base_server_requirements + spec.requirements_txt
|
|
585
|
+
if spec.requirements
|
|
586
|
+
else base_server_requirements
|
|
587
|
+
)
|
|
372
588
|
if spec.requirements_file is not None:
|
|
373
|
-
|
|
589
|
+
self._copy_into_build_dir(
|
|
374
590
|
truss_dir / spec.requirements_file,
|
|
591
|
+
build_dir,
|
|
375
592
|
USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME,
|
|
376
593
|
)
|
|
377
594
|
(build_dir / REQUIREMENTS_TXT_FILENAME).write_text(
|
|
@@ -381,24 +598,28 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
381
598
|
|
|
382
599
|
self._render_dockerfile(
|
|
383
600
|
build_dir,
|
|
601
|
+
should_install_server_requirements,
|
|
384
602
|
model_files,
|
|
385
603
|
use_hf_secret,
|
|
386
604
|
cached_files,
|
|
387
605
|
external_data_files,
|
|
606
|
+
self._spec.build_commands,
|
|
388
607
|
)
|
|
389
608
|
|
|
390
609
|
def _render_dockerfile(
|
|
391
610
|
self,
|
|
392
611
|
build_dir: Path,
|
|
612
|
+
should_install_server_requirements: bool,
|
|
393
613
|
model_files: Dict[str, Any],
|
|
394
614
|
use_hf_secret: bool,
|
|
395
615
|
cached_files: List[str],
|
|
396
616
|
external_data_files: List[Tuple[str, str]],
|
|
617
|
+
build_commands: List[str],
|
|
397
618
|
):
|
|
398
619
|
config = self._spec.config
|
|
399
620
|
data_dir = build_dir / config.data_dir
|
|
621
|
+
model_dir = build_dir / config.model_module_dir
|
|
400
622
|
bundled_packages_dir = build_dir / config.bundled_packages_dir
|
|
401
|
-
|
|
402
623
|
dockerfile_template = read_template_from_fs(
|
|
403
624
|
TEMPLATES_DIR, SERVER_DOCKERFILE_TEMPLATE_NAME
|
|
404
625
|
)
|
|
@@ -423,9 +644,31 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
423
644
|
build_dir / USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME
|
|
424
645
|
)
|
|
425
646
|
|
|
426
|
-
|
|
647
|
+
max_supported_python_version_in_custom_base_image = (
|
|
648
|
+
MAX_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE
|
|
649
|
+
)
|
|
650
|
+
min_supported_python_version_in_custom_base_image = (
|
|
651
|
+
MIN_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE
|
|
652
|
+
)
|
|
653
|
+
max_supported_python_minor_version_in_custom_base_image = (
|
|
654
|
+
MAX_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE.split(".")[1]
|
|
655
|
+
)
|
|
656
|
+
min_supported_python_minor_version_in_custom_base_image = (
|
|
657
|
+
MIN_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE.split(".")[1]
|
|
658
|
+
)
|
|
659
|
+
supported_python_major_version_in_custom_base_image = (
|
|
660
|
+
MIN_SUPPORTED_PYTHON_VERSION_IN_CUSTOM_BASE_IMAGE.split(".")[0]
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
hf_access_token = config.secrets.get(constants.HF_ACCESS_TOKEN_KEY)
|
|
427
664
|
dockerfile_contents = dockerfile_template.render(
|
|
665
|
+
should_install_server_requirements=should_install_server_requirements,
|
|
428
666
|
base_image_name_and_tag=base_image_name_and_tag,
|
|
667
|
+
max_supported_python_version_in_custom_base_image=max_supported_python_version_in_custom_base_image,
|
|
668
|
+
min_supported_python_version_in_custom_base_image=min_supported_python_version_in_custom_base_image,
|
|
669
|
+
max_supported_python_minor_version_in_custom_base_image=max_supported_python_minor_version_in_custom_base_image,
|
|
670
|
+
min_supported_python_minor_version_in_custom_base_image=min_supported_python_minor_version_in_custom_base_image,
|
|
671
|
+
supported_python_major_version_in_custom_base_image=supported_python_major_version_in_custom_base_image,
|
|
429
672
|
should_install_system_requirements=should_install_system_requirements,
|
|
430
673
|
should_install_requirements=should_install_python_requirements,
|
|
431
674
|
should_install_user_requirements_file=should_install_user_requirements_file,
|
|
@@ -433,6 +676,7 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
433
676
|
python_version=python_version,
|
|
434
677
|
live_reload=config.live_reload,
|
|
435
678
|
data_dir_exists=data_dir.exists(),
|
|
679
|
+
model_dir_exists=model_dir.exists(),
|
|
436
680
|
bundled_packages_dir_exists=bundled_packages_dir.exists(),
|
|
437
681
|
truss_hash=directory_content_hash(
|
|
438
682
|
self._truss_dir, self._spec.hash_ignore_patterns
|
|
@@ -445,6 +689,8 @@ class ServingImageBuilder(ImageBuilder):
|
|
|
445
689
|
hf_access_token=hf_access_token,
|
|
446
690
|
hf_access_token_file_name=HF_ACCESS_TOKEN_FILE_NAME,
|
|
447
691
|
external_data_files=external_data_files,
|
|
692
|
+
build_commands=build_commands,
|
|
693
|
+
use_local_chains_src=config.use_local_chains_src,
|
|
448
694
|
**FILENAME_CONSTANTS_MAP,
|
|
449
695
|
)
|
|
450
696
|
docker_file_path = build_dir / MODEL_DOCKERFILE_NAME
|
|
@@ -36,9 +36,7 @@ def truss_base_image_name(job_type: str) -> str:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def truss_base_image_tag(
|
|
39
|
-
python_version: str,
|
|
40
|
-
use_gpu: bool,
|
|
41
|
-
version_tag: Optional[str] = None,
|
|
39
|
+
python_version: str, use_gpu: bool, version_tag: Optional[str] = None
|
|
42
40
|
) -> str:
|
|
43
41
|
if version_tag is None:
|
|
44
42
|
version_tag = f"v{__version__}"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, List
|
|
4
|
+
|
|
5
|
+
from truss.util.path import copy_tree_or_file
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class DockerBuildEmulatorResult:
|
|
10
|
+
workdir: Path = field(default_factory=lambda: Path("/"))
|
|
11
|
+
env: Dict = field(default_factory=dict)
|
|
12
|
+
entrypoint: List = field(default_factory=list)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DockerBuildEmulator:
|
|
16
|
+
"""Emulates Docker Builds
|
|
17
|
+
|
|
18
|
+
As running docker builds is expensive, this class emulates the docker build
|
|
19
|
+
by parsing the docker file and applying certain commands to create an
|
|
20
|
+
appropriate enviroment in a directory to simulate the root of the file system.
|
|
21
|
+
|
|
22
|
+
Support COPY, ENV, ENTRYPOINT, WORKDIR commands. All other commands are ignored.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, dockerfile_path: Path, context_dir: Path) -> None:
|
|
26
|
+
import dockerfile
|
|
27
|
+
|
|
28
|
+
self._commands = dockerfile.parse_file(str(dockerfile_path))
|
|
29
|
+
self._context_dir = context_dir
|
|
30
|
+
|
|
31
|
+
def run(self, fs_root_dir: Path) -> DockerBuildEmulatorResult:
|
|
32
|
+
def _resolve_env(key: str) -> str:
|
|
33
|
+
if key.startswith("$"):
|
|
34
|
+
key = key.replace("$", "", 1)
|
|
35
|
+
v = result.env[key]
|
|
36
|
+
return v
|
|
37
|
+
return key
|
|
38
|
+
|
|
39
|
+
def _resolve_values(keys: List[str]) -> List[str]:
|
|
40
|
+
return list(map(_resolve_env, keys))
|
|
41
|
+
|
|
42
|
+
result = DockerBuildEmulatorResult()
|
|
43
|
+
for cmd in self._commands:
|
|
44
|
+
if cmd.cmd not in ["ENV", "ENTRYPOINT", "COPY", "WORKDIR"]:
|
|
45
|
+
continue
|
|
46
|
+
values = _resolve_values(cmd.value)
|
|
47
|
+
if cmd.cmd == "ENV":
|
|
48
|
+
result.env[values[0]] = values[1]
|
|
49
|
+
if cmd.cmd == "ENTRYPOINT":
|
|
50
|
+
result.entrypoint = list(values)
|
|
51
|
+
if cmd.cmd == "COPY":
|
|
52
|
+
src, dst = values
|
|
53
|
+
src = src.replace("./", "", 1)
|
|
54
|
+
dst = dst.replace("/", "", 1)
|
|
55
|
+
copy_tree_or_file(self._context_dir / src, fs_root_dir / dst)
|
|
56
|
+
if cmd.cmd == "WORKDIR":
|
|
57
|
+
result.workdir = result.workdir / values[0]
|
|
58
|
+
return result
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
|
+
from truss.base.truss_spec import TrussSpec
|
|
4
5
|
from truss.contexts.local_loader.truss_module_loader import truss_module_loaded
|
|
5
6
|
from truss.contexts.local_loader.utils import (
|
|
6
7
|
prepare_secrets,
|
|
7
8
|
signature_accepts_keyword_arg,
|
|
8
9
|
)
|
|
9
10
|
from truss.contexts.truss_context import TrussContext
|
|
10
|
-
from truss.server.common.patches import apply_patches
|
|
11
|
-
from truss.truss_spec import TrussSpec
|
|
11
|
+
from truss.templates.server.common.patches import apply_patches
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class LoadModelLocal(TrussContext):
|