phrasplit 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {phrasplit-0.2.0 → phrasplit-0.2.2}/PKG-INFO +123 -27
- {phrasplit-0.2.0 → phrasplit-0.2.2}/README.md +119 -25
- phrasplit-0.2.2/benchmarks/benchmark_simple_vs_spacy.py +116 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/phrasplit_segmenter.py +8 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/runbatcheval.py +23 -7
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/api.rst +16 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/cli.rst +42 -7
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/index.rst +33 -6
- phrasplit-0.2.2/docs/installation.rst +127 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/usage.rst +55 -3
- phrasplit-0.2.2/examples/simple_vs_spacy.py +44 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/_version.py +3 -3
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/cli.py +62 -3
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/splitter.py +270 -46
- phrasplit-0.2.2/phrasplit/splitter_without_spacy.py +494 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/PKG-INFO +123 -27
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/SOURCES.txt +6 -1
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/requires.txt +4 -1
- {phrasplit-0.2.0 → phrasplit-0.2.2}/pyproject.toml +4 -1
- phrasplit-0.2.2/tests/test_comparison.py +139 -0
- phrasplit-0.2.2/tests/test_splitter_without_spacy.py +682 -0
- phrasplit-0.2.0/docs/installation.rst +0 -73
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.github/pytest.ini +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.github/workflows/codecov.yml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.github/workflows/pre-commit.yml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.github/workflows/python-publish.yml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.github/workflows/tests.yml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.gitignore +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.pre-commit-config.yaml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.prettierrc.yml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.readthedocs.yaml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/.ruff.toml +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/LICENSE +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/.gitignore +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/README.md +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/build-testset.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/cleanup.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/compare_segmenters.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/debug_sentence.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/runeverything.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/segmenteval.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/sentencizer_segmenter.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/benchmarks/spacy_segmenter.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/conf.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/examples.rst +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/make.bat +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/make.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/docs/requirements.txt +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/__init__.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/audiobook_preparation.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/basic_usage.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/batch_processing.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/subtitle_generation.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/examples/text_analysis.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/__init__.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/abbreviations.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit/py.typed +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/dependency_links.txt +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/entry_points.txt +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/phrasplit.egg-info/top_level.txt +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/requirements-test.txt +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/setup.cfg +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/setup.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/tests/__init__.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/tests/test_cli.py +0 -0
- {phrasplit-0.2.0 → phrasplit-0.2.2}/tests/test_splitter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phrasplit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A simple tool to split text.
|
|
5
5
|
Author-email: Holger Nahrstaedt <nahrstaedt@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -41,10 +41,12 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
License-File: LICENSE
|
|
42
42
|
Requires-Dist: click>=8.0.0
|
|
43
43
|
Requires-Dist: rich>=13.0.0
|
|
44
|
-
|
|
44
|
+
Provides-Extra: nlp
|
|
45
|
+
Requires-Dist: spacy>=3.5.0; extra == "nlp"
|
|
45
46
|
Provides-Extra: dev
|
|
46
47
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
47
48
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
49
|
+
Requires-Dist: spacy>=3.5.0; extra == "dev"
|
|
48
50
|
Dynamic: license-file
|
|
49
51
|
|
|
50
52
|
[](https://pypi.org/project/phrasplit/)
|
|
@@ -54,33 +56,75 @@ Dynamic: license-file
|
|
|
54
56
|
|
|
55
57
|
# phrasplit
|
|
56
58
|
|
|
57
|
-
A Python library for splitting text into sentences, clauses, or paragraphs
|
|
58
|
-
NLP
|
|
59
|
+
A Python library for splitting text into sentences, clauses, or paragraphs. Choose
|
|
60
|
+
between spaCy NLP for best accuracy or fast regex-based splitting for simple use cases.
|
|
59
61
|
|
|
60
62
|
## Features
|
|
61
63
|
|
|
62
|
-
- **
|
|
64
|
+
- **Two modes**: spaCy (accurate) or simple regex (fast, no ML dependencies)
|
|
65
|
+
- **Sentence splitting**: Intelligent sentence boundary detection
|
|
63
66
|
- **Clause splitting**: Split sentences at commas for natural pause points
|
|
64
|
-
- **Paragraph splitting**: Split text at double newlines
|
|
67
|
+
- **Paragraph splitting**: Split text at double newlines (no spaCy needed)
|
|
65
68
|
- **Hierarchical splitting**: Split text with paragraph/sentence position tracking
|
|
66
69
|
- **Long line splitting**: Break long lines at sentence/clause boundaries
|
|
67
70
|
- **Abbreviation handling**: Correctly handles Mr., Dr., U.S.A., etc.
|
|
68
71
|
- **Ellipsis support**: Preserves ellipses without incorrect splitting
|
|
72
|
+
- **25+ languages**: Multi-language abbreviation support
|
|
69
73
|
|
|
70
74
|
## Installation
|
|
71
75
|
|
|
76
|
+
### Basic Installation (Simple Mode)
|
|
77
|
+
|
|
78
|
+
For fast, regex-based splitting without ML dependencies:
|
|
79
|
+
|
|
72
80
|
```bash
|
|
73
81
|
pip install phrasplit
|
|
74
82
|
```
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
### Full Installation (spaCy Mode)
|
|
85
|
+
|
|
86
|
+
For best accuracy with complex text, install with spaCy:
|
|
77
87
|
|
|
78
88
|
```bash
|
|
89
|
+
pip install phrasplit[nlp]
|
|
79
90
|
python -m spacy download en_core_web_sm
|
|
80
91
|
```
|
|
81
92
|
|
|
93
|
+
## Performance Comparison
|
|
94
|
+
|
|
95
|
+
| Mode | Speed | Accuracy | Dependencies | When to Use |
|
|
96
|
+
| ---------- | ----------- | -------- | ----------------------- | -------------------------------- |
|
|
97
|
+
| **Simple** | ~60x faster | ~85-90% | None (regex only) | Simple text, speed-critical apps |
|
|
98
|
+
| **spaCy** | Baseline | ~95%+ | spaCy + models (~500MB) | Complex text, best accuracy |
|
|
99
|
+
|
|
100
|
+
Benchmark results (1000 sentences):
|
|
101
|
+
|
|
102
|
+
- spaCy: 1091ms
|
|
103
|
+
- Simple: 17ms (63x faster)
|
|
104
|
+
|
|
105
|
+
Both modes produce nearly identical results for well-formatted text.
|
|
106
|
+
|
|
82
107
|
## Quick Start
|
|
83
108
|
|
|
109
|
+
### Auto-Detection (Recommended)
|
|
110
|
+
|
|
111
|
+
Phrasplit automatically uses spaCy if installed, otherwise falls back to simple mode:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from phrasplit import split_sentences, split_clauses, split_paragraphs
|
|
115
|
+
|
|
116
|
+
# Uses spaCy if installed, otherwise simple mode
|
|
117
|
+
text = "Dr. Smith is here. She has a Ph.D. in Chemistry."
|
|
118
|
+
sentences = split_sentences(text)
|
|
119
|
+
# ['Dr. Smith is here.', 'She has a Ph.D. in Chemistry.']
|
|
120
|
+
|
|
121
|
+
# Force simple mode (even if spaCy is installed)
|
|
122
|
+
sentences = split_sentences(text, use_spacy=False)
|
|
123
|
+
|
|
124
|
+
# Force spaCy mode (error if not installed)
|
|
125
|
+
sentences = split_sentences(text, use_spacy=True)
|
|
126
|
+
```
|
|
127
|
+
|
|
84
128
|
### Python API
|
|
85
129
|
|
|
86
130
|
```python
|
|
@@ -96,7 +140,7 @@ text = "I like coffee, and I like tea."
|
|
|
96
140
|
clauses = split_clauses(text)
|
|
97
141
|
# ['I like coffee,', 'and I like tea.']
|
|
98
142
|
|
|
99
|
-
# Split text into paragraphs
|
|
143
|
+
# Split text into paragraphs (no spaCy needed)
|
|
100
144
|
text = "First paragraph.\n\nSecond paragraph."
|
|
101
145
|
paragraphs = split_paragraphs(text)
|
|
102
146
|
# ['First paragraph.', 'Second paragraph.']
|
|
@@ -140,24 +184,33 @@ Available modes:
|
|
|
140
184
|
### Command Line Interface
|
|
141
185
|
|
|
142
186
|
```bash
|
|
143
|
-
# Split into sentences
|
|
187
|
+
# Split into sentences (auto-detects spaCy or uses simple mode)
|
|
144
188
|
phrasplit sentences input.txt -o output.txt
|
|
145
189
|
|
|
190
|
+
# Force simple mode (60x faster, no spaCy required)
|
|
191
|
+
phrasplit sentences input.txt --simple
|
|
192
|
+
|
|
146
193
|
# Split into clauses
|
|
147
194
|
phrasplit clauses input.txt -o output.txt
|
|
148
195
|
|
|
149
|
-
#
|
|
196
|
+
# Use simple mode for clauses (faster)
|
|
197
|
+
phrasplit clauses input.txt --simple -o output.txt
|
|
198
|
+
|
|
199
|
+
# Split into paragraphs (no spaCy needed)
|
|
150
200
|
phrasplit paragraphs input.txt -o output.txt
|
|
151
201
|
|
|
152
202
|
# Split long lines (default max 80 characters)
|
|
153
203
|
phrasplit longlines input.txt -o output.txt --max-length 60
|
|
154
204
|
|
|
155
|
-
#
|
|
205
|
+
# Long lines with simple mode
|
|
206
|
+
phrasplit longlines input.txt --simple --max-length 60
|
|
207
|
+
|
|
208
|
+
# Use a different spaCy model (only for spaCy mode)
|
|
156
209
|
phrasplit sentences input.txt --model en_core_web_lg
|
|
157
210
|
|
|
158
211
|
# Read from stdin (pipe or redirect)
|
|
159
212
|
echo "Hello world. This is a test." | phrasplit sentences
|
|
160
|
-
cat input.txt | phrasplit clauses -o output.txt
|
|
213
|
+
cat input.txt | phrasplit clauses --simple -o output.txt
|
|
161
214
|
|
|
162
215
|
# Explicit stdin with dash
|
|
163
216
|
phrasplit sentences - < input.txt
|
|
@@ -165,21 +218,28 @@ phrasplit sentences - < input.txt
|
|
|
165
218
|
|
|
166
219
|
## API Reference
|
|
167
220
|
|
|
168
|
-
### `split_sentences(text, language_model="en_core_web_sm", apply_corrections=True,
|
|
221
|
+
### `split_sentences(text, language_model="en_core_web_sm", apply_corrections=True, use_spacy=None)`
|
|
169
222
|
|
|
170
|
-
Split text into sentences
|
|
223
|
+
Split text into sentences.
|
|
171
224
|
|
|
172
225
|
**Parameters:**
|
|
173
226
|
|
|
174
227
|
- `text`: Input text string
|
|
175
|
-
- `language_model`:
|
|
228
|
+
- `language_model`: Language model name (e.g., "en_core_web_sm", "de_core_news_sm")
|
|
229
|
+
- For spaCy mode: Name of the spaCy model to use
|
|
230
|
+
- For simple mode: Used to determine language for abbreviation handling
|
|
176
231
|
- `apply_corrections`: Apply post-processing corrections for URLs and abbreviations
|
|
177
|
-
(default: True)
|
|
178
|
-
- `
|
|
232
|
+
(default: True, only applies to spaCy mode)
|
|
233
|
+
- `use_spacy`: Choose implementation:
|
|
234
|
+
- `None` (default): Auto-detect (use spaCy if available)
|
|
235
|
+
- `True`: Force spaCy mode (raises ImportError if not installed)
|
|
236
|
+
- `False`: Force simple regex mode
|
|
179
237
|
|
|
180
238
|
**Returns:** List of sentences
|
|
181
239
|
|
|
182
|
-
|
|
240
|
+
**Raises:** `ImportError` if `use_spacy=True` but spaCy is not installed
|
|
241
|
+
|
|
242
|
+
### `split_clauses(text, language_model="en_core_web_sm", use_spacy=None)`
|
|
183
243
|
|
|
184
244
|
Split text into comma-separated parts. Useful for creating natural pause points in
|
|
185
245
|
audiobook/TTS applications.
|
|
@@ -187,13 +247,14 @@ audiobook/TTS applications.
|
|
|
187
247
|
**Parameters:**
|
|
188
248
|
|
|
189
249
|
- `text`: Input text string
|
|
190
|
-
- `language_model`:
|
|
250
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
251
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
191
252
|
|
|
192
253
|
**Returns:** List of clauses (comma stays at end of each part)
|
|
193
254
|
|
|
194
255
|
### `split_paragraphs(text)`
|
|
195
256
|
|
|
196
|
-
Split text into paragraphs at double newlines.
|
|
257
|
+
Split text into paragraphs at double newlines. Works without spaCy.
|
|
197
258
|
|
|
198
259
|
**Parameters:**
|
|
199
260
|
|
|
@@ -201,7 +262,7 @@ Split text into paragraphs at double newlines.
|
|
|
201
262
|
|
|
202
263
|
**Returns:** List of paragraphs
|
|
203
264
|
|
|
204
|
-
### `split_text(text, mode="sentence", language_model="en_core_web_sm", apply_corrections=True,
|
|
265
|
+
### `split_text(text, mode="sentence", language_model="en_core_web_sm", apply_corrections=True, use_spacy=None)`
|
|
205
266
|
|
|
206
267
|
Split text into segments with hierarchical position information.
|
|
207
268
|
|
|
@@ -209,9 +270,9 @@ Split text into segments with hierarchical position information.
|
|
|
209
270
|
|
|
210
271
|
- `text`: Input text string
|
|
211
272
|
- `mode`: Splitting mode - "paragraph", "sentence", or "clause"
|
|
212
|
-
- `language_model`:
|
|
273
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
213
274
|
- `apply_corrections`: Apply post-processing corrections (default: True)
|
|
214
|
-
- `
|
|
275
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
215
276
|
|
|
216
277
|
**Returns:** List of `Segment` namedtuples with fields:
|
|
217
278
|
|
|
@@ -219,7 +280,7 @@ Split text into segments with hierarchical position information.
|
|
|
219
280
|
- `paragraph`: Paragraph index (0-based)
|
|
220
281
|
- `sentence`: Sentence index within paragraph (0-based), None for paragraph mode
|
|
221
282
|
|
|
222
|
-
### `split_long_lines(text, max_length, language_model="en_core_web_sm")`
|
|
283
|
+
### `split_long_lines(text, max_length, language_model="en_core_web_sm", use_spacy=None)`
|
|
223
284
|
|
|
224
285
|
Split lines exceeding max_length at sentence/clause boundaries.
|
|
225
286
|
|
|
@@ -227,7 +288,8 @@ Split lines exceeding max_length at sentence/clause boundaries.
|
|
|
227
288
|
|
|
228
289
|
- `text`: Input text string
|
|
229
290
|
- `max_length`: Maximum line length in characters (must be >= 1)
|
|
230
|
-
- `language_model`:
|
|
291
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
292
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
231
293
|
|
|
232
294
|
**Returns:** List of lines, each within max_length (except single words exceeding limit)
|
|
233
295
|
|
|
@@ -286,10 +348,44 @@ for paragraph in split_paragraphs(text):
|
|
|
286
348
|
|
|
287
349
|
## Requirements
|
|
288
350
|
|
|
289
|
-
- Python 3.
|
|
290
|
-
- spaCy 3.5+
|
|
351
|
+
- Python 3.10+
|
|
291
352
|
- click 8.0+
|
|
292
353
|
- rich 13.0+
|
|
354
|
+
- spaCy 3.5+ (optional, for best accuracy)
|
|
355
|
+
|
|
356
|
+
## Choosing Between Modes
|
|
357
|
+
|
|
358
|
+
### Use Simple Mode When:
|
|
359
|
+
|
|
360
|
+
- Processing simple, well-formatted text
|
|
361
|
+
- Speed is critical (60-100x faster)
|
|
362
|
+
- Deploying in constrained environments (no ML dependencies)
|
|
363
|
+
- Installing spaCy models is not feasible (~500MB per language)
|
|
364
|
+
|
|
365
|
+
### Use spaCy Mode When:
|
|
366
|
+
|
|
367
|
+
- Processing complex, informal, or poorly formatted text
|
|
368
|
+
- Accuracy is paramount (5-10% better)
|
|
369
|
+
- Already using spaCy in your pipeline
|
|
370
|
+
- Working with academic or literary texts
|
|
371
|
+
|
|
372
|
+
## Migration Guide
|
|
373
|
+
|
|
374
|
+
### Upgrading from Previous Versions
|
|
375
|
+
|
|
376
|
+
Version 1.x made spaCy optional. Your existing code continues to work:
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
# Old code (still works, auto-uses spaCy if installed)
|
|
380
|
+
from phrasplit import split_sentences
|
|
381
|
+
sentences = split_sentences(text)
|
|
382
|
+
|
|
383
|
+
# New: Explicit control
|
|
384
|
+
sentences = split_sentences(text, use_spacy=False) # Force simple
|
|
385
|
+
sentences = split_sentences(text, use_spacy=True) # Force spaCy
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
The `split_on_colon` parameter is deprecated and will be removed in a future version.
|
|
293
389
|
|
|
294
390
|
## License
|
|
295
391
|
|
|
@@ -5,33 +5,75 @@
|
|
|
5
5
|
|
|
6
6
|
# phrasplit
|
|
7
7
|
|
|
8
|
-
A Python library for splitting text into sentences, clauses, or paragraphs
|
|
9
|
-
NLP
|
|
8
|
+
A Python library for splitting text into sentences, clauses, or paragraphs. Choose
|
|
9
|
+
between spaCy NLP for best accuracy or fast regex-based splitting for simple use cases.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
- **
|
|
13
|
+
- **Two modes**: spaCy (accurate) or simple regex (fast, no ML dependencies)
|
|
14
|
+
- **Sentence splitting**: Intelligent sentence boundary detection
|
|
14
15
|
- **Clause splitting**: Split sentences at commas for natural pause points
|
|
15
|
-
- **Paragraph splitting**: Split text at double newlines
|
|
16
|
+
- **Paragraph splitting**: Split text at double newlines (no spaCy needed)
|
|
16
17
|
- **Hierarchical splitting**: Split text with paragraph/sentence position tracking
|
|
17
18
|
- **Long line splitting**: Break long lines at sentence/clause boundaries
|
|
18
19
|
- **Abbreviation handling**: Correctly handles Mr., Dr., U.S.A., etc.
|
|
19
20
|
- **Ellipsis support**: Preserves ellipses without incorrect splitting
|
|
21
|
+
- **25+ languages**: Multi-language abbreviation support
|
|
20
22
|
|
|
21
23
|
## Installation
|
|
22
24
|
|
|
25
|
+
### Basic Installation (Simple Mode)
|
|
26
|
+
|
|
27
|
+
For fast, regex-based splitting without ML dependencies:
|
|
28
|
+
|
|
23
29
|
```bash
|
|
24
30
|
pip install phrasplit
|
|
25
31
|
```
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
### Full Installation (spaCy Mode)
|
|
34
|
+
|
|
35
|
+
For best accuracy with complex text, install with spaCy:
|
|
28
36
|
|
|
29
37
|
```bash
|
|
38
|
+
pip install phrasplit[nlp]
|
|
30
39
|
python -m spacy download en_core_web_sm
|
|
31
40
|
```
|
|
32
41
|
|
|
42
|
+
## Performance Comparison
|
|
43
|
+
|
|
44
|
+
| Mode | Speed | Accuracy | Dependencies | When to Use |
|
|
45
|
+
| ---------- | ----------- | -------- | ----------------------- | -------------------------------- |
|
|
46
|
+
| **Simple** | ~60x faster | ~85-90% | None (regex only) | Simple text, speed-critical apps |
|
|
47
|
+
| **spaCy** | Baseline | ~95%+ | spaCy + models (~500MB) | Complex text, best accuracy |
|
|
48
|
+
|
|
49
|
+
Benchmark results (1000 sentences):
|
|
50
|
+
|
|
51
|
+
- spaCy: 1091ms
|
|
52
|
+
- Simple: 17ms (63x faster)
|
|
53
|
+
|
|
54
|
+
Both modes produce nearly identical results for well-formatted text.
|
|
55
|
+
|
|
33
56
|
## Quick Start
|
|
34
57
|
|
|
58
|
+
### Auto-Detection (Recommended)
|
|
59
|
+
|
|
60
|
+
Phrasplit automatically uses spaCy if installed, otherwise falls back to simple mode:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from phrasplit import split_sentences, split_clauses, split_paragraphs
|
|
64
|
+
|
|
65
|
+
# Uses spaCy if installed, otherwise simple mode
|
|
66
|
+
text = "Dr. Smith is here. She has a Ph.D. in Chemistry."
|
|
67
|
+
sentences = split_sentences(text)
|
|
68
|
+
# ['Dr. Smith is here.', 'She has a Ph.D. in Chemistry.']
|
|
69
|
+
|
|
70
|
+
# Force simple mode (even if spaCy is installed)
|
|
71
|
+
sentences = split_sentences(text, use_spacy=False)
|
|
72
|
+
|
|
73
|
+
# Force spaCy mode (error if not installed)
|
|
74
|
+
sentences = split_sentences(text, use_spacy=True)
|
|
75
|
+
```
|
|
76
|
+
|
|
35
77
|
### Python API
|
|
36
78
|
|
|
37
79
|
```python
|
|
@@ -47,7 +89,7 @@ text = "I like coffee, and I like tea."
|
|
|
47
89
|
clauses = split_clauses(text)
|
|
48
90
|
# ['I like coffee,', 'and I like tea.']
|
|
49
91
|
|
|
50
|
-
# Split text into paragraphs
|
|
92
|
+
# Split text into paragraphs (no spaCy needed)
|
|
51
93
|
text = "First paragraph.\n\nSecond paragraph."
|
|
52
94
|
paragraphs = split_paragraphs(text)
|
|
53
95
|
# ['First paragraph.', 'Second paragraph.']
|
|
@@ -91,24 +133,33 @@ Available modes:
|
|
|
91
133
|
### Command Line Interface
|
|
92
134
|
|
|
93
135
|
```bash
|
|
94
|
-
# Split into sentences
|
|
136
|
+
# Split into sentences (auto-detects spaCy or uses simple mode)
|
|
95
137
|
phrasplit sentences input.txt -o output.txt
|
|
96
138
|
|
|
139
|
+
# Force simple mode (60x faster, no spaCy required)
|
|
140
|
+
phrasplit sentences input.txt --simple
|
|
141
|
+
|
|
97
142
|
# Split into clauses
|
|
98
143
|
phrasplit clauses input.txt -o output.txt
|
|
99
144
|
|
|
100
|
-
#
|
|
145
|
+
# Use simple mode for clauses (faster)
|
|
146
|
+
phrasplit clauses input.txt --simple -o output.txt
|
|
147
|
+
|
|
148
|
+
# Split into paragraphs (no spaCy needed)
|
|
101
149
|
phrasplit paragraphs input.txt -o output.txt
|
|
102
150
|
|
|
103
151
|
# Split long lines (default max 80 characters)
|
|
104
152
|
phrasplit longlines input.txt -o output.txt --max-length 60
|
|
105
153
|
|
|
106
|
-
#
|
|
154
|
+
# Long lines with simple mode
|
|
155
|
+
phrasplit longlines input.txt --simple --max-length 60
|
|
156
|
+
|
|
157
|
+
# Use a different spaCy model (only for spaCy mode)
|
|
107
158
|
phrasplit sentences input.txt --model en_core_web_lg
|
|
108
159
|
|
|
109
160
|
# Read from stdin (pipe or redirect)
|
|
110
161
|
echo "Hello world. This is a test." | phrasplit sentences
|
|
111
|
-
cat input.txt | phrasplit clauses -o output.txt
|
|
162
|
+
cat input.txt | phrasplit clauses --simple -o output.txt
|
|
112
163
|
|
|
113
164
|
# Explicit stdin with dash
|
|
114
165
|
phrasplit sentences - < input.txt
|
|
@@ -116,21 +167,28 @@ phrasplit sentences - < input.txt
|
|
|
116
167
|
|
|
117
168
|
## API Reference
|
|
118
169
|
|
|
119
|
-
### `split_sentences(text, language_model="en_core_web_sm", apply_corrections=True,
|
|
170
|
+
### `split_sentences(text, language_model="en_core_web_sm", apply_corrections=True, use_spacy=None)`
|
|
120
171
|
|
|
121
|
-
Split text into sentences
|
|
172
|
+
Split text into sentences.
|
|
122
173
|
|
|
123
174
|
**Parameters:**
|
|
124
175
|
|
|
125
176
|
- `text`: Input text string
|
|
126
|
-
- `language_model`:
|
|
177
|
+
- `language_model`: Language model name (e.g., "en_core_web_sm", "de_core_news_sm")
|
|
178
|
+
- For spaCy mode: Name of the spaCy model to use
|
|
179
|
+
- For simple mode: Used to determine language for abbreviation handling
|
|
127
180
|
- `apply_corrections`: Apply post-processing corrections for URLs and abbreviations
|
|
128
|
-
(default: True)
|
|
129
|
-
- `
|
|
181
|
+
(default: True, only applies to spaCy mode)
|
|
182
|
+
- `use_spacy`: Choose implementation:
|
|
183
|
+
- `None` (default): Auto-detect (use spaCy if available)
|
|
184
|
+
- `True`: Force spaCy mode (raises ImportError if not installed)
|
|
185
|
+
- `False`: Force simple regex mode
|
|
130
186
|
|
|
131
187
|
**Returns:** List of sentences
|
|
132
188
|
|
|
133
|
-
|
|
189
|
+
**Raises:** `ImportError` if `use_spacy=True` but spaCy is not installed
|
|
190
|
+
|
|
191
|
+
### `split_clauses(text, language_model="en_core_web_sm", use_spacy=None)`
|
|
134
192
|
|
|
135
193
|
Split text into comma-separated parts. Useful for creating natural pause points in
|
|
136
194
|
audiobook/TTS applications.
|
|
@@ -138,13 +196,14 @@ audiobook/TTS applications.
|
|
|
138
196
|
**Parameters:**
|
|
139
197
|
|
|
140
198
|
- `text`: Input text string
|
|
141
|
-
- `language_model`:
|
|
199
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
200
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
142
201
|
|
|
143
202
|
**Returns:** List of clauses (comma stays at end of each part)
|
|
144
203
|
|
|
145
204
|
### `split_paragraphs(text)`
|
|
146
205
|
|
|
147
|
-
Split text into paragraphs at double newlines.
|
|
206
|
+
Split text into paragraphs at double newlines. Works without spaCy.
|
|
148
207
|
|
|
149
208
|
**Parameters:**
|
|
150
209
|
|
|
@@ -152,7 +211,7 @@ Split text into paragraphs at double newlines.
|
|
|
152
211
|
|
|
153
212
|
**Returns:** List of paragraphs
|
|
154
213
|
|
|
155
|
-
### `split_text(text, mode="sentence", language_model="en_core_web_sm", apply_corrections=True,
|
|
214
|
+
### `split_text(text, mode="sentence", language_model="en_core_web_sm", apply_corrections=True, use_spacy=None)`
|
|
156
215
|
|
|
157
216
|
Split text into segments with hierarchical position information.
|
|
158
217
|
|
|
@@ -160,9 +219,9 @@ Split text into segments with hierarchical position information.
|
|
|
160
219
|
|
|
161
220
|
- `text`: Input text string
|
|
162
221
|
- `mode`: Splitting mode - "paragraph", "sentence", or "clause"
|
|
163
|
-
- `language_model`:
|
|
222
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
164
223
|
- `apply_corrections`: Apply post-processing corrections (default: True)
|
|
165
|
-
- `
|
|
224
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
166
225
|
|
|
167
226
|
**Returns:** List of `Segment` namedtuples with fields:
|
|
168
227
|
|
|
@@ -170,7 +229,7 @@ Split text into segments with hierarchical position information.
|
|
|
170
229
|
- `paragraph`: Paragraph index (0-based)
|
|
171
230
|
- `sentence`: Sentence index within paragraph (0-based), None for paragraph mode
|
|
172
231
|
|
|
173
|
-
### `split_long_lines(text, max_length, language_model="en_core_web_sm")`
|
|
232
|
+
### `split_long_lines(text, max_length, language_model="en_core_web_sm", use_spacy=None)`
|
|
174
233
|
|
|
175
234
|
Split lines exceeding max_length at sentence/clause boundaries.
|
|
176
235
|
|
|
@@ -178,7 +237,8 @@ Split lines exceeding max_length at sentence/clause boundaries.
|
|
|
178
237
|
|
|
179
238
|
- `text`: Input text string
|
|
180
239
|
- `max_length`: Maximum line length in characters (must be >= 1)
|
|
181
|
-
- `language_model`:
|
|
240
|
+
- `language_model`: Language model name (default: "en_core_web_sm")
|
|
241
|
+
- `use_spacy`: Choose implementation (default: None for auto-detect)
|
|
182
242
|
|
|
183
243
|
**Returns:** List of lines, each within max_length (except single words exceeding limit)
|
|
184
244
|
|
|
@@ -237,10 +297,44 @@ for paragraph in split_paragraphs(text):
|
|
|
237
297
|
|
|
238
298
|
## Requirements
|
|
239
299
|
|
|
240
|
-
- Python 3.
|
|
241
|
-
- spaCy 3.5+
|
|
300
|
+
- Python 3.10+
|
|
242
301
|
- click 8.0+
|
|
243
302
|
- rich 13.0+
|
|
303
|
+
- spaCy 3.5+ (optional, for best accuracy)
|
|
304
|
+
|
|
305
|
+
## Choosing Between Modes
|
|
306
|
+
|
|
307
|
+
### Use Simple Mode When:
|
|
308
|
+
|
|
309
|
+
- Processing simple, well-formatted text
|
|
310
|
+
- Speed is critical (60-100x faster)
|
|
311
|
+
- Deploying in constrained environments (no ML dependencies)
|
|
312
|
+
- Installing spaCy models is not feasible (~500MB per language)
|
|
313
|
+
|
|
314
|
+
### Use spaCy Mode When:
|
|
315
|
+
|
|
316
|
+
- Processing complex, informal, or poorly formatted text
|
|
317
|
+
- Accuracy is paramount (5-10% better)
|
|
318
|
+
- Already using spaCy in your pipeline
|
|
319
|
+
- Working with academic or literary texts
|
|
320
|
+
|
|
321
|
+
## Migration Guide
|
|
322
|
+
|
|
323
|
+
### Upgrading from Previous Versions
|
|
324
|
+
|
|
325
|
+
Version 1.x made spaCy optional. Your existing code continues to work:
|
|
326
|
+
|
|
327
|
+
```python
|
|
328
|
+
# Old code (still works, auto-uses spaCy if installed)
|
|
329
|
+
from phrasplit import split_sentences
|
|
330
|
+
sentences = split_sentences(text)
|
|
331
|
+
|
|
332
|
+
# New: Explicit control
|
|
333
|
+
sentences = split_sentences(text, use_spacy=False) # Force simple
|
|
334
|
+
sentences = split_sentences(text, use_spacy=True) # Force spaCy
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The `split_on_colon` parameter is deprecated and will be removed in a future version.
|
|
244
338
|
|
|
245
339
|
## License
|
|
246
340
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Performance benchmark comparing spaCy vs simple splitters.
|
|
2
|
+
|
|
3
|
+
Run this script to benchmark both implementations.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
from phrasplit import split_sentences
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def benchmark_split_sentences(
|
|
12
|
+
text: str, runs: int = 5
|
|
13
|
+
) -> tuple[float, float, int, int]:
|
|
14
|
+
"""Benchmark sentence splitting with both implementations."""
|
|
15
|
+
# Warm up
|
|
16
|
+
split_sentences(text, use_spacy=True)
|
|
17
|
+
split_sentences(text, use_spacy=False)
|
|
18
|
+
|
|
19
|
+
# Benchmark spaCy
|
|
20
|
+
spacy_times = []
|
|
21
|
+
spacy_count = 0
|
|
22
|
+
for _ in range(runs):
|
|
23
|
+
start = time.time()
|
|
24
|
+
result = split_sentences(text, use_spacy=True)
|
|
25
|
+
spacy_times.append(time.time() - start)
|
|
26
|
+
spacy_count = len(result)
|
|
27
|
+
|
|
28
|
+
# Benchmark simple
|
|
29
|
+
simple_times = []
|
|
30
|
+
simple_count = 0
|
|
31
|
+
for _ in range(runs):
|
|
32
|
+
start = time.time()
|
|
33
|
+
result = split_sentences(text, use_spacy=False)
|
|
34
|
+
simple_times.append(time.time() - start)
|
|
35
|
+
simple_count = len(result)
|
|
36
|
+
|
|
37
|
+
spacy_avg = sum(spacy_times) / len(spacy_times)
|
|
38
|
+
simple_avg = sum(simple_times) / len(simple_times)
|
|
39
|
+
|
|
40
|
+
return spacy_avg, simple_avg, spacy_count, simple_count
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main() -> None:
|
|
44
|
+
"""Run benchmarks and print results."""
|
|
45
|
+
print("=" * 70)
|
|
46
|
+
print("Phrasplit Performance Benchmark: spaCy vs Simple Mode")
|
|
47
|
+
print("=" * 70)
|
|
48
|
+
|
|
49
|
+
# Test 1: Short text (a few sentences)
|
|
50
|
+
print("\n1. Short text (3 sentences, ~50 words)")
|
|
51
|
+
print("-" * 70)
|
|
52
|
+
short_text = (
|
|
53
|
+
"Dr. Smith has a Ph.D. in Chemistry. "
|
|
54
|
+
'She said, "It\'s working!" The results were published.'
|
|
55
|
+
)
|
|
56
|
+
spacy_time, simple_time, spacy_count, simple_count = benchmark_split_sentences(
|
|
57
|
+
short_text
|
|
58
|
+
)
|
|
59
|
+
print(f" spaCy: {spacy_time * 1000:.2f}ms ({spacy_count} sentences)")
|
|
60
|
+
print(f" Simple: {simple_time * 1000:.2f}ms ({simple_count} sentences)")
|
|
61
|
+
print(f" Speedup: {spacy_time / simple_time:.1f}x")
|
|
62
|
+
|
|
63
|
+
# Test 2: Medium text (many sentences)
|
|
64
|
+
print("\n2. Medium text (100 sentences)")
|
|
65
|
+
print("-" * 70)
|
|
66
|
+
medium_text = ". ".join([f"This is sentence number {i}" for i in range(100)])
|
|
67
|
+
spacy_time, simple_time, spacy_count, simple_count = benchmark_split_sentences(
|
|
68
|
+
medium_text
|
|
69
|
+
)
|
|
70
|
+
print(f" spaCy: {spacy_time * 1000:.2f}ms ({spacy_count} sentences)")
|
|
71
|
+
print(f" Simple: {simple_time * 1000:.2f}ms ({simple_count} sentences)")
|
|
72
|
+
print(f" Speedup: {spacy_time / simple_time:.1f}x")
|
|
73
|
+
|
|
74
|
+
# Test 3: Complex text with abbreviations
|
|
75
|
+
print("\n3. Complex text (abbreviations, acronyms, URLs)")
|
|
76
|
+
print("-" * 70)
|
|
77
|
+
complex_text = (
|
|
78
|
+
"Mr. J.R.R. Tolkien wrote many books. "
|
|
79
|
+
"Visit www.example.com for more info. "
|
|
80
|
+
"The U.S.A. is a big country. "
|
|
81
|
+
"Prof. Green met Dr. Stone at Inc. headquarters."
|
|
82
|
+
)
|
|
83
|
+
spacy_time, simple_time, spacy_count, simple_count = benchmark_split_sentences(
|
|
84
|
+
complex_text
|
|
85
|
+
)
|
|
86
|
+
print(f" spaCy: {spacy_time * 1000:.2f}ms ({spacy_count} sentences)")
|
|
87
|
+
print(f" Simple: {simple_time * 1000:.2f}ms ({simple_count} sentences)")
|
|
88
|
+
print(f" Speedup: {spacy_time / simple_time:.1f}x")
|
|
89
|
+
|
|
90
|
+
# Test 4: Very long text
|
|
91
|
+
print("\n4. Long text (1000 sentences)")
|
|
92
|
+
print("-" * 70)
|
|
93
|
+
long_text = ". ".join(
|
|
94
|
+
[f"Sentence {i} with some more words to make it realistic" for i in range(1000)]
|
|
95
|
+
)
|
|
96
|
+
spacy_time, simple_time, spacy_count, simple_count = benchmark_split_sentences(
|
|
97
|
+
long_text, runs=3
|
|
98
|
+
)
|
|
99
|
+
print(f" spaCy: {spacy_time * 1000:.2f}ms ({spacy_count} sentences)")
|
|
100
|
+
print(f" Simple: {simple_time * 1000:.2f}ms ({simple_count} sentences)")
|
|
101
|
+
print(f" Speedup: {spacy_time / simple_time:.1f}x")
|
|
102
|
+
|
|
103
|
+
# Summary
|
|
104
|
+
print("\n" + "=" * 70)
|
|
105
|
+
print("SUMMARY")
|
|
106
|
+
print("=" * 70)
|
|
107
|
+
print("Simple mode is typically 20-100x faster than spaCy for common text.")
|
|
108
|
+
print("Both implementations produce similar results for well-formatted text.")
|
|
109
|
+
print("\nWhen to use:")
|
|
110
|
+
print(" • Simple mode: Speed-critical applications, simple text, no ML models")
|
|
111
|
+
print(" • spaCy mode: Complex text, best accuracy, NLP pipelines")
|
|
112
|
+
print("=" * 70)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
main()
|
|
@@ -143,6 +143,12 @@ def main() -> None:
|
|
|
143
143
|
default=False,
|
|
144
144
|
help="Disable splitting on colons",
|
|
145
145
|
)
|
|
146
|
+
parser.add_argument(
|
|
147
|
+
"--simple",
|
|
148
|
+
action="store_true",
|
|
149
|
+
default=False,
|
|
150
|
+
help="Use simple regex-based splitting (no spaCy required)",
|
|
151
|
+
)
|
|
146
152
|
|
|
147
153
|
args = parser.parse_args()
|
|
148
154
|
|
|
@@ -162,10 +168,12 @@ def main() -> None:
|
|
|
162
168
|
# Use the actual phrasplit.split_sentences() function
|
|
163
169
|
# Long text handling is built-in (automatic chunking)
|
|
164
170
|
split_on_colon = not args.no_split_on_colon
|
|
171
|
+
use_spacy = None if not args.simple else False
|
|
165
172
|
sentences = split_sentences(
|
|
166
173
|
line,
|
|
167
174
|
language_model=model_name,
|
|
168
175
|
split_on_colon=split_on_colon,
|
|
176
|
+
use_spacy=use_spacy,
|
|
169
177
|
)
|
|
170
178
|
|
|
171
179
|
# Write each sentence on its own line
|