stream2sentence 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ from .stream2sentence import generate_sentences
@@ -0,0 +1,161 @@
1
+ """
2
+ Real-time processing and delivery of sentences from a continuous stream of characters or text chunks
3
+ """
4
+
5
+ import re
6
+ import nltk
7
+ from typing import Iterator
8
+
9
+ def initialize_nltk():
10
+ """
11
+ Initializes NLTK by downloading required data for sentence tokenization.
12
+ """
13
+ try:
14
+ _ = nltk.data.find('tokenizers/punkt')
15
+ except LookupError:
16
+ nltk.download('punkt')
17
+
18
+ initialize_nltk()
19
+
20
+ def _remove_links(text: str) -> str:
21
+ """
22
+ Removes any links from the input text.
23
+
24
+ Args:
25
+ text (str): Input text
26
+
27
+ Returns:
28
+ str: Text with links removed
29
+ """
30
+ pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
31
+ return re.sub(pattern, '', text)
32
+
33
+ def _remove_emojis(text: str) -> str:
34
+ """
35
+ Removes emojis from the input text.
36
+
37
+ Args:
38
+ text (str): Input text
39
+
40
+ Returns:
41
+ str: Text with emojis removed
42
+ """
43
+ emoji_pattern = re.compile("["
44
+ u"\U0001F600-\U0001F64F"
45
+ u"\U0001F300-\U0001F5FF"
46
+ u"\U0001F680-\U0001F6FF"
47
+ u"\U0001F1E0-\U0001F1FF"
48
+ u"\U00002702-\U000027B0"
49
+ u"\U000024C2-\U0001F251"
50
+ "]+", flags=re.UNICODE)
51
+ return emoji_pattern.sub(r'', text)
52
+
53
+ def _generate_characters(generator: Iterator[str],
54
+ log_characters: bool = False) -> Iterator[str]:
55
+ """
56
+ Generates individual characters from a text generator.
57
+
58
+ Args:
59
+ generator (Iterator[str]): Input text generator
60
+ log_characters (bool): Whether to log the characters to the console
61
+
62
+ Yields:
63
+ Individual characters from the generator
64
+ """
65
+ for chunk in generator:
66
+ for char in chunk:
67
+ if log_characters:
68
+ print(char, end="", flush=True)
69
+ yield char
70
+
71
+ def _clean_text(text: str,
72
+ cleanup_text_links: bool = False,
73
+ cleanup_text_emojis: bool = False) -> str:
74
+ """
75
+ Cleans the text by removing links and emojis.
76
+
77
+ Args:
78
+ text (str): Input text
79
+ cleanup_text_links (boolean, optional): Remove non-desired links from the stream.
80
+ cleanup_text_emojis (boolean, optional): Remove non-desired emojis from the stream.
81
+
82
+ Returns:
83
+ str: Cleaned text
84
+ """
85
+ if cleanup_text_links:
86
+ text = _remove_links(text)
87
+ if cleanup_text_emojis:
88
+ text = _remove_emojis(text)
89
+
90
+ text = text.strip()
91
+ return text
92
+
93
+ def generate_sentences(generator: Iterator[str],
94
+ context_size: int = 20,
95
+ minimum_sentence_length: int = 1,
96
+ quick_yield_single_sentence_fragment: bool = False,
97
+ cleanup_text_links: bool = False,
98
+ cleanup_text_emojis: bool = False,
99
+ log_characters: bool = False) -> Iterator[str]:
100
+ """
101
+ Generates sentences from a stream of characters or input chunks.
102
+
103
+ Args:
104
+ generator (Iterator[str]): Input character generator
105
+ context_size (int): The character context size for sentence detection. A larger context ensures more reliable sentence detection. Default value is 10 characters.
106
+ minimum_sentence_length (int): Minimum character length for a sentence. Short sentences will combine with the subsequent sentence to enhance synthesis quality. Default value is 8 characters.
107
+ quick_yield_single_sentence_fragment (bool): Whether to return a sentence fragment as fast as possible (for realtime speech synthesis)
108
+ cleanup_text_links (boolean, optional): Remove non-desired links from the stream.
109
+ cleanup_text_emojis (boolean, optional): Remove non-desired emojis from the stream.
110
+ log_characters (bool): Whether to log the characters to the console
111
+
112
+ Yields:
113
+ Iterator[str]: Sentences based on input characters
114
+ """
115
+
116
+ buffer = ''
117
+ is_first_sentence = True
118
+
119
+ sentence_delimiters = '.?!;:-,\n…)]}'
120
+
121
+ for char in _generate_characters(generator, log_characters):
122
+
123
+ if char:
124
+ buffer += char
125
+
126
+ if is_first_sentence and len(buffer) > 1 and quick_yield_single_sentence_fragment:
127
+
128
+ if buffer[-1] in sentence_delimiters:
129
+ yield _clean_text(buffer, cleanup_text_links, cleanup_text_emojis)
130
+ buffer = ""
131
+ is_first_sentence = False
132
+ continue
133
+
134
+ # Check if minimum length reached
135
+ if len(buffer) <= minimum_sentence_length + context_size:
136
+ continue
137
+
138
+ # Potential delimiter character has to be a bit away from the end of the buffer
139
+ # For reliable sentence detection the engine needs enough context to work with
140
+ delimiter_char = buffer[-context_size]
141
+
142
+ if delimiter_char in sentence_delimiters:
143
+
144
+ sentences = nltk.tokenize.sent_tokenize(buffer)
145
+ if len(sentences) > 1:
146
+ if len(sentences[0]) == len(buffer) - context_size + 1:
147
+ yield _clean_text(buffer[:-context_size + 1], cleanup_text_links, cleanup_text_emojis)
148
+ buffer = buffer[-context_size + 1:]
149
+ is_first_sentence = False
150
+
151
+ # Yield remaining buffer
152
+ if buffer:
153
+ sentences = nltk.tokenize.sent_tokenize(buffer)
154
+ sentence_buffer = ""
155
+ for sentence in sentences:
156
+ sentence_buffer += sentence
157
+ if len(sentence_buffer) < minimum_sentence_length:
158
+ sentence_buffer += " "
159
+ continue
160
+ yield _clean_text(sentence_buffer, cleanup_text_links, cleanup_text_emojis)
161
+ sentence_buffer = ""
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.1
2
+ Name: stream2sentence
3
+ Version: 0.1.1
4
+ Summary: Real-time processing and delivery of sentences from a continuous stream of characters or text chunks.
5
+ Home-page: https://github.com/KoljaB/stream2sentence
6
+ Author: Kolja Beigel
7
+ Author-email: kolja.beigel@web.de
8
+ Keywords: realtime,text streaming,stream,sentence,sentence detection,sentence generation,tts,speech synthesis,nltk,text analysis,audio processing,boundary detection,sentence boundary detection
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.6
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: nltk >=3.6
15
+
16
+ # Real-Time Sentence Detection
17
+
18
+ Real-time processing and delivery of sentences from a continuous stream of characters or text chunks.
19
+
20
+ ## Table of Contents
21
+
22
+ - [Features](#features)
23
+ - [Installation](#installation)
24
+ - [Usage](#usage)
25
+ - [Configuration](#configuration)
26
+ - [Contributing](#contributing)
27
+ - [License](#license)
28
+
29
+ ## Features
30
+
31
+ - Generates sentences from a stream of text in real-time.
32
+ - Customizable to finetune/balance speed vs reliability.
33
+ - Option to clean the output by removing links and emojis from the detected sentences.
34
+ - Easy to configure and integrate.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install stream2sentence
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ Pass a generator of characters or text chunks to `generate_sentences()` to get a generator of sentences in return.
45
+
46
+ Here's a basic example:
47
+
48
+ ```python
49
+ from stream2sentence import generate_sentences
50
+
51
+ # Dummy generator for demonstration
52
+ def dummy_generator():
53
+ yield "This is a sentence. And here's another! Yet, "
54
+ yield "there's more. This ends now."
55
+
56
+ for sentence in generate_sentences(dummy_generator()):
57
+ print(sentence)
58
+ ```
59
+
60
+ This will output:
61
+ ```
62
+ This is a sentence.
63
+ And here's another!
64
+ Yet, there's more.
65
+ This ends now.
66
+ ```
67
+
68
+ One main use case of this library is enable fast text to speech synthesis in the context of character feeds generated from large language models: this library enables fastest possible access to a complete sentence or sentence fragment (using the quick_yield_single_sentence_fragment flag) that then can be synthesized in realtime. The usage of this is demonstrated in the test_stream_from_llm.py file in the tests directory.
69
+
70
+ ## Configuration
71
+
72
+ The `generate_sentences()` function has the following parameters:
73
+
74
+ - `generator`: Input character generator.
75
+ Iterator that emits chunks of text. These chunks can be of any size, and they'll be processed one by one to extract sentences from them. It forms the primary source from which the function reads and generates sentences.
76
+
77
+ - `quick_yield_single_sentence_fragment`: Whether to return a sentence fragment as fast as possible.
78
+ This is a feature for realtime speech synthesis. In some use cases you want to audio stream a minimal chunk of text as fast as possible, even when it means to synthesize mid-sentence. In this case you set this flag to True which will yield a synthesizable sentence fragment as early as possible.
79
+
80
+ - `context_size`: Context size for sentence detection.
81
+ This controls how much context is looked at to detect sentence boundaries. It determines the number of characters around a potential delimiter (like a period) that are considered when detecting sentence boundaries. A larger context size allows more reliable sentence boundary detection, but requires buffering more characters before emitting a sentence.
82
+ Default is 10 characters. Increasing this can help detect sentences more accurately, at the cost of added latency.
83
+
84
+ - `minimum_sentence_length`: Minimum length of a sentence to be detected.
85
+ Specifies the minimum number of characters a chunk of text should have before it's considered a potential sentence. This ensures that very short sequences of characters are not mistakenly identified as sentences.Shorter fragments are ignored and kept in the buffer.
86
+ Default is 8 characters. Increasing this avoids emitting very short sentence fragments, at the cost of potentially missing some sentences.
87
+
88
+ - `quick_yield_single_sentence_fragment`: Yield a sentence fragment quickly for real-time applications.
89
+ When set to True, this option allows the function to quickly yield a sentence fragment as soon as it identifies a potential sentence delimiter, without waiting for further context. This is useful for applications like real-time speech synthesis where there's a need for immediate feedback even if the entire sentence isn't complete.
90
+ Default is False. Set to True for faster but potentially less accurate sentence yields.
91
+
92
+ - `cleanup_text_links`: Option to remove links from the output sentences.
93
+ When set to True, this option enables the function to identify and remove HTTP/HTTPS hyperlinks from the emitted output sentences. This helps clean up the output by avoiding unnecessary links.
94
+ Default is False. Set to True if links are not required in the output.
95
+
96
+ - `cleanup_text_emojis`: Option to remove emojis from the output sentences.
97
+ If True, any Unicode emoji characters are identified and removed from the emitted output sentences. This can help to clean up the output.
98
+ Default is False. Set to True if emojis are not required in the output.
99
+
100
+ - `log_characters`: Option to log characters to the console.
101
+ When enabled, each character processed by the function is printed to the console. This is mainly for debugging purposes to observe the flow of characters through the function.
102
+ Default is False. Set to True for a visual representation of characters being processed. Example: allows printing llm output to console when using stream2sentence to prepare input generation for text to speech synthesis.
103
+
104
+
105
+ ## Contributing
106
+
107
+ Any Contributions you make are welcome and **greatly appreciated**.
108
+
109
+ 1. **Fork** the Project.
110
+ 2. **Create** your Feature Branch (`git checkout -b feature/AmazingFeature`).
111
+ 3. **Commit** your Changes (`git commit -m 'Add some AmazingFeature'`).
112
+ 4. **Push** to the Branch (`git push origin feature/AmazingFeature`).
113
+ 5. **Open** a Pull Request.
114
+
115
+ ## License
116
+
117
+ This project is licensed under the MIT License. For more details, see the [`LICENSE`](LICENSE) file.
118
+
119
+ ---
120
+
121
+ Project created and maintained by [Kolja Beigel](https://github.com/KoljaB).
@@ -0,0 +1,6 @@
1
+ stream2sentence/__init__.py,sha256=_-8GjderFI-gHmS4qyG3hafZ7K_XXa5OqjC6XVTyqy4,47
2
+ stream2sentence/stream2sentence.py,sha256=TYTASkFRTdtLsZe5dX4eJlBQ47qnQ7J-SO-4JOht6eg,6052
3
+ stream2sentence-0.1.1.dist-info/METADATA,sha256=6OtBSMHfwZLP5q59lq3UTKF6fpdd_pIyxdGlc_uFnMA,6398
4
+ stream2sentence-0.1.1.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
5
+ stream2sentence-0.1.1.dist-info/top_level.txt,sha256=7RtS4EfUkpV3tMMyUqRgSGDvRm2rPBAYdazTN2z8m1A,16
6
+ stream2sentence-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.41.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ stream2sentence