Add split_text_by_spaces string util
This commit is contained in:
@@ -24,6 +24,7 @@ from pipecat.frames.frames import (
|
||||
LLMTextFrame,
|
||||
)
|
||||
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
|
||||
from pipecat.utils.string import split_text_by_characters
|
||||
from pipecat.utils.text.base_text_aggregator import BaseTextAggregator
|
||||
from pipecat.utils.text.simple_text_aggregator import SimpleTextAggregator
|
||||
|
||||
@@ -83,14 +84,19 @@ class LLMTextProcessor(FrameProcessor):
|
||||
await self._text_aggregator.reset()
|
||||
|
||||
async def _handle_llm_text(self, in_frame: LLMTextFrame):
|
||||
aggregation = await self._text_aggregator.aggregate(in_frame.text)
|
||||
if aggregation:
|
||||
out_frame = AggregatedTextFrame(
|
||||
text=aggregation.text,
|
||||
aggregated_by=aggregation.type,
|
||||
)
|
||||
out_frame.skip_tts = in_frame.skip_tts
|
||||
await self.push_frame(out_frame)
|
||||
# Split text by characters to normalize LLM output into individual characters
|
||||
# This ensures consistent aggregation behavior regardless of LLM chunk size
|
||||
characters = split_text_by_characters(in_frame.text)
|
||||
|
||||
for character in characters:
|
||||
aggregation = await self._text_aggregator.aggregate(character)
|
||||
if aggregation:
|
||||
out_frame = AggregatedTextFrame(
|
||||
text=aggregation.text,
|
||||
aggregated_by=aggregation.type,
|
||||
)
|
||||
out_frame.skip_tts = in_frame.skip_tts
|
||||
await self.push_frame(out_frame)
|
||||
|
||||
async def _handle_llm_end(self, skip_tts: Optional[bool] = None):
|
||||
# Flush any remaining aggregated text at the end of the LLM response
|
||||
|
||||
@@ -51,6 +51,7 @@ from pipecat.processors.frame_processor import FrameDirection
|
||||
from pipecat.services.ai_service import AIService
|
||||
from pipecat.services.websocket_service import WebsocketService
|
||||
from pipecat.transcriptions.language import Language
|
||||
from pipecat.utils.string import split_text_by_characters
|
||||
from pipecat.utils.text.base_text_aggregator import BaseTextAggregator
|
||||
from pipecat.utils.text.base_text_filter import BaseTextFilter
|
||||
from pipecat.utils.text.simple_text_aggregator import SimpleTextAggregator
|
||||
@@ -539,17 +540,26 @@ class TTSService(AIService):
|
||||
text = frame.text
|
||||
includes_inter_frame_spaces = frame.includes_inter_frame_spaces
|
||||
aggregated_by = "token"
|
||||
else:
|
||||
aggregate = await self._text_aggregator.aggregate(frame.text)
|
||||
if aggregate:
|
||||
text = aggregate.text
|
||||
aggregated_by = aggregate.type
|
||||
|
||||
if text:
|
||||
logger.trace(f"Pushing TTS frames for text: {text}, {aggregated_by}")
|
||||
await self._push_tts_frames(
|
||||
AggregatedTextFrame(text, aggregated_by), includes_inter_frame_spaces
|
||||
)
|
||||
if text:
|
||||
logger.trace(f"Pushing TTS frames for text: {text}, {aggregated_by}")
|
||||
await self._push_tts_frames(
|
||||
AggregatedTextFrame(text, aggregated_by), includes_inter_frame_spaces
|
||||
)
|
||||
else:
|
||||
# Split text by characters to normalize input into individual characters
|
||||
# This ensures consistent aggregation behavior regardless of input chunk size
|
||||
characters = split_text_by_characters(frame.text)
|
||||
|
||||
for character in characters:
|
||||
aggregate = await self._text_aggregator.aggregate(character)
|
||||
if aggregate:
|
||||
text = aggregate.text
|
||||
aggregated_by = aggregate.type
|
||||
logger.trace(f"Pushing TTS frames for text: {text}, {aggregated_by}")
|
||||
await self._push_tts_frames(
|
||||
AggregatedTextFrame(text, aggregated_by), includes_inter_frame_spaces
|
||||
)
|
||||
|
||||
async def _push_tts_frames(
|
||||
self, src_frame: AggregatedTextFrame, includes_inter_frame_spaces: Optional[bool] = False
|
||||
|
||||
@@ -280,3 +280,27 @@ def concatenate_aggregated_text(text_parts: List[TextPartForConcatenation]) -> s
|
||||
result = result.strip()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def split_text_by_characters(text: str) -> List[str]:
|
||||
"""Split text into individual characters.
|
||||
|
||||
Returns each character as a separate string element, allowing character-by-character
|
||||
processing while maintaining the ability to reconstruct the original text.
|
||||
|
||||
Args:
|
||||
text: The text to split into characters.
|
||||
|
||||
Returns:
|
||||
A list of individual characters.
|
||||
|
||||
Example::
|
||||
|
||||
>>> split_text_by_characters("Hello world!")
|
||||
["H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
|
||||
>>> split_text_by_characters("Hi")
|
||||
["H", "i"]
|
||||
>>> split_text_by_characters("")
|
||||
[]
|
||||
"""
|
||||
return list(text)
|
||||
|
||||
Reference in New Issue
Block a user