From 6b7f924af606bffd006a7e239af5be281ae9f83d Mon Sep 17 00:00:00 2001 From: Kwindla Hultman Kramer Date: Mon, 30 Sep 2024 14:33:08 -0700 Subject: [PATCH] tts sentence aggregation fix --- .../07a-interruptible-anthropic.py | 27 ++++++++----------- src/pipecat/services/ai_services.py | 12 +++++---- src/pipecat/utils/string.py | 6 ++--- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/examples/foundational/07a-interruptible-anthropic.py b/examples/foundational/07a-interruptible-anthropic.py index 2bded2480..288cb1b31 100644 --- a/examples/foundational/07a-interruptible-anthropic.py +++ b/examples/foundational/07a-interruptible-anthropic.py @@ -5,29 +5,24 @@ # import asyncio -import aiohttp import os import sys +import aiohttp +from dotenv import load_dotenv +from loguru import logger +from runner import configure + from pipecat.frames.frames import LLMMessagesFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask -from pipecat.processors.aggregators.llm_response import ( - LLMAssistantResponseAggregator, - LLMUserResponseAggregator, -) -from pipecat.services.cartesia import CartesiaTTSService +from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext from pipecat.services.anthropic import AnthropicLLMService +from pipecat.services.cartesia import CartesiaTTSService from pipecat.transports.services.daily import DailyParams, DailyTransport from pipecat.vad.silero import SileroVADAnalyzer -from runner import configure - -from loguru import logger - -from dotenv import load_dotenv - load_dotenv(override=True) logger.remove(0) @@ -69,17 +64,17 @@ async def main(): }, ] - tma_in = LLMUserResponseAggregator(messages) - tma_out = LLMAssistantResponseAggregator(messages) + context = OpenAILLMContext(messages) + context_aggregator = llm.create_context_aggregator(context) pipeline = Pipeline( [ transport.input(), # Transport user input - tma_in, # User responses + context_aggregator.user(), # User responses llm, # LLM tts, # TTS transport.output(), # Transport bot output - tma_out, # Assistant spoken responses + context_aggregator.assistant(), # Assistant spoken responses ] ) diff --git a/src/pipecat/services/ai_services.py b/src/pipecat/services/ai_services.py index ba78b24f8..8386fccd5 100644 --- a/src/pipecat/services/ai_services.py +++ b/src/pipecat/services/ai_services.py @@ -228,16 +228,18 @@ class TTSService(AIService): text = frame.text else: self._current_sentence += frame.text - if match_endofsentence(self._current_sentence): - text = self._current_sentence - self._current_sentence = "" + eos_end_marker = match_endofsentence(self._current_sentence) + if eos_end_marker: + text = self._current_sentence[:eos_end_marker] + self._current_sentence = self._current_sentence[eos_end_marker:] if text: await self._push_tts_frames(text) async def _push_tts_frames(self, text: str): - text = text.strip() - if not text: + # Don't send only whitespace. This causes problems for some TTS models. But also don't + # strip all whitespace, as whitespace can influence prosody. + if not text.strip(): return await self.start_processing_metrics() diff --git a/src/pipecat/utils/string.py b/src/pipecat/utils/string.py index cf9a22ad8..936764345 100644 --- a/src/pipecat/utils/string.py +++ b/src/pipecat/utils/string.py @@ -6,7 +6,6 @@ import re - ENDOFSENTENCE_PATTERN_STR = r""" (? bool: - return ENDOFSENTENCE_PATTERN.search(text.rstrip()) is not None +def match_endofsentence(text: str) -> int: + match = ENDOFSENTENCE_PATTERN.search(text.rstrip()) + return match.end() if match else 0