livekit-plugins-groq 0.1.1__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.
@@ -0,0 +1,30 @@
1
+ # Copyright 2023 LiveKit, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from livekit.agents import Plugin
16
+
17
+ from .log import logger
18
+ from .services import LLM, STT
19
+ from .tts import TTS
20
+ from .version import __version__
21
+
22
+ __all__ = ["TTS", "LLM", "STT", "__version__"]
23
+
24
+
25
+ class GroqPlugin(Plugin):
26
+ def __init__(self):
27
+ super().__init__(__name__, __version__, __package__, logger)
28
+
29
+
30
+ Plugin.register_plugin(GroqPlugin())
@@ -0,0 +1,3 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger("livekit.plugins.groq")
@@ -0,0 +1,54 @@
1
+ from typing import Literal
2
+
3
+ # listing production models from https://console.groq.com/docs/models
4
+
5
+ STTModels = Literal[
6
+ "whisper-large-v3",
7
+ "whisper-large-v3-turbo",
8
+ "distil-whisper-large-v3-en",
9
+ ]
10
+
11
+ LLMModels = Literal[
12
+ "llama3-8b-8192",
13
+ "llama3-70b-8192",
14
+ "llama-guard-3-8b",
15
+ "llama-3.1-8b-instant",
16
+ "llama-3.3-70b-versatile",
17
+ ]
18
+
19
+ TTSModels = Literal[
20
+ "playai-tts",
21
+ "playai-tts-arabic",
22
+ ]
23
+
24
+ TTSVoices = Literal[
25
+ "Aaliyah-PlayAI",
26
+ "Abigail-PlayAI",
27
+ "Angelo-PlayAI",
28
+ "Arthur-PlayAI",
29
+ "Aurora-PlayAI",
30
+ "Autumn-PlayAI",
31
+ "Ayla-Meditation-PlayAI",
32
+ "Ayla-Advertising-PlayAI",
33
+ "Bryan-PlayAI",
34
+ "Chuck-PlayAI",
35
+ "Darrell-PlayAI",
36
+ "Dexter-PlayAI",
37
+ "Donovan-PlayAI",
38
+ "Eileen-PlayAI",
39
+ "Eleanor-PlayAI",
40
+ "Erasmo-PlayAI",
41
+ "Hudson-PlayAI",
42
+ "Inara-PlayAI",
43
+ "Luna-PlayAI",
44
+ "Nia-PlayAI",
45
+ "Phoebe-PlayAI",
46
+ "Ranger-PlayAI",
47
+ "Sophia-PlayAI",
48
+ "Waylon-PlayAI",
49
+ "William-Training-PlayAI",
50
+ "Nasser-PlayAI",
51
+ "Khalid-PlayAI",
52
+ "Amira-PlayAI",
53
+ "Ahmad-PlayAI",
54
+ ]
@@ -0,0 +1,80 @@
1
+ import os
2
+ from typing import Literal, Union
3
+
4
+ import openai
5
+ from livekit.agents.llm import ToolChoice
6
+ from livekit.plugins.openai import LLM as OpenAILLM
7
+ from livekit.plugins.openai import STT as OpenAISTT
8
+
9
+ from .models import LLMModels, STTModels
10
+
11
+
12
+ class LLM(OpenAILLM):
13
+ def __init__(
14
+ self,
15
+ *,
16
+ model: str | LLMModels = "llama-3.3-70b-versatile",
17
+ api_key: str | None = None,
18
+ user: str | None = None,
19
+ temperature: float | None = None,
20
+ parallel_tool_calls: bool | None = None,
21
+ tool_choice: Union[ToolChoice, Literal["auto", "required", "none"]] = "auto",
22
+ max_tokens: int | None = None,
23
+ base_url: str | None = "https://api.groq.com/openai/v1",
24
+ client: openai.AsyncClient | None = None,
25
+ ):
26
+ """
27
+ Create a new instance of Groq LLM.
28
+
29
+ ``api_key`` must be set to your Groq API key, either using the argument or by setting
30
+ the ``GROQ_API_KEY`` environmental variable.
31
+ """
32
+ super().__init__(
33
+ model=model,
34
+ api_key=_get_api_key(api_key),
35
+ base_url=base_url,
36
+ client=client,
37
+ user=user,
38
+ temperature=temperature,
39
+ parallel_tool_calls=parallel_tool_calls,
40
+ tool_choice=tool_choice,
41
+ max_tokens=max_tokens,
42
+ )
43
+
44
+
45
+ class STT(OpenAISTT):
46
+ def __init__(
47
+ self,
48
+ *,
49
+ model: STTModels | str = "whisper-large-v3-turbo",
50
+ api_key: str | None = None,
51
+ base_url: str | None = "https://api.groq.com/openai/v1",
52
+ client: openai.AsyncClient | None = None,
53
+ language: str = "en",
54
+ prompt: str | None = None,
55
+ detect_language: bool = False,
56
+ ):
57
+ """
58
+ Create a new instance of Groq STT.
59
+
60
+ ``api_key`` must be set to your Groq API key, either using the argument or by setting
61
+ the ``GROQ_API_KEY`` environmental variable.
62
+ """
63
+ super().__init__(
64
+ model=model,
65
+ api_key=_get_api_key(api_key),
66
+ base_url=base_url,
67
+ client=client,
68
+ language=language,
69
+ detect_language=detect_language,
70
+ prompt=prompt,
71
+ )
72
+
73
+
74
+ def _get_api_key(key: str | None) -> str:
75
+ key = key or os.environ.get("GROQ_API_KEY")
76
+ if not key:
77
+ raise ValueError(
78
+ "GROQ_API_KEY is required, either as argument or set GROQ_API_KEY environmental variable"
79
+ )
80
+ return key
@@ -0,0 +1,212 @@
1
+ # Copyright 2023 LiveKit, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import asyncio
18
+ import os
19
+ from dataclasses import dataclass
20
+ from typing import Optional
21
+
22
+ import aiohttp
23
+ from livekit.agents import (
24
+ APIConnectionError,
25
+ APIConnectOptions,
26
+ APIStatusError,
27
+ APITimeoutError,
28
+ tts,
29
+ utils,
30
+ )
31
+
32
+ from .log import logger
33
+ from .models import TTSModels, TTSVoices
34
+
35
+ DEFAULT_BASE_URL = "https://api.groq.com/openai/v1"
36
+ SAMPLE_RATE = 48000
37
+ NUM_CHANNELS = 1
38
+
39
+
40
+ @dataclass
41
+ class _TTSOptions:
42
+ model: TTSModels | str
43
+ voice: TTSVoices | str
44
+ api_key: str
45
+ base_url: str
46
+
47
+
48
+ class TTS(tts.TTS):
49
+ def __init__(
50
+ self,
51
+ *,
52
+ base_url: str | None = None,
53
+ model: TTSModels | str = "playai-tts",
54
+ voice: TTSVoices | str = "Eileen-PlayAI",
55
+ api_key: str | None = None,
56
+ http_session: aiohttp.ClientSession | None = None,
57
+ ) -> None:
58
+ """
59
+ Create a new instance of Groq TTS.
60
+
61
+ if `api_key` is not provided, it will be read from the ``GROQ_API_KEY``
62
+ environmental variable.
63
+
64
+ Args:
65
+ model (SpeechModels | str, optional): Model to use. Default is "playai-tts".
66
+ voice (SpeechVoices | str, optional): Voice to use. Default is "Autumn-PlayAI".
67
+ api_key (str | None, optional): API key to use. Default is None.
68
+ """
69
+
70
+ super().__init__(
71
+ capabilities=tts.TTSCapabilities(
72
+ streaming=False,
73
+ ),
74
+ sample_rate=SAMPLE_RATE,
75
+ num_channels=1,
76
+ )
77
+
78
+ self._session = http_session
79
+
80
+ if not base_url:
81
+ base_url = DEFAULT_BASE_URL
82
+
83
+ if not api_key:
84
+ api_key = os.getenv("GROQ_API_KEY")
85
+ if not api_key:
86
+ raise ValueError("GROQ_API_KEY is not set")
87
+
88
+ self._opts = _TTSOptions(
89
+ model=model,
90
+ voice=voice,
91
+ api_key=api_key,
92
+ base_url=base_url,
93
+ )
94
+
95
+ def _ensure_session(self) -> aiohttp.ClientSession:
96
+ if not self._session:
97
+ self._session = utils.http_context.http_session()
98
+
99
+ return self._session
100
+
101
+ def update_options(
102
+ self,
103
+ *,
104
+ model: TTSModels | None = None,
105
+ voice: TTSVoices | None = None,
106
+ ) -> None:
107
+ """
108
+ Update the TTS options.
109
+
110
+ Args:
111
+ model (SpeechModels | str, optional): Model to use. Default is None.
112
+ voice (SpeechVoices | str, optional): Voice to use. Default is None.
113
+ """
114
+ if model:
115
+ self._opts.model = model
116
+ if voice:
117
+ self._opts.voice = voice
118
+
119
+ def synthesize(
120
+ self,
121
+ text: str,
122
+ *,
123
+ conn_options: Optional[APIConnectOptions] = None,
124
+ segment_id: str | None = None,
125
+ ) -> "ChunkedStream":
126
+ return ChunkedStream(
127
+ tts=self,
128
+ input_text=text,
129
+ conn_options=conn_options,
130
+ opts=self._opts,
131
+ session=self._ensure_session(),
132
+ segment_id=segment_id,
133
+ )
134
+
135
+
136
+ class ChunkedStream(tts.ChunkedStream):
137
+ def __init__(
138
+ self,
139
+ *,
140
+ tts: TTS,
141
+ input_text: str,
142
+ conn_options: Optional[APIConnectOptions] = None,
143
+ opts: _TTSOptions,
144
+ session: aiohttp.ClientSession,
145
+ segment_id: str | None = None,
146
+ ) -> None:
147
+ super().__init__(tts=tts, input_text=input_text, conn_options=conn_options)
148
+ self._opts = opts
149
+ self._session = session
150
+ self._segment_id = segment_id
151
+
152
+ async def _run(self) -> None:
153
+ request_id = utils.shortuuid()
154
+ headers = {
155
+ "Authorization": f"Bearer {self._opts.api_key}",
156
+ "Content-Type": "application/json",
157
+ }
158
+ payload = {
159
+ "model": self._opts.model,
160
+ "voice": self._opts.voice,
161
+ "input": self._input_text,
162
+ "response_format": "wav",
163
+ }
164
+
165
+ decoder = utils.codecs.AudioStreamDecoder(
166
+ sample_rate=SAMPLE_RATE,
167
+ num_channels=NUM_CHANNELS,
168
+ )
169
+
170
+ decode_task: Optional[asyncio.Task] = None
171
+ api_url = f"{self._opts.base_url}/audio/speech"
172
+ try:
173
+ async with self._session.post(
174
+ api_url, headers=headers, json=payload
175
+ ) as response:
176
+ if not response.content_type.startswith("audio"):
177
+ content = await response.text()
178
+ logger.error("Groq returned non-audio data: %s", content)
179
+ return
180
+
181
+ async def _decode_loop():
182
+ try:
183
+ async for bytes_data, _ in response.content.iter_chunks():
184
+ decoder.push(bytes_data)
185
+ finally:
186
+ decoder.end_input()
187
+
188
+ decode_task = asyncio.create_task(_decode_loop())
189
+ emitter = tts.SynthesizedAudioEmitter(
190
+ event_ch=self._event_ch,
191
+ request_id=request_id,
192
+ segment_id=self._segment_id,
193
+ )
194
+ async for frame in decoder:
195
+ emitter.push(frame)
196
+ emitter.flush()
197
+
198
+ except asyncio.TimeoutError as e:
199
+ raise APITimeoutError() from e
200
+ except aiohttp.ClientResponseError as e:
201
+ raise APIStatusError(
202
+ message=e.message,
203
+ status_code=e.status,
204
+ request_id=request_id,
205
+ body=None,
206
+ ) from e
207
+ except Exception as e:
208
+ raise APIConnectionError() from e
209
+ finally:
210
+ if decode_task:
211
+ await utils.aio.gracefully_cancel(decode_task)
212
+ await decoder.aclose()
@@ -0,0 +1,15 @@
1
+ # Copyright 2023 LiveKit, Inc.
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ __version__ = "0.1.1"
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: livekit-plugins-groq
3
+ Version: 0.1.1
4
+ Summary: Groq inference plugin for LiveKit
5
+ Home-page: https://github.com/livekit/agents
6
+ License: Apache-2.0
7
+ Project-URL: Documentation, https://docs.livekit.io
8
+ Project-URL: Website, https://livekit.io/
9
+ Project-URL: Source, https://github.com/livekit/agents
10
+ Keywords: groq,llm,stt,tts,webrtc,livekit
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Topic :: Multimedia :: Sound/Audio
14
+ Classifier: Topic :: Multimedia :: Video
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Requires-Python: >=3.9.0
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: livekit-agents<1.0.0,>=0.12.16
23
+ Requires-Dist: livekit-plugins-openai<1.0.0,>=0.11.2
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: home-page
28
+ Dynamic: keywords
29
+ Dynamic: license
30
+ Dynamic: project-url
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # LiveKit Plugins Groq
36
+
37
+ Agent Framework plugin for services from Groq. Currently supporting STT, and LLM
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install livekit-plugins-groq
43
+ ```
44
+
45
+ ## Pre-requisites
46
+
47
+ For credentials, you'll need a Groq Cloud account and obtain the correct credentials. Credentials can be passed directly or via GROQ_API_KEY environment variable
@@ -0,0 +1,10 @@
1
+ livekit/plugins/groq/__init__.py,sha256=3FCdFGFsZtZnoWLJfPQPh8tzt44chzmrpXzCckIldGg,930
2
+ livekit/plugins/groq/log.py,sha256=nCRNT6C52cMuAbBzdH15Fz933CLPZNkSZ1JPJyVdI1Y,67
3
+ livekit/plugins/groq/models.py,sha256=TyU9m3NrdtZi7UxgiKPgNGiZIsJiJQLdtbZkQEqzDAU,1086
4
+ livekit/plugins/groq/services.py,sha256=5vZv9E8UkrGpFyI5oFcddfks38MHpfTHm5VmIbvQEqA,2472
5
+ livekit/plugins/groq/tts.py,sha256=ZKNox2WI3PzPGS0HFtcIHSz4oLEx4F45udtC-fL6vBE,6315
6
+ livekit/plugins/groq/version.py,sha256=IK31lfqSqfmET1Eqg7jx5fIpK4f_5uvSS80S-StV7zA,599
7
+ livekit_plugins_groq-0.1.1.dist-info/METADATA,sha256=T2tTOhRl5PDp5aJ2ybdgp2s5yyKaaw-ap5cUojAhkeM,1564
8
+ livekit_plugins_groq-0.1.1.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
9
+ livekit_plugins_groq-0.1.1.dist-info/top_level.txt,sha256=OoDok3xUmXbZRvOrfvvXB-Juu4DX79dlq188E19YHoo,8
10
+ livekit_plugins_groq-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (77.0.3)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ livekit