livekit-plugins-volcenginee 1.3.7__tar.gz → 1.3.9__tar.gz
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.
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/PKG-INFO +1 -1
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/llm.py +44 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/stt.py +40 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/tts.py +42 -0
- livekit_plugins_volcenginee-1.3.9/livekit/plugins/volcengine/version.py +1 -0
- livekit_plugins_volcenginee-1.3.7/livekit/plugins/volcengine/version.py +0 -1
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/.gitignore +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/README.md +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/__init__.py +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/log.py +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/py.typed +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/realtime.py +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/livekit/plugins/volcengine/utils.py +0 -0
- {livekit_plugins_volcenginee-1.3.7 → livekit_plugins_volcenginee-1.3.9}/pyproject.toml +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import os
|
|
5
|
+
import time
|
|
4
6
|
from dataclasses import dataclass
|
|
5
7
|
from typing import Any, Literal
|
|
6
8
|
|
|
@@ -110,6 +112,48 @@ class LLM(llm.LLM):
|
|
|
110
112
|
),
|
|
111
113
|
)
|
|
112
114
|
|
|
115
|
+
self._prewarm_task: asyncio.Task[None] | None = None
|
|
116
|
+
|
|
117
|
+
def prewarm(self) -> None:
|
|
118
|
+
"""Issue a tiny 1-token chat completion to warm the model and prime
|
|
119
|
+
the HTTP connection.
|
|
120
|
+
|
|
121
|
+
Doubao's first call typically pays 1–3 s of model warm-up cost; a
|
|
122
|
+
discardable 1-token call ahead of the first real turn hides that
|
|
123
|
+
cost from the per-turn TTFT — the single largest knob for first-turn
|
|
124
|
+
latency on this plugin. The cost is ~5–10 tokens per session start.
|
|
125
|
+
|
|
126
|
+
Mirrors the ``connection_pool.prewarm`` convention: schedule a
|
|
127
|
+
background task and return immediately.
|
|
128
|
+
"""
|
|
129
|
+
if self._prewarm_task is not None and not self._prewarm_task.done():
|
|
130
|
+
return
|
|
131
|
+
try:
|
|
132
|
+
loop = asyncio.get_running_loop()
|
|
133
|
+
except RuntimeError:
|
|
134
|
+
logger.debug("llm prewarm skipped: no running event loop")
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
model = self._opts.model
|
|
138
|
+
|
|
139
|
+
async def _impl() -> None:
|
|
140
|
+
t0 = time.perf_counter()
|
|
141
|
+
try:
|
|
142
|
+
await self._client.chat.completions.create(
|
|
143
|
+
model=model,
|
|
144
|
+
messages=[{"role": "user", "content": "hi"}],
|
|
145
|
+
max_tokens=1,
|
|
146
|
+
stream=False,
|
|
147
|
+
)
|
|
148
|
+
logger.info(
|
|
149
|
+
"llm prewarm: warmup call completed in %.0f ms",
|
|
150
|
+
(time.perf_counter() - t0) * 1000,
|
|
151
|
+
)
|
|
152
|
+
except Exception as exc: # noqa: BLE001
|
|
153
|
+
logger.warning("llm prewarm failed: %s", exc)
|
|
154
|
+
|
|
155
|
+
self._prewarm_task = loop.create_task(_impl(), name="volcengine.llm.prewarm")
|
|
156
|
+
|
|
113
157
|
def chat(
|
|
114
158
|
self,
|
|
115
159
|
*,
|
|
@@ -225,12 +225,52 @@ class STT(stt.STT):
|
|
|
225
225
|
|
|
226
226
|
self._session = http_session
|
|
227
227
|
self._streams = weakref.WeakSet[SpeechStream]()
|
|
228
|
+
self._prewarm_task: asyncio.Task[None] | None = None
|
|
228
229
|
|
|
229
230
|
def _ensure_session(self) -> aiohttp.ClientSession:
|
|
230
231
|
if not self._session:
|
|
231
232
|
self._session = utils.http_context.http_session()
|
|
232
233
|
return self._session
|
|
233
234
|
|
|
235
|
+
def prewarm(self) -> None:
|
|
236
|
+
"""Open the STT WebSocket and send the handshake payload so the first
|
|
237
|
+
user turn doesn't pay the TLS + WS-upgrade + auth round-trip cost.
|
|
238
|
+
|
|
239
|
+
Mirrors the ``connection_pool.prewarm`` convention: schedule a
|
|
240
|
+
background task and return immediately. The framework calls this
|
|
241
|
+
synchronously before the session starts, so the actual WS work
|
|
242
|
+
happens concurrently while the user is still getting ready to
|
|
243
|
+
speak.
|
|
244
|
+
"""
|
|
245
|
+
if self._prewarm_task is not None and not self._prewarm_task.done():
|
|
246
|
+
return
|
|
247
|
+
try:
|
|
248
|
+
loop = asyncio.get_running_loop()
|
|
249
|
+
except RuntimeError:
|
|
250
|
+
logger.debug("stt prewarm skipped: no running event loop")
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
async def _impl() -> None:
|
|
254
|
+
try:
|
|
255
|
+
session = self._ensure_session()
|
|
256
|
+
async with session.ws_connect(
|
|
257
|
+
self._opts.get_ws_url(),
|
|
258
|
+
headers=self._opts.get_ws_header(),
|
|
259
|
+
max_msg_size=1000000000,
|
|
260
|
+
) as ws:
|
|
261
|
+
await ws.send_bytes(self._opts.get_ws_query_params())
|
|
262
|
+
# Wait briefly so we also eat the auth roundtrip; the
|
|
263
|
+
# server ack arrives within a few hundred ms.
|
|
264
|
+
try:
|
|
265
|
+
await asyncio.wait_for(ws.receive(), timeout=2.0)
|
|
266
|
+
except asyncio.TimeoutError:
|
|
267
|
+
pass
|
|
268
|
+
logger.info("stt prewarm: ws handshake completed")
|
|
269
|
+
except Exception as exc: # noqa: BLE001
|
|
270
|
+
logger.warning("stt prewarm failed: %s", exc)
|
|
271
|
+
|
|
272
|
+
self._prewarm_task = loop.create_task(_impl(), name="volcengine.stt.prewarm")
|
|
273
|
+
|
|
234
274
|
async def _recognize_impl(
|
|
235
275
|
self,
|
|
236
276
|
buffer: AudioBuffer,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import base64
|
|
4
5
|
import gzip
|
|
5
6
|
import json
|
|
@@ -164,12 +165,53 @@ class TTS(tts.TTS):
|
|
|
164
165
|
self._session = http_session
|
|
165
166
|
self._min_sentence_length = min_sentence_length
|
|
166
167
|
self._streams = weakref.WeakSet[SynthesizeStream]()
|
|
168
|
+
self._prewarm_task: asyncio.Task[None] | None = None
|
|
167
169
|
|
|
168
170
|
def _ensure_session(self) -> aiohttp.ClientSession:
|
|
169
171
|
if self._session is None:
|
|
170
172
|
self._session = utils.http_context.http_session()
|
|
171
173
|
return self._session
|
|
172
174
|
|
|
175
|
+
def prewarm(self) -> None:
|
|
176
|
+
"""Make a tiny HTTP synthesize call to prime the TLS connection and
|
|
177
|
+
warm the TTS model.
|
|
178
|
+
|
|
179
|
+
Shaves the per-call TLS + model load cost off the first turn's TTS
|
|
180
|
+
TTFB. The warmup text is two characters; the audio is discarded.
|
|
181
|
+
|
|
182
|
+
Mirrors the ``connection_pool.prewarm`` convention: schedule a
|
|
183
|
+
background task and return immediately.
|
|
184
|
+
"""
|
|
185
|
+
if self._prewarm_task is not None and not self._prewarm_task.done():
|
|
186
|
+
return
|
|
187
|
+
try:
|
|
188
|
+
loop = asyncio.get_running_loop()
|
|
189
|
+
except RuntimeError:
|
|
190
|
+
logger.debug("tts prewarm skipped: no running event loop")
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
async def _impl() -> None:
|
|
194
|
+
t0 = time.perf_counter()
|
|
195
|
+
try:
|
|
196
|
+
session = self._ensure_session()
|
|
197
|
+
payload = self._opts.get_http_request("你好")
|
|
198
|
+
headers = self._opts.get_http_header()
|
|
199
|
+
async with session.post(
|
|
200
|
+
self._opts.get_http_url(),
|
|
201
|
+
json=payload,
|
|
202
|
+
timeout=aiohttp.ClientTimeout(total=30, sock_connect=10),
|
|
203
|
+
headers=headers,
|
|
204
|
+
) as resp:
|
|
205
|
+
await resp.read()
|
|
206
|
+
logger.info(
|
|
207
|
+
"tts prewarm: warmup synthesize completed in %.0f ms",
|
|
208
|
+
(time.perf_counter() - t0) * 1000,
|
|
209
|
+
)
|
|
210
|
+
except Exception as exc: # noqa: BLE001
|
|
211
|
+
logger.warning("tts prewarm failed: %s", exc)
|
|
212
|
+
|
|
213
|
+
self._prewarm_task = loop.create_task(_impl(), name="volcengine.tts.prewarm")
|
|
214
|
+
|
|
173
215
|
def synthesize(
|
|
174
216
|
self, text, *, conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS
|
|
175
217
|
):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.9"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.3.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|