<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Speedyk-005</title>
    <description>The latest articles on DEV Community by Speedyk-005 (@speed_k_7e1b449706e59e433).</description>
    <link>https://dev.to/speed_k_7e1b449706e59e433</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2273923%2F3adfb205-24cf-4e87-ba59-30c6e0beb6ac.jpg</url>
      <title>DEV Community: Speedyk-005</title>
      <link>https://dev.to/speed_k_7e1b449706e59e433</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/speed_k_7e1b449706e59e433"/>
    <language>en</language>
    <item>
      <title>yasbd-lib vs PySBD: two philosophies of sentence boundary detection</title>
      <dc:creator>Speedyk-005</dc:creator>
      <pubDate>Sun, 19 Jul 2026 19:22:59 +0000</pubDate>
      <link>https://dev.to/speed_k_7e1b449706e59e433/yasbd-lib-vs-pysbd-two-philosophies-of-sentence-boundary-detection-i88</link>
      <guid>https://dev.to/speed_k_7e1b449706e59e433/yasbd-lib-vs-pysbd-two-philosophies-of-sentence-boundary-detection-i88</guid>
      <description>&lt;p&gt;Sentence boundary detection sounds boring. Split on &lt;code&gt;.&lt;/code&gt; &lt;code&gt;?&lt;/code&gt; &lt;code&gt;!&lt;/code&gt;, done, right? Anyone who has tried knows otherwise. Abbreviations, decimals, URLs, nested quotes, ellipsis, legal citations, biomedical jargon—each one turns "split text" into a language-specific puzzle.&lt;/p&gt;

&lt;p&gt;Two Python libraries tackle this problem with different philosophies. &lt;a href="https://github.com/nipunsadvilkar/pySBD/" rel="noopener noreferrer"&gt;pysbd&lt;/a&gt; has been the go-to since 2020 with 22 languages, ported from Ruby's pragmatic segmenter [1]. &lt;a href="https://github.com/speedyk-005/yasbd-lib/" rel="noopener noreferrer"&gt;yasbd-lib&lt;/a&gt; is newer, covers 39 languages, and takes a different architectural approach.&lt;/p&gt;

&lt;p&gt;This is the difference between protecting boundaries and finding them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture: Mutation vs. Pointers
&lt;/h2&gt;

&lt;p&gt;To understand how these engines behave on large datasets, we have to look at how they treat input strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  PySBD: The Transformation Pipeline
&lt;/h3&gt;

&lt;p&gt;PySBD operates as a multi-stage transformation pipeline [1]. It treats text as a mutable object that must be modified before it can be split [1]. To prevent punctuation within abbreviations, numbers, or URLs from triggering false splits, PySBD applies regular expressions to replace characters with placeholder tokens [1].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Raw Input Text] --&amp;gt; B["Replace . with {} / Mask URLs"]
    B --&amp;gt; C[Run Rule Engine]
    C --&amp;gt; D[Split on Splitting Marks]
    D --&amp;gt; E[Reverse Replacement / Restore Text]
    E --&amp;gt; F[Extract Text Segments]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structural consequence: &lt;strong&gt;the original string layout is transformed during processing.&lt;/strong&gt; Because the text is modified mid-flight, calculating exact character offsets (spans) relative to the original uncleaned text requires a post-processing reconstruction step [1]. If you enable text cleaning (&lt;code&gt;clean=True&lt;/code&gt;), PySBD raises an error when requesting character spans because it cannot guarantee coordinate matching after modification [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  yasbd-lib: The Query Planning Approach
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yasbd-lib&lt;/code&gt; treats text as immutable [2]. It does not modify the raw string [2]. Instead, its architecture resembles a database query planner—generating candidate coordinate arrays and using language-specific filters to narrow down boundary slices [2].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Raw Input String] --&amp;gt; B[Pass 1: Aggressive Candidate Identification]
    B --&amp;gt; C[Pass 2: Modular Filter Elimination]
    C --&amp;gt; D[Project Slices / Return Index Pointers]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By evolving integer pointers rather than altering text strings, &lt;code&gt;yasbd-lib&lt;/code&gt; maintains context of the source layout throughout processing [2]. Token spans are tracked as a first-class structural signal during parsing rather than reconstructed afterward [2].&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep-Dive Feature Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Spans and Character Offsets
&lt;/h3&gt;

&lt;p&gt;Because PySBD does not natively track indices during its transformation phase, calculating character offsets requires a post-processing step that searches the original document to locate each sentence [1].&lt;/p&gt;

&lt;h4&gt;
  
  
  The PySBD Reconstruction Step
&lt;/h4&gt;

&lt;p&gt;PySBD reconstructs spans by scanning the original text for each sentence (&lt;a href="https://github.com/nipunsadvilkar/pySBD/blob/5905f13/pysbd/segmenter.py#L59-L77" rel="noopener noreferrer"&gt;source&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sentences_with_char_spans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sent_spans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;prior_end_char_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finditer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{0}\s*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sent&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;original_text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;match_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;match_start_idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match_end_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match_end_idx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prior_end_char_idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sent_spans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nc"&gt;TextSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match_start_idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match_end_idx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;prior_end_char_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match_end_idx&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sent_spans&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Trade-off:&lt;/strong&gt; This reconstruction performs repeated searches over the original document. In pathological cases—such as documents with many repeated sentences—this can approach quadratic behavior. For typical use cases, the overhead is manageable, but it does add runtime cost on longer texts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  The yasbd-lib Approach
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;yasbd-lib&lt;/code&gt;, spans are produced natively during boundary detection [2]. It emits boundary allocations dynamically, avoiding lookback overhead [2]. The library also provides an adapter layer for migrating from PySBD [2]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yasbd.utils.pysbd_adapter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Segmenter&lt;/span&gt;

&lt;span class="n"&gt;seg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Segmenter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ja&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;田中さんは「準備は完了しました」そう言って部屋を出た。U.S.A.の経済政策 is complex.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ['田中さんは「準備は完了しました」そう言って部屋を出た。', 'U.S.A.の経済政策 is complex.']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Memory and Streaming
&lt;/h3&gt;

&lt;p&gt;PySBD processes text as complete string buffers [1]. &lt;code&gt;yasbd-lib&lt;/code&gt; provides abstractions for memory-constrained environments through lazy evaluation via &lt;code&gt;ParagraphStream&lt;/code&gt; and &lt;code&gt;StreamCleaner&lt;/code&gt; [2]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yasbd.utils.cleaner&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StreamCleaner&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yasbd&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BoundaryDetector&lt;/span&gt;

&lt;span class="n"&gt;cleaner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StreamCleaner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello  world.   This is  messy.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;detector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BoundaryDetector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;detector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cleaner&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ['Hello world.', 'This is messy.']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Resource Management
&lt;/h3&gt;

&lt;p&gt;Under the hood of the &lt;code&gt;BoundaryDetector&lt;/code&gt; pipeline, &lt;code&gt;yasbd-lib&lt;/code&gt; manages execution rules using a 5-entry LRU cache (&lt;code&gt;_MAX_CACHED_RULES = 5&lt;/code&gt;) [2]. When using automatic language identification (&lt;code&gt;lang="auto"&lt;/code&gt;), if confidence drops below the threshold (&lt;code&gt;_MIN_CONFIDENCE = 0.8&lt;/code&gt;), the module logs an informational message rather than masking the failure [2]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# From boundary_detector.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_language&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;_MIN_CONFIDENCE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;log_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low confidence ({:.2f}) for detected lang {!r} in auto mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, &lt;code&gt;yasbd-lib&lt;/code&gt; supports preserving token boundaries inside parentheses or brackets via &lt;code&gt;preserve_quote_and_paren=True&lt;/code&gt; [2].&lt;/p&gt;




&lt;h2&gt;
  
  
  Maintenance Status: A Critical Consideration
&lt;/h2&gt;

&lt;p&gt;The architectural differences matter, but there's another factor: &lt;strong&gt;PySBD is effectively unmaintained.&lt;/strong&gt; As of December 2025, an open issue (#135) [9] notes that the repository has seen no recent updates, with multiple open PRs from contributors and a maintainer who has seemingly abandoned the project. The issue author explicitly requested archiving the project to signal to downstream users that they should no longer incorporate it [9].&lt;/p&gt;

&lt;p&gt;The maintenance situation has real consequences. Consider these unresolved issues:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Issue #79] [10] - Infinite Loop (October 2020):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;segmenter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pysbd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Segmenter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;..[111 111 111 111 111 111 111 111 111 111]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;segmenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Hangs indefinitely
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is catastrophic backtracking in &lt;code&gt;NUMBERED_REFERENCE_REGEX&lt;/code&gt;. The maintainer acknowledged it in February 2021, saying "Need to dug into details" [10]. Over four years later, it remains unresolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Issue #92] [11] - Catastrophic Backtracking in HTMLTagRule (February 2021):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;HTMLTagRule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;\/?\w+((\s+\w+(\s*=\s*(?:\".*?\"|&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.*?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;|[\^&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\"&amp;gt;\s]+))?)+\s*|\s*)\/?&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When processing unfinished HTML attributes, this regex can cause the segmenter to hang indefinitely [11]. A simplified fix was proposed in the same issue, but it remains unreviewed and unmerged.&lt;/p&gt;

&lt;p&gt;Both issues stem from the same root cause: &lt;strong&gt;regex patterns with nested quantifiers in the transformation pipeline&lt;/strong&gt; [10, 11]. The project has no active maintainer to review or merge fixes [9].&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yasbd-lib&lt;/code&gt; was built in response to this situation, offering a drop-in adapter for PySBD to fix edge cases without heavy refactoring [2, 9].&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmark Comparisons
&lt;/h2&gt;

&lt;p&gt;The architectural differences influence accuracy and performance.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PySBD&lt;/th&gt;
&lt;th&gt;yasbd-lib&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.7–3.11 [1]&lt;/td&gt;
&lt;td&gt;3.10–3.14 [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unmaintained (as of 2025) [9]&lt;/td&gt;
&lt;td&gt;Actively maintained [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Known Issues&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Infinite loop on numbered references [10]; catastrophic backtracking in HTML cleaner [11]&lt;/td&gt;
&lt;td&gt;No known catastrophic backtracking issues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Approach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monolithic transformation pipeline [1]&lt;/td&gt;
&lt;td&gt;Modular immutable pipeline [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;String mutation with placeholder tokens [1]&lt;/td&gt;
&lt;td&gt;Pointer-based operations [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language Profiles&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;22 Languages [1]&lt;/td&gt;
&lt;td&gt;39 Languages [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;English Golden Score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;77 / 92 (83.7%) [2]&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;91 / 92 (98.9%)&lt;/strong&gt; [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Framework Adapters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native API [1]&lt;/td&gt;
&lt;td&gt;spaCy v3+ integration [2]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Benchmark Note:&lt;/strong&gt; The English Golden Score is measured on the project's expanded golden corpus of 92 evaluation cases [2]. The original PySBD corpus contained 48 cases; the expanded set removes ambiguous examples and adds coverage for abbreviation chains, contiguous terminators, and other edge cases. Full methodology and test cases are available in the &lt;a href="https://github.com/speedyk-005/yasbd-lib/tree/main/benchmarks" rel="noopener noreferrer"&gt;benchmarks directory&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fspeedyk-005%2Fyasbd-lib%2Fmain%2Fbenchmarks%2Fbench.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fspeedyk-005%2Fyasbd-lib%2Fmain%2Fbenchmarks%2Fbench.png" alt="SBD Benchmark Performance" width="799" height="498"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A multi-library performance comparison across increasing text sizes. yasbd-lib consistently outperforms alternatives at every scale.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Edge Case Behavior
&lt;/h3&gt;

&lt;p&gt;Consider how both engines handle challenging inputs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input with numbered references (Issue #79):&lt;/strong&gt; &lt;code&gt;"..[111 111 111 111 111 111 111 111 111 111]"&lt;/code&gt; [10]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PySBD:&lt;/strong&gt; Can enter an infinite loop due to catastrophic backtracking in &lt;code&gt;NUMBERED_REFERENCE_REGEX&lt;/code&gt;. This was reported in October 2020 and remains unresolved [10].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;yasbd-lib:&lt;/strong&gt; The two-pass boundary detection approach avoids complex regex substitutions, preventing this class of issue [2].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Input with unfinished HTML (Issue #92):&lt;/strong&gt; &lt;code&gt;"&amp;lt;iframe width="100%" ... src="url Lorem ipsum..."&lt;/code&gt; [11]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PySBD:&lt;/strong&gt; The HTML cleaning regex can cause catastrophic backtracking, hanging the segmenter indefinitely [11]. Reported in February 2021, still unresolved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;yasbd-lib:&lt;/strong&gt; Uses a &lt;code&gt;StreamCleaner&lt;/code&gt; with configurable cleaning steps, including optional HTML unwrapping that avoids nested quantifiers [2].&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Extensibility: Configuration Approaches
&lt;/h2&gt;

&lt;p&gt;What happens when you need to handle custom abbreviations like &lt;code&gt;"Com."&lt;/code&gt; or &lt;code&gt;"Adm."&lt;/code&gt;?&lt;/p&gt;
&lt;h3&gt;
  
  
  PySBD: Internal Rule Modification
&lt;/h3&gt;

&lt;p&gt;Because PySBD's rules operate on a shared transformation timeline, they are interdependent [1]. Adding exceptions requires modifying the internal mutation flow [1].&lt;/p&gt;

&lt;p&gt;As documented in [Issue #108] [3]:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Unfortunately, there is no specific documentation about modifying rules as there are so many and each rule is associated with some form of transformation... All those operations need to be performed in that sequence as they are interrelated... Best way is to use python debugger and see how your input text goes through different transformations."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Adding rules without understanding the full pipeline can break downstream regex patterns [1]. With the project unmaintained, there is no clear path for getting such fixes merged upstream [9].&lt;/p&gt;
&lt;h3&gt;
  
  
  yasbd-lib: Declarative Language Profiles
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yasbd-lib&lt;/code&gt; decouples matching mechanics from language-specific data [2]. It exposes structured hooks for customization [2]:&lt;/p&gt;

&lt;p&gt;The base &lt;code&gt;Rules&lt;/code&gt; class defines sets for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TITLE_ABBRVS&lt;/strong&gt;: Honorifics that should not split sentences&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REFERENCE_ABBRVS&lt;/strong&gt;: Citation abbreviations (&lt;code&gt;fig&lt;/code&gt;, &lt;code&gt;pág&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INLINE_ONLY_ABBRVS&lt;/strong&gt;: Abbreviations that don't end sentences (&lt;code&gt;blvd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DATE_ABBRVS&lt;/strong&gt;: Month and weekday abbreviations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DOTTED_GEOPOL_ABBRVS&lt;/strong&gt;: Geo abbreviations like &lt;code&gt;U.S.&lt;/code&gt;, &lt;code&gt;E.U.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TERMINATORS&lt;/strong&gt;: Extra sentence-ending punctuation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COMMON_SENT_STARTERS&lt;/strong&gt;: Boundary hints for languages without spaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;POST_QUOTATIVE_PARTICLES&lt;/strong&gt; and &lt;strong&gt;REPORTING_WORDS&lt;/strong&gt;: For dialogue attribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To add a new language, you create a file like &lt;code&gt;fr.py&lt;/code&gt;, subclass &lt;code&gt;Rules&lt;/code&gt; as &lt;code&gt;FrRules&lt;/code&gt;, and override only the sets your language needs. The &lt;a href="https://github.com/speedyk-005/yasbd-lib/blob/main/src/yasbd/rules/_template.py" rel="noopener noreferrer"&gt;language template&lt;/a&gt; [6] provides the structure.&lt;/p&gt;
&lt;h3&gt;
  
  
  External Language Packs
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yasbd-lib&lt;/code&gt; supports loading custom language modules at runtime via &lt;code&gt;register_lang_packs()&lt;/code&gt; [2]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yasbd.rules&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;register_lang_packs&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;yasbd&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BoundaryDetector&lt;/span&gt;

&lt;span class="nf"&gt;register_lang_packs&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clinical_yasbd_pack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;detector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BoundaryDetector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clinical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changes to a language-specific profile do not affect the core engine's boundary detection [2].&lt;/p&gt;

&lt;h4&gt;
  
  
  Language Profile Policy
&lt;/h4&gt;

&lt;p&gt;As documented in [Issue #198] [5], &lt;code&gt;yasbd-lib&lt;/code&gt; has frozen its built-in language set at 39 profiles for the v1.x series to maintain API stability. Additional languages must be loaded externally via &lt;code&gt;register_lang_packs()&lt;/code&gt; using community-maintained packages like &lt;code&gt;yasbd-extras&lt;/code&gt; or &lt;code&gt;yasbd-community&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Which Library Should You Choose?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    A[Which SBD to choose?] --&amp;gt; B{Using legacy spaCy v2?}
    B -- Yes --&amp;gt; C[Consider PySBD with caution]
    B -- No --&amp;gt; D{Need active maintenance?}
    D -- Yes --&amp;gt; E[Use yasbd-lib]
    D -- No --&amp;gt; F[Use yasbd-lib for accuracy gains]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consider PySBD only if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Absolute legacy lock-in:&lt;/strong&gt; You are maintaining an existing pipeline tied to &lt;code&gt;spaCy v2&lt;/code&gt; or older deployments that cannot be migrated. Be aware that the project is unmaintained and has known unresolved issues, including infinite loops with numbered references and catastrophic backtracking with certain HTML inputs [9, 10, 11].&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use yasbd-lib if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active maintenance:&lt;/strong&gt; The project is actively maintained with a clear contribution path [2].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance at scale:&lt;/strong&gt; Benchmark results on the &lt;em&gt;Sherlock Holmes&lt;/em&gt; text (594k characters) show yasbd completing in approximately 1.6 seconds compared to 13.3 seconds for PySBD on the same hardware [2]. (These results are from the project's benchmark suite; your mileage may vary based on hardware and Python version.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character span accuracy:&lt;/strong&gt; Native span tracking may be preferable for downstream tasks like NER training or RAG indexing [2].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-standard inputs:&lt;/strong&gt; The modular design handles raw markdown, chat logs, and multilingual text [2].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom language rules:&lt;/strong&gt; The declarative profile system simplifies adding new languages or domain-specific abbreviations [2].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration path:&lt;/strong&gt; The included PySBD adapter allows incremental migration without rewriting your entire pipeline [2].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No catastrophic backtracking:&lt;/strong&gt; The pointer-based architecture avoids the regex issues that plague PySBD's transformation pipeline [2, 10, 11].&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[1] &lt;a href="https://github.com/nipunsadvilkar/pySBD" rel="noopener noreferrer"&gt;PySBD GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[2] &lt;a href="https://github.com/speedyk-005/yasbd-lib/" rel="noopener noreferrer"&gt;yasbd-lib GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[3] &lt;a href="https://github.com/nipunsadvilkar/pySBD/issues/108" rel="noopener noreferrer"&gt;PySBD Issue #108: Examples of modifying sentence segmentation rules&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="https://github.com/speedyk-005/yasbd-lib/issues/20" rel="noopener noreferrer"&gt;yasbd-lib Issue #20: Help Add More Languages to Yasbd&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[5] &lt;a href="https://github.com/speedyk-005/yasbd-lib/issues/198" rel="noopener noreferrer"&gt;yasbd-lib Issue #198: Core Languages Locked at 39&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[6] &lt;a href="https://github.com/speedyk-005/yasbd-lib/blob/main/src/yasbd/rules/_template.py" rel="noopener noreferrer"&gt;yasbd-lib Language Template&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[7] &lt;a href="https://github.com/speedyk-005/yasbd-lib/tree/main/benchmarks" rel="noopener noreferrer"&gt;yasbd-lib Benchmarks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[8] &lt;a href="https://arxiv.org/abs/2010.09657" rel="noopener noreferrer"&gt;PySBD Paper: arXiv:2010.09657&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[9] &lt;a href="https://github.com/nipunsadvilkar/pySBD/issues/135" rel="noopener noreferrer"&gt;PySBD Issue #135: Archive Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[10] &lt;a href="https://github.com/nipunsadvilkar/pySBD/issues/79" rel="noopener noreferrer"&gt;PySBD Issue #79: Infinite loop?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[11] &lt;a href="https://github.com/nipunsadvilkar/pySBD/issues/92" rel="noopener noreferrer"&gt;PySBD Issue #92: Catastrophic backtracking in HTMLTagRule&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nlp</category>
      <category>python</category>
      <category>sentencesplitter</category>
      <category>rulebased</category>
    </item>
    <item>
      <title># Introducing chunklet-py 2.2.0+:</title>
      <dc:creator>Speedyk-005</dc:creator>
      <pubDate>Mon, 23 Feb 2026 03:10:16 +0000</pubDate>
      <link>https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8</link>
      <guid>https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8</guid>
      <description>&lt;p&gt;The Smart Text Chunking Library You Didn't Know You Needed&lt;/p&gt;

&lt;p&gt;Ever tried splitting text for your RAG pipeline and ended up with chunks that cut sentences in half? Or worse — chunks that lose all context between them?&lt;/p&gt;

&lt;p&gt;Yeah, I've been there too. That's exactly why I built &lt;a href="https://github.com/speedyk-005/chunklet-py" rel="noopener noreferrer"&gt;chunklet-py&lt;/a&gt; — a Python library that actually understands text structure.&lt;/p&gt;

&lt;p&gt;This post hits only the highlights and doesn't cover everything — visit the &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/" rel="noopener noreferrer"&gt;full documentation&lt;/a&gt; for everything else, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom sentence splitters for specialized languages&lt;/li&gt;
&lt;li&gt;Custom document processors for unusual file formats&lt;/li&gt;
&lt;li&gt;Custom tokenizers to match your LLM&lt;/li&gt;
&lt;li&gt;The rich metadata you can get.&lt;/li&gt;
&lt;li&gt;CLI flags for batch processing, parallel jobs, error handling, timeouts&lt;/li&gt;
&lt;li&gt;Additional args like &lt;code&gt;n_jobs&lt;/code&gt;, &lt;code&gt;lang&lt;/code&gt;, &lt;code&gt;show_progress&lt;/code&gt;, ...&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;Quick heads up!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This tutorial requires &lt;code&gt;chunklet-py v2.2.0+&lt;/code&gt; and uses APIs not available in earlier versions. &lt;/p&gt;

&lt;p&gt;Upgrade to the latest version and see the &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; or &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/whats-new/" rel="noopener noreferrer"&gt;What’s New&lt;/a&gt; for details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem with Dumb Splitting
&lt;/h2&gt;

&lt;p&gt;Here's what usually happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The naive approach
&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works... until it doesn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentences cut mid-way ("The model got 75%" → "75%" becomes meaningless)&lt;/li&gt;
&lt;li&gt;No context between chunks&lt;/li&gt;
&lt;li&gt;Broken code if you're chunking source files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution: chunklet-py
&lt;/h2&gt;

&lt;p&gt;A smart text and code chunking library that respects natural boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;50+ languages supported&lt;/strong&gt; — Auto-detects language and applies the right splitting rules. No more treating German the same as English.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple constraint types&lt;/strong&gt; — Mix and match:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;max_sentences&lt;/code&gt; — group by sentences&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_tokens&lt;/code&gt; — respect LLM context limits
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_section_breaks&lt;/code&gt; — keep Markdown headers together (headings &lt;code&gt;##&lt;/code&gt;, horizontal rules &lt;code&gt;---&lt;/code&gt;, &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; tags)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_lines&lt;/code&gt; — for code chunking&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_functions&lt;/code&gt; — keep functions together&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multiple file formats&lt;/strong&gt; — PDF, DOCX, EPUB, HTML, Markdown, LaTeX, ODT, CSV, Excel, plain text — one library handles them all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rich metadata&lt;/strong&gt; — Every chunk comes with source references, character spans, and structural info.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Composable constraints&lt;/strong&gt; — Mix and match limits to get exactly the chunks you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pluggable architecture&lt;/strong&gt; — Swap in custom tokenizers, sentence splitters, or document processors.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's New in v2.2.0
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Unification&lt;/strong&gt; — Methods renamed to &lt;code&gt;chunk_text&lt;/code&gt;, &lt;code&gt;chunk_file&lt;/code&gt;, &lt;code&gt;chunk_texts&lt;/code&gt;, &lt;code&gt;chunk_files&lt;/code&gt; for consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualizer redesign&lt;/strong&gt; — Fullscreen mode, 3-row layout, smoother hovers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More code languages&lt;/strong&gt; — ColdFusion, VB.NET, PHP 8 attributes, Pascal support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruff&lt;/strong&gt; — Switched to Ruff for faster linting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/whats-new/" rel="noopener noreferrer"&gt;What's New&lt;/a&gt; page for full details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet-py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For document support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet-py[structured-document]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet-py[code]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For visualization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet-py[visualization]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Imports
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DocumentChunker&lt;/span&gt;   &lt;span class="c1"&gt;# For PDFs, DOCX, and general text
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CodeChunker&lt;/span&gt;       &lt;span class="c1"&gt;# For source code
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceSplitter&lt;/span&gt;  &lt;span class="c1"&gt;# For just sentences
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;visualizer&lt;/span&gt;        &lt;span class="c1"&gt;# Web-based visualizer
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DocumentChunker API
&lt;/h3&gt;

&lt;p&gt;Four methods cover most use cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Return Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chunk_text(text)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;List[Chunk]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chunk_file(path)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Path or str&lt;/td&gt;
&lt;td&gt;List[Chunk]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chunk_texts(list)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List[str]&lt;/td&gt;
&lt;td&gt;Generator[Chunk]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chunk_files(list)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List[Path]&lt;/td&gt;
&lt;td&gt;Generator[Chunk]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  DocumentChunker Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chunker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DocumentChunker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Feel free to mix and match these
&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_sentences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# Stop after X sentences
&lt;/span&gt;    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# Don't blow up the LLM context
&lt;/span&gt;    &lt;span class="n"&gt;max_section_breaks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Respect the Markdown headers
&lt;/span&gt;    &lt;span class="n"&gt;overlap_percent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# Give it some "memory" of the last chunk
&lt;/span&gt;    &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;               &lt;span class="c1"&gt;# Skip the first N sentences
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CodeChunker Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chunker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CodeChunker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# Height limit
&lt;/span&gt;    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# Width limit
&lt;/span&gt;    &lt;span class="n"&gt;max_functions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# One function per chunk
&lt;/span&gt;    &lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;# True: Crash on big blocks; False: Slice anyway
&lt;/span&gt;    &lt;span class="n"&gt;include_comments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# True by default
&lt;/span&gt;    &lt;span class="n"&gt;docstring_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Options are: all, excluded, summary
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;Token Counter Requirement&lt;/strong&gt;&lt;br&gt;
When using the max_tokens constraint, a token_counter function is essential. This function, which you provide, should accept a string and return an integer representing its token count. Failing to provide a token_counter will result in a &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/exceptions-and-warnings/#missingtokencountererror" rel="noopener noreferrer"&gt;MissingTokenCounterError&lt;/a&gt;.&lt;br&gt;
You can also provide the token_counter directly to any chunking method. If provided in both the constructor and the method, the one in the method will be used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  SentenceSplitter (Just Sentences)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceSplitter&lt;/span&gt;

&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceSplitter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# You can also set it to "auto"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handles tricky cases like "Dr." or "U.S.A." without breaking them up.&lt;/p&gt;

&lt;p&gt;50+ languages are explicitly supported through dedicated libraries (pysbd covers 40+, Indic NLP Library covers 11, sentsplit covers 4, and Sentencex covers ~15, with some overlap), plus the Fallback Splitter handles any other language via Unicode rules (&lt;a href="https://speedyk-005.github.io/chunklet-py/latest/supported-languages/" rel="noopener noreferrer"&gt;Supported Languages Documentation&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Output Object
&lt;/h3&gt;

&lt;p&gt;Chunkers return Chunk objects (Box instances), so you use dot notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# The actual text/code
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Chunk metadata
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Visualizer (Interactive Web UI)
&lt;/h3&gt;

&lt;p&gt;Launch a web interface to experiment with chunking parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chunklet visualize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or programmatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;visualizer&lt;/span&gt;

&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visualizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Visualizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Opens in your browser
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CLI Examples
&lt;/h2&gt;

&lt;p&gt;Prefer the terminal? chunklet-py ships with a &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/getting-started/cli/" rel="noopener noreferrer"&gt;full CLI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some quick examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic text chunking&lt;/span&gt;
chunklet chunk &lt;span class="s2"&gt;"Your text here."&lt;/span&gt; &lt;span class="nt"&gt;--max-tokens&lt;/span&gt; 500

&lt;span class="c"&gt;# Chunk a file&lt;/span&gt;
chunklet chunk &lt;span class="nt"&gt;--source&lt;/span&gt; document.pdf &lt;span class="nt"&gt;--max-tokens&lt;/span&gt; 500 &lt;span class="nt"&gt;--metadata&lt;/span&gt;

&lt;span class="c"&gt;# Split text into sentences&lt;/span&gt;
chunklet &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="s2"&gt;"Your text here."&lt;/span&gt; &lt;span class="nt"&gt;--lang&lt;/span&gt; en

&lt;span class="c"&gt;# Split a file into sentences&lt;/span&gt;
chunklet &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt; my_file.txt &lt;span class="nt"&gt;--destination&lt;/span&gt; sentences.txt

&lt;span class="c"&gt;# Start the interactive visualizer&lt;/span&gt;
chunklet visualize

&lt;span class="c"&gt;# Code chunking&lt;/span&gt;
chunklet chunk &lt;span class="nt"&gt;--code&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt; my_script.py &lt;span class="nt"&gt;--max-functions&lt;/span&gt; 1

&lt;span class="c"&gt;# Batch processing a directory&lt;/span&gt;
chunklet chunk &lt;span class="nt"&gt;--doc&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt; ./my_docs &lt;span class="nt"&gt;--destination&lt;/span&gt; ./chunks &lt;span class="nt"&gt;--n-jobs&lt;/span&gt; 4

&lt;span class="c"&gt;# With error handling&lt;/span&gt;
chunklet chunk &lt;span class="nt"&gt;--doc&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt; ./my_docs &lt;span class="nt"&gt;--on-errors&lt;/span&gt; skip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Compares
&lt;/h2&gt;

&lt;p&gt;While there are other chunking libraries available, Chunklet-py stands out for its unique combination of versatility, performance, and ease of use. Here's a quick look at how it compares to some of the alternatives:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Key Differentiator&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;chunklet-py&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All-in-one, lightweight, multilingual, language-agnostic with specialized algorithms.&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Text, Code, Docs&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/langchain-ai/langchain" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full LLM framework with basic splitters (e.g., RecursiveCharacterTextSplitter, Markdown, HTML, code splitters). Good for prototyping but basic for complex docs or multilingual needs.&lt;/td&gt;
&lt;td&gt;Full Stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/chonkie-inc/chonkie" rel="noopener noreferrer"&gt;Chonkie&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;All-in-one pipeline (chunking + embeddings + vector DB). Uses &lt;code&gt;tree-sitter&lt;/code&gt; for code. Multilingual.&lt;/td&gt;
&lt;td&gt;Pipelines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/isaacus-dev/semchunk" rel="noopener noreferrer"&gt;Semchunk&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Text-only, fast semantic splitting. Built-in tiktoken/HuggingFace support. 85% faster than alternatives.&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/CintraAI/code-chunker" rel="noopener noreferrer"&gt;CintraAI Code Chunker&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Code-specific, uses &lt;code&gt;tree-sitter&lt;/code&gt;. Initially supports Python, JS, CSS only.&lt;/td&gt;
&lt;td&gt;Code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Chunklet-py is a specialized, drop-in replacement for the chunking step in any RAG pipeline. It handles text, documents, and code without heavy dependencies, while keeping your project lightweight.&lt;/p&gt;




&lt;h2&gt;
  
  
  🙌 Contributors &amp;amp; Thanks
&lt;/h2&gt;

&lt;p&gt;A huge thank you to the awesome people who helped shape Chunklet-py:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jmbernabotto" rel="noopener noreferrer"&gt;@jmbernabotto&lt;/a&gt; — for helping mostly on the CLI part, suggesting fixes, features, and design improvements.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/arnoldfranz" rel="noopener noreferrer"&gt;@arnoldfranz&lt;/a&gt; — for reporting the CLI Path Validation Bug (#6) that helped improve error handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/speedyk-005/chunklet-py/blob/main/LICENSE" rel="noopener noreferrer"&gt;LICENSE&lt;/a&gt; file for all the details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Chunklet-py is production-ready. It's lightweight, has no heavy dependencies, and the API is consistent — no more guessing which method name to use.&lt;/p&gt;

&lt;p&gt;Check it out: &lt;a href="https://github.com/speedyk-005/chunklet-py" rel="noopener noreferrer"&gt;github.com/speedyk-005/chunklet-py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Questions? Drop them in the comments!&lt;/p&gt;

</description>
      <category>rag</category>
      <category>chunk</category>
      <category>llm</category>
      <category>python</category>
    </item>
    <item>
      <title>**Chunklet-py (v2+): One Library to Split Them All - Sentence, Code, Docs**</title>
      <dc:creator>Speedyk-005</dc:creator>
      <pubDate>Sat, 20 Dec 2025 18:24:05 +0000</pubDate>
      <link>https://dev.to/speed_k_7e1b449706e59e433/chunklet-py-one-library-to-split-them-all-sentence-code-docs-2eeg</link>
      <guid>https://dev.to/speed_k_7e1b449706e59e433/chunklet-py-one-library-to-split-them-all-sentence-code-docs-2eeg</guid>
      <description>&lt;p&gt;I've been working on &lt;strong&gt;Chunklet-py&lt;/strong&gt; - a powerful Python library for intelligent text and document chunking that's perfect for LLM/RAG applications. Here's why you might want to check it out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ This guide targets &lt;code&gt;chunklet-py v2.1.1&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
APIs from &lt;code&gt;v2.2.0+&lt;/code&gt; are not included.&lt;br&gt;&lt;br&gt;
See the &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/" rel="noopener noreferrer"&gt;latest docs&lt;/a&gt; for updates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🔧 &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Chunklet-py is your friendly neighborhood text splitter that takes all kinds of content and breaks it into smart, context-aware chunks. Instead of dumb character-count splitting, it gives you specialized tools for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sentence Splitter&lt;/strong&gt; - Multilingual text splitting (50+ languages!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain Text Chunker&lt;/strong&gt; - Basic text chunking with constraints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Chunker&lt;/strong&gt; - Processes PDFs, DOCX, EPUB, ODT, CSV, Excel, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Chunker&lt;/strong&gt; - Language-agnostic code splitting that preserves structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunk Visualizer&lt;/strong&gt; - Interactive web interface for real-time chunk exploration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 &lt;strong&gt;Key Features&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blazingly Fast&lt;/strong&gt;: Parallel processing for large document batches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Featherlight Footprint&lt;/strong&gt;: Lightweight and memory-efficient&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich Metadata&lt;/strong&gt;: Context-aware metadata for advanced RAG applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Mastery&lt;/strong&gt;: 50+ languages with intelligent detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Triple Interface&lt;/strong&gt;: CLI, library, or web interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infinitely Customizable&lt;/strong&gt;: Pluggable token counters, custom splitters, processors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💻 &lt;strong&gt;Quick Example&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PlainTextChunker&lt;/span&gt;

&lt;span class="n"&gt;chunker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PlainTextChunker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your long text here...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_sentences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Metadata: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📊 &lt;strong&gt;Why It Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Traditional text splitting often breaks meaning - mid-sentence cuts, lost context, language confusion. Chunklet-py keeps your content's structure and meaning intact, making it perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing data for LLMs&lt;/li&gt;
&lt;li&gt;Building RAG systems&lt;/li&gt;
&lt;li&gt;AI search applications&lt;/li&gt;
&lt;li&gt;Document processing pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠️ &lt;strong&gt;Installation&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet-py

&lt;span class="c"&gt;# For full features:&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"chunklet-py[all]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📈 &lt;strong&gt;Community &amp;amp; Stats&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;50+ languages&lt;/strong&gt; supported&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10+ document formats&lt;/strong&gt; processed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MIT licensed&lt;/strong&gt; - free and open source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active development&lt;/strong&gt; with comprehensive testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://speedyk-005.github.io/chunklet-py/latest" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and &lt;a href="https://github.com/speedyk-005/chunklet-py" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for more details!&lt;/p&gt;

&lt;p&gt;What do you think? Have you worked on similar text processing challenges? Any questions about chunking strategies or the library?&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Related Posts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🚀 Latest version (v2.2.0+):&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8"&gt;https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧠 Legacy version (v1, outdated):&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/speed_k_7e1b449706e59e433/stop-breaking-context-smarter-text-chunking-for-python-nlp-projects-2n8n"&gt;https://dev.to/speed_k_7e1b449706e59e433/stop-breaking-context-smarter-text-chunking-for-python-nlp-projects-2n8n&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>nlp</category>
      <category>chunker</category>
      <category>rag</category>
    </item>
    <item>
      <title>**"Stop Breaking Context: Smarter Text Chunking for Python NLP Projects"**</title>
      <dc:creator>Speedyk-005</dc:creator>
      <pubDate>Wed, 13 Aug 2025 21:59:51 +0000</pubDate>
      <link>https://dev.to/speed_k_7e1b449706e59e433/stop-breaking-context-smarter-text-chunking-for-python-nlp-projects-2n8n</link>
      <guid>https://dev.to/speed_k_7e1b449706e59e433/stop-breaking-context-smarter-text-chunking-for-python-nlp-projects-2n8n</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Chunklet: Smarter Text Chunking for Python Developers&lt;/strong&gt;
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;This post is outdated&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This guide uses &lt;code&gt;chunklet v1.x&lt;/code&gt;, which is no longer maintained. see the Migration Guide: &lt;a href="https://speedyk-005.github.io/chunklet-py/latest/migration/" rel="noopener noreferrer"&gt;https://speedyk-005.github.io/chunklet-py/latest/migration/&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;👉 Use &lt;code&gt;chunklet-py v2.x&lt;/code&gt; instead:&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/speed_k_7e1b449706e59e433/chunklet-py-one-library-to-split-them-all-sentence-code-docs-2eeg"&gt;https://dev.to/speed_k_7e1b449706e59e433/chunklet-py-one-library-to-split-them-all-sentence-code-docs-2eeg&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;🚀 Latest version (v2.2.0+):&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8"&gt;https://dev.to/speed_k_7e1b449706e59e433/-introducing-chunklet-py-dj8&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Context Matters in Text Splitting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When preprocessing documents for NLP tasks, standard splitting methods often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break sentences mid-thought (&lt;code&gt;"The patient showed improvement. However," → "However,"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Ignore linguistic boundaries in non-English texts&lt;/li&gt;
&lt;li&gt;Lose critical context between chunks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chunklet solves this with structural awareness.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Installation &amp;amp; Basic Usage&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;chunklet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Minimal Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;chunklet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Chunklet&lt;/span&gt;

&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First sentence. Second sentence. Third sentence.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;chunker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Chunklet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_sentences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Output:
# ["First sentence. Second sentence.", "Third sentence."]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This preserves complete sentences while respecting chunk size limits.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Key Features Explained&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hybrid Chunking Mode&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Combines structural and size-based splitting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_sentences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Structural limit
&lt;/span&gt;    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Size limit
&lt;/span&gt;    &lt;span class="n"&gt;overlap_percent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;  &lt;span class="c1"&gt;# Context preservation
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Why this matters:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevents chunks from becoming too long or too short&lt;/li&gt;
&lt;li&gt;Overlap maintains relationships between sections&lt;/li&gt;
&lt;li&gt;Works equally well on code, markdown, or prose&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Multilingual Support&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Auto-detection (36+ languages)
&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multilingual_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Manual override
&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;japanese_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ja&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;How it works:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses &lt;code&gt;py3langid&lt;/code&gt; for fast language detection&lt;/li&gt;
&lt;li&gt;Applies language-specific sentence boundaries&lt;/li&gt;
&lt;li&gt;Falls back to regex for unsupported languages&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Real-World Use Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Preparing Legal Documents&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;legal_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contract.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;legal_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;overlap_percent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;  &lt;span class="c1"&gt;# Critical for clause relationships
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Why it works:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preserves entire contract clauses&lt;/li&gt;
&lt;li&gt;Maintains references between sections (e.g., "as defined in Section 2.1")&lt;/li&gt;
&lt;li&gt;Handles complex punctuation in legal prose&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Processing Academic Papers&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chunker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Chunklet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sentence_splitter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;custom_academic_splitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Handles citations
&lt;/span&gt;    &lt;span class="n"&gt;token_counter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;scibert_tokenizer&lt;/span&gt;  &lt;span class="c1"&gt;# Domain-specific counting
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Customization options:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plug in any sentence splitter&lt;/li&gt;
&lt;li&gt;Use HuggingFace tokenizers&lt;/li&gt;
&lt;li&gt;Adjust chunking thresholds per document type&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Performance Considerations&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# For large datasets:
&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;batch_chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;n_jobs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# Parallel processing
&lt;/span&gt;    &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;     &lt;span class="c1"&gt;# Documents per batch
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Optimization tips:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable &lt;code&gt;use_cache=True&lt;/code&gt; for repeated texts&lt;/li&gt;
&lt;li&gt;Pre-filter very short/long documents&lt;/li&gt;
&lt;li&gt;Monitor memory with &lt;code&gt;memory_profiler&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Ready to try?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/Speedyk-005/chunklet" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt; | &lt;a href="https://pypi.org/project/chunklet/" rel="noopener noreferrer"&gt;PyPI Package&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>nlp</category>
      <category>opensource</category>
      <category>rag</category>
    </item>
  </channel>
</rss>
