livekit-plugins-aws 1.0.21__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.
- livekit/plugins/aws/llm.py +5 -5
- livekit/plugins/aws/stt.py +36 -46
- livekit/plugins/aws/tts.py +5 -5
- livekit/plugins/aws/utils.py +1 -32
- livekit/plugins/aws/version.py +1 -1
- {livekit_plugins_aws-1.0.21.dist-info → livekit_plugins_aws-1.0.22.dist-info}/METADATA +2 -3
- livekit_plugins_aws-1.0.22.dist-info/RECORD +12 -0
- livekit_plugins_aws-1.0.21.dist-info/RECORD +0 -12
- {livekit_plugins_aws-1.0.21.dist-info → livekit_plugins_aws-1.0.22.dist-info}/WHEEL +0 -0
livekit/plugins/aws/llm.py
CHANGED
|
@@ -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
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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")
|
livekit/plugins/aws/stt.py
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
136
|
+
self._client = client
|
|
154
137
|
|
|
155
138
|
async def _run(self) -> None:
|
|
156
|
-
|
|
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
|
|
156
|
+
stream = await self._client.start_stream_transcription(**filtered_config)
|
|
174
157
|
|
|
175
|
-
|
|
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
|
-
|
|
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
|
|
livekit/plugins/aws/tts.py
CHANGED
|
@@ -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
|
|
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
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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,
|
livekit/plugins/aws/utils.py
CHANGED
|
@@ -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"
|
|
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
|
|
livekit/plugins/aws/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: livekit-plugins-aws
|
|
3
|
-
Version: 1.0.
|
|
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/
|
|
@@ -20,8 +20,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
20
20
|
Requires-Python: >=3.9.0
|
|
21
21
|
Requires-Dist: aioboto3>=14.1.0
|
|
22
22
|
Requires-Dist: amazon-transcribe>=0.6.2
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist: livekit-agents>=1.0.21
|
|
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=5lzQkS1jEPqreexacwMd18b2EOx7R5m8AQMKtQRBgC4,601
|
|
10
|
-
livekit_plugins_aws-1.0.21.dist-info/METADATA,sha256=Q0ybhRgmTwtyDysQpsFl1Ql4RlckArFXQypR68urjjM,1560
|
|
11
|
-
livekit_plugins_aws-1.0.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
-
livekit_plugins_aws-1.0.21.dist-info/RECORD,,
|
|
File without changes
|