Fast, parallel sentence boundary detection using Delta-Stack Monoid algorithm
Project description
Sakurs Python Bindings
High-performance sentence boundary detection for Python using the Delta-Stack Monoid algorithm.
Table of Contents
- Installation
- Quick Start
- API Reference
- Supported Languages
- Performance Tips
- Benchmarks
- Error Handling
- Development
- License
Installation
pip install sakurs
To build from source:
git clone https://github.com/sog4be/sakurs.git
cd sakurs/sakurs-py
uv pip install -e .
Requirements: Python 3.9 or later
Quick Start
import sakurs
# Simple sentence splitting
sentences = sakurs.split("Hello world. This is a test.")
print(sentences) # ['Hello world.', 'This is a test.']
# Process files directly
sentences = sakurs.split("document.txt") # Path as string
sentences = sakurs.split(Path("document.txt")) # Path object
# Specify language
sentences = sakurs.split("これは日本語です。テストです。", language="ja")
print(sentences) # ['これは日本語です。', 'テストです。']
# Get detailed output with offsets
results = sakurs.split(text, return_details=True)
for sentence in results:
print(f"{sentence.text} [{sentence.start}:{sentence.end}]")
# Memory-efficient processing for large files
for sentence in sakurs.split_large_file("huge_corpus.txt", max_memory_mb=50):
process(sentence) # Process each sentence as it's found
# Responsive iteration (loads all, yields incrementally)
for sentence in sakurs.iter_split("document.txt"):
print(sentence) # Get results as they're processed
API Reference
Table of Contents
Functions
sakurs.split
Split text or file into sentences.
Signature:
sakurs.split(
input,
*,
language=None,
language_config=None,
threads=None,
chunk_kb=None,
parallel=False,
execution_mode="adaptive",
return_details=False,
encoding="utf-8"
)
Parameters:
input(str | Path | TextIO | BinaryIO): Text string, file path, or file-like objectlanguage(str, optional): Language code ("en", "ja")language_config(LanguageConfig, optional): Custom language configurationthreads(int, optional): Number of threads (None for auto)chunk_kb(int, optional): Chunk size in KB (default: 256) for parallel processing (default: 256)parallel(bool): Force parallel processing even for small inputsexecution_mode(str): "sequential", "parallel", or "adaptive" (default)return_details(bool): Return Sentence objects with metadata instead of stringsencoding(str): Text encoding for file inputs (default: "utf-8")
Returns: List[str] or List[Sentence] if return_details=True
sakurs.iter_split
Process input and return sentences as an iterator. Loads entire input but yields incrementally.
Signature:
sakurs.iter_split(
input,
*,
language=None,
language_config=None,
threads=None,
chunk_kb=None,
encoding="utf-8"
)
Parameters: Same as split() except no return_details parameter
Returns: Iterator[str] - Iterator yielding sentences
sakurs.split_large_file
Process large files with limited memory usage.
Signature:
sakurs.split_large_file(
file_path,
*,
language=None,
language_config=None,
max_memory_mb=100,
overlap_size=1024,
encoding="utf-8"
)
Parameters:
file_path(str | Path): Path to the filelanguage(str, optional): Language codelanguage_config(LanguageConfig, optional): Custom language configurationmax_memory_mb(int): Maximum memory to use in MB (default: 100)overlap_size(int): Bytes to overlap between chunks (default: 1024)encoding(str): File encoding (default: "utf-8")
Returns: Iterator[str] - Iterator yielding sentences
sakurs.load
Create a processor instance for repeated use.
Signature:
sakurs.load(
language,
*,
threads=None,
chunk_kb=None,
execution_mode="adaptive"
)
Parameters:
language(str): Language code ("en" or "ja")threads(int, optional): Number of threadschunk_kb(int, optional): Chunk size in KB (default: 256)execution_mode(str): Processing mode
Returns: SentenceSplitter instance
sakurs.supported_languages
Get list of supported languages.
Signature:
sakurs.supported_languages()
Returns: List[str] - Supported language codes
Classes
sakurs.SentenceSplitter
Main sentence splitter class for sentence boundary detection.
Constructor Parameters:
language(str, optional): Language codelanguage_config(LanguageConfig, optional): Custom language configurationthreads(int, optional): Number of threadschunk_kb(int, optional): Chunk size in KB (default: 256)execution_mode(str): "sequential", "parallel", or "adaptive"streaming(bool): Enable streaming mode configurationstream_chunk_mb(int): Chunk size in MB for streaming mode
Methods:
split(input, *, return_details=False, encoding="utf-8"): Split text or file into sentencesiter_split(input, *, encoding="utf-8"): Return iterator over sentences__enter__()/__exit__(): Context manager support
sakurs.Sentence
Sentence with metadata (returned when return_details=True).
Attributes:
text(str): The sentence textstart(int): Character offset of sentence startend(int): Character offset of sentence endconfidence(float): Confidence score (default: 1.0)metadata(dict): Additional metadata
sakurs.LanguageConfig
Language configuration for custom rules.
Class Methods:
from_toml(path): Load configuration from TOML fileto_toml(path): Save configuration to TOML file
Attributes:
code(str): Language codename(str): Language nameterminators(TerminatorConfig): Sentence terminator rulesellipsis(EllipsisConfig): Ellipsis handling rulesabbreviations(AbbreviationConfig): Abbreviation rulesenclosures(EnclosureConfig): Enclosure (quotes, parentheses) rulessuppression(SuppressionConfig): Pattern suppression rules
Supported Languages
- English (
en,english) - Japanese (
ja,japanese)
Performance Tips
-
Choose the right function for your use case:
# For small to medium texts - use split() sentences = sakurs.split(text) # For responsive processing - use iter_split() for sentence in sakurs.iter_split(document): process_immediately(sentence) # For huge files with memory constraints - use split_large_file() for sentence in sakurs.split_large_file("10gb_corpus.txt", max_memory_mb=100): index_sentence(sentence)
-
Reuse SentenceSplitter instances: Create once, use many times
processor = sakurs.load("en", threads=4) for document in documents: sentences = processor.split(document)
-
Configure for your workload:
# For CPU-bound batch processing processor = sakurs.load("en", threads=8, execution_mode="parallel") # For I/O-bound or interactive use processor = sakurs.load("en", threads=2, execution_mode="adaptive") # For memory-constrained environments processor = sakurs.SentenceSplitter(language="en", streaming=True, stream_chunk_mb=5)
-
Adjust chunk size for document characteristics:
# For texts with many short sentences sentences = sakurs.split(text, chunk_kb=64) # For texts with long sentences sentences = sakurs.split(text, chunk_kb=512)
Benchmarks
Sakurs demonstrates significant performance improvements over existing Python sentence segmentation libraries. Benchmarks are run automatically in CI and results are displayed in GitHub Actions job summaries.
Running Benchmarks Locally
To run performance benchmarks comparing sakurs with other libraries:
# Install benchmark dependencies
uv pip install -e ".[benchmark]"
# Run all benchmarks
pytest benchmarks/ --benchmark-only
# Run specific language benchmarks
pytest benchmarks/test_benchmark_english.py --benchmark-only
pytest benchmarks/test_benchmark_japanese.py --benchmark-only
Benchmark Libraries
- English: Compared against PySBD
- Japanese: Compared against ja_sentence_segmenter
Error Handling
import sakurs
# Language errors
try:
processor = sakurs.load("unsupported_language")
except sakurs.InvalidLanguageError as e:
print(f"Language error: {e}")
# File errors
try:
sentences = sakurs.split("nonexistent.txt")
except sakurs.FileNotFoundError as e:
print(f"File error: {e}")
# Configuration errors
try:
config = sakurs.LanguageConfig.from_toml("invalid.toml")
except sakurs.ConfigurationError as e:
print(f"Config error: {e}")
# The library handles edge cases gracefully
sentences = sakurs.split("") # Returns []
sentences = sakurs.split("No punctuation") # Returns ["No punctuation"]
Development
This package is built with PyO3 and maturin.
Building from Source
For development, we recommend building and installing wheels rather than using editable installs:
# Build the wheel
maturin build --release --features extension-module
# Install the wheel (force reinstall to ensure updates)
uv pip install --force-reinstall target/wheels/*.whl
Important Note: Avoid using pip install -e . or maturin develop as they can lead to stale binaries that don't reflect Rust code changes. The editable install mechanism doesn't properly track changes in the compiled Rust extension module.
Development Workflow
- Make changes to the Rust code
- Build the wheel:
maturin build --release --features extension-module - Install the wheel:
uv pip install --force-reinstall target/wheels/*.whl - Run tests:
python -m pytest tests/
For convenience, you can use the Makefile from the project root:
make py-dev # Builds and installs the wheel
make py-test # Builds, installs, and runs tests
Troubleshooting
If your changes aren't reflected after rebuilding:
- Check if you have an editable install:
uv pip show sakurs(look for "Editable project location") - Uninstall completely:
uv pip uninstall sakurs -y - Reinstall from wheel as shown above
- Use
.venv/bin/pythondirectly instead ofuv runto avoid automatic editable install restoration
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sakurs-0.1.2-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: sakurs-0.1.2-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00da0e1d9f9fe34255a336b6f3eb2a85af06df44fce3b591bdcfc61e087fea2d
|
|
| MD5 |
5a867a9e5890a666e8f0c16e60d50b15
|
|
| BLAKE2b-256 |
6465101d76b4751a2a333893057c5645f864da94858e4051aa1b37cd4d956603
|
Provenance
The following attestation bundles were made for sakurs-0.1.2-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on sog4be/sakurs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sakurs-0.1.2-cp39-abi3-win_amd64.whl -
Subject digest:
00da0e1d9f9fe34255a336b6f3eb2a85af06df44fce3b591bdcfc61e087fea2d - Sigstore transparency entry: 2084484571
- Sigstore integration time:
-
Permalink:
sog4be/sakurs@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sog4be
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a327c2d90cf09c5b997deeaa0da6a7c2dcbd451508692b6abbd59db1259811f
|
|
| MD5 |
7f286163cb582f79aebca85bf497fbf4
|
|
| BLAKE2b-256 |
c034d556589c19f4eef6f39b025675c170ccf28ebba542e04bf381d7efcb49e1
|
Provenance
The following attestation bundles were made for sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on sog4be/sakurs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
8a327c2d90cf09c5b997deeaa0da6a7c2dcbd451508692b6abbd59db1259811f - Sigstore transparency entry: 2084484575
- Sigstore integration time:
-
Permalink:
sog4be/sakurs@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sog4be
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f47226979ef360e8efde528df1d575da3008a98ba57a6fc32a316a1716078a5
|
|
| MD5 |
5af5abc10463a04ffb174088e286f994
|
|
| BLAKE2b-256 |
b5475b9e0c8ec2f051ea859ab384c15b39a9b42f377636d813a176e6482f9e13
|
Provenance
The following attestation bundles were made for sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on sog4be/sakurs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
2f47226979ef360e8efde528df1d575da3008a98ba57a6fc32a316a1716078a5 - Sigstore transparency entry: 2084484587
- Sigstore integration time:
-
Permalink:
sog4be/sakurs@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sog4be
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b123ff24169e97e13a1f1bb445f7ccb56332e213f2d15dbd2ddfa777dea952f
|
|
| MD5 |
f4c83f1c8aec4f62ad27e4de0f709cd9
|
|
| BLAKE2b-256 |
0fa89b8d22501e45e69562e5c71a45244f04d2b09a696c4e367102b1c0afc33a
|
Provenance
The following attestation bundles were made for sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on sog4be/sakurs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
9b123ff24169e97e13a1f1bb445f7ccb56332e213f2d15dbd2ddfa777dea952f - Sigstore transparency entry: 2084484561
- Sigstore integration time:
-
Permalink:
sog4be/sakurs@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/sog4be
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@09f066c8a343bea30b383f2da0fcc01dcc5d8f48 -
Trigger Event:
push
-
Statement type: