services(riva): first working version of ParakeetSTTService
This commit is contained in:
committed by
vipyne
parent
ce94421c90
commit
7e407e5548
@@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import AsyncGenerator, List, Optional, Union, Iterator
|
from typing import AsyncGenerator, Optional
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pydantic.main import BaseModel
|
from pydantic.main import BaseModel
|
||||||
@@ -13,7 +13,6 @@ from pydantic.main import BaseModel
|
|||||||
from pipecat.frames.frames import (
|
from pipecat.frames.frames import (
|
||||||
CancelFrame,
|
CancelFrame,
|
||||||
EndFrame,
|
EndFrame,
|
||||||
ErrorFrame,
|
|
||||||
Frame,
|
Frame,
|
||||||
InterimTranscriptionFrame,
|
InterimTranscriptionFrame,
|
||||||
StartFrame,
|
StartFrame,
|
||||||
@@ -23,7 +22,6 @@ from pipecat.frames.frames import (
|
|||||||
TTSStoppedFrame,
|
TTSStoppedFrame,
|
||||||
)
|
)
|
||||||
from pipecat.services.ai_services import STTService, TTSService
|
from pipecat.services.ai_services import STTService, TTSService
|
||||||
from pipecat.transcriptions.language import Language
|
|
||||||
from pipecat.utils.time import time_now_iso8601
|
from pipecat.utils.time import time_now_iso8601
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -74,12 +72,6 @@ class FastpitchTTSService(TTSService):
|
|||||||
|
|
||||||
self.service = riva.client.SpeechSynthesisService(auth)
|
self.service = riva.client.SpeechSynthesisService(auth)
|
||||||
|
|
||||||
async def stop(self, frame: EndFrame):
|
|
||||||
await super().stop(frame)
|
|
||||||
|
|
||||||
async def cancel(self, frame: CancelFrame):
|
|
||||||
await super().cancel(frame)
|
|
||||||
|
|
||||||
async def run_tts(self, text: str) -> AsyncGenerator[Frame, None]:
|
async def run_tts(self, text: str) -> AsyncGenerator[Frame, None]:
|
||||||
logger.debug(f"Generating TTS: [{text}]")
|
logger.debug(f"Generating TTS: [{text}]")
|
||||||
|
|
||||||
@@ -130,17 +122,12 @@ class ParakeetSTTService(STTService):
|
|||||||
|
|
||||||
self.set_model_name("parakeet-ctc-1.1b-asr")
|
self.set_model_name("parakeet-ctc-1.1b-asr")
|
||||||
|
|
||||||
input_device = 0
|
|
||||||
list_devices = False
|
|
||||||
profanity_filter = False
|
profanity_filter = False
|
||||||
automatic_punctuation = False
|
automatic_punctuation = False
|
||||||
no_verbatim_transcripts = False
|
no_verbatim_transcripts = False
|
||||||
language_code = "en-US"
|
language_code = "en-US"
|
||||||
model_name = ""
|
|
||||||
boosted_lm_words = None
|
boosted_lm_words = None
|
||||||
boosted_lm_score = 4.0
|
boosted_lm_score = 4.0
|
||||||
speaker_diarization = False
|
|
||||||
diarization_max_speakers = 3
|
|
||||||
start_history = -1
|
start_history = -1
|
||||||
start_threshold = -1.0
|
start_threshold = -1.0
|
||||||
stop_history = -1
|
stop_history = -1
|
||||||
@@ -148,10 +135,7 @@ class ParakeetSTTService(STTService):
|
|||||||
stop_history_eou = -1
|
stop_history_eou = -1
|
||||||
stop_threshold_eou = -1.0
|
stop_threshold_eou = -1.0
|
||||||
custom_configuration = ""
|
custom_configuration = ""
|
||||||
ssl_cert = None
|
|
||||||
use_ssl = True
|
|
||||||
sample_rate_hz: int = 16000
|
sample_rate_hz: int = 16000
|
||||||
file_streaming_chunk = 1600
|
|
||||||
|
|
||||||
metadata = [
|
metadata = [
|
||||||
["function-id", model],
|
["function-id", model],
|
||||||
@@ -189,56 +173,86 @@ class ParakeetSTTService(STTService):
|
|||||||
riva.client.add_custom_configuration_to_config(config, custom_configuration)
|
riva.client.add_custom_configuration_to_config(config, custom_configuration)
|
||||||
|
|
||||||
# this doesn't work, but something like this perhaps? part 1
|
# this doesn't work, but something like this perhaps? part 1
|
||||||
self.audio = []
|
self._queue = asyncio.Queue()
|
||||||
self.responses = self.asr_service.streaming_response_generator(
|
|
||||||
audio_chunks=[self.audio],
|
|
||||||
streaming_config=self.config,
|
|
||||||
)
|
|
||||||
|
|
||||||
def can_generate_metrics(self) -> bool:
|
def can_generate_metrics(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def start(self, frame: StartFrame):
|
async def start(self, frame: StartFrame):
|
||||||
await super().start(frame)
|
await super().start(frame)
|
||||||
|
self._thread_task = self.get_event_loop().create_task(self._thread_task_handler())
|
||||||
|
self._response_task = self.get_event_loop().create_task(self._response_task_handler())
|
||||||
|
self._response_queue = asyncio.Queue()
|
||||||
|
|
||||||
async def stop(self, frame: EndFrame):
|
async def stop(self, frame: EndFrame):
|
||||||
await super().stop(frame)
|
await super().stop(frame)
|
||||||
|
await self._stop_tasks()
|
||||||
|
|
||||||
async def cancel(self, frame: CancelFrame):
|
async def cancel(self, frame: CancelFrame):
|
||||||
await super().cancel(frame)
|
await super().cancel(frame)
|
||||||
|
await self._stop_tasks()
|
||||||
|
|
||||||
async def run_stt(self, audio: bytes) -> AsyncGenerator[Frame, None]:
|
async def _stop_tasks(self):
|
||||||
# this doesn't work, but something like this perhaps? part 2
|
self._thread_task.cancel()
|
||||||
self.audio.append(audio)
|
await self._thread_task
|
||||||
|
self._response_task.cancel()
|
||||||
|
await self._response_task
|
||||||
|
|
||||||
# need to start to run this generator only once somewhere...
|
def _response_handler(self):
|
||||||
# 'start' function doesn't work...
|
responses = self.asr_service.streaming_response_generator(
|
||||||
# something about the event loop...
|
audio_chunks=self,
|
||||||
# maybe an audio buffer... though my attempt at that didn't work either
|
streaming_config=self.config,
|
||||||
for response in self.responses:
|
)
|
||||||
|
for response in responses:
|
||||||
if not response.results:
|
if not response.results:
|
||||||
continue
|
continue
|
||||||
partial_transcript = ""
|
asyncio.run_coroutine_threadsafe(
|
||||||
for result in response.results:
|
self._response_queue.put(response), self.get_event_loop()
|
||||||
if result:
|
)
|
||||||
if not result.alternatives:
|
|
||||||
continue
|
async def _thread_task_handler(self):
|
||||||
transcript = result.alternatives[0].transcript
|
try:
|
||||||
if transcript:
|
self._thread_running = True
|
||||||
language = None
|
await asyncio.to_thread(self._response_handler)
|
||||||
if len(transcript) > 0:
|
except asyncio.CancelledError:
|
||||||
await self.stop_ttfb_metrics()
|
self._thread_running = False
|
||||||
if result.is_final:
|
pass
|
||||||
await self.stop_processing_metrics()
|
|
||||||
yield TranscriptionFrame(
|
async def _handle_response(self, response):
|
||||||
transcript, "", time_now_iso8601(), language
|
for result in response.results:
|
||||||
)
|
if result and not result.alternatives:
|
||||||
else:
|
continue
|
||||||
yield InterimTranscriptionFrame(
|
|
||||||
transcript, "", time_now_iso8601(), language
|
transcript = result.alternatives[0].transcript
|
||||||
)
|
if transcript and len(transcript) > 0:
|
||||||
|
await self.stop_ttfb_metrics()
|
||||||
|
if result.is_final:
|
||||||
|
await self.stop_processing_metrics()
|
||||||
|
await self.push_frame(
|
||||||
|
TranscriptionFrame(transcript, "", time_now_iso8601(), None)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self.push_frame(
|
||||||
|
InterimTranscriptionFrame(transcript, "", time_now_iso8601(), None)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _response_task_handler(self):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
response = await self._response_queue.get()
|
||||||
|
await self._handle_response(response)
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
break
|
||||||
|
|
||||||
|
async def run_stt(self, audio: bytes) -> AsyncGenerator[Frame, None]:
|
||||||
|
await self._queue.put(audio)
|
||||||
yield None
|
yield None
|
||||||
|
|
||||||
async def _on_speech_started(self, *args, **kwargs):
|
def __next__(self) -> bytes:
|
||||||
await self.start_ttfb_metrics()
|
if not self._thread_running:
|
||||||
await self.start_processing_metrics()
|
raise StopIteration
|
||||||
|
future = asyncio.run_coroutine_threadsafe(self._queue.get(), self.get_event_loop())
|
||||||
|
return future.result()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|||||||
Reference in New Issue
Block a user