
    4 j^                    j   d dl mZ d dlZd dlZd dlZd dlmZmZmZ d dl	m
Z
 d dlmZ d dlmZ d dlZd dlmZ erd dlZd dlZd dlZi Z	 dZ	  ed	 eD              Zdd
ZddZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ G d d      Z	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)    )annotationsN)CallableSequenceTYPE_CHECKING)	lru_cache)
accumulate)suppress)tqdm).?!*;,()[]u   “u   ”u   ‘u   ’'"`:u   —u   …/\u   –&-c              #  F   K   | ]  }t        j                  |        y wN)reescape).0splitters     D/home/agent/.local/lib/python3.12/site-packages/semchunk/semchunk.py	<genexpr>r$   :   s        9AQY89L  9As   !c           	        d}d| v sd| v r't        t        j                  d|       t              }nd| v r&t        t        j                  d|       t              }nt        j                  d|       rt        t        j                  d	|       t              }t        |      d
k(  rt
        D ]d  }t        j                  | d|       x}s|j                  d
      }t        j                  |      }||t        j                  d| d| |       fc S  n!t        D ]
  }|| v sd} n d|t        |       fS ||| j                  |      fS )zDSplit text using the most semantically meaningful splitter possible.T
z[\r\n]+)key	z\t+z\sz\s+   z(\s)z(?<=r   F )maxr   findalllensearch0_REGEX_ESCAPED_NON_WHITESPACE_SEMANTIC_SPLITTERSgroupr    split"_NON_WHITESPACE_SEMANTIC_SPLITTERSlist)textsplitter_is_whitespacer"   escaped_precederwhitespace_preceded_by_precederescaped_splitters         r#   _split_textr:   <   sO    " t|tt|rzz*d3=	rzz&$/S9	5$	rzz&$/S9 x=A$T { 79yyEUDVVZA[]a7bb3b>DDQGH')yy':$#%;RXXN^M__`aq`rFsuy=zzz{ ; 	:H4).&	: -tDz99 +TZZ-AAA    c                L    ||k  r||z   dz  }| |   |k  r|dz   }n|}||k  r|S )N   r*    )sortedtargetlowhighmids        r#   bisect_leftrD   g   sC    
*Tza#;'C D * Jr;   c                2   d}|}||   }	|	||z  z   }
||k  rgt        ||
||      }t        ||dz
        } ||j                  | ||             }||   |	z
  }|r|dkD  r||z  }|	||z  z   }
||kD  r|}n|dz   }||k  rg|dz
  }||j                  | ||       fS )zMerge splits until a chunk size is reached, returning the index of the last split included in the merged chunk along with the merged chunk itself.g?)rA   rB   r*   r   )rD   minjoin)splitscum_lens
chunk_sizer"   token_counterstartrB   averagerA   offsetr@   imidpointtokens	local_cumends                   r#   merge_splitsrT   t   s    
 G
Ce_FzG+,F
*&c=q$(#x}}VE(-CDEX&/	!&(GzG34FJD Q,C! *$ 'CfU3/000r;   c	           
     x  + |}	|}
| x}rh|r%t         j                  | t        |      |            }|r?|dk  rt        j                  ||z        nt        ||dz
        }|r||z
  }t        ||      }
t        |       \  }}}g }t        |      }|D cg c]  }t        |       }}t        t        |d            }t        dg|D cg c]  }||z   	 c}z         }|D cg c]  }||z   	 }}t        |      dz   }g }t               +	 t        t        ||            D ]Q  \  }\  }}|+v r ||      |
kD  r:t        ||
|d|dz   |      \  }}|j                  |       |j                  |       n_t        |||
||||      \  }}+j!                  t#        |dz   |             |j%                  |       ||   |z
  }|j%                  ||f       |r|t        |      dz
  k(  rt'        +fdt#        |dz   t        |            D              r ||d   |z   x}       |
k  r| |d<   |d   \  }}!||!|z   f|d<   |r|d   d   n|}|j%                  |       |j%                  |||z   f       T |r!t        ||      D "#cg c]  \  }"}#|"s	|"j)                         r|"|#f }$}"}#|$r"t        |$ \  }}t        |      t        |      }}ng g }}|r|r|
}%|}&|}'t        |&      }(t        j                  ||%z        })t        j                  |%z        }*t#        t+        dt        j,                  |(|)z
  |*z        dz               D cg c]'  }|'||*z  x}   d   |'t        ||)z   |(      dz
     d   f) }}|D !cg c]
  \  }}!| ||!  }}}!|	r||fS |S ||fS c c}w c c}w c c}w c c}#}"w c c}w c c}!}w )	a  Split a text into semantically meaningful chunks of a specified size as determined by the provided token counter.

    Args:
        text (str): The text to be chunked.
        chunk_size (int): The maximum number of tokens a chunk may contain.
        token_counter (Callable[[str], int]): A callable that takes a string and returns the number of tokens in it.
        memoize (bool, optional): Whether to memoize the token counter. Defaults to `True`.
        offsets (bool, optional): Whether to return the start and end offsets of each chunk. Defaults to `False`.
        overlap (float | int | None, optional): The proportion of the chunk size, or, if >=1, the number of tokens, by which chunks should overlap. Defaults to `None`, in which case no overlapping occurs.
        cache_maxsize (int | None, optional): The maximum number of text-token count pairs that can be stored in the token counter's cache. Defaults to `None`, which makes the cache unbounded. This argument is only used if `memoize` is `True`.

    Returns:
        list[str] | tuple[list[str], list[tuple[int, int]]]: A list of chunks up to `chunk_size`-tokens-long, with any whitespace used to split the text removed, and, if `offsets` is `True`, a list of tuples of the form `(start, end)` where `start` is the index of the first character of the chunk in the original text and `end` is the index of the character after the last character of the chunk such that `chunks[i] == text[offsets[i][0]:offsets[i][1]]`.r*   r   )initialT)r5   rJ   rK   offsets_recursion_depth_start)rH   rI   rJ   r"   rK   rL   rB   c              3  &   K   | ]  }|v  
 y wr   r>   )r!   jskipss     r#   r$   zchunk.<locals>.<genexpr>   s     'VqU
'Vs   )_memoized_token_counters
setdefaultr   mathfloorrF   r:   r.   r4   r   set	enumeratezipchunkextendrT   updaterangeappendallisspacer,   ceil),r5   rJ   rK   memoizerW   overlapcache_maxsizerX   rY   return_offsetslocal_chunk_sizeis_first_callunoverlapped_chunk_sizer"   r6   rH   splitter_lenr2   
split_lensrI   	split_lensplit_startsrL   num_splits_plus_onechunksrO   split_start
new_chunksnew_offsetsfinal_split_in_chunk_i	new_chunk	split_endlast_chunk_with_splitterrS   re   rN   chunks_and_offsetssubchunk_size	subchunks
suboffsetsnum_subchunkssubchunks_per_chunksubchunk_strider\   s,                                              @r#   re   re      sc   4 N! -,,},4??OgyYfOghuOvwM:AA+djjg!563wXbefXfKgG *4w*>'#&w0G#H  0;4/@,H$fGx=L*01#e*1J1Jz156Hqcz$Z)Y%=$ZZ[L0<=uEFN=L=f+/FEE^ $-S-F#G 7>E;: "22&+++!1A!5"'#J MM*%NN;'
 1=!+!+(1-"I LLq1u&<=> MM)$ %%;<|KINNK34 &Vq C'VE!a%V<U'V$Vh9NN5OScc5r
$R[
s$cL&89 +2A{h'u|';<=o7>t CFvwCWy-%[`inivivixufoyy!#56OFG"6lDMGF !"GF v,MI J	NM #'**]*# #jj'-7O s1diiAT1TXg0g&hkl&lmn
  _)< <>qAs5+>#>NQRRSTUVG  9@@*%d5o@F@ 7?" 7?c 2$Z=H z2 As0   NN!
!N&
N+N+"N+,N1>N6c                  P    e Zd ZddZ	 	 	 	 	 	 ddZ	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)	Chunkerc                     || _         || _        y r   rJ   rK   )selfrJ   rK   s      r#   __init__zChunker.__init__:  s    $*r;   c                     d fd}|S )zeConstruct a function that chunks a text and returns the chunks along with their offsets if necessary.c                N    t        | j                  j                  d      S )NF)r5   rJ   rK   rm   rW   rn   )re   rJ   rK   )r5   rW   rn   r   s    r#   _chunkz,Chunker._make_chunk_function.<locals>._chunkE  s,    ??"00 r;   )r5   strreturn3list[str] | tuple[list[str], list[tuple[int, int]]]r>   )r   rW   rn   r   s   ``` r#   _make_chunk_functionzChunker._make_chunk_function>  s    	 r;   Nc                   | j                  ||      }t        |t              r ||      S |r|dk(  rt        |      }|dk(  r|D cg c]
  } ||       }}n4t	        j
                  |d      5 }	|	j                  |||      }ddd       |r!t         \  }
}t        |
      t        |      fS S c c}w # 1 sw Y   3xY w)a  Split text or texts into semantically meaningful chunks of a specified size as determined by the provided tokenizer or token counter.

        Args:
            text_or_texts (str | Sequence[str]): The text or texts to be chunked.
            processes (int, optional): The number of processes to use when chunking multiple texts. Defaults to `1` in which case chunking will occur in the main process.
            progress (bool, optional): Whether to display a progress bar when chunking multiple texts. Defaults to `False`.
            offsets (bool, optional): Whether to return the start and end offsets of each chunk. Defaults to `False`.
            overlap (float | int | None, optional): The proportion of the chunk size, or, if >=1, the number of tokens, by which chunks should overlap. Defaults to `None`, in which case no overlapping occurs.

        Returns:
            list[str] | tuple[list[str], list[tuple[int, int]]] | list[list[str]] | tuple[list[list[str]], list[list[tuple[int, int]]]]: If a single text has been provided, a list of chunks up to `chunk_size`-tokens-long, with any whitespace used to split the text removed, and, if `offsets` is `True`, a list of tuples of the form `(start, end)` where `start` is the index of the first character of the chunk in the original text and `end` is the index of the character succeeding the last character of the chunk such that `chunks[i] == text[offsets[i][0]:offsets[i][1]]`.

            If multiple texts have been provided, a list of lists of chunks, with each inner list corresponding to the chunks of one of the provided input texts, and, if `offsets` is `True`, a list of lists of tuples of the chunks' offsets to the original texts, as described above.)rW   rn   r*   T)use_dill)progress_barN)	r   
isinstancer   r
   mpire
WorkerPoolmaprd   r4   )r   text_or_texts	processesprogressrW   rn   chunk_functionr5   r   poolry   offsets_s               r#   __call__zChunker.__call__Q  s    6 227G2TmS)!-00	Q /M>CP!Q4."6!Q!Q !!)d; dt%)XXnmZbX%c"d "$67FH<h//!! "Rd ds   B20B77C )rJ   intrK   Callable[[str], int]r   None)rW   boolrn   float | int | Noner   zDCallable[[str], list[str] | tuple[list[str], list[tuple[int, int]]]])r*   FFN)r   zstr | Sequence[str]r   r   r   r   rW   r   rn   zint | float | Noner   z{list[str] | tuple[list[str], list[tuple[int, int]]] | list[list[str]] | tuple[list[list[str]], list[list[tuple[int, int]]]])__name__
__module____qualname__r   r   r   r>   r;   r#   r   r   9  sv    + $ 
N	, &*/"*/" /" 	/"
 /" $/"	>/"r;   r   c                Z    t         t              r	 ddl}	  |j                         }| qdD ]l  }t         |      st        t         |            s& t         |             }	t        |	d      sD|	sGt        d |	D              sZt        d |	D               n t         d	      rht         j                  t               rN j                  t         d
      rAt#        t              5  t%         j'                  d            z  ddd       nt        d      t         d
      r9dt)        j*                   j&                        j,                  v rd fd}
n	d fd}
n }
dz
  |
dfd}|}
|r%t.        j1                  |
 t3        |      |
            }
t5        |
      S # t        $ r  |j
                         }Y w xY w# t        $ rA 	 ddl}|j                  j                         }n# t        $ r t        d  d      w xY wY w xY w# 1 sw Y   xY w)a/  Construct a chunker that splits one or more texts into semantically meaningful chunks of a specified size as determined by the provided tokenizer or token counter.

    Args:
        tokenizer_or_token_counter (str | tiktoken.Encoding | transformers.PreTrainedTokenizer | tokenizers.Tokenizer | Callable[[str], int]): Either: the name of a `tiktoken` or `transformers` tokenizer (with priority given to the former); a tokenizer that possesses an `encode` attribute (e.g., a `tiktoken`, `transformers` or `tokenizers` tokenizer); or a token counter that returns the number of tokens in a input.
        chunk_size (int, optional): The maximum number of tokens a chunk may contain. Defaults to `None` in which case it will be set to the same value as the tokenizer's `model_max_length` attribute (deducted by the number of tokens returned by attempting to tokenize an empty string) if possible otherwise a `ValueError` will be raised.
        max_token_chars (int, optional): The maximum number of characters a token may contain. Used to significantly speed up the token counting of long inputs. Defaults to `None` in which case it will either not be used or will, if possible, be set to the number of characters in the longest token in the tokenizer's vocabulary as determined by the `token_byte_values` or `get_vocab` methods.
        memoize (bool, optional): Whether to memoize the token counter. Defaults to `True`.
        cache_maxsize (int, optional): The maximum number of text-token count pairs that can be stored in the token counter's cache. Defaults to `None`, which makes the cache unbounded. This argument is only used if `memoize` is `True`.

    Returns:
        Callable[[str | Sequence[str], bool, bool, bool, int | float | None], list[str] | tuple[list[str], list[tuple[int, int]]] | list[list[str]] | tuple[list[list[str]], list[list[tuple[int, int]]]]]: A chunker that takes either a single text or a sequence of texts and returns, depending on whether multiple texts have been provided, a list or list of lists of chunks up to `chunk_size`-tokens-long with any whitespace used to split the text removed, and, if the optional `offsets` argument to the chunker is `True`, a list or lists of tuples of the form `(start, end)` where `start` is the index of the first character of a chunk in a text and `end` is the index of the character succeeding the last character of the chunk such that `chunks[i] == text[offsets[i][0]:offsets[i][1]]`.

        The resulting chunker can be passed a `processes` argument that specifies the number of processes to be used when chunking multiple texts.

        It is also possible to pass a `progress` argument which, if set to `True` and multiple texts are passed, will display a progress bar.

        As described above, the `offsets` argument, if set to `True`, will cause the chunker to return the start and end offsets of each chunk.

        The chunker accepts an `overlap` argument that specifies the proportion of the chunk size, or, if >=1, the number of tokens, by which chunks should overlap. It defaults to `None`, in which case no overlapping occurs.r   Nr   z" was provided to `semchunk.chunkerify` as the name of a tokenizer but neither `tiktoken` nor `transformers` have a tokenizer by that name. Perhaps they are not installed or maybe there is a typo in that name?)token_byte_values	get_vocab__iter__c              3  4   K   | ]  }t        |d         yw)__len__N)hasattrr!   tokens     r#   r$   zchunkerify.<locals>.<genexpr>  s     ?m^cy@Y?ms   c              3  2   K   | ]  }t        |        y wr   r.   r   s     r#   r$   zchunkerify.<locals>.<genexpr>  s     )H#e*)Hs   model_max_lengthencoder+   a!  Your desired chunk size was not passed to `semchunk.chunkerify` and the provided tokenizer either lacks an attribute named 'model_max_length' or that attribute is not an integer. Either specify a chunk size or provide a tokenizer that has a 'model_max_length' attribute that is an integer.add_special_tokensc                <    t        j                  | d            S )NF)r   r.   r   r5   tokenizer_or_token_counters    r#   rK   z!chunkerify.<locals>.token_counter  s     5<<TV[<\]]r;   c                8    t        j                  |             S r   r   r   s    r#   rK   z!chunkerify.<locals>.token_counter  s    5<<TBCCr;   r*   c                f    dz  }t        |       |kD  r | d |z          kD  rdz   S  |       S )N   r*   r   )r5   	heuristicrJ   max_token_charsoriginal_token_counters     r#   faster_token_counterz(chunkerify.<locals>.faster_token_counter  sI    "QI4y9$)?EbySbGb@c)dgq)q!A~%)$//r;   r   )r5   r   r   r   )r   r   tiktokenencoding_for_model	Exceptionget_encodingtransformersAutoTokenizerfrom_pretrained
ValueErrorr   callablegetattrrj   r,   r   r   r	   r.   r   inspect	signature
parametersr^   r_   r   r   )r   rJ   r   rm   ro   r   	tokenizerr   $potential_vocabulary_getter_functionvocabrK   r   r   s   ```         @r#   
chunkerifyr     sx   @ ,c2	N7H778RS	  &/" 5
 	0 13WX]e24XY^ b :<`ac5*-%C?mgl?m<m&))H%)H&HO	 -/ABz&77H
 4DDJ 18<i( M#&@&G&G&K"LLJM M  t 
 )847#4#45O5V5V#W#b#bb^
D 3 ")A-!.	0 - 0;;MKc9UbKcdqKrs jFFi  N1H112LM	N  		#(66FFGab	  23  4E  F  			JM MsR   G F1 1H 1GG GG 	HG=<H=HHH H*)r5   r   r   ztuple[str, bool, list[str]])
r?   r4   r@   r   rA   r   rB   r   r   r   )rH   z	list[str]rI   z	list[int]rJ   r   r"   r   rK   r   rL   r   rB   r   r   ztuple[int, str])TFNNr   r   )r5   r   rJ   r   rK   r   rm   r   rW   r   rn   r   ro   
int | NonerX   r   rY   r   r   r   )NNTN)r   zhstr | tiktoken.Encoding | transformers.PreTrainedTokenizer | tokenizers.Tokenizer | Callable[[str], int]rJ   r   r   r   rm   r   ro   r   r   r   )
__future__r   r   r`   r   typingr   r   r   	functoolsr   	itertoolsr   
contextlibr	   r   r
   r   
tokenizersr   r^   r3   tupler0   r:   rD   rT   re   r   r   r>   r;   r#   <module>r      s   " 	   4 4         9& "> S38  9A]  9A  4A 0(BV
11!*18;1GJ1[c1lo1wz11J "& $a
aa (a 	a
 a  a a a a 9aHG" G"` ""& ${G!{G {G  {G {G {G {Gr;   