processors(realtime-ai): add support making TTS to speak

This commit is contained in:
Aleix Conchillo Flaqué
2024-07-19 14:11:58 -07:00
parent b85dd7283a
commit b0b1475563
3 changed files with 39 additions and 9 deletions

View File

@@ -177,6 +177,15 @@ class LLMMessagesUpdateFrame(DataFrame):
messages: List[dict] messages: List[dict]
@dataclass
class TTSSpeakFrame(DataFrame):
"""A frame that contains a text that should be spoken by the TTS in the
pipeline (if any).
"""
text: str
@dataclass @dataclass
class TransportMessageFrame(DataFrame): class TransportMessageFrame(DataFrame):
message: Any message: Any

View File

@@ -16,6 +16,7 @@ from pipecat.frames.frames import (
LLMMessagesUpdateFrame, LLMMessagesUpdateFrame,
LLMModelUpdateFrame, LLMModelUpdateFrame,
StartFrame, StartFrame,
TTSSpeakFrame,
TTSVoiceUpdateFrame, TTSVoiceUpdateFrame,
TransportMessageFrame) TransportMessageFrame)
from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.pipeline import Pipeline
@@ -57,9 +58,19 @@ class RealtimeAISetup(BaseModel):
config: Optional[RealtimeAIConfig] = None config: Optional[RealtimeAIConfig] = None
class RealtimeAILLMMessageData(BaseModel):
messages: List[dict]
class RealtimeAITTSMessageData(BaseModel):
text: str
class RealtimeAIMessageData(BaseModel): class RealtimeAIMessageData(BaseModel):
setup: Optional[RealtimeAISetup] = None setup: Optional[RealtimeAISetup] = None
config: Optional[RealtimeAIConfig] = None config: Optional[RealtimeAIConfig] = None
llm: Optional[RealtimeAILLMMessageData] = None
tts: Optional[RealtimeAITTSMessageData] = None
class RealtimeAIMessage(BaseModel): class RealtimeAIMessage(BaseModel):
@@ -135,9 +146,11 @@ class RealtimeAIProcessor(FrameProcessor):
case "llm-get-context": case "llm-get-context":
await self._handle_llm_get_context() await self._handle_llm_get_context()
case "llm-append-context": case "llm-append-context":
await self._handle_llm_append_context(message.data.config) await self._handle_llm_append_context(message.data.llm)
case "llm-update-context": case "llm-update-context":
await self._handle_llm_update_context(message.data.config) await self._handle_llm_update_context(message.data.llm)
case "tts-speak":
await self._handle_tts_speak(message.data.tts)
except ValidationError as e: except ValidationError as e:
await self._send_response(message.type, False, f"invalid message: {e}") await self._send_response(message.type, False, f"invalid message: {e}")
@@ -206,14 +219,19 @@ class RealtimeAIProcessor(FrameProcessor):
message = TransportMessageFrame(message=response.model_dump(exclude_none=True)) message = TransportMessageFrame(message=response.model_dump(exclude_none=True))
await self.push_frame(message) await self.push_frame(message)
async def _handle_llm_append_context(self, config: RealtimeAIConfig): async def _handle_llm_append_context(self, data: RealtimeAILLMMessageData):
if config.llm and config.llm.messages: if data and data.messages:
frame = LLMMessagesAppendFrame(config.llm.messages) frame = LLMMessagesAppendFrame(data.messages)
await self.push_frame(frame) await self.push_frame(frame)
async def _handle_llm_update_context(self, config: RealtimeAIConfig): async def _handle_llm_update_context(self, data: RealtimeAILLMMessageData):
if config.llm and config.llm.messages: if data and data.messages:
frame = LLMMessagesUpdateFrame(config.llm.messages) frame = LLMMessagesUpdateFrame(data.messages)
await self.push_frame(frame)
async def _handle_tts_speak(self, data: RealtimeAITTSMessageData):
if data and data.text:
frame = TTSSpeakFrame(text=data.text)
await self.push_frame(frame) await self.push_frame(frame)
async def _send_response(self, type: str, success: bool, error: str | None = None): async def _send_response(self, type: str, success: bool, error: str | None = None):

View File

@@ -19,6 +19,7 @@ from pipecat.frames.frames import (
LLMFullResponseEndFrame, LLMFullResponseEndFrame,
StartFrame, StartFrame,
StartInterruptionFrame, StartInterruptionFrame,
TTSSpeakFrame,
TTSStartedFrame, TTSStartedFrame,
TTSStoppedFrame, TTSStoppedFrame,
TTSVoiceUpdateFrame, TTSVoiceUpdateFrame,
@@ -178,7 +179,7 @@ class TTSService(AIService):
if text: if text:
await self._push_tts_frames(text) await self._push_tts_frames(text)
async def _push_tts_frames(self, text: str): async def _push_tts_frames(self, text: str, text_passthrough: bool = True):
text = text.strip() text = text.strip()
if not text: if not text:
return return
@@ -209,6 +210,8 @@ class TTSService(AIService):
await self.push_frame(frame, direction) await self.push_frame(frame, direction)
else: else:
await self.push_frame(frame, direction) await self.push_frame(frame, direction)
elif isinstance(frame, TTSSpeakFrame):
await self._push_tts_frames(frame.text, False)
elif isinstance(frame, TTSVoiceUpdateFrame): elif isinstance(frame, TTSVoiceUpdateFrame):
await self.set_voice(frame.voice) await self.set_voice(frame.voice)
else: else: