truss 0.11.1rc15__py3-none-any.whl → 0.11.2rc2__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.

@@ -296,18 +296,6 @@ def _get_checkpoint_ids_to_deploy(
296
296
  return checkpoint_ids
297
297
 
298
298
 
299
- def _select_single_checkpoint(checkpoint_id_options: List[str]) -> List[str]:
300
- """Select a single checkpoint using interactive prompt."""
301
- checkpoint_id = inquirer.select(
302
- message="Select the checkpoints to deploy:", choices=checkpoint_id_options
303
- ).execute()
304
-
305
- if not checkpoint_id:
306
- raise click.UsageError("A checkpoint must be selected.")
307
-
308
- return [checkpoint_id]
309
-
310
-
311
299
  def _select_multiple_checkpoints(checkpoint_id_options: List[str]) -> List[str]:
312
300
  """Select multiple checkpoints using interactive checkbox."""
313
301
  checkpoint_ids = inquirer.checkbox(
@@ -6,7 +6,7 @@ loguru>=0.7.2
6
6
  python-json-logger>=2.0.2
7
7
  tenacity>=8.1.0
8
8
  # To avoid divergence, this should follow the latest release.
9
- truss==0.11.1rc15
9
+ truss==0.11.1
10
10
  uvicorn>=0.24.0
11
11
  uvloop>=0.19.0
12
12
  websockets>=10.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: truss
3
- Version: 0.11.1rc15
3
+ Version: 0.11.2rc2
4
4
  Summary: A seamless bridge from model development to model delivery
5
5
  Project-URL: Repository, https://github.com/basetenlabs/truss
6
6
  Project-URL: Homepage, https://truss.baseten.co
@@ -24,7 +24,7 @@ truss/cli/train/metrics_watcher.py,sha256=smz-zrEsBj_-wJHI0pAZ-EAPrvfCWzq1eQjGiF
24
24
  truss/cli/train/poller.py,sha256=TGRzELxsicga0bEXewSX1ujw6lfPmDnHd6nr8zvOFO8,3550
25
25
  truss/cli/train/types.py,sha256=alGtr4Q71GeB65PpGMhsoKygw4k_ncR6MKIP1ioP8rI,951
26
26
  truss/cli/train/deploy_checkpoints/__init__.py,sha256=wL-M2yu8PxO2tFvjwshXAfPnB-5TlvsBp2v_bdzimRU,99
27
- truss/cli/train/deploy_checkpoints/deploy_checkpoints.py,sha256=KUaUl5a2lGy-l5rZZJv-rxIAsCJPRNC8h1909fXVKtE,17763
27
+ truss/cli/train/deploy_checkpoints/deploy_checkpoints.py,sha256=nJHUjR4f4_13mFPNetWKq7ecsqr-cradbv3RBBDj2pk,17364
28
28
  truss/cli/train/deploy_checkpoints/deploy_checkpoints_helpers.py,sha256=6x5nS_HnWYtS9vi-Pg8akzrJk9L_agjvFhm5EFh1m6Y,1964
29
29
  truss/cli/train/deploy_checkpoints/deploy_full_checkpoints.py,sha256=FYRG5KTMlxEMZS-RA_m2gp1wuqWbSpqt2RhdQfLibhA,3968
30
30
  truss/cli/train/deploy_checkpoints/deploy_lora_checkpoints.py,sha256=P91dIAzuhl2GlzmrWwCcYI7uCMT1Lm7C79JQHM_exN4,4442
@@ -72,7 +72,7 @@ truss/templates/cache_requirements.txt,sha256=xoPoJ-OVnf1z6oq_RVM3vCr3ionByyqMLj
72
72
  truss/templates/copy_cache_files.Dockerfile.jinja,sha256=Os5zFdYLZ_AfCRGq4RcpVTObOTwL7zvmwYcvOzd_Zqo,126
73
73
  truss/templates/docker_server_requirements.txt,sha256=PyhOPKAmKW1N2vLvTfLMwsEtuGpoRrbWuNo7tT6v2Mc,18
74
74
  truss/templates/server.Dockerfile.jinja,sha256=CUYnF_hgxPGq2re7__0UPWlwzOHMoFkxp6NVKi3U16s,7071
75
- truss/templates/control/requirements.txt,sha256=x3hyJl3abQQhOsx7SuBYgk_PHkwbyXJ4N_g7vkXYIu0,254
75
+ truss/templates/control/requirements.txt,sha256=tJGr83WoE0CZm2FrloZ9VScK84q-_FTuVXjDYrexhW0,250
76
76
  truss/templates/control/control/application.py,sha256=jYeta6hWe1SkfLL3W4IDmdYjg3ZuKqI_UagWYs5RB_E,3793
77
77
  truss/templates/control/control/endpoints.py,sha256=VQ1lvZjFvR091yRkiFdvXw1Q7PiNGXT9rJwY7_sX6yg,11828
78
78
  truss/templates/control/control/server.py,sha256=R4Y219i1dcz0kkksN8obLoX-YXWGo9iW1igindyG50c,3128
@@ -348,27 +348,27 @@ truss_chains/__init__.py,sha256=QDw1YwdqMaQpz5Oltu2Eq2vzEX9fDrMoqnhtbeh60i4,1278
348
348
  truss_chains/framework.py,sha256=CS7tSegPe2Q8UUT6CDkrtSrB3utr_1QN1jTEPjrj5Ug,67519
349
349
  truss_chains/private_types.py,sha256=6CaQEPawFLXjEbJ-01lqfexJtUIekF_q61LNENWegFo,8917
350
350
  truss_chains/public_api.py,sha256=0AXV6UdZIFAMycUNG_klgo4aLFmBZeKGfrulZEWzR0M,9532
351
- truss_chains/public_types.py,sha256=8cBstm5m_9aN_U2WoSHQ9s2z6gTdSEl-nVgXyneU3nY,29166
351
+ truss_chains/public_types.py,sha256=Am1vc5pWuEDs65UQp8Be4iOU05kMXjPG3QrJfNXDmHs,29225
352
352
  truss_chains/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
353
353
  truss_chains/pydantic_numpy.py,sha256=MG8Ji_Inwo_JSfM2n7TPj8B-nbrBlDYsY3SOeBwD8fE,4289
354
354
  truss_chains/streaming.py,sha256=DGl2LEAN67YwP7Nn9MK488KmYc4KopWmcHuE6WjyO1Q,12521
355
355
  truss_chains/utils.py,sha256=LvpCG2lnN6dqPqyX3PwLH9tyjUzqQN3N4WeEFROMHak,6291
356
356
  truss_chains/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
357
- truss_chains/deployment/code_gen.py,sha256=AmAUZ3h1hP3uYkl3J6o096K5RFLuBOP7kOFSnFC_C4U,32568
357
+ truss_chains/deployment/code_gen.py,sha256=IBOYdhsWUyW_sBVhlEQAhvwxKcsGflDjgmR-1HyJJLg,32666
358
358
  truss_chains/deployment/deployment_client.py,sha256=haFiVmQek42ewlN_YflBaRDQT4ZYbmT20tvvJOkcUX0,32899
359
359
  truss_chains/reference_code/reference_chainlet.py,sha256=5feSeqGtrHDbldkfZCfX2R5YbbW0Uhc35mhaP2pXrHw,1340
360
360
  truss_chains/reference_code/reference_model.py,sha256=emH3hb23E_nbP98I37PGp1Xk1hz3g3lQ00tiLo55cSM,322
361
361
  truss_chains/remote_chainlet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
362
362
  truss_chains/remote_chainlet/model_skeleton.py,sha256=8ZReLOO2MLcdg7bNZ61C-6j-e68i2Z-fFlyV3sz0qH8,2376
363
363
  truss_chains/remote_chainlet/stub.py,sha256=Y2gDUzMY9WRaQNHIz-o4dfLUfFyYV9dUhIRQcfgrY8g,17209
364
- truss_chains/remote_chainlet/utils.py,sha256=nnJQG3hXIoGghWEGPIAqKfRaueCLgSdwNI2x9B7BSaY,23080
364
+ truss_chains/remote_chainlet/utils.py,sha256=Zn3GZRvK8f65WUa-qa-8uPFZ2pD7ukRFxbLOvT-BL0Q,24063
365
365
  truss_train/__init__.py,sha256=7hE6j6-u6UGzCGaNp3CsCN0kAVjBus1Ekups-Bk0fi4,837
366
366
  truss_train/definitions.py,sha256=V985HhY4rdXL10DZxpFEpze9ScxzWErMht4WwaPknGU,6789
367
367
  truss_train/deployment.py,sha256=lWWANSuzBWu2M4oK4qD7n-oVR1JKdmw2Pn5BJQHg-Ck,3074
368
368
  truss_train/loader.py,sha256=0o66EjBaHc2YY4syxxHVR4ordJWs13lNXnKjKq2wq0U,1630
369
369
  truss_train/public_api.py,sha256=9N_NstiUlmBuLUwH_fNG_1x7OhGCytZLNvqKXBlStrM,1220
370
- truss-0.11.1rc15.dist-info/METADATA,sha256=FEwmol_o_slcTpiH9EWPFnpTPTlVQwPImFV2jCvNhdw,6673
371
- truss-0.11.1rc15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
372
- truss-0.11.1rc15.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
373
- truss-0.11.1rc15.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
374
- truss-0.11.1rc15.dist-info/RECORD,,
370
+ truss-0.11.2rc2.dist-info/METADATA,sha256=l4V9tHBGTjs14pZeFWIR5VCFsS1ArDKc3er-aKHkGqM,6672
371
+ truss-0.11.2rc2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
372
+ truss-0.11.2rc2.dist-info/entry_points.txt,sha256=-MwKfHHQHQ6j0HqIgvxrz3CehCmczDLTD-OsRHnjjuU,130
373
+ truss-0.11.2rc2.dist-info/licenses/LICENSE,sha256=FTqGzu85i-uw1Gi8E_o0oD60bH9yQ_XIGtZbA1QUYiw,1064
374
+ truss-0.11.2rc2.dist-info/RECORD,,
@@ -544,7 +544,11 @@ async def websocket(self, websocket: fastapi.WebSocket) -> None:
544
544
  )"""
545
545
  return _Source(
546
546
  src=src,
547
- imports={"import fastapi", "from truss_chains.remote_chainlet import utils"},
547
+ imports={
548
+ "import fastapi",
549
+ "from starlette.websockets import WebSocketState",
550
+ "from truss_chains.remote_chainlet import utils",
551
+ },
548
552
  )
549
553
 
550
554
 
@@ -482,9 +482,11 @@ class WebSocketProtocol(Protocol):
482
482
  async def send_bytes(self, data: bytes) -> None: ...
483
483
  async def send_json(self, data: Any) -> None: ...
484
484
 
485
- def iter_text(self) -> AsyncIterator[str]: ...
486
- def iter_bytes(self) -> AsyncIterator[bytes]: ...
487
- def iter_json(self) -> AsyncIterator[Any]: ...
485
+ async def iter_text(self) -> AsyncIterator[str]: ...
486
+ async def iter_bytes(self) -> AsyncIterator[bytes]: ...
487
+ async def iter_json(self) -> AsyncIterator[Any]: ...
488
+
489
+ def is_connected(self) -> bool: ...
488
490
 
489
491
 
490
492
  class EngineBuilderLLMInput(pydantic.BaseModel):
@@ -39,7 +39,7 @@ if TYPE_CHECKING:
39
39
  try:
40
40
  import prometheus_client
41
41
  except ImportError:
42
- logging.warning("Optional `prometheus_client` is not installed. ")
42
+ logging.warning("Optional `prometheus_client` is not installed.")
43
43
 
44
44
  class _NoOpMetric:
45
45
  def labels(self, *args: object, **kwargs: object) -> "_NoOpMetric":
@@ -65,6 +65,26 @@ except ImportError:
65
65
  return _NoOpMetric()
66
66
 
67
67
 
68
+ try:
69
+ from fastapi import WebSocketDisconnect
70
+ except ImportError:
71
+ # NB(nikhil): Stub implementation of WebSocketDisconnect, in case local environment doesn't have
72
+ # fastapi.
73
+ class WebSocketDisconnect(Exception): # type: ignore[no-redef]
74
+ def __init__(self, code: int, reason: Optional[str] = None):
75
+ super().__init__()
76
+ self.code = code
77
+ self.reason = reason
78
+
79
+
80
+ try:
81
+ from starlette.websockets import WebSocketState
82
+ except ImportError:
83
+ # NB(nikhil): Stub implementation of WebSocketState, in case local environment doesn't have starlette.
84
+ class WebSocketState: # type: ignore[no-redef]
85
+ CONNECTED = "connected"
86
+
87
+
68
88
  T = TypeVar("T")
69
89
 
70
90
  _LockT = TypeVar("_LockT", bound=Union[threading.Lock, asyncio.Lock])
@@ -588,17 +608,12 @@ class WebsocketWrapperFastAPI:
588
608
  await self._websocket.close(code=code, reason=reason)
589
609
 
590
610
  async def receive(self) -> Union[str, bytes]:
591
- try:
592
- import fastapi
593
- except ImportError:
594
- raise utils.make_optional_import_error("fastapi")
595
-
596
611
  message = await self._websocket.receive()
597
612
 
598
613
  if message.get("type") == "websocket.disconnect":
599
614
  # NB(nikhil): Mimics FastAPI `_raise_on_disconnect`, since otherwise the user has no
600
615
  # way of detecting that the client disconnected.
601
- raise fastapi.WebSocketDisconnect(message["code"], message.get("reason"))
616
+ raise WebSocketDisconnect(message["code"], message.get("reason"))
602
617
  elif message.get("text"):
603
618
  return typing.cast(str, message["text"])
604
619
  else:
@@ -623,13 +638,19 @@ class WebsocketWrapperFastAPI:
623
638
  await self._websocket.send_json(data)
624
639
 
625
640
  async def iter_text(self) -> AsyncIterator[str]:
626
- while True:
627
- yield await self.receive_text()
641
+ return self._websocket.iter_text()
628
642
 
629
643
  async def iter_bytes(self) -> AsyncIterator[bytes]:
630
- while True:
631
- yield await self.receive_bytes()
644
+ return self._websocket.iter_bytes()
632
645
 
633
646
  async def iter_json(self) -> AsyncIterator[Any]:
634
- while True:
635
- yield await self.receive_json()
647
+ return self._websocket.iter_json()
648
+
649
+ async def is_connected(self) -> bool:
650
+ # NB(nikhil): This isn't a foolproof mechanism for detecting whether a websocket
651
+ # connection is actually alive, ping/pong messages are best suited for that. However,
652
+ # as a heuristic to determine if a message is safe to send, this can do a pretty good job.
653
+ return (
654
+ self._websocket.application_state == WebSocketState.CONNECTED
655
+ and self._websocket.client_state == WebSocketState.CONNECTED
656
+ )