Skip to main content

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

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 object
  • language (str, optional): Language code ("en", "ja")
  • language_config (LanguageConfig, optional): Custom language configuration
  • threads (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 inputs
  • execution_mode (str): "sequential", "parallel", or "adaptive" (default)
  • return_details (bool): Return Sentence objects with metadata instead of strings
  • encoding (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 file
  • language (str, optional): Language code
  • language_config (LanguageConfig, optional): Custom language configuration
  • max_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 threads
  • chunk_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 code
  • language_config (LanguageConfig, optional): Custom language configuration
  • threads (int, optional): Number of threads
  • chunk_kb (int, optional): Chunk size in KB (default: 256)
  • execution_mode (str): "sequential", "parallel", or "adaptive"
  • streaming (bool): Enable streaming mode configuration
  • stream_chunk_mb (int): Chunk size in MB for streaming mode

Methods:

  • split(input, *, return_details=False, encoding="utf-8"): Split text or file into sentences
  • iter_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 text
  • start (int): Character offset of sentence start
  • end (int): Character offset of sentence end
  • confidence (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 file
  • to_toml(path): Save configuration to TOML file

Attributes:

  • code (str): Language code
  • name (str): Language name
  • terminators (TerminatorConfig): Sentence terminator rules
  • ellipsis (EllipsisConfig): Ellipsis handling rules
  • abbreviations (AbbreviationConfig): Abbreviation rules
  • enclosures (EnclosureConfig): Enclosure (quotes, parentheses) rules
  • suppression (SuppressionConfig): Pattern suppression rules

Supported Languages

  • English (en, english)
  • Japanese (ja, japanese)

Performance Tips

  1. 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)
    
  2. Reuse SentenceSplitter instances: Create once, use many times

    processor = sakurs.load("en", threads=4)
    for document in documents:
        sentences = processor.split(document)
    
  3. 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)
    
  4. 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

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

  1. Make changes to the Rust code
  2. Build the wheel: maturin build --release --features extension-module
  3. Install the wheel: uv pip install --force-reinstall target/wheels/*.whl
  4. 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/python directly instead of uv run to avoid automatic editable install restoration

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sakurs-0.1.2-cp39-abi3-win_amd64.whl (1.4 MB view details)

Uploaded CPython 3.9+Windows x86-64

sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

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

Hashes for sakurs-0.1.2-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 00da0e1d9f9fe34255a336b6f3eb2a85af06df44fce3b591bdcfc61e087fea2d
MD5 5a867a9e5890a666e8f0c16e60d50b15
BLAKE2b-256 6465101d76b4751a2a333893057c5645f864da94858e4051aa1b37cd4d956603

See more details on using hashes here.

Provenance

The following attestation bundles were made for sakurs-0.1.2-cp39-abi3-win_amd64.whl:

Publisher: release.yml on sog4be/sakurs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for sakurs-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8a327c2d90cf09c5b997deeaa0da6a7c2dcbd451508692b6abbd59db1259811f
MD5 7f286163cb582f79aebca85bf497fbf4
BLAKE2b-256 c034d556589c19f4eef6f39b025675c170ccf28ebba542e04bf381d7efcb49e1

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sakurs-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2f47226979ef360e8efde528df1d575da3008a98ba57a6fc32a316a1716078a5
MD5 5af5abc10463a04ffb174088e286f994
BLAKE2b-256 b5475b9e0c8ec2f051ea859ab384c15b39a9b42f377636d813a176e6482f9e13

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for sakurs-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9b123ff24169e97e13a1f1bb445f7ccb56332e213f2d15dbd2ddfa777dea952f
MD5 f4c83f1c8aec4f62ad27e4de0f709cd9
BLAKE2b-256 0fa89b8d22501e45e69562e5c71a45244f04d2b09a696c4e367102b1c0afc33a

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page