livellm 1.3.0__py3-none-any.whl → 1.3.6__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.
livellm/livellm.py CHANGED
@@ -493,7 +493,8 @@ class LivellmWsClient(BaseLivellmClient):
493
493
  def __init__(
494
494
  self,
495
495
  base_url: str,
496
- timeout: Optional[float] = None
496
+ timeout: Optional[float] = None,
497
+ max_size: Optional[int] = None
497
498
  ):
498
499
  # Convert HTTP(S) URL to WS(S) URL
499
500
  base_url = base_url.rstrip("/")
@@ -511,6 +512,7 @@ class LivellmWsClient(BaseLivellmClient):
511
512
  self.websocket = None
512
513
  # Lazily-created clients
513
514
  self._transcription = None
515
+ self.max_size = max_size or 1024 * 1024 * 10 # 10MB is default max size
514
516
 
515
517
  async def connect(self):
516
518
  """Establish WebSocket connection."""
@@ -520,7 +522,8 @@ class LivellmWsClient(BaseLivellmClient):
520
522
  self.websocket = await websockets.connect(
521
523
  self.base_url,
522
524
  open_timeout=self.timeout,
523
- close_timeout=self.timeout
525
+ close_timeout=self.timeout,
526
+ max_size=self.max_size
524
527
  )
525
528
 
526
529
  return self.websocket
@@ -561,11 +564,11 @@ class LivellmWsClient(BaseLivellmClient):
561
564
 
562
565
  if response.status == WsStatus.ERROR:
563
566
  raise Exception(f"WebSocket stream failed: {response.error}")
564
-
565
- yield response
566
-
567
+
567
568
  if response.status == WsStatus.SUCCESS:
568
569
  break
570
+
571
+ yield response
569
572
 
570
573
  # Implement abstract methods from BaseLivellmClient
571
574
 
@@ -28,9 +28,17 @@ class EncodedSpeakResponse(BaseModel):
28
28
  content_type: SpeakMimeType = Field(..., description="The content type of the audio")
29
29
  sample_rate: int = Field(..., description="The sample rate of the audio")
30
30
 
31
- @field_validator('audio', mode='after')
31
+ @field_validator("audio", mode="after")
32
32
  @classmethod
33
33
  def validate_audio(cls, v: bytes | str) -> bytes:
34
- if isinstance(v, bytes):
35
- return base64.b64decode(v) # decode from base64 string to bytes
36
- return v # if bytes, assume it's already a base64 decoded bytes
34
+ """
35
+ Ensure that `audio` is always returned as raw bytes.
36
+
37
+ - If the server returns a base64-encoded *string*, decode it.
38
+ - If the server already returned raw bytes, pass them through.
39
+ """
40
+ if isinstance(v, str):
41
+ # Server sent base64-encoded string → decode to raw bytes
42
+ return base64.b64decode(v)
43
+ # Already bytes → assume it's raw audio
44
+ return v
livellm/transcripton.py CHANGED
@@ -10,11 +10,12 @@ import json
10
10
 
11
11
 
12
12
  class TranscriptionWsClient:
13
- def __init__(self, base_url: str, timeout: Optional[float] = None):
13
+ def __init__(self, base_url: str, timeout: Optional[float] = None, max_size: Optional[int] = None):
14
14
  self.base_url = base_url.rstrip("/")
15
15
  self.url = f"{base_url}/livellm/ws/transcription"
16
16
  self.timeout = timeout
17
17
  self.websocket = None
18
+ self.max_size = max_size or 1024 * 1024 * 10 # 10MB is default max size
18
19
 
19
20
  async def connect(self):
20
21
  """
@@ -23,7 +24,8 @@ class TranscriptionWsClient:
23
24
  self.websocket = await websockets.connect(
24
25
  self.url,
25
26
  open_timeout=self.timeout,
26
- close_timeout=self.timeout
27
+ close_timeout=self.timeout,
28
+ max_size=self.max_size
27
29
  )
28
30
 
29
31
  async def disconnect(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: livellm
3
- Version: 1.3.0
3
+ Version: 1.3.6
4
4
  Summary: Python client for the LiveLLM Server
5
5
  Project-URL: Homepage, https://github.com/qalby-tech/livellm-client-py
6
6
  Project-URL: Repository, https://github.com/qalby-tech/livellm-client-py
@@ -1,7 +1,7 @@
1
1
  livellm/__init__.py,sha256=p2Szx7PELGYi-PTnSNnRPGVbU438ZBTFXYAQoMToUfE,440
2
- livellm/livellm.py,sha256=tbkMZFhl46Mbp-gJFsRBxahXU35wyVYmcDH1bAtnUPc,32135
2
+ livellm/livellm.py,sha256=Z3UpG8rxQXTW9qT4EPi6b7qOx3xHL-i-Mz5fKX24QPM,32303
3
3
  livellm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- livellm/transcripton.py,sha256=4BVCzhm304aqv81BDWAvYYKqxJ1YJU7r7POLbbXFhpk,4047
4
+ livellm/transcripton.py,sha256=2ttPzc8A6uQL5VouLLb4aj7Q-cMCx3V1HXH2qhpUMfM,4195
5
5
  livellm/models/__init__.py,sha256=tCX_Q3ALjO0jbqhLFsVoITSm1AV--3pF5ZZc_l0VC1o,1447
6
6
  livellm/models/common.py,sha256=YqRwP6ChWbRdoen4MU6RO4u6HeM0mQJbXiiRV4DuauM,1740
7
7
  livellm/models/fallback.py,sha256=zGG_MjdbaTx0fqKZTEg3ullej-CJznPfwaon0jEvRvI,1170
@@ -12,9 +12,9 @@ livellm/models/agent/agent.py,sha256=-UcGv5Bzw5ALmWX4lIqpbWqMVjCsjBc0KIE6_JKbCXM
12
12
  livellm/models/agent/chat.py,sha256=zGfeEHx0luwq23pqWF1megcuEDUl6IhV4keLJeZry_A,1028
13
13
  livellm/models/agent/tools.py,sha256=wVWfx6_jxL3IcmX_Nt_PonZ3RQLtpfqJnszHz32BQiU,1403
14
14
  livellm/models/audio/__init__.py,sha256=sz2NxCOfFGVvp-XQUsdgOR_TYBO1Wb-8LLXaZDEiAZk,282
15
- livellm/models/audio/speak.py,sha256=ZOHmTfQsqbm-8Nb2Ee1SfNpCbwxk-Mcvm6Km1W63ymA,1617
15
+ livellm/models/audio/speak.py,sha256=lDITZ7fiLRuDhA-LxCPQ6Yraxr33B6Lg7VyR4CkuGk8,1872
16
16
  livellm/models/audio/transcribe.py,sha256=Leji2lk5zfq4GE-fw-z2dZR8BuijzW8TJ12GHw_UZJY,2085
17
- livellm-1.3.0.dist-info/METADATA,sha256=c1sJdLRtKRKWn7e6ZPRaE2ITROHC8DLDVJ_tovZqMMc,18701
18
- livellm-1.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
- livellm-1.3.0.dist-info/licenses/LICENSE,sha256=yapGO2C_00ymEx6TADdbU8Oyc1bWOrZY-fjP-agmFL4,1071
20
- livellm-1.3.0.dist-info/RECORD,,
17
+ livellm-1.3.6.dist-info/METADATA,sha256=e7TYTCh3xtNS8POgIxe4gADiBS2a_cs6IlL6by0kJsw,18701
18
+ livellm-1.3.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
+ livellm-1.3.6.dist-info/licenses/LICENSE,sha256=yapGO2C_00ymEx6TADdbU8Oyc1bWOrZY-fjP-agmFL4,1071
20
+ livellm-1.3.6.dist-info/RECORD,,