first
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from queue import Queue
|
||||
from threading import Event
|
||||
from typing import Iterator, Union
|
||||
|
||||
from speech_to_speech.api.openai_realtime.runtime_config import RuntimeConfig
|
||||
from speech_to_speech.baseHandler import BaseHandler
|
||||
from speech_to_speech.LLM.chat import make_user_message
|
||||
from speech_to_speech.pipeline.events import PartialTranscriptionEvent, TranscriptionCompletedEvent
|
||||
from speech_to_speech.pipeline.handler_types import LLMIn, STTOut
|
||||
from speech_to_speech.pipeline.messages import GenerateResponseRequest, PartialTranscription, Transcription
|
||||
from speech_to_speech.pipeline.queue_types import TextEventItem
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TranscriptionNotifier(BaseHandler[STTOut, Union[STTOut, LLMIn]]):
|
||||
"""Sits between STT and LLM.
|
||||
|
||||
For **realtime mode** (no ``runtime_config``): emits transcription events
|
||||
on ``text_output_queue`` for protocol translation but yields nothing -- the
|
||||
``RealtimeService`` builds ``GenerateResponseRequest`` directly.
|
||||
|
||||
For **legacy mode** (``runtime_config`` provided): appends the user
|
||||
message to ``runtime_config.chat`` and yields a
|
||||
``GenerateResponseRequest`` so the LLM handler receives a uniform input
|
||||
type regardless of pipeline mode.
|
||||
"""
|
||||
|
||||
def setup(
|
||||
self,
|
||||
text_output_queue: Queue[TextEventItem] | None = None,
|
||||
runtime_config: RuntimeConfig | None = None,
|
||||
should_listen: Event | None = None,
|
||||
) -> None:
|
||||
self.text_output_queue = text_output_queue
|
||||
self.runtime_config = runtime_config
|
||||
self.should_listen = should_listen
|
||||
|
||||
def process(self, transcription: STTOut) -> Iterator[Union[STTOut, LLMIn]]:
|
||||
if isinstance(transcription, PartialTranscription):
|
||||
if self.text_output_queue and transcription.text:
|
||||
self.text_output_queue.put(
|
||||
PartialTranscriptionEvent(
|
||||
delta=str(transcription.text),
|
||||
turn_id=transcription.turn_id,
|
||||
turn_revision=transcription.turn_revision,
|
||||
)
|
||||
)
|
||||
logger.debug("Partial transcription: %s", str(transcription.text)[:80])
|
||||
return
|
||||
|
||||
if isinstance(transcription, Transcription):
|
||||
text = transcription.text
|
||||
language_code = transcription.language_code
|
||||
turn_id = transcription.turn_id
|
||||
turn_revision = transcription.turn_revision
|
||||
speech_stopped_at_s = transcription.speech_stopped_at_s
|
||||
else:
|
||||
text = transcription
|
||||
language_code = None
|
||||
turn_id = None
|
||||
turn_revision = None
|
||||
speech_stopped_at_s = None
|
||||
|
||||
transcript = str(text)
|
||||
# Always close the client-visible transcription item. Empty final STT
|
||||
# results should not trigger the LLM, but clients may already have
|
||||
# received partial deltas and still need a completed event.
|
||||
if self.text_output_queue is not None:
|
||||
self.text_output_queue.put(
|
||||
TranscriptionCompletedEvent(
|
||||
transcript=transcript,
|
||||
language_code=language_code,
|
||||
turn_id=turn_id,
|
||||
turn_revision=turn_revision,
|
||||
speech_stopped_at_s=speech_stopped_at_s,
|
||||
)
|
||||
)
|
||||
|
||||
if not transcript:
|
||||
logger.debug("Transcription completed with empty transcript")
|
||||
if self.should_listen is not None:
|
||||
self.should_listen.set()
|
||||
logger.debug("Empty transcription completed; listening re-enabled")
|
||||
return
|
||||
|
||||
if language_code:
|
||||
logger.info("Transcription completed (language=%s): %s", language_code, transcript)
|
||||
else:
|
||||
logger.info("Transcription completed: %s", transcript)
|
||||
|
||||
if self.runtime_config is not None:
|
||||
self.runtime_config.chat.add_item(make_user_message(transcript))
|
||||
yield GenerateResponseRequest(
|
||||
runtime_config=self.runtime_config,
|
||||
language_code=language_code,
|
||||
turn_id=turn_id,
|
||||
turn_revision=turn_revision,
|
||||
speech_stopped_at_s=speech_stopped_at_s,
|
||||
)
|
||||
Reference in New Issue
Block a user