11"""Async I/O protocol implementation for the LM Studio remote access API."""
22
33import asyncio
4- import warnings
54
65from abc import abstractmethod
76from contextlib import AsyncExitStack , asynccontextmanager
109108# and similar tasks is published from `json_api`.
110109# Bypassing the high level API, and working more
111110# directly with the underlying websocket(s) is
112- # supported (hence the public names), but they're
113- # not exported via the top-level `lmstudio` API .
111+ # not supported due to the complexity of the task
112+ # management details (hence the private names) .
114113__all__ = [
115114 "AnyAsyncDownloadedModel" ,
116115 "AsyncClient" ,
@@ -215,7 +214,7 @@ async def receive_result(self) -> Any:
215214 return self ._rpc .handle_rx_message (message )
216215
217216
218- class AsyncLMStudioWebsocket (LMStudioWebsocket [AsyncWebSocketSession ]):
217+ class _AsyncLMStudioWebsocket (LMStudioWebsocket [AsyncWebSocketSession ]):
219218 """Asynchronous websocket client that handles demultiplexing of reply messages."""
220219
221220 def __init__ (
@@ -331,7 +330,7 @@ async def remote_call(
331330 return await rpc .receive_result ()
332331
333332
334- class AsyncSession (ClientSession ["AsyncClient" , AsyncLMStudioWebsocket ]):
333+ class _AsyncSession (ClientSession ["AsyncClient" , _AsyncLMStudioWebsocket ]):
335334 """Async client session interfaces applicable to all API namespaces."""
336335
337336 def __init__ (self , client : "AsyncClient" ) -> None :
@@ -354,7 +353,7 @@ async def __aexit__(self, *args: Any) -> None:
354353 await self .disconnect ()
355354
356355 @sdk_public_api_async ()
357- async def connect (self ) -> AsyncLMStudioWebsocket :
356+ async def connect (self ) -> _AsyncLMStudioWebsocket :
358357 """Connect the client session."""
359358 self ._fail_if_connected ("Attempted to connect already connected session" )
360359 api_host = self ._client .api_host
@@ -367,7 +366,7 @@ async def connect(self) -> AsyncLMStudioWebsocket:
367366 resources = self ._resource_manager
368367 client = self ._client
369368 self ._lmsws = lmsws = await resources .enter_async_context (
370- AsyncLMStudioWebsocket (
369+ _AsyncLMStudioWebsocket (
371370 client ._task_manager , session_url , client ._auth_details
372371 )
373372 )
@@ -411,7 +410,7 @@ async def remote_call(
411410
412411
413412TAsyncSessionModel = TypeVar (
414- "TAsyncSessionModel" , bound = "AsyncSessionModel [Any, Any, Any, Any]"
413+ "TAsyncSessionModel" , bound = "_AsyncSessionModel [Any, Any, Any, Any]"
415414)
416415TAsyncModelHandle = TypeVar ("TAsyncModelHandle" , bound = "AsyncModelHandle[Any]" )
417416
@@ -467,7 +466,7 @@ async def model(
467466class AsyncDownloadedEmbeddingModel (
468467 AsyncDownloadedModel [
469468 EmbeddingModelInfo ,
470- "AsyncSessionEmbedding " ,
469+ "_AsyncSessionEmbedding " ,
471470 EmbeddingLoadModelConfig ,
472471 EmbeddingLoadModelConfigDict ,
473472 "AsyncEmbeddingModel" ,
@@ -476,7 +475,7 @@ class AsyncDownloadedEmbeddingModel(
476475 """Asynchronous download listing for an embedding model."""
477476
478477 def __init__ (
479- self , model_info : DictObject , session : "AsyncSessionEmbedding "
478+ self , model_info : DictObject , session : "_AsyncSessionEmbedding "
480479 ) -> None :
481480 """Initialize downloaded embedding model details."""
482481 super ().__init__ (EmbeddingModelInfo , model_info , session )
@@ -485,23 +484,23 @@ def __init__(
485484class AsyncDownloadedLlm (
486485 AsyncDownloadedModel [
487486 LlmInfo ,
488- "AsyncSessionLlm " ,
487+ "_AsyncSessionLlm " ,
489488 LlmLoadModelConfig ,
490489 LlmLoadModelConfigDict ,
491490 "AsyncLLM" ,
492491 ]
493492):
494493 """Asynchronous ownload listing for an LLM."""
495494
496- def __init__ (self , model_info : DictObject , session : "AsyncSessionLlm " ) -> None :
495+ def __init__ (self , model_info : DictObject , session : "_AsyncSessionLlm " ) -> None :
497496 """Initialize downloaded embedding model details."""
498497 super ().__init__ (LlmInfo , model_info , session )
499498
500499
501500AnyAsyncDownloadedModel : TypeAlias = AsyncDownloadedModel [Any , Any , Any , Any , Any ]
502501
503502
504- class AsyncSessionSystem ( AsyncSession ):
503+ class _AsyncSessionSystem ( _AsyncSession ):
505504 """Async client session for the system namespace."""
506505
507506 API_NAMESPACE = "system"
@@ -531,7 +530,7 @@ def _process_download_listing(
531530 )
532531
533532
534- class _AsyncSessionFiles (AsyncSession ):
533+ class _AsyncSessionFiles (_AsyncSession ):
535534 """Async client session for the files namespace."""
536535
537536 API_NAMESPACE = "files"
@@ -562,7 +561,7 @@ async def prepare_image(
562561 return await self ._fetch_file_handle (file_data )
563562
564563
565- class AsyncModelDownloadOption (ModelDownloadOptionBase [AsyncSession ]):
564+ class AsyncModelDownloadOption (ModelDownloadOptionBase [_AsyncSession ]):
566565 """A single download option for a model search result."""
567566
568567 @sdk_public_api_async ()
@@ -577,10 +576,10 @@ async def download(
577576 return await channel .wait_for_result ()
578577
579578
580- class AsyncAvailableModel (AvailableModelBase [AsyncSession ]):
579+ class AsyncAvailableModel (AvailableModelBase [_AsyncSession ]):
581580 """A model available for download from the model repository."""
582581
583- _session : AsyncSession
582+ _session : _AsyncSession
584583
585584 @sdk_public_api_async ()
586585 async def get_download_options (
@@ -595,7 +594,7 @@ async def get_download_options(
595594 return final
596595
597596
598- class AsyncSessionRepository ( AsyncSession ):
597+ class _AsyncSessionRepository ( _AsyncSession ):
599598 """Async client session for the repository namespace."""
600599
601600 API_NAMESPACE = "repository"
@@ -616,8 +615,8 @@ async def search_models(
616615TAsyncDownloadedModel = TypeVar ("TAsyncDownloadedModel" , bound = AnyAsyncDownloadedModel )
617616
618617
619- class AsyncSessionModel (
620- AsyncSession ,
618+ class _AsyncSessionModel (
619+ _AsyncSession ,
621620 Generic [
622621 TAsyncModelHandle ,
623622 TLoadConfig ,
@@ -630,7 +629,7 @@ class AsyncSessionModel(
630629 _API_TYPES : Type [ModelSessionTypes [TLoadConfig ]]
631630
632631 @property
633- def _system_session (self ) -> AsyncSessionSystem :
632+ def _system_session (self ) -> _AsyncSessionSystem :
634633 return self ._client .system
635634
636635 @property
@@ -922,8 +921,8 @@ async def cancel(self) -> None:
922921 await self ._channel .cancel ()
923922
924923
925- class AsyncSessionLlm (
926- AsyncSessionModel [
924+ class _AsyncSessionLlm (
925+ _AsyncSessionModel [
927926 "AsyncLLM" ,
928927 LlmLoadModelConfig ,
929928 LlmLoadModelConfigDict ,
@@ -1028,8 +1027,8 @@ async def _apply_prompt_template(
10281027 return response .get ("formatted" , "" ) if response else ""
10291028
10301029
1031- class AsyncSessionEmbedding (
1032- AsyncSessionModel [
1030+ class _AsyncSessionEmbedding (
1031+ _AsyncSessionModel [
10331032 "AsyncEmbeddingModel" ,
10341033 EmbeddingLoadModelConfig ,
10351034 EmbeddingLoadModelConfigDict ,
@@ -1115,7 +1114,7 @@ async def get_context_length(self) -> int:
11151114AnyAsyncModel : TypeAlias = AsyncModelHandle [Any ]
11161115
11171116
1118- class AsyncLLM (AsyncModelHandle [AsyncSessionLlm ]):
1117+ class AsyncLLM (AsyncModelHandle [_AsyncSessionLlm ]):
11191118 """Reference to a loaded LLM model."""
11201119
11211120 @sdk_public_api_async ()
@@ -1258,7 +1257,7 @@ async def apply_prompt_template(
12581257 )
12591258
12601259
1261- class AsyncEmbeddingModel (AsyncModelHandle [AsyncSessionEmbedding ]):
1260+ class AsyncEmbeddingModel (AsyncModelHandle [_AsyncSessionEmbedding ]):
12621261 """Reference to a loaded embedding model."""
12631262
12641263 # Alas, type hints don't properly support distinguishing str vs Iterable[str]:
@@ -1271,24 +1270,17 @@ async def embed(
12711270 return await self ._session ._embed (self .identifier , input )
12721271
12731272
1274- TAsyncSession = TypeVar ("TAsyncSession" , bound = AsyncSession )
1275-
1276- _ASYNC_API_STABILITY_WARNING = """\
1277- Note the async API is not yet stable and is expected to change in future releases
1278- """
1273+ TAsyncSession = TypeVar ("TAsyncSession" , bound = _AsyncSession )
12791274
12801275
12811276class AsyncClient (ClientBase ):
12821277 """Async SDK client interface."""
12831278
12841279 def __init__ (self , api_host : str | None = None ) -> None :
12851280 """Initialize API client."""
1286- # Warn about the async API stability, since we expect it to change
1287- # (in particular, accepting coroutine functions as callbacks)
1288- warnings .warn (_ASYNC_API_STABILITY_WARNING , FutureWarning )
12891281 super ().__init__ (api_host )
12901282 self ._resources = AsyncExitStack ()
1291- self ._sessions : dict [str , AsyncSession ] = {}
1283+ self ._sessions : dict [str , _AsyncSession ] = {}
12921284 self ._task_manager = AsyncTaskManager ()
12931285 # Unlike the sync API, we don't support GC-based resource
12941286 # management in the async API. Structured concurrency
@@ -1301,12 +1293,12 @@ def __init__(self, api_host: str | None = None) -> None:
13011293 # TODO: revisit lazy connections given the task manager implementation
13021294 # (for example, eagerly start tasks for all sessions, and lazily
13031295 # trigger events that allow them to initiate their connection)
1304- _ALL_SESSIONS : tuple [Type [AsyncSession ], ...] = (
1305- AsyncSessionEmbedding ,
1296+ _ALL_SESSIONS : tuple [Type [_AsyncSession ], ...] = (
1297+ _AsyncSessionEmbedding ,
13061298 _AsyncSessionFiles ,
1307- AsyncSessionLlm ,
1308- AsyncSessionRepository ,
1309- AsyncSessionSystem ,
1299+ _AsyncSessionLlm ,
1300+ _AsyncSessionRepository ,
1301+ _AsyncSessionSystem ,
13101302 )
13111303
13121304 async def __aenter__ (self ) -> Self :
@@ -1342,30 +1334,30 @@ def _get_session(self, cls: Type[TAsyncSession]) -> TAsyncSession:
13421334
13431335 @property
13441336 @sdk_public_api ()
1345- def llm (self ) -> AsyncSessionLlm :
1337+ def llm (self ) -> _AsyncSessionLlm :
13461338 """Return the LLM API client session."""
1347- return self ._get_session (AsyncSessionLlm )
1339+ return self ._get_session (_AsyncSessionLlm )
13481340
13491341 @property
13501342 @sdk_public_api ()
1351- def embedding (self ) -> AsyncSessionEmbedding :
1343+ def embedding (self ) -> _AsyncSessionEmbedding :
13521344 """Return the embedding model API client session."""
1353- return self ._get_session (AsyncSessionEmbedding )
1345+ return self ._get_session (_AsyncSessionEmbedding )
13541346
13551347 @property
1356- def system (self ) -> AsyncSessionSystem :
1348+ def system (self ) -> _AsyncSessionSystem :
13571349 """Return the system API client session."""
1358- return self ._get_session (AsyncSessionSystem )
1350+ return self ._get_session (_AsyncSessionSystem )
13591351
13601352 @property
13611353 def files (self ) -> _AsyncSessionFiles :
13621354 """Return the files API client session."""
13631355 return self ._get_session (_AsyncSessionFiles )
13641356
13651357 @property
1366- def repository (self ) -> AsyncSessionRepository :
1358+ def repository (self ) -> _AsyncSessionRepository :
13671359 """Return the repository API client session."""
1368- return self ._get_session (AsyncSessionRepository )
1360+ return self ._get_session (_AsyncSessionRepository )
13691361
13701362 # Convenience methods
13711363 # Not yet implemented (server API only supports the same file types as prepare_image)
0 commit comments