livekit-plugins-aws 1.0.20__py3-none-any.whl → 1.0.22__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 livekit-plugins-aws might be problematic. Click here for more details.

@@ -31,7 +31,7 @@ from livekit.agents.types import (
31
31
  from livekit.agents.utils import is_given
32
32
 
33
33
  from .log import logger
34
- from .utils import get_aws_async_session, to_chat_ctx, to_fnc_ctx
34
+ from .utils import to_chat_ctx, to_fnc_ctx
35
35
 
36
36
  TEXT_MODEL = Literal["anthropic.claude-3-5-sonnet-20241022-v2:0"]
37
37
 
@@ -83,10 +83,10 @@ class LLM(llm.LLM):
83
83
  """ # noqa: E501
84
84
  super().__init__()
85
85
 
86
- self._session = session or get_aws_async_session(
87
- api_key=api_key if is_given(api_key) else None,
88
- api_secret=api_secret if is_given(api_secret) else None,
89
- region=region if is_given(region) else None,
86
+ self._session = session or aioboto3.Session(
87
+ aws_access_key_id=api_key if is_given(api_key) else None,
88
+ aws_secret_access_key=api_secret if is_given(api_secret) else None,
89
+ region_name=region if is_given(region) else None,
90
90
  )
91
91
 
92
92
  model = model if is_given(model) else os.environ.get("BEDROCK_INFERENCE_PROFILE_ARN")
@@ -13,22 +13,26 @@
13
13
  from __future__ import annotations
14
14
 
15
15
  import asyncio
16
+ import os
16
17
  from dataclasses import dataclass
17
18
 
18
- import aioboto3
19
- from amazon_transcribe.auth import StaticCredentialResolver
19
+ from amazon_transcribe.auth import AwsCrtCredentialResolver
20
20
  from amazon_transcribe.client import TranscribeStreamingClient
21
- from amazon_transcribe.model import Result, TranscriptEvent
21
+ from amazon_transcribe.exceptions import BadRequestException
22
+ from amazon_transcribe.model import Result, StartStreamTranscriptionEventStream, TranscriptEvent
22
23
 
23
24
  from livekit import rtc
24
- from livekit.agents import DEFAULT_API_CONNECT_OPTIONS, APIConnectOptions, stt, utils
25
+ from livekit.agents import (
26
+ DEFAULT_API_CONNECT_OPTIONS,
27
+ APIConnectOptions,
28
+ stt,
29
+ utils,
30
+ )
25
31
  from livekit.agents.types import NOT_GIVEN, NotGivenOr
26
32
  from livekit.agents.utils import is_given
27
33
 
28
34
  from .log import logger
29
- from .utils import DEFAULT_REGION, get_aws_async_session
30
-
31
- REFRESH_INTERVAL = 1800
35
+ from .utils import DEFAULT_REGION
32
36
 
33
37
 
34
38
  @dataclass
@@ -53,9 +57,7 @@ class STT(stt.STT):
53
57
  self,
54
58
  *,
55
59
  region: NotGivenOr[str] = NOT_GIVEN,
56
- api_key: NotGivenOr[str] = NOT_GIVEN,
57
- api_secret: NotGivenOr[str] = NOT_GIVEN,
58
- sample_rate: int = 48000,
60
+ sample_rate: int = 24000,
59
61
  language: str = "en-US",
60
62
  encoding: str = "pcm",
61
63
  vocabulary_name: NotGivenOr[str] = NOT_GIVEN,
@@ -68,15 +70,15 @@ class STT(stt.STT):
68
70
  enable_partial_results_stabilization: NotGivenOr[bool] = NOT_GIVEN,
69
71
  partial_results_stability: NotGivenOr[str] = NOT_GIVEN,
70
72
  language_model_name: NotGivenOr[str] = NOT_GIVEN,
71
- session: aioboto3.Session | None = None,
72
- refresh_interval: NotGivenOr[int] = NOT_GIVEN,
73
73
  ):
74
74
  super().__init__(capabilities=stt.STTCapabilities(streaming=True, interim_results=True))
75
- self._region = region if is_given(region) else DEFAULT_REGION
76
- self._session = session or get_aws_async_session(
77
- api_key=api_key if is_given(api_key) else None,
78
- api_secret=api_secret if is_given(api_secret) else None,
75
+
76
+ if not is_given(region):
77
+ region = os.getenv("AWS_REGION") or DEFAULT_REGION
78
+ self._region = region
79
+ self._client = TranscribeStreamingClient(
79
80
  region=self._region,
81
+ credential_resolver=AwsCrtCredentialResolver(None),
80
82
  )
81
83
 
82
84
  self._config = STTOptions(
@@ -94,27 +96,8 @@ class STT(stt.STT):
94
96
  partial_results_stability=partial_results_stability,
95
97
  language_model_name=language_model_name,
96
98
  )
97
- self._pool = utils.ConnectionPool[TranscribeStreamingClient](
98
- connect_cb=self._create_client,
99
- max_session_duration=refresh_interval
100
- if is_given(refresh_interval)
101
- else REFRESH_INTERVAL,
102
- )
103
-
104
- async def _create_client(self) -> TranscribeStreamingClient:
105
- creds = await self._session.get_credentials()
106
- frozen_credentials = await creds.get_frozen_credentials()
107
- return TranscribeStreamingClient(
108
- region=self._region,
109
- credential_resolver=StaticCredentialResolver(
110
- access_key_id=frozen_credentials.access_key,
111
- secret_access_key=frozen_credentials.secret_key,
112
- session_token=frozen_credentials.token,
113
- ),
114
- )
115
99
 
116
100
  async def aclose(self) -> None:
117
- await self._pool.aclose()
118
101
  await super().aclose()
119
102
 
120
103
  async def _recognize_impl(
@@ -134,7 +117,7 @@ class STT(stt.STT):
134
117
  ) -> SpeechStream:
135
118
  return SpeechStream(
136
119
  stt=self,
137
- pool=self._pool,
120
+ client=self._client,
138
121
  conn_options=conn_options,
139
122
  opts=self._config,
140
123
  )
@@ -145,15 +128,15 @@ class SpeechStream(stt.SpeechStream):
145
128
  self,
146
129
  stt: STT,
147
130
  opts: STTOptions,
148
- pool: utils.ConnectionPool[TranscribeStreamingClient],
131
+ client: TranscribeStreamingClient,
149
132
  conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
150
133
  ) -> None:
151
134
  super().__init__(stt=stt, conn_options=conn_options, sample_rate=opts.sample_rate)
152
135
  self._opts = opts
153
- self._pool = pool
136
+ self._client = client
154
137
 
155
138
  async def _run(self) -> None:
156
- async with self._pool.connection() as client:
139
+ while True:
157
140
  live_config = {
158
141
  "language_code": self._opts.language,
159
142
  "media_sample_rate_hz": self._opts.sample_rate,
@@ -170,27 +153,34 @@ class SpeechStream(stt.SpeechStream):
170
153
  "language_model_name": self._opts.language_model_name,
171
154
  }
172
155
  filtered_config = {k: v for k, v in live_config.items() if v and is_given(v)}
173
- stream = await client.start_stream_transcription(**filtered_config)
156
+ stream = await self._client.start_stream_transcription(**filtered_config)
174
157
 
175
- @utils.log_exceptions(logger=logger)
176
- async def input_generator():
158
+ async def input_generator(stream: StartStreamTranscriptionEventStream):
177
159
  async for frame in self._input_ch:
178
160
  if isinstance(frame, rtc.AudioFrame):
179
161
  await stream.input_stream.send_audio_event(audio_chunk=frame.data.tobytes())
180
162
  await stream.input_stream.end_stream()
181
163
 
182
- @utils.log_exceptions(logger=logger)
183
- async def handle_transcript_events():
164
+ async def handle_transcript_events(stream: StartStreamTranscriptionEventStream):
184
165
  async for event in stream.output_stream:
185
166
  if isinstance(event, TranscriptEvent):
186
167
  self._process_transcript_event(event)
187
168
 
188
169
  tasks = [
189
- asyncio.create_task(input_generator()),
190
- asyncio.create_task(handle_transcript_events()),
170
+ asyncio.create_task(input_generator(stream)),
171
+ asyncio.create_task(handle_transcript_events(stream)),
191
172
  ]
192
173
  try:
193
174
  await asyncio.gather(*tasks)
175
+ except BadRequestException as e:
176
+ if e.message and e.message.startswith("Your request timed out"):
177
+ # AWS times out after 15s of inactivity, this tends to happen
178
+ # at the end of the session, when the input is gone, we'll ignore it and
179
+ # just treat it as a silent retry
180
+ logger.info("restarting transcribe session")
181
+ continue
182
+ else:
183
+ raise e
194
184
  finally:
195
185
  await utils.aio.gracefully_cancel(*tasks)
196
186
 
@@ -34,7 +34,7 @@ from livekit.agents.types import (
34
34
  from livekit.agents.utils import is_given
35
35
 
36
36
  from .models import TTS_LANGUAGE, TTS_SPEECH_ENGINE
37
- from .utils import _strip_nones, get_aws_async_session
37
+ from .utils import _strip_nones
38
38
 
39
39
  TTS_NUM_CHANNELS: int = 1
40
40
  DEFAULT_SPEECH_ENGINE: TTS_SPEECH_ENGINE = "generative"
@@ -90,10 +90,10 @@ class TTS(tts.TTS):
90
90
  sample_rate=sample_rate,
91
91
  num_channels=TTS_NUM_CHANNELS,
92
92
  )
93
- self._session = session or get_aws_async_session(
94
- api_key=api_key if is_given(api_key) else None,
95
- api_secret=api_secret if is_given(api_secret) else None,
96
- region=region if is_given(region) else None,
93
+ self._session = session or aioboto3.Session(
94
+ aws_access_key_id=api_key if is_given(api_key) else None,
95
+ aws_secret_access_key=api_secret if is_given(api_secret) else None,
96
+ region_name=region if is_given(region) else None,
97
97
  )
98
98
  self._opts = _TTSOptions(
99
99
  voice=voice,
@@ -3,44 +3,13 @@ from __future__ import annotations
3
3
  import json
4
4
  from typing import Any
5
5
 
6
- import aioboto3
7
- import boto3
8
- from botocore.exceptions import NoCredentialsError
9
-
10
6
  from livekit.agents import llm
11
7
  from livekit.agents.llm import ChatContext, FunctionTool, ImageContent, utils
12
8
 
13
- __all__ = ["to_fnc_ctx", "to_chat_ctx", "get_aws_async_session"]
9
+ __all__ = ["to_fnc_ctx", "to_chat_ctx"]
14
10
  DEFAULT_REGION = "us-east-1"
15
11
 
16
12
 
17
- def get_aws_async_session(
18
- region: str | None = None,
19
- api_key: str | None = None,
20
- api_secret: str | None = None,
21
- ) -> aioboto3.Session:
22
- _validate_aws_credentials(api_key, api_secret)
23
- session = aioboto3.Session(
24
- aws_access_key_id=api_key,
25
- aws_secret_access_key=api_secret,
26
- region_name=region or DEFAULT_REGION,
27
- )
28
- return session
29
-
30
-
31
- def _validate_aws_credentials(
32
- api_key: str | None = None,
33
- api_secret: str | None = None,
34
- ) -> None:
35
- try:
36
- session = boto3.Session(aws_access_key_id=api_key, aws_secret_access_key=api_secret)
37
- creds = session.get_credentials()
38
- if not creds:
39
- raise ValueError("No credentials found")
40
- except (NoCredentialsError, Exception) as e:
41
- raise ValueError(f"Unable to locate valid AWS credentials: {str(e)}") from e
42
-
43
-
44
13
  def to_fnc_ctx(fncs: list[FunctionTool]) -> list[dict]:
45
14
  return [_build_tool_spec(fnc) for fnc in fncs]
46
15
 
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "1.0.20"
15
+ __version__ = "1.0.22"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: livekit-plugins-aws
3
- Version: 1.0.20
3
+ Version: 1.0.22
4
4
  Summary: LiveKit Agents Plugin for services from AWS
5
5
  Project-URL: Documentation, https://docs.livekit.io
6
6
  Project-URL: Website, https://livekit.io/
@@ -18,10 +18,9 @@ Classifier: Topic :: Multimedia :: Sound/Audio
18
18
  Classifier: Topic :: Multimedia :: Video
19
19
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
20
  Requires-Python: >=3.9.0
21
- Requires-Dist: aioboto3==14.1.0
22
- Requires-Dist: amazon-transcribe==0.6.2
23
- Requires-Dist: boto3==1.37.1
24
- Requires-Dist: livekit-agents>=1.0.20
21
+ Requires-Dist: aioboto3>=14.1.0
22
+ Requires-Dist: amazon-transcribe>=0.6.2
23
+ Requires-Dist: livekit-agents>=1.0.22
25
24
  Description-Content-Type: text/markdown
26
25
 
27
26
  # AWS plugin for LiveKit Agents
@@ -0,0 +1,12 @@
1
+ livekit/plugins/aws/__init__.py,sha256=fkbgTfNZc6z4VxbYGNdY73EoGvNuRcJiuD-OlUHvjHU,1322
2
+ livekit/plugins/aws/llm.py,sha256=Z9FFjAZPKgX3NKE7J2rUBUVul-T-3sIHIl5W4b0bzLs,11249
3
+ livekit/plugins/aws/log.py,sha256=jFief0Xhv0n_F6sp6UFu9VKxs2bXNVGAfYGmEYfR_2Q,66
4
+ livekit/plugins/aws/models.py,sha256=Nf8RFmDulW7h03dG2lERTog3mgDK0TbLvW0eGOncuEE,704
5
+ livekit/plugins/aws/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ livekit/plugins/aws/stt.py,sha256=JzCRxLec7ZbbNHUbjLl5PgzgvZBppeprQMmb_U5EpAI,8946
7
+ livekit/plugins/aws/tts.py,sha256=iO4lBO1ggE2OBN5j54novJnwPa8GhyW0wiY-Xj8VDEk,7336
8
+ livekit/plugins/aws/utils.py,sha256=UcKrSYrZf7SKYua1F51KZHskXRC5L5h-_WpFoPWLowo,4037
9
+ livekit/plugins/aws/version.py,sha256=-8dkOE2vDSF9WN8VoBrSwU2sb5YBGFuwPnSQXQ-uaYM,601
10
+ livekit_plugins_aws-1.0.22.dist-info/METADATA,sha256=Que989diZatTKKrH49PHZnNtletiCi6nt7uxJtPqT_8,1531
11
+ livekit_plugins_aws-1.0.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ livekit_plugins_aws-1.0.22.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- livekit/plugins/aws/__init__.py,sha256=fkbgTfNZc6z4VxbYGNdY73EoGvNuRcJiuD-OlUHvjHU,1322
2
- livekit/plugins/aws/llm.py,sha256=k9RTldvqg3uFW36jjBrrT0pdMyJJH_88RwI--0f10Pw,11251
3
- livekit/plugins/aws/log.py,sha256=jFief0Xhv0n_F6sp6UFu9VKxs2bXNVGAfYGmEYfR_2Q,66
4
- livekit/plugins/aws/models.py,sha256=Nf8RFmDulW7h03dG2lERTog3mgDK0TbLvW0eGOncuEE,704
5
- livekit/plugins/aws/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- livekit/plugins/aws/stt.py,sha256=FgZ0hN-ToqQRzesdV28GNkHw_x2X_sFugji_BnLXm7c,9448
7
- livekit/plugins/aws/tts.py,sha256=-YK_jgJxQUG5LKHNeqTfjOm6fQhoEEbHps300goTtMQ,7338
8
- livekit/plugins/aws/utils.py,sha256=BqZPyLr-xETbGybhE3-lEJovqkuCuAd-cxtUO3aFAVM,4988
9
- livekit/plugins/aws/version.py,sha256=t4KmPVTpEy1pOJ2GRCA-GNJfCQq_-zHNDBxGj4GKfVk,601
10
- livekit_plugins_aws-1.0.20.dist-info/METADATA,sha256=JThAx7JyHInOgQHgs92i1BKypGnYZQCWa11rE2Eayg0,1560
11
- livekit_plugins_aws-1.0.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- livekit_plugins_aws-1.0.20.dist-info/RECORD,,