tetra-rp 0.10.0__py3-none-any.whl → 0.12.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 tetra-rp might be problematic. Click here for more details.

@@ -1,11 +1,22 @@
1
- # TODO: generate using betterproto
1
+ """Remote execution protocol definitions using Pydantic models.
2
+
3
+ This module defines the request/response protocol for remote function and class execution.
4
+ The models align with the protobuf schema for communication with remote workers.
5
+ """
6
+
2
7
  from abc import ABC, abstractmethod
3
- from typing import Dict, List, Optional
8
+ from typing import Any, Dict, List, Optional
4
9
 
5
10
  from pydantic import BaseModel, Field, model_validator
6
11
 
7
12
 
8
13
  class FunctionRequest(BaseModel):
14
+ """Request model for remote function or class execution.
15
+
16
+ Supports both function-based execution and class instantiation with method calls.
17
+ All serialized data (args, kwargs, etc.) are base64-encoded cloudpickle strings.
18
+ """
19
+
9
20
  # MADE OPTIONAL - can be None for class-only execution
10
21
  function_name: Optional[str] = Field(
11
22
  default=None,
@@ -15,19 +26,19 @@ class FunctionRequest(BaseModel):
15
26
  default=None,
16
27
  description="Source code of the function to execute",
17
28
  )
18
- args: List = Field(
29
+ args: List[str] = Field(
19
30
  default_factory=list,
20
31
  description="List of base64-encoded cloudpickle-serialized arguments",
21
32
  )
22
- kwargs: Dict = Field(
33
+ kwargs: Dict[str, str] = Field(
23
34
  default_factory=dict,
24
35
  description="Dictionary of base64-encoded cloudpickle-serialized keyword arguments",
25
36
  )
26
- dependencies: Optional[List] = Field(
37
+ dependencies: Optional[List[str]] = Field(
27
38
  default=None,
28
39
  description="Optional list of pip packages to install before executing the function",
29
40
  )
30
- system_dependencies: Optional[List] = Field(
41
+ system_dependencies: Optional[List[str]] = Field(
31
42
  default=None,
32
43
  description="Optional list of system dependencies to install before executing the function",
33
44
  )
@@ -44,11 +55,11 @@ class FunctionRequest(BaseModel):
44
55
  default=None,
45
56
  description="Source code of the class to instantiate (for class execution)",
46
57
  )
47
- constructor_args: Optional[List] = Field(
58
+ constructor_args: List[str] = Field(
48
59
  default_factory=list,
49
60
  description="List of base64-encoded cloudpickle-serialized constructor arguments",
50
61
  )
51
- constructor_kwargs: Optional[Dict] = Field(
62
+ constructor_kwargs: Dict[str, str] = Field(
52
63
  default_factory=dict,
53
64
  description="Dictionary of base64-encoded cloudpickle-serialized constructor keyword arguments",
54
65
  )
@@ -65,6 +76,16 @@ class FunctionRequest(BaseModel):
65
76
  description="Whether to create a new instance or reuse existing one",
66
77
  )
67
78
 
79
+ # Download acceleration fields
80
+ accelerate_downloads: bool = Field(
81
+ default=True,
82
+ description="Enable download acceleration for dependencies and models",
83
+ )
84
+ hf_models_to_cache: Optional[List[str]] = Field(
85
+ default=None,
86
+ description="List of HuggingFace model IDs to pre-cache using acceleration",
87
+ )
88
+
68
89
  @model_validator(mode="after")
69
90
  def validate_execution_requirements(self) -> "FunctionRequest":
70
91
  """Validate that required fields are provided based on execution_type"""
@@ -92,7 +113,12 @@ class FunctionRequest(BaseModel):
92
113
 
93
114
 
94
115
  class FunctionResponse(BaseModel):
95
- # EXISTING FIELDS (unchanged)
116
+ """Response model for remote function or class execution results.
117
+
118
+ Contains execution results, error information, and metadata about class instances
119
+ when applicable. The result field contains base64-encoded cloudpickle data.
120
+ """
121
+
96
122
  success: bool = Field(
97
123
  description="Indicates if the function execution was successful",
98
124
  )
@@ -108,12 +134,10 @@ class FunctionResponse(BaseModel):
108
134
  default=None,
109
135
  description="Captured standard output from the function execution",
110
136
  )
111
-
112
- # NEW FIELDS FOR CLASS SUPPORT
113
137
  instance_id: Optional[str] = Field(
114
138
  default=None, description="ID of the class instance that was used/created"
115
139
  )
116
- instance_info: Optional[Dict] = Field(
140
+ instance_info: Optional[Dict[str, Any]] = Field(
117
141
  default=None,
118
142
  description="Metadata about the class instance (creation time, call count, etc.)",
119
143
  )
@@ -4,6 +4,7 @@ import inspect
4
4
  import textwrap
5
5
  import hashlib
6
6
  import traceback
7
+ import threading
7
8
  import cloudpickle
8
9
  import logging
9
10
  from ..core.resources import LiveServerless
@@ -16,8 +17,9 @@ from ..protos.remote_execution import (
16
17
  log = logging.getLogger(__name__)
17
18
 
18
19
 
19
- # global in memory cache, TODO: use a more robust cache in future
20
+ # Global in-memory cache with thread safety
20
21
  _SERIALIZED_FUNCTION_CACHE = {}
22
+ _function_cache_lock = threading.RLock()
21
23
 
22
24
 
23
25
  def get_function_source(func):
@@ -60,21 +62,34 @@ class LiveServerlessStub(RemoteExecutorStub):
60
62
  def __init__(self, server: LiveServerless):
61
63
  self.server = server
62
64
 
63
- def prepare_request(self, func, dependencies, system_dependencies, *args, **kwargs):
65
+ def prepare_request(
66
+ self,
67
+ func,
68
+ dependencies,
69
+ system_dependencies,
70
+ accelerate_downloads,
71
+ hf_models_to_cache,
72
+ *args,
73
+ **kwargs,
74
+ ):
64
75
  source, src_hash = get_function_source(func)
65
76
 
66
77
  request = {
67
78
  "function_name": func.__name__,
68
79
  "dependencies": dependencies,
69
80
  "system_dependencies": system_dependencies,
81
+ "accelerate_downloads": accelerate_downloads,
82
+ "hf_models_to_cache": hf_models_to_cache,
70
83
  }
71
84
 
72
- # check if the function is already cached
73
- if src_hash not in _SERIALIZED_FUNCTION_CACHE:
74
- # Cache the serialized function
75
- _SERIALIZED_FUNCTION_CACHE[src_hash] = source
85
+ # Thread-safe cache access
86
+ with _function_cache_lock:
87
+ # check if the function is already cached
88
+ if src_hash not in _SERIALIZED_FUNCTION_CACHE:
89
+ # Cache the serialized function
90
+ _SERIALIZED_FUNCTION_CACHE[src_hash] = source
76
91
 
77
- request["function_code"] = _SERIALIZED_FUNCTION_CACHE[src_hash]
92
+ request["function_code"] = _SERIALIZED_FUNCTION_CACHE[src_hash]
78
93
 
79
94
  # Serialize arguments using cloudpickle
80
95
  if args:
@@ -2,6 +2,7 @@ import logging
2
2
  from functools import singledispatch
3
3
 
4
4
  from ..core.resources import (
5
+ CpuLiveServerless,
5
6
  CpuServerlessEndpoint,
6
7
  LiveServerless,
7
8
  ServerlessEndpoint,
@@ -20,19 +21,31 @@ def stub_resource(resource, **extra):
20
21
  return fallback
21
22
 
22
23
 
23
- @stub_resource.register(LiveServerless)
24
- def _(resource, **extra):
24
+ def _create_live_serverless_stub(resource, **extra):
25
+ """Create a live serverless stub for both LiveServerless and CpuLiveServerless."""
25
26
  stub = LiveServerlessStub(resource)
26
27
 
27
28
  # Function execution
28
29
  async def stubbed_resource(
29
- func, dependencies, system_dependencies, *args, **kwargs
30
+ func,
31
+ dependencies,
32
+ system_dependencies,
33
+ accelerate_downloads,
34
+ hf_models_to_cache,
35
+ *args,
36
+ **kwargs,
30
37
  ) -> dict:
31
38
  if args == (None,):
32
39
  args = []
33
40
 
34
41
  request = stub.prepare_request(
35
- func, dependencies, system_dependencies, *args, **kwargs
42
+ func,
43
+ dependencies,
44
+ system_dependencies,
45
+ accelerate_downloads,
46
+ hf_models_to_cache,
47
+ *args,
48
+ **kwargs,
36
49
  )
37
50
  response = await stub.ExecuteFunction(request)
38
51
  return stub.handle_response(response)
@@ -48,15 +61,27 @@ def _(resource, **extra):
48
61
  return stubbed_resource
49
62
 
50
63
 
64
+ @stub_resource.register(LiveServerless)
65
+ def _(resource, **extra):
66
+ return _create_live_serverless_stub(resource, **extra)
67
+
68
+
69
+ @stub_resource.register(CpuLiveServerless)
70
+ def _(resource, **extra):
71
+ return _create_live_serverless_stub(resource, **extra)
72
+
73
+
51
74
  @stub_resource.register(ServerlessEndpoint)
52
75
  def _(resource, **extra):
53
76
  async def stubbed_resource(
54
- func, dependencies, system_dependencies, *args, **kwargs
77
+ func,
78
+ dependencies,
79
+ system_dependencies,
80
+ accelerate_downloads,
81
+ hf_models_to_cache,
82
+ *args,
83
+ **kwargs,
55
84
  ) -> dict:
56
- if args == (None,):
57
- # cleanup: when the function is called with no args
58
- args = []
59
-
60
85
  if dependencies or system_dependencies:
61
86
  log.warning(
62
87
  "Dependencies are not supported for ServerlessEndpoint. "
@@ -74,12 +99,14 @@ def _(resource, **extra):
74
99
  @stub_resource.register(CpuServerlessEndpoint)
75
100
  def _(resource, **extra):
76
101
  async def stubbed_resource(
77
- func, dependencies, system_dependencies, *args, **kwargs
102
+ func,
103
+ dependencies,
104
+ system_dependencies,
105
+ accelerate_downloads,
106
+ hf_models_to_cache,
107
+ *args,
108
+ **kwargs,
78
109
  ) -> dict:
79
- if args == (None,):
80
- # cleanup: when the function is called with no args
81
- args = []
82
-
83
110
  if dependencies or system_dependencies:
84
111
  log.warning(
85
112
  "Dependencies are not supported for CpuServerlessEndpoint. "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tetra_rp
3
- Version: 0.10.0
3
+ Version: 0.12.0
4
4
  Summary: A Python library for distributed inference and serving of machine learning models
5
5
  Author-email: Marut Pandya <pandyamarut@gmail.com>, Patrick Rachford <prachford@icloud.com>, Dean Quinanola <dean.quinanola@runpod.io>
6
6
  License: MIT
@@ -13,6 +13,7 @@ Description-Content-Type: text/markdown
13
13
  Requires-Dist: cloudpickle>=3.1.1
14
14
  Requires-Dist: runpod
15
15
  Requires-Dist: python-dotenv>=1.0.0
16
+ Requires-Dist: pydantic>=2.0.0
16
17
 
17
18
  # Tetra: Serverless computing for AI workloads
18
19
 
@@ -0,0 +1,38 @@
1
+ tetra_rp/__init__.py,sha256=_D3Wbtv9tBh_WGS4Si5uQbsefL63GqqjoGTN3R8P6fA,769
2
+ tetra_rp/client.py,sha256=urSVh0j9didd9U8lboPv3TtFYURp2XO6ReOICr9Xrls,3414
3
+ tetra_rp/execute_class.py,sha256=jYNFalqqjKvvCz1zzodRvOkrLQd2FYnLYa4EElEYp8w,12243
4
+ tetra_rp/logger.py,sha256=gk5-PWp3k_GQ5DxndsRkBCX0jarp_3lgZ1oiTFuThQg,1125
5
+ tetra_rp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ tetra_rp/core/api/__init__.py,sha256=oldrEKMwxYoBPLvPfVlaFS3wfUtTTxCN6-HzlpTh6vE,124
7
+ tetra_rp/core/api/runpod.py,sha256=3TTx1fkXMLZ2R5JCrQYPEn8dhdUsBt8i5OEwAfaKQ_k,10451
8
+ tetra_rp/core/resources/__init__.py,sha256=ZvSfceYV4S1Xo3YA03B-sR5VRud8BKfx5Pe44xFfruo,911
9
+ tetra_rp/core/resources/base.py,sha256=UJeDiFN45aO1n5SBcxn56ohLhj-AWHoj0KO7mF4yJ_o,1440
10
+ tetra_rp/core/resources/cloud.py,sha256=XJOWPfzYlDVJGHxgffcfpEaOKrWhGdi7AzTlaGuYj0o,70
11
+ tetra_rp/core/resources/constants.py,sha256=F1gPqFaXcCmfrbUSO9PQtUBv984TxFc3pySgVy-kXk8,158
12
+ tetra_rp/core/resources/cpu.py,sha256=szhkjaJ9OnjzLvaD7Yc2hRCR-C9eyB6tswo1Qe6VuZ0,3962
13
+ tetra_rp/core/resources/environment.py,sha256=FC9kJCa8YLSar75AKUKqJYnNLrUdjZj8ZTOrspBrS00,1267
14
+ tetra_rp/core/resources/gpu.py,sha256=mMOPLhBugFBAMAl3ezhjAxKuvYya5_9A_h7kvaCoAfk,1885
15
+ tetra_rp/core/resources/live_serverless.py,sha256=FLmaQdn5UMczEfkP3qykIfRVfZeyYdvyNHX9Nd13_54,1868
16
+ tetra_rp/core/resources/network_volume.py,sha256=h_1xhrbBm9jJWROOGl5qy9u4_kCKSyV4idzt0567-J8,5193
17
+ tetra_rp/core/resources/resource_manager.py,sha256=K-SgCk2BMNEAnkB87YynxUH-suZcdcOPLMonL7EogIw,4988
18
+ tetra_rp/core/resources/serverless.py,sha256=1T21RkMjGnM1I87AsGQ6qazp7A9cE7LwH_c6yJ5shPQ,13427
19
+ tetra_rp/core/resources/serverless_cpu.py,sha256=OiG1C_5_j7pYPHdGp3lQQanIl2ak81u8-jlZo2OXflA,5567
20
+ tetra_rp/core/resources/template.py,sha256=qQ8Wd7Rzr1_YeAbW1V7_k7AVHzgWR_RPjcaRfKsetAk,3141
21
+ tetra_rp/core/resources/utils.py,sha256=mgXfgz_NuHN_IC7TzMNdH9II-LMjxcDCG7syDTcPiGs,1721
22
+ tetra_rp/core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ tetra_rp/core/utils/backoff.py,sha256=1pfa0smFNpib8nztcIgBbtrVvQeECKh-aNOfL2TztgU,1324
24
+ tetra_rp/core/utils/constants.py,sha256=Dm4XiO5zTzfdqOSeYVfAjaf2LyHnIEVmbOi_s_k1J_E,375
25
+ tetra_rp/core/utils/file_lock.py,sha256=bxtAexD2rbqMhdr94VbmKdNp0gfKRgxDXx1n7LX4Eso,8269
26
+ tetra_rp/core/utils/json.py,sha256=q0r7aEdfh8kKVeHGeh9fBDfuhHYNopSreislAMB6HhM,1163
27
+ tetra_rp/core/utils/lru_cache.py,sha256=drwKg-DfLbeBRGTzuxKqNKMQq0EuZV15LMTZIOyZuVk,2618
28
+ tetra_rp/core/utils/singleton.py,sha256=lSXgEQGX9nzhrc05GMpThn9SHKG45iajBbSEtwCcNyI,632
29
+ tetra_rp/protos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ tetra_rp/protos/remote_execution.py,sha256=flKJG0U4ked84cXyF4Gfs_7fBgLsEVOzBv8ZWB9UlP0,5648
31
+ tetra_rp/stubs/__init__.py,sha256=ozKsHs8q0T7o2qhQEquub9hqomh1Htys53mMraaRu2E,72
32
+ tetra_rp/stubs/live_serverless.py,sha256=2bQ47Hq4D8o3YydkxR6QVuLjYrzYS427r3067beYK2A,4550
33
+ tetra_rp/stubs/registry.py,sha256=akJREObyvTAVp6Rvxw8O49W52eJAjByleLU_phMyaDI,3351
34
+ tetra_rp/stubs/serverless.py,sha256=BM_a5Ml5VADBYu2WRNmo9qnicP8NnXDGl5ywifulbD0,947
35
+ tetra_rp-0.12.0.dist-info/METADATA,sha256=u2OHbJV-8KIiOca3SenK2J6I8ms13P8Jc64KGNhFAyE,28077
36
+ tetra_rp-0.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ tetra_rp-0.12.0.dist-info/top_level.txt,sha256=bBay7JTDwJXsTYvVjrwno9hnF-j0q272lk65f2AcPjU,9
38
+ tetra_rp-0.12.0.dist-info/RECORD,,
@@ -1,36 +0,0 @@
1
- tetra_rp/__init__.py,sha256=-1S5sYIKtnUV8V1HlSIbX1yZwiUrsO8J5b3ZEIR_phU,687
2
- tetra_rp/client.py,sha256=rAMMmn4ejAayFXJMZzx7dG_8Y65tCEMI6wSSKgur4zQ,2500
3
- tetra_rp/execute_class.py,sha256=HoH-qWDA7X6yGvQMwmHn5-MKxbLWHEDEHsuat5dzl2U,11912
4
- tetra_rp/logger.py,sha256=gk5-PWp3k_GQ5DxndsRkBCX0jarp_3lgZ1oiTFuThQg,1125
5
- tetra_rp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- tetra_rp/core/api/__init__.py,sha256=oldrEKMwxYoBPLvPfVlaFS3wfUtTTxCN6-HzlpTh6vE,124
7
- tetra_rp/core/api/runpod.py,sha256=3TTx1fkXMLZ2R5JCrQYPEn8dhdUsBt8i5OEwAfaKQ_k,10451
8
- tetra_rp/core/resources/__init__.py,sha256=UhIwo1Y6-tw5qsULamR296sQiztuz-oWrSTreqfmFSw,814
9
- tetra_rp/core/resources/base.py,sha256=UJeDiFN45aO1n5SBcxn56ohLhj-AWHoj0KO7mF4yJ_o,1440
10
- tetra_rp/core/resources/cloud.py,sha256=XJOWPfzYlDVJGHxgffcfpEaOKrWhGdi7AzTlaGuYj0o,70
11
- tetra_rp/core/resources/constants.py,sha256=F1gPqFaXcCmfrbUSO9PQtUBv984TxFc3pySgVy-kXk8,158
12
- tetra_rp/core/resources/cpu.py,sha256=YIE-tKolSU3JJzpPB7ey-PbRdqKWsJZ_Ad4h2OYaaiA,1231
13
- tetra_rp/core/resources/environment.py,sha256=FC9kJCa8YLSar75AKUKqJYnNLrUdjZj8ZTOrspBrS00,1267
14
- tetra_rp/core/resources/gpu.py,sha256=2jIIMr8PNnlIAP8ZTKO8Imx-rdxXp2rbdSHJeVfjawk,1858
15
- tetra_rp/core/resources/live_serverless.py,sha256=A3JRdCYwHR2KN_OlmTLcv-m_ObxNhBhc5CnUzXOpOtc,1177
16
- tetra_rp/core/resources/network_volume.py,sha256=h11dRlAkkxrqyNvUP9Eb8BHAUSFQyRP4lNgBdKChezw,5391
17
- tetra_rp/core/resources/resource_manager.py,sha256=kUVZDblfUzaG78S8FwOzu4rN6QSegUgQNK3fJ_X7l0w,2834
18
- tetra_rp/core/resources/serverless.py,sha256=48mENAPQrR8fMjWFpb7mpGFOMqjXZnRWGULGH7NPa5E,13629
19
- tetra_rp/core/resources/template.py,sha256=UkflJXZFWIbQkLuUt4oRLAjn-yIpw9_mT2X1cAH69CU,3141
20
- tetra_rp/core/resources/utils.py,sha256=mgXfgz_NuHN_IC7TzMNdH9II-LMjxcDCG7syDTcPiGs,1721
21
- tetra_rp/core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- tetra_rp/core/utils/backoff.py,sha256=1pfa0smFNpib8nztcIgBbtrVvQeECKh-aNOfL2TztgU,1324
23
- tetra_rp/core/utils/constants.py,sha256=Dm4XiO5zTzfdqOSeYVfAjaf2LyHnIEVmbOi_s_k1J_E,375
24
- tetra_rp/core/utils/json.py,sha256=q0r7aEdfh8kKVeHGeh9fBDfuhHYNopSreislAMB6HhM,1163
25
- tetra_rp/core/utils/lru_cache.py,sha256=drwKg-DfLbeBRGTzuxKqNKMQq0EuZV15LMTZIOyZuVk,2618
26
- tetra_rp/core/utils/singleton.py,sha256=JRli0HhBfq4P9mBUOg1TZUUwMvIenRqWdymX3qFMm2k,210
27
- tetra_rp/protos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- tetra_rp/protos/remote_execution.py,sha256=F4uwobnp5q-lX3lR7NCAB23J6OzlzcsB35cezwuoSnI,4638
29
- tetra_rp/stubs/__init__.py,sha256=ozKsHs8q0T7o2qhQEquub9hqomh1Htys53mMraaRu2E,72
30
- tetra_rp/stubs/live_serverless.py,sha256=o1NH5XEwUD-27NXJsEGO0IwnuDp8iXwUiw5nZtaZZOI,4199
31
- tetra_rp/stubs/registry.py,sha256=dmbyC7uBp04_sXsG2wJCloFfFRzYjYQ-naEBKhTRo-U,2839
32
- tetra_rp/stubs/serverless.py,sha256=BM_a5Ml5VADBYu2WRNmo9qnicP8NnXDGl5ywifulbD0,947
33
- tetra_rp-0.10.0.dist-info/METADATA,sha256=Ck626kHGCXM6r5CHIm9P7gcg1q3IGWhB7Wiw7x0yIJs,28046
34
- tetra_rp-0.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- tetra_rp-0.10.0.dist-info/top_level.txt,sha256=bBay7JTDwJXsTYvVjrwno9hnF-j0q272lk65f2AcPjU,9
36
- tetra_rp-0.10.0.dist-info/RECORD,,