36 lines
1.1 KiB
Python
36 lines
1.1 KiB
Python
|
|
import re
|
||
|
|
|
||
|
|
# Satzende: . ! ? … gefolgt von Whitespace (oder Stringende beim flush).
|
||
|
|
_SENTENCE_END = re.compile(r"[.!?…]+(?=\s)")
|
||
|
|
|
||
|
|
|
||
|
|
class SentenceChunker:
|
||
|
|
"""Inkrementelle Satzsegmentierung fuer gestreamte LLM-Token.
|
||
|
|
|
||
|
|
`feed(delta)` liefert die seit dem letzten Aufruf fertig gewordenen Saetze,
|
||
|
|
`flush()` den verbleibenden Rest (z. B. der letzte Satz ohne abschliessendes
|
||
|
|
Leerzeichen). Damit kann pro Satz schon TTS erzeugt werden, waehrend das LLM
|
||
|
|
noch weiterschreibt.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
self._buffer = ""
|
||
|
|
|
||
|
|
def feed(self, text: str) -> list[str]:
|
||
|
|
self._buffer += text
|
||
|
|
sentences: list[str] = []
|
||
|
|
while True:
|
||
|
|
match = _SENTENCE_END.search(self._buffer)
|
||
|
|
if not match:
|
||
|
|
break
|
||
|
|
end = match.end()
|
||
|
|
sentence = self._buffer[:end].strip()
|
||
|
|
self._buffer = self._buffer[end:]
|
||
|
|
if sentence:
|
||
|
|
sentences.append(sentence)
|
||
|
|
return sentences
|
||
|
|
|
||
|
|
def flush(self) -> str:
|
||
|
|
rest = self._buffer.strip()
|
||
|
|
self._buffer = ""
|
||
|
|
return rest
|