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.

Files changed (362) hide show
  1. truss/__init__.py +10 -3
  2. truss/api/__init__.py +123 -0
  3. truss/api/definitions.py +51 -0
  4. truss/base/constants.py +116 -0
  5. truss/base/custom_types.py +29 -0
  6. truss/{errors.py → base/errors.py} +4 -0
  7. truss/base/trt_llm_config.py +310 -0
  8. truss/{truss_config.py → base/truss_config.py} +344 -31
  9. truss/{truss_spec.py → base/truss_spec.py} +20 -6
  10. truss/{validation.py → base/validation.py} +60 -11
  11. truss/cli/cli.py +841 -88
  12. truss/{remote → cli}/remote_cli.py +2 -7
  13. truss/contexts/docker_build_setup.py +67 -0
  14. truss/contexts/image_builder/cache_warmer.py +2 -8
  15. truss/contexts/image_builder/image_builder.py +1 -1
  16. truss/contexts/image_builder/serving_image_builder.py +292 -46
  17. truss/contexts/image_builder/util.py +1 -3
  18. truss/contexts/local_loader/docker_build_emulator.py +58 -0
  19. truss/contexts/local_loader/load_model_local.py +2 -2
  20. truss/contexts/local_loader/truss_module_loader.py +1 -1
  21. truss/contexts/local_loader/utils.py +1 -1
  22. truss/local/local_config.py +2 -6
  23. truss/local/local_config_handler.py +20 -5
  24. truss/patch/__init__.py +1 -0
  25. truss/patch/hash.py +4 -70
  26. truss/patch/signature.py +4 -16
  27. truss/patch/truss_dir_patch_applier.py +3 -78
  28. truss/remote/baseten/api.py +308 -23
  29. truss/remote/baseten/auth.py +3 -3
  30. truss/remote/baseten/core.py +257 -50
  31. truss/remote/baseten/custom_types.py +44 -0
  32. truss/remote/baseten/error.py +4 -0
  33. truss/remote/baseten/remote.py +369 -118
  34. truss/remote/baseten/service.py +118 -11
  35. truss/remote/baseten/utils/status.py +29 -0
  36. truss/remote/baseten/utils/tar.py +34 -22
  37. truss/remote/baseten/utils/transfer.py +36 -23
  38. truss/remote/remote_factory.py +14 -5
  39. truss/remote/truss_remote.py +72 -45
  40. truss/templates/base.Dockerfile.jinja +18 -16
  41. truss/templates/cache.Dockerfile.jinja +3 -3
  42. truss/{server → templates/control}/control/application.py +14 -35
  43. truss/{server → templates/control}/control/endpoints.py +39 -9
  44. truss/{server/control/patch/types.py → templates/control/control/helpers/custom_types.py} +13 -52
  45. truss/{server → templates/control}/control/helpers/inference_server_controller.py +4 -8
  46. truss/{server → templates/control}/control/helpers/inference_server_process_controller.py +2 -4
  47. truss/{server → templates/control}/control/helpers/inference_server_starter.py +5 -10
  48. truss/{server/control → templates/control/control/helpers}/truss_patch/model_code_patch_applier.py +8 -6
  49. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/model_container_patch_applier.py +18 -26
  50. truss/templates/control/control/helpers/truss_patch/requirement_name_identifier.py +66 -0
  51. truss/{server → templates/control}/control/server.py +11 -6
  52. truss/templates/control/requirements.txt +9 -0
  53. truss/templates/custom_python_dx/my_model.py +28 -0
  54. truss/templates/docker_server/proxy.conf.jinja +42 -0
  55. truss/templates/docker_server/supervisord.conf.jinja +27 -0
  56. truss/templates/docker_server_requirements.txt +1 -0
  57. truss/templates/server/common/errors.py +231 -0
  58. truss/{server → templates/server}/common/patches/whisper/patch.py +1 -0
  59. truss/{server/common/patches/__init__.py → templates/server/common/patches.py} +1 -3
  60. truss/{server → templates/server}/common/retry.py +1 -0
  61. truss/{server → templates/server}/common/schema.py +11 -9
  62. truss/templates/server/common/tracing.py +157 -0
  63. truss/templates/server/main.py +9 -0
  64. truss/templates/server/model_wrapper.py +961 -0
  65. truss/templates/server/requirements.txt +21 -0
  66. truss/templates/server/truss_server.py +447 -0
  67. truss/templates/server.Dockerfile.jinja +62 -14
  68. truss/templates/shared/dynamic_config_resolver.py +28 -0
  69. truss/templates/shared/lazy_data_resolver.py +164 -0
  70. truss/templates/shared/log_config.py +125 -0
  71. truss/{server → templates}/shared/secrets_resolver.py +1 -2
  72. truss/{server → templates}/shared/serialization.py +31 -9
  73. truss/{server → templates}/shared/util.py +3 -13
  74. truss/templates/trtllm-audio/model/model.py +49 -0
  75. truss/templates/trtllm-audio/packages/sigint_patch.py +14 -0
  76. truss/templates/trtllm-audio/packages/whisper_trt/__init__.py +215 -0
  77. truss/templates/trtllm-audio/packages/whisper_trt/assets.py +25 -0
  78. truss/templates/trtllm-audio/packages/whisper_trt/batching.py +52 -0
  79. truss/templates/trtllm-audio/packages/whisper_trt/custom_types.py +26 -0
  80. truss/templates/trtllm-audio/packages/whisper_trt/modeling.py +184 -0
  81. truss/templates/trtllm-audio/packages/whisper_trt/tokenizer.py +185 -0
  82. truss/templates/trtllm-audio/packages/whisper_trt/utils.py +245 -0
  83. truss/templates/trtllm-briton/src/extension.py +64 -0
  84. truss/tests/conftest.py +302 -94
  85. truss/tests/contexts/image_builder/test_serving_image_builder.py +74 -31
  86. truss/tests/contexts/local_loader/test_load_local.py +2 -2
  87. truss/tests/contexts/local_loader/test_truss_module_finder.py +1 -1
  88. truss/tests/patch/test_calc_patch.py +439 -127
  89. truss/tests/patch/test_dir_signature.py +3 -12
  90. truss/tests/patch/test_hash.py +1 -1
  91. truss/tests/patch/test_signature.py +1 -1
  92. truss/tests/patch/test_truss_dir_patch_applier.py +23 -11
  93. truss/tests/patch/test_types.py +2 -2
  94. truss/tests/remote/baseten/test_api.py +153 -58
  95. truss/tests/remote/baseten/test_auth.py +2 -1
  96. truss/tests/remote/baseten/test_core.py +160 -12
  97. truss/tests/remote/baseten/test_remote.py +489 -77
  98. truss/tests/remote/baseten/test_service.py +55 -0
  99. truss/tests/remote/test_remote_factory.py +16 -18
  100. truss/tests/remote/test_truss_remote.py +26 -17
  101. truss/tests/templates/control/control/helpers/test_context_managers.py +11 -0
  102. truss/tests/templates/control/control/helpers/test_model_container_patch_applier.py +184 -0
  103. truss/tests/templates/control/control/helpers/test_requirement_name_identifier.py +89 -0
  104. truss/tests/{server → templates/control}/control/test_server.py +79 -24
  105. truss/tests/{server → templates/control}/control/test_server_integration.py +24 -16
  106. truss/tests/templates/core/server/test_dynamic_config_resolver.py +108 -0
  107. truss/tests/templates/core/server/test_lazy_data_resolver.py +329 -0
  108. truss/tests/templates/core/server/test_lazy_data_resolver_v2.py +79 -0
  109. truss/tests/{server → templates}/core/server/test_secrets_resolver.py +1 -1
  110. truss/tests/{server → templates/server}/common/test_retry.py +3 -3
  111. truss/tests/templates/server/test_model_wrapper.py +248 -0
  112. truss/tests/{server → templates/server}/test_schema.py +3 -5
  113. truss/tests/{server/core/server/common → templates/server}/test_truss_server.py +8 -5
  114. truss/tests/test_build.py +9 -52
  115. truss/tests/test_config.py +336 -77
  116. truss/tests/test_context_builder_image.py +3 -11
  117. truss/tests/test_control_truss_patching.py +7 -12
  118. truss/tests/test_custom_server.py +38 -0
  119. truss/tests/test_data/context_builder_image_test/test.py +3 -0
  120. truss/tests/test_data/happy.ipynb +56 -0
  121. truss/tests/test_data/model_load_failure_test/config.yaml +2 -0
  122. truss/tests/test_data/model_load_failure_test/model/__init__.py +0 -0
  123. truss/tests/test_data/patch_ping_test_server/__init__.py +0 -0
  124. truss/{test_data → tests/test_data}/patch_ping_test_server/app.py +3 -9
  125. truss/{test_data → tests/test_data}/server.Dockerfile +20 -21
  126. truss/tests/test_data/server_conformance_test_truss/__init__.py +0 -0
  127. truss/tests/test_data/server_conformance_test_truss/model/__init__.py +0 -0
  128. truss/{test_data → tests/test_data}/server_conformance_test_truss/model/model.py +1 -3
  129. truss/tests/test_data/test_async_truss/__init__.py +0 -0
  130. truss/tests/test_data/test_async_truss/model/__init__.py +0 -0
  131. truss/tests/test_data/test_basic_truss/__init__.py +0 -0
  132. truss/tests/test_data/test_basic_truss/config.yaml +16 -0
  133. truss/tests/test_data/test_basic_truss/model/__init__.py +0 -0
  134. truss/tests/test_data/test_build_commands/__init__.py +0 -0
  135. truss/tests/test_data/test_build_commands/config.yaml +13 -0
  136. truss/tests/test_data/test_build_commands/model/__init__.py +0 -0
  137. truss/{test_data/test_streaming_async_generator_truss → tests/test_data/test_build_commands}/model/model.py +2 -3
  138. truss/tests/test_data/test_build_commands_failure/__init__.py +0 -0
  139. truss/tests/test_data/test_build_commands_failure/config.yaml +14 -0
  140. truss/tests/test_data/test_build_commands_failure/model/__init__.py +0 -0
  141. truss/tests/test_data/test_build_commands_failure/model/model.py +17 -0
  142. truss/tests/test_data/test_concurrency_truss/__init__.py +0 -0
  143. truss/tests/test_data/test_concurrency_truss/config.yaml +4 -0
  144. truss/tests/test_data/test_concurrency_truss/model/__init__.py +0 -0
  145. truss/tests/test_data/test_custom_server_truss/__init__.py +0 -0
  146. truss/tests/test_data/test_custom_server_truss/config.yaml +20 -0
  147. truss/tests/test_data/test_custom_server_truss/test_docker_image/Dockerfile +17 -0
  148. truss/tests/test_data/test_custom_server_truss/test_docker_image/README.md +10 -0
  149. truss/tests/test_data/test_custom_server_truss/test_docker_image/VERSION +1 -0
  150. truss/tests/test_data/test_custom_server_truss/test_docker_image/__init__.py +0 -0
  151. truss/tests/test_data/test_custom_server_truss/test_docker_image/app.py +19 -0
  152. truss/tests/test_data/test_custom_server_truss/test_docker_image/build_upload_new_image.sh +6 -0
  153. truss/tests/test_data/test_openai/__init__.py +0 -0
  154. truss/{test_data/test_basic_truss → tests/test_data/test_openai}/config.yaml +1 -2
  155. truss/tests/test_data/test_openai/model/__init__.py +0 -0
  156. truss/tests/test_data/test_openai/model/model.py +15 -0
  157. truss/tests/test_data/test_pyantic_v1/__init__.py +0 -0
  158. truss/tests/test_data/test_pyantic_v1/model/__init__.py +0 -0
  159. truss/tests/test_data/test_pyantic_v1/model/model.py +28 -0
  160. truss/tests/test_data/test_pyantic_v1/requirements.txt +1 -0
  161. truss/tests/test_data/test_pyantic_v2/__init__.py +0 -0
  162. truss/tests/test_data/test_pyantic_v2/config.yaml +13 -0
  163. truss/tests/test_data/test_pyantic_v2/model/__init__.py +0 -0
  164. truss/tests/test_data/test_pyantic_v2/model/model.py +30 -0
  165. truss/tests/test_data/test_pyantic_v2/requirements.txt +1 -0
  166. truss/tests/test_data/test_requirements_file_truss/__init__.py +0 -0
  167. truss/tests/test_data/test_requirements_file_truss/config.yaml +13 -0
  168. truss/tests/test_data/test_requirements_file_truss/model/__init__.py +0 -0
  169. truss/{test_data → tests/test_data}/test_requirements_file_truss/model/model.py +1 -0
  170. truss/tests/test_data/test_streaming_async_generator_truss/__init__.py +0 -0
  171. truss/tests/test_data/test_streaming_async_generator_truss/config.yaml +4 -0
  172. truss/tests/test_data/test_streaming_async_generator_truss/model/__init__.py +0 -0
  173. truss/tests/test_data/test_streaming_async_generator_truss/model/model.py +7 -0
  174. truss/tests/test_data/test_streaming_read_timeout/__init__.py +0 -0
  175. truss/tests/test_data/test_streaming_read_timeout/model/__init__.py +0 -0
  176. truss/tests/test_data/test_streaming_truss/__init__.py +0 -0
  177. truss/tests/test_data/test_streaming_truss/config.yaml +4 -0
  178. truss/tests/test_data/test_streaming_truss/model/__init__.py +0 -0
  179. truss/tests/test_data/test_streaming_truss_with_error/__init__.py +0 -0
  180. truss/tests/test_data/test_streaming_truss_with_error/model/__init__.py +0 -0
  181. truss/{test_data → tests/test_data}/test_streaming_truss_with_error/model/model.py +3 -11
  182. truss/tests/test_data/test_streaming_truss_with_error/packages/__init__.py +0 -0
  183. truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_1.py +5 -0
  184. truss/tests/test_data/test_streaming_truss_with_error/packages/helpers_2.py +2 -0
  185. truss/tests/test_data/test_streaming_truss_with_tracing/__init__.py +0 -0
  186. truss/tests/test_data/test_streaming_truss_with_tracing/config.yaml +43 -0
  187. truss/tests/test_data/test_streaming_truss_with_tracing/model/__init__.py +0 -0
  188. truss/tests/test_data/test_streaming_truss_with_tracing/model/model.py +65 -0
  189. truss/tests/test_data/test_trt_llm_truss/__init__.py +0 -0
  190. truss/tests/test_data/test_trt_llm_truss/config.yaml +15 -0
  191. truss/tests/test_data/test_trt_llm_truss/model/__init__.py +0 -0
  192. truss/tests/test_data/test_trt_llm_truss/model/model.py +15 -0
  193. truss/tests/test_data/test_truss/__init__.py +0 -0
  194. truss/tests/test_data/test_truss/config.yaml +4 -0
  195. truss/tests/test_data/test_truss/model/__init__.py +0 -0
  196. truss/tests/test_data/test_truss/model/dummy +0 -0
  197. truss/tests/test_data/test_truss/packages/__init__.py +0 -0
  198. truss/tests/test_data/test_truss/packages/test_package/__init__.py +0 -0
  199. truss/tests/test_data/test_truss_server_caching_truss/__init__.py +0 -0
  200. truss/tests/test_data/test_truss_server_caching_truss/model/__init__.py +0 -0
  201. truss/tests/test_data/test_truss_with_error/__init__.py +0 -0
  202. truss/tests/test_data/test_truss_with_error/config.yaml +4 -0
  203. truss/tests/test_data/test_truss_with_error/model/__init__.py +0 -0
  204. truss/tests/test_data/test_truss_with_error/model/model.py +8 -0
  205. truss/tests/test_data/test_truss_with_error/packages/__init__.py +0 -0
  206. truss/tests/test_data/test_truss_with_error/packages/helpers_1.py +5 -0
  207. truss/tests/test_data/test_truss_with_error/packages/helpers_2.py +2 -0
  208. truss/tests/test_docker.py +2 -1
  209. truss/tests/test_model_inference.py +1340 -292
  210. truss/tests/test_model_schema.py +33 -26
  211. truss/tests/test_testing_utilities_for_other_tests.py +50 -5
  212. truss/tests/test_truss_gatherer.py +3 -5
  213. truss/tests/test_truss_handle.py +62 -59
  214. truss/tests/test_util.py +2 -1
  215. truss/tests/test_validation.py +15 -13
  216. truss/tests/trt_llm/test_trt_llm_config.py +41 -0
  217. truss/tests/trt_llm/test_validation.py +91 -0
  218. truss/tests/util/test_config_checks.py +40 -0
  219. truss/tests/util/test_env_vars.py +14 -0
  220. truss/tests/util/test_path.py +10 -23
  221. truss/trt_llm/config_checks.py +43 -0
  222. truss/trt_llm/validation.py +42 -0
  223. truss/truss_handle/__init__.py +0 -0
  224. truss/truss_handle/build.py +122 -0
  225. truss/{decorators.py → truss_handle/decorators.py} +1 -1
  226. truss/truss_handle/patch/__init__.py +0 -0
  227. truss/{patch → truss_handle/patch}/calc_patch.py +146 -92
  228. truss/{types.py → truss_handle/patch/custom_types.py} +35 -27
  229. truss/{patch → truss_handle/patch}/dir_signature.py +1 -1
  230. truss/truss_handle/patch/hash.py +71 -0
  231. truss/{patch → truss_handle/patch}/local_truss_patch_applier.py +6 -4
  232. truss/truss_handle/patch/signature.py +22 -0
  233. truss/truss_handle/patch/truss_dir_patch_applier.py +87 -0
  234. truss/{readme_generator.py → truss_handle/readme_generator.py} +3 -2
  235. truss/{truss_gatherer.py → truss_handle/truss_gatherer.py} +3 -2
  236. truss/{truss_handle.py → truss_handle/truss_handle.py} +174 -78
  237. truss/util/.truss_ignore +3 -0
  238. truss/{docker.py → util/docker.py} +6 -2
  239. truss/util/download.py +6 -15
  240. truss/util/env_vars.py +41 -0
  241. truss/util/log_utils.py +52 -0
  242. truss/util/path.py +20 -20
  243. truss/util/requirements.py +11 -0
  244. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/METADATA +18 -16
  245. truss-0.60.0.dist-info/RECORD +324 -0
  246. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/WHEEL +1 -1
  247. truss-0.60.0.dist-info/entry_points.txt +4 -0
  248. truss_chains/__init__.py +71 -0
  249. truss_chains/definitions.py +756 -0
  250. truss_chains/deployment/__init__.py +0 -0
  251. truss_chains/deployment/code_gen.py +816 -0
  252. truss_chains/deployment/deployment_client.py +871 -0
  253. truss_chains/framework.py +1480 -0
  254. truss_chains/public_api.py +231 -0
  255. truss_chains/py.typed +0 -0
  256. truss_chains/pydantic_numpy.py +131 -0
  257. truss_chains/reference_code/reference_chainlet.py +34 -0
  258. truss_chains/reference_code/reference_model.py +10 -0
  259. truss_chains/remote_chainlet/__init__.py +0 -0
  260. truss_chains/remote_chainlet/model_skeleton.py +60 -0
  261. truss_chains/remote_chainlet/stub.py +380 -0
  262. truss_chains/remote_chainlet/utils.py +332 -0
  263. truss_chains/streaming.py +378 -0
  264. truss_chains/utils.py +178 -0
  265. CODE_OF_CONDUCT.md +0 -131
  266. CONTRIBUTING.md +0 -48
  267. README.md +0 -137
  268. context_builder.Dockerfile +0 -24
  269. truss/blob/blob_backend.py +0 -10
  270. truss/blob/blob_backend_registry.py +0 -23
  271. truss/blob/http_public_blob_backend.py +0 -23
  272. truss/build/__init__.py +0 -2
  273. truss/build/build.py +0 -143
  274. truss/build/configure.py +0 -63
  275. truss/cli/__init__.py +0 -2
  276. truss/cli/console.py +0 -5
  277. truss/cli/create.py +0 -5
  278. truss/config/trt_llm.py +0 -81
  279. truss/constants.py +0 -61
  280. truss/model_inference.py +0 -123
  281. truss/patch/types.py +0 -30
  282. truss/pytest.ini +0 -7
  283. truss/server/common/errors.py +0 -100
  284. truss/server/common/termination_handler_middleware.py +0 -64
  285. truss/server/common/truss_server.py +0 -389
  286. truss/server/control/patch/model_code_patch_applier.py +0 -46
  287. truss/server/control/patch/requirement_name_identifier.py +0 -17
  288. truss/server/inference_server.py +0 -29
  289. truss/server/model_wrapper.py +0 -434
  290. truss/server/shared/logging.py +0 -81
  291. truss/templates/trtllm/model/model.py +0 -97
  292. truss/templates/trtllm/packages/build_engine_utils.py +0 -34
  293. truss/templates/trtllm/packages/constants.py +0 -11
  294. truss/templates/trtllm/packages/schema.py +0 -216
  295. truss/templates/trtllm/packages/tensorrt_llm_model_repository/ensemble/config.pbtxt +0 -246
  296. truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/1/model.py +0 -181
  297. truss/templates/trtllm/packages/tensorrt_llm_model_repository/postprocessing/config.pbtxt +0 -64
  298. truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/1/model.py +0 -260
  299. truss/templates/trtllm/packages/tensorrt_llm_model_repository/preprocessing/config.pbtxt +0 -99
  300. truss/templates/trtllm/packages/tensorrt_llm_model_repository/tensorrt_llm/config.pbtxt +0 -208
  301. truss/templates/trtllm/packages/triton_client.py +0 -150
  302. truss/templates/trtllm/packages/utils.py +0 -43
  303. truss/test_data/context_builder_image_test/test.py +0 -4
  304. truss/test_data/happy.ipynb +0 -54
  305. truss/test_data/model_load_failure_test/config.yaml +0 -2
  306. truss/test_data/test_concurrency_truss/config.yaml +0 -2
  307. truss/test_data/test_streaming_async_generator_truss/config.yaml +0 -2
  308. truss/test_data/test_streaming_truss/config.yaml +0 -3
  309. truss/test_data/test_truss/config.yaml +0 -2
  310. truss/tests/server/common/test_termination_handler_middleware.py +0 -93
  311. truss/tests/server/control/test_model_container_patch_applier.py +0 -203
  312. truss/tests/server/core/server/common/test_util.py +0 -19
  313. truss/tests/server/test_model_wrapper.py +0 -87
  314. truss/util/data_structures.py +0 -16
  315. truss-0.10.0rc1.dist-info/RECORD +0 -216
  316. truss-0.10.0rc1.dist-info/entry_points.txt +0 -3
  317. truss/{server/shared → base}/__init__.py +0 -0
  318. truss/{server → templates/control}/control/helpers/context_managers.py +0 -0
  319. truss/{server/control → templates/control/control/helpers}/errors.py +0 -0
  320. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/__init__.py +0 -0
  321. truss/{server/control/patch → templates/control/control/helpers/truss_patch}/system_packages.py +0 -0
  322. truss/{test_data/annotated_types_truss/model → templates/server}/__init__.py +0 -0
  323. truss/{server → templates/server}/common/__init__.py +0 -0
  324. truss/{test_data/gcs_fix/model → templates/shared}/__init__.py +0 -0
  325. truss/templates/{trtllm → trtllm-briton}/README.md +0 -0
  326. truss/{test_data/server_conformance_test_truss/model → tests/test_data}/__init__.py +0 -0
  327. truss/{test_data/test_basic_truss/model → tests/test_data/annotated_types_truss}/__init__.py +0 -0
  328. truss/{test_data → tests/test_data}/annotated_types_truss/config.yaml +0 -0
  329. truss/{test_data/test_requirements_file_truss → tests/test_data/annotated_types_truss}/model/__init__.py +0 -0
  330. truss/{test_data → tests/test_data}/annotated_types_truss/model/model.py +0 -0
  331. truss/{test_data → tests/test_data}/auto-mpg.data +0 -0
  332. truss/{test_data → tests/test_data}/context_builder_image_test/Dockerfile +0 -0
  333. truss/{test_data/test_truss/model → tests/test_data/context_builder_image_test}/__init__.py +0 -0
  334. truss/{test_data/test_truss_server_caching_truss/model → tests/test_data/gcs_fix}/__init__.py +0 -0
  335. truss/{test_data → tests/test_data}/gcs_fix/config.yaml +0 -0
  336. truss/tests/{local → test_data/gcs_fix/model}/__init__.py +0 -0
  337. truss/{test_data → tests/test_data}/gcs_fix/model/model.py +0 -0
  338. truss/{test_data/test_truss/model/dummy → tests/test_data/model_load_failure_test/__init__.py} +0 -0
  339. truss/{test_data → tests/test_data}/model_load_failure_test/model/model.py +0 -0
  340. truss/{test_data → tests/test_data}/pima-indians-diabetes.csv +0 -0
  341. truss/{test_data → tests/test_data}/readme_int_example.md +0 -0
  342. truss/{test_data → tests/test_data}/readme_no_example.md +0 -0
  343. truss/{test_data → tests/test_data}/readme_str_example.md +0 -0
  344. truss/{test_data → tests/test_data}/server_conformance_test_truss/config.yaml +0 -0
  345. truss/{test_data → tests/test_data}/test_async_truss/config.yaml +0 -0
  346. truss/{test_data → tests/test_data}/test_async_truss/model/model.py +3 -3
  347. /truss/{test_data → tests/test_data}/test_basic_truss/model/model.py +0 -0
  348. /truss/{test_data → tests/test_data}/test_concurrency_truss/model/model.py +0 -0
  349. /truss/{test_data/test_requirements_file_truss → tests/test_data/test_pyantic_v1}/config.yaml +0 -0
  350. /truss/{test_data → tests/test_data}/test_requirements_file_truss/requirements.txt +0 -0
  351. /truss/{test_data → tests/test_data}/test_streaming_read_timeout/config.yaml +0 -0
  352. /truss/{test_data → tests/test_data}/test_streaming_read_timeout/model/model.py +0 -0
  353. /truss/{test_data → tests/test_data}/test_streaming_truss/model/model.py +0 -0
  354. /truss/{test_data → tests/test_data}/test_streaming_truss_with_error/config.yaml +0 -0
  355. /truss/{test_data → tests/test_data}/test_truss/examples.yaml +0 -0
  356. /truss/{test_data → tests/test_data}/test_truss/model/model.py +0 -0
  357. /truss/{test_data → tests/test_data}/test_truss/packages/test_package/test.py +0 -0
  358. /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/config.yaml +0 -0
  359. /truss/{test_data → tests/test_data}/test_truss_server_caching_truss/model/model.py +0 -0
  360. /truss/{patch → truss_handle/patch}/constants.py +0 -0
  361. /truss/{notebook.py → util/notebook.py} +0 -0
  362. {truss-0.10.0rc1.dist-info → truss-0.60.0.dist-info}/LICENSE +0 -0
@@ -1,389 +0,0 @@
1
- import asyncio
2
- import json
3
- import logging
4
- import multiprocessing
5
- import os
6
- import signal
7
- import socket
8
- import sys
9
- import time
10
- from collections.abc import Generator
11
- from pathlib import Path
12
- from typing import AsyncGenerator, Dict, List, Optional, Union
13
-
14
- import truss.server.common.errors as errors
15
- import truss.server.shared.util as utils
16
- import uvicorn
17
- from fastapi import Depends, FastAPI, HTTPException, Request
18
- from fastapi.responses import ORJSONResponse, StreamingResponse
19
- from fastapi.routing import APIRoute as FastAPIRoute
20
- from starlette.middleware.base import BaseHTTPMiddleware
21
- from starlette.requests import ClientDisconnect
22
- from starlette.responses import Response
23
- from truss.server.common.termination_handler_middleware import (
24
- TerminationHandlerMiddleware,
25
- )
26
- from truss.server.model_wrapper import ModelWrapper
27
- from truss.server.shared.logging import setup_logging
28
- from truss.server.shared.serialization import (
29
- DeepNumpyEncoder,
30
- truss_msgpack_deserialize,
31
- truss_msgpack_serialize,
32
- )
33
-
34
- # [IMPORTANT] A lot of things depend on this currently.
35
- # Please consider the following when increasing this:
36
- # 1. Self-termination on model load fail.
37
- # 2. Graceful termination.
38
- DEFAULT_NUM_WORKERS = 1
39
- DEFAULT_NUM_SERVER_PROCESSES = 1
40
- WORKER_TERMINATION_TIMEOUT_SECS = 120.0
41
- WORKER_TERMINATION_CHECK_INTERVAL_SECS = 0.5
42
-
43
-
44
- async def parse_body(request: Request) -> bytes:
45
- """
46
- Used by FastAPI to read body in an asynchronous manner
47
- """
48
- try:
49
- return await request.body()
50
- except ClientDisconnect as exc:
51
- error_message = "Client disconnected"
52
- logging.error(error_message)
53
- raise HTTPException(status_code=499, detail=error_message) from exc
54
-
55
-
56
- FORMAT = "%(asctime)s.%(msecs)03d %(name)s %(levelname)s [%(funcName)s():%(lineno)s] %(message)s"
57
- DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
58
- INFERENCE_SERVER_FAILED_FILE = Path("~/inference_server_crashed.txt").expanduser()
59
- logging.basicConfig(level=logging.INFO, format=FORMAT, datefmt=DATE_FORMAT)
60
-
61
-
62
- class UvicornCustomServer(multiprocessing.Process):
63
- def __init__(
64
- self, config: uvicorn.Config, sockets: Optional[List[socket.socket]] = None
65
- ):
66
- super().__init__()
67
- self.sockets = sockets
68
- self.config = config
69
-
70
- def stop(self):
71
- self.terminate()
72
-
73
- def run(self):
74
- server = uvicorn.Server(config=self.config)
75
- asyncio.run(server.serve(sockets=self.sockets))
76
-
77
-
78
- class BasetenEndpoints:
79
- """The implementation of the model server endpoints.
80
-
81
- Historically, we relied on the kserve server interface, which assumes that
82
- multiple models are running behind a registry. As a result, some arguments to
83
- to functions will rename unused except for backwards compatibility checks.
84
- """
85
-
86
- def __init__(self, model: ModelWrapper) -> None:
87
- self._model = model
88
-
89
- def _safe_lookup_model(self, model_name: str) -> ModelWrapper:
90
- if model_name != self._model.name:
91
- raise errors.ModelMissingError(model_name)
92
- return self._model
93
-
94
- @staticmethod
95
- def check_healthy(model: ModelWrapper):
96
- if model.load_failed():
97
- INFERENCE_SERVER_FAILED_FILE.touch()
98
- os.kill(os.getpid(), signal.SIGKILL)
99
-
100
- if not model.ready:
101
- raise errors.ModelNotReady(model.name)
102
-
103
- async def model_ready(self, model_name: str) -> Dict[str, Union[str, bool]]:
104
- self.check_healthy(self._safe_lookup_model(model_name))
105
-
106
- return {}
107
-
108
- async def invocations_ready(self) -> Dict[str, Union[str, bool]]:
109
- """
110
- This method provides compatibility with Sagemaker hosting for the 'ping' endpoint.
111
- """
112
- if self._model is None:
113
- raise errors.ModelMissingError("model")
114
- self.check_healthy(self._model)
115
-
116
- return {}
117
-
118
- async def invocations(
119
- self, request: Request, body_raw: bytes = Depends(parse_body)
120
- ) -> Response:
121
- """
122
- This method provides compatibility with Sagemaker hosting for the 'invocations' endpoint.
123
- """
124
- return await self.predict(self._model.name, request, body_raw)
125
-
126
- async def predict(
127
- self, model_name: str, request: Request, body_raw: bytes = Depends(parse_body)
128
- ) -> Response:
129
- """
130
- This method calls the user-provided predict method
131
- """
132
- model: ModelWrapper = self._safe_lookup_model(model_name)
133
-
134
- self.check_healthy(model)
135
-
136
- body: Dict
137
- if self.is_binary(request):
138
- body = truss_msgpack_deserialize(body_raw)
139
- else:
140
- try:
141
- body = json.loads(body_raw)
142
- except json.JSONDecodeError as e:
143
- error_message = f"Invalid JSON payload: {str(e)}"
144
- logging.error(error_message)
145
- raise HTTPException(status_code=400, detail=error_message)
146
-
147
- # calls ModelWrapper.__call__, which runs validate, preprocess, predict, and postprocess
148
- response: Union[Dict, Generator] = await model(
149
- body,
150
- headers=utils.transform_keys(request.headers, lambda key: key.lower()),
151
- )
152
-
153
- # In the case that the model returns a Generator object, return a
154
- # StreamingResponse instead.
155
- if isinstance(response, (AsyncGenerator, Generator)):
156
- # media_type in StreamingResponse sets the Content-Type header
157
- return StreamingResponse(response, media_type="application/octet-stream")
158
-
159
- response_headers = {}
160
- if self.is_binary(request):
161
- response_headers["Content-Type"] = "application/octet-stream"
162
- return Response(
163
- content=truss_msgpack_serialize(response), headers=response_headers
164
- )
165
- else:
166
- response_headers["Content-Type"] = "application/json"
167
- return Response(
168
- content=json.dumps(response, cls=DeepNumpyEncoder),
169
- headers=response_headers,
170
- )
171
-
172
- async def schema(self, model_name: str) -> Dict:
173
- model: ModelWrapper = self._safe_lookup_model(model_name)
174
-
175
- if model.truss_schema is None:
176
- print("DID NOT FIND MODEL SCHEMA")
177
- # If there is not a TrussSchema, we return a 404.
178
-
179
- if model.ready:
180
- raise HTTPException(status_code=404, detail="No schema found")
181
- else:
182
- raise HTTPException(
183
- status_code=503,
184
- detail="Schema not available, please try again later.",
185
- )
186
- else:
187
- return model.truss_schema.serialize()
188
-
189
- @staticmethod
190
- def is_binary(request: Request):
191
- return (
192
- "Content-Type" in request.headers
193
- and request.headers["Content-Type"] == "application/octet-stream"
194
- )
195
-
196
-
197
- class TrussServer:
198
- """This wrapper class manages creation and cleanup of uvicorn server processes running the FastAPI inference server app
199
-
200
- TrussServer runs as a main process managing UvicornCustomServer subprocesses that in turn may manage
201
- their own worker processes. Notably, this main process is kept alive when running `servers_task()`
202
- because of the child uvicorn server processes' main loop.
203
-
204
- """
205
-
206
- def __init__(
207
- self,
208
- http_port: int,
209
- config: Dict,
210
- setup_json_logger: bool = True,
211
- ):
212
- self.http_port = http_port
213
- self._config = config
214
- self._model = ModelWrapper(self._config)
215
- self._endpoints = BasetenEndpoints(self._model)
216
- self._setup_json_logger = setup_json_logger
217
-
218
- def cleanup(self):
219
- if INFERENCE_SERVER_FAILED_FILE.exists():
220
- INFERENCE_SERVER_FAILED_FILE.unlink()
221
-
222
- def on_startup(self):
223
- """
224
- This method will be started inside the main process, so here is where we want to setup our logging and model
225
- """
226
- self.cleanup()
227
-
228
- if self._setup_json_logger:
229
- setup_logging()
230
-
231
- self._model.start_load()
232
-
233
- def create_application(self):
234
- app = FastAPI(
235
- title="Baseten Inference Server",
236
- docs_url=None,
237
- redoc_url=None,
238
- default_response_class=ORJSONResponse,
239
- on_startup=[self.on_startup],
240
- routes=[
241
- # liveness endpoint
242
- FastAPIRoute(r"/", lambda: True),
243
- # readiness endpoint
244
- FastAPIRoute(
245
- r"/v1/models/{model_name}", self._endpoints.model_ready, tags=["V1"]
246
- ),
247
- FastAPIRoute(
248
- r"/v1/models/{model_name}/schema",
249
- self._endpoints.schema,
250
- methods=["GET"],
251
- tags=["V1"],
252
- ),
253
- FastAPIRoute(
254
- r"/v1/models/{model_name}:predict",
255
- self._endpoints.predict,
256
- methods=["POST"],
257
- tags=["V1"],
258
- ),
259
- FastAPIRoute(
260
- r"/v1/models/{model_name}:predict_binary",
261
- self._endpoints.predict,
262
- methods=["POST"],
263
- tags=["V1"],
264
- ),
265
- # Endpoint aliases for Sagemaker hosting
266
- FastAPIRoute(r"/ping", self._endpoints.invocations_ready),
267
- FastAPIRoute(
268
- r"/invocations",
269
- self._endpoints.invocations,
270
- methods=["POST"],
271
- ),
272
- ],
273
- exception_handlers={
274
- errors.InferenceError: errors.inference_error_handler,
275
- errors.ModelNotFound: errors.model_not_found_handler,
276
- errors.ModelNotReady: errors.model_not_ready_handler,
277
- NotImplementedError: errors.not_implemented_error_handler,
278
- HTTPException: errors.http_exception_handler,
279
- Exception: errors.generic_exception_handler,
280
- },
281
- )
282
-
283
- def exit_self():
284
- # Note that this kills the current process, the worker process, not
285
- # the main truss_server process.
286
- utils.kill_child_processes(os.getpid())
287
- sys.exit()
288
-
289
- termination_handler_middleware = TerminationHandlerMiddleware(
290
- on_stop=lambda: None,
291
- on_term=exit_self,
292
- )
293
- app.add_middleware(BaseHTTPMiddleware, dispatch=termination_handler_middleware)
294
- return app
295
-
296
- def start(self):
297
- cfg = uvicorn.Config(
298
- self.create_application(),
299
- # We hard-code the http parser as h11 (the default) in case the user has
300
- # httptools installed, which does not work with our requests & version
301
- # of uvicorn.
302
- http="h11",
303
- host="0.0.0.0",
304
- port=self.http_port,
305
- workers=DEFAULT_NUM_WORKERS,
306
- log_config={
307
- "version": 1,
308
- "formatters": {
309
- "default": {
310
- "()": "uvicorn.logging.DefaultFormatter",
311
- "datefmt": DATE_FORMAT,
312
- "fmt": "%(asctime)s.%(msecs)03d %(name)s %(levelprefix)s %(message)s",
313
- "use_colors": None,
314
- },
315
- "access": {
316
- "()": "uvicorn.logging.AccessFormatter",
317
- "datefmt": DATE_FORMAT,
318
- "fmt": "%(asctime)s.%(msecs)03d %(name)s %(levelprefix)s %(client_addr)s %(process)s - "
319
- '"%(request_line)s" %(status_code)s',
320
- # noqa: E501
321
- },
322
- },
323
- "handlers": {
324
- "default": {
325
- "formatter": "default",
326
- "class": "logging.StreamHandler",
327
- "stream": "ext://sys.stderr",
328
- },
329
- "access": {
330
- "formatter": "access",
331
- "class": "logging.StreamHandler",
332
- "stream": "ext://sys.stdout",
333
- },
334
- },
335
- "loggers": {
336
- "uvicorn": {"handlers": ["default"], "level": "INFO"},
337
- "uvicorn.error": {"level": "INFO"},
338
- "uvicorn.access": {
339
- "handlers": ["access"],
340
- "level": "INFO",
341
- "propagate": False,
342
- },
343
- },
344
- },
345
- )
346
-
347
- # Call this so uvloop gets used
348
- cfg.setup_event_loop()
349
-
350
- async def serve():
351
- serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
352
- serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
353
- serversocket.bind((cfg.host, cfg.port))
354
- serversocket.listen(5)
355
-
356
- num_server_procs = self._config.get("runtime", {}).get(
357
- "num_workers", DEFAULT_NUM_SERVER_PROCESSES
358
- )
359
- logging.info(f"starting {num_server_procs} uvicorn server processes")
360
- servers: List[UvicornCustomServer] = []
361
- for _ in range(num_server_procs):
362
- server = UvicornCustomServer(config=cfg, sockets=[serversocket])
363
- server.start()
364
- servers.append(server)
365
-
366
- def stop_servers():
367
- # Send stop signal, then wait for all to exit
368
- for server in servers:
369
- # Sends term signal to the process, which should be handled
370
- # by the termination handler.
371
- server.stop()
372
-
373
- termination_check_attempts = int(
374
- WORKER_TERMINATION_TIMEOUT_SECS
375
- / WORKER_TERMINATION_CHECK_INTERVAL_SECS
376
- )
377
- for _ in range(termination_check_attempts):
378
- time.sleep(WORKER_TERMINATION_CHECK_INTERVAL_SECS)
379
- if utils.all_processes_dead(servers):
380
- return
381
-
382
- for sig in [signal.SIGINT, signal.SIGTERM, signal.SIGQUIT]:
383
- signal.signal(sig, lambda sig, frame: stop_servers())
384
-
385
- async def servers_task():
386
- servers = [serve()]
387
- await asyncio.gather(*servers)
388
-
389
- asyncio.run(servers_task())
@@ -1,46 +0,0 @@
1
- import logging
2
- import os
3
- from pathlib import Path
4
- from typing import Union
5
-
6
- from truss.server.control.patch.types import Action, ModelCodePatch, PackagePatch
7
-
8
-
9
- def apply_code_patch(
10
- relative_dir: Path,
11
- patch: Union[ModelCodePatch, PackagePatch],
12
- logger: logging.Logger,
13
- ):
14
- logger.debug(f"Applying code patch {patch.to_dict()}")
15
- filepath: Path = relative_dir / patch.path
16
- action = patch.action
17
-
18
- if action in [Action.ADD, Action.UPDATE]:
19
- filepath.parent.mkdir(parents=True, exist_ok=True)
20
- action_log = "Adding" if action == Action.ADD else "Updating"
21
- logger.info(f"{action_log} file {filepath}")
22
- with filepath.open("w") as file:
23
- content = patch.content
24
- if content is None:
25
- raise ValueError(
26
- "Invalid patch: content of a file update patch should not be None."
27
- )
28
- file.write(content)
29
-
30
- elif action == Action.REMOVE:
31
- if not filepath.exists():
32
- logger.warning(f"Could not delete file {filepath}: not found.")
33
- elif filepath.is_file():
34
- logger.info(f"Deleting file {filepath}")
35
- filepath.unlink()
36
- # attempt to recursively remove potentially empty directories, if applicable
37
- # os.removedirs raises OSError with errno 39 when this process encounters a non-empty dir
38
- try:
39
- os.removedirs(filepath.parent)
40
- except OSError as e:
41
- if e.errno == 39: # Directory not empty
42
- pass
43
- else:
44
- raise
45
- else:
46
- raise ValueError(f"Unknown patch action {action}")
@@ -1,17 +0,0 @@
1
- from typing import Dict, List
2
-
3
- import pkg_resources
4
- from pkg_resources.extern.packaging import requirements # type: ignore
5
-
6
-
7
- def identify_requirement_name(req: str) -> str:
8
- try:
9
- parsed_req = pkg_resources.Requirement.parse(req)
10
- return parsed_req.name # type: ignore
11
- except (requirements.InvalidRequirement, ValueError):
12
- # default to the whole line if we can't parse it.
13
- return req.strip()
14
-
15
-
16
- def reqs_by_name(reqs: List[str]) -> Dict[str, str]:
17
- return {identify_requirement_name(req): req for req in reqs}
@@ -1,29 +0,0 @@
1
- import os
2
- from pathlib import Path
3
- from typing import Dict
4
-
5
- from truss.server.common.truss_server import TrussServer
6
- from truss.server.shared.logging import setup_logging
7
- from truss.truss_config import TrussConfig
8
-
9
- CONFIG_FILE = "config.yaml"
10
-
11
- setup_logging()
12
-
13
-
14
- class ConfiguredTrussServer:
15
- _config: Dict
16
- _port: int
17
-
18
- def __init__(self, config_path: str, port: int):
19
- self._port = port
20
- self._config = TrussConfig.from_yaml(Path(config_path)).to_dict(verbose=True)
21
-
22
- def start(self):
23
- server = TrussServer(http_port=self._port, config=self._config)
24
- server.start()
25
-
26
-
27
- if __name__ == "__main__":
28
- env_port = int(os.environ.get("INFERENCE_SERVER_PORT", "8080"))
29
- ConfiguredTrussServer(CONFIG_FILE, env_port).start()