
    Oj:                     $   S r SSKrSSKJrJr  SSKJrJr  SSKJr  SSK	J
r
  SSK	Jr  SS	K	Jr  SS
K	Jr  \R                   " S5      r/ SQr " S S5      rS\S\R*                  R,                  R.                  S\4S jrS\S\4S jr " S S5      rg)z)[Experimental] Text Only Local Tokenizer.    N)AnyIterable)OptionalUnion)sentencepiece_model_pb2   )_common)_local_tokenizer_loader)_transformers)typeszgoogle_genai.local_tokenizer)_parse_hex_byte_token_str_to_bytesLocalTokenizer_TextsAccumulatorc                      \ rS rSrSrSS jrS\\   4S jrS\\	R                     SS4S jrS	\	R                  SS4S
 jrS\	R                  SS4S jrS\	R                  S\	R                  4S jrS\\	R                     SS4S jrS\\	R$                     SS4S jrS\	R$                  SS4S jrS\	R*                  S\	R*                  4S jrS\	R.                  S\	R.                  4S jrS\\\4   S\\\4   4S jrS\S\4S jrSrg)r   '   a  Accumulates countable texts from `Content` and `Tool` objects.

This class is responsible for traversing complex `Content` and `Tool`
objects and extracting all the text content that should be included when
calculating token counts.

A key feature of this class is its ability to detect unsupported fields in
`Content` objects. If a user provides a `Content` object with fields that
this local tokenizer doesn't recognize (e.g., new fields added in a future
API update), this class will log a warning.

The detection mechanism for `Content` objects works by recursively building
a "counted" version of the input object. This "counted" object only
contains the data that was successfully processed and added to the text
list for tokenization. After traversing the input, the original `Content`
object is compared to the "counted" object. If they don't match, it
signifies the presence of unsupported fields, and a warning is logged.
returnNc                     / U l         g N_textsselfs    ^/var/www/html/leaf-doctor-v1/venv/lib/python3.13/site-packages/google/genai/local_tokenizer.py__init___TextsAccumulator.__init__;   s	    DK    c                     U R                   $ r   r   r   s    r   	get_texts_TextsAccumulator.get_texts>   s    ;;r   contentsc                 8    U H  nU R                  U5        M     g r   )add_content)r   r!   contents      r   add_contents_TextsAccumulator.add_contentsA   s    
w r   r$   c                 x   [         R                  " / UR                  S9nUR                  (       GaL  UR                   GH;  nUR                  c   e[         R                  " 5       nUR
                  c  UR                  b  [        S5      eUR                  b  UR                  Ul        UR                  b,  U R                  UR                  5        UR                  Ul	        UR                  b,  U R                  UR                  5        UR                  Ul        UR                  b6  UR                  Ul        U R                  R                  UR                  5        UR                  R                  U5        GM>     UR!                  SS9UR!                  SS9:w  a  ["        R%                  SU SU S35        g g )N)partsrolez6LocalTokenizers do not support non-text content types.T)exclude_nonezHContent contains unsupported types for token counting. Supported fields z. Got .)r   Contentr)   r(   Part	file_datainline_data
ValueErrorvideo_metadatafunction_calladd_function_callfunction_responseadd_function_responsetextr   append
model_dumploggerwarning)r   r$   counted_contentpartcounted_parts        r   r#   _TextsAccumulator.add_contentE   s   mm"7<<@O}}}--$$$000zz|>>%)9)9)EF  *(,(;(;,
%)

 
 !3!3
4'+'9'9,
$!!-

$
$T%;%;
<+/+A+A,
(99 "ii,

++

TYY
'$$\2%  ( t,0J0J 1K 1  nn$%VG9A7r   r2   c                    UR                   (       a%  U R                  R                  UR                   5        [        R                  " UR                   S9nUR
                  (       a"  U R                  UR
                  5      nX2l        gg)z}Processes a function call and adds relevant text to the accumulator.

Args:
    function_call: The function call to process.
)nameN)r@   r   r7   r   FunctionCallargs_dict_traverse)r   r2   counted_function_callcounted_argss       r   r3   #_TextsAccumulator.add_function_calld   sf     
kk++,!..M4F4FG((););<l#/  r   toolc                     [         R                  " / S9nUR                  (       aS  UR                   HC  nU R                  U5      nUR                  c  / Ul        UR                  R	                  U5        ME     U$ )N)function_declarations)r   ToolrI   _function_declaration_traverser7   )r   rG   counted_toolfunction_declarationcounted_function_declarations        r   add_tool_TextsAccumulator.add_toolq   sq    ::B7L!!"&"<"<
'+'J'J (
$ --5/1,
,**112NO #= r   toolsc                 8    U H  nU R                  U5        M     g r   )rO   )r   rQ   rG   s      r   	add_tools_TextsAccumulator.add_tools~   s    
mmD r   function_responsesc                 8    U H  nU R                  U5        M     g r   )r5   )r   rU   r4   s      r   add_function_responses(_TextsAccumulator.add_function_responses   s     0
  !23 0r   r4   c                 "   [         R                  " 5       nUR                  (       a6  U R                  R	                  UR                  5        UR                  Ul        UR
                  (       a"  U R                  UR
                  5      nX2l        g g r   )r   FunctionResponser@   r   r7   responserC   )r   r4   counted_function_responsecounted_responses       r   r5   '_TextsAccumulator.add_function_response   sp     !& 6 6 8
kk*//0'8'='=$!!,,->-G-GH+;( "r   rM   c                    [         R                  " 5       nUR                  (       a6  U R                  R	                  UR                  5        UR                  Ul        UR
                  (       a6  U R                  R	                  UR
                  5        UR
                  Ul        UR                  (       a!  U R                  UR                  5      nX2l        UR                  (       a!  U R                  UR                  5      nXBl        U$ r   )	r   FunctionDeclarationr@   r   r7   description
parameters
add_schemar[   )r   rM   rN   counted_parametersr]   s        r   rK   0_TextsAccumulator._function_declaration_traverse   s     $)#<#<#>   
kk-223*>*C*C"'''
kk-99:

*
* #. &&??+?+J+JK0B-$$)=)F)FG.>+''r   schemac                    [         R                  " 5       nUR                  (       a  UR                  Ul        UR                  (       a  UR                  Ul        UR                  b  UR                  Ul        UR
                  (       a6  U R                  R                  UR
                  5        UR
                  Ul        UR                  (       a6  U R                  R                  UR                  5        UR                  Ul        UR                  (       a6  U R                  R                  UR                  5        UR                  Ul	        UR                  (       a6  U R                  R                  UR                  5        UR                  Ul        UR                  (       a  UR                  Ul        UR                  (       a!  U R                  UR                  5      nX2l        UR                  (       a[  0 nUR                  R                  5        H5  u  pVU R                  R                  U5        U R                  U5      nXtU'   M7     XBl        UR                   (       a!  U R#                  UR                   5      nXl        U$ )zProcesses a schema and adds relevant text to the accumulator.

Args:
    schema: The schema to process.

Returns:
    The new schema object with only countable fields.
)r   Schematypetitledefaultformatr   r7   ra   enumextendrequiredproperty_orderingitemsrc   
propertiesexample_any_traverse)	r   rf   counted_schemacounted_schema_itemsdkeyvaluecounted_valuecounted_schema_examples	            r   rc   _TextsAccumulator.add_schema   s    \\^N{{"KKn||#\\n~~!%~~n}}
kk'$mmn
kk++,#)#5#5n {{
kk%"KKn
kk) &n)/)A)An&||!__V\\:1
a))//1*#3.# 2 #$~~#11&..A5r   rw   c                     0 nU R                   R                  [        UR                  5       5      5        UR	                  5        H  u  p4U R                  U5      X#'   M     U$ )zProcesses a dict and adds relevant text to the accumulator.

Args:
    d: The dict to process.

Returns:
    The new dict object with only countable fields.
)r   rn   listkeysrq   rt   )r   rw   counted_dictrx   vals        r   rC    _TextsAccumulator._dict_traverse   sP     LKKtAFFH~&GGI,,S1l r   ry   c                 ,   [        U[        5      (       a  U R                  R                  U5        U$ [        U[        5      (       a  U R                  U5      $ [        U[        5      (       a!  U Vs/ s H  o R                  U5      PM     sn$ U$ s  snf )zProcesses a value and adds relevant text to the accumulator.

Args:
    value: The value to process.

Returns:
    The new value with only countable fields.
)
isinstancestrr   r7   dictrC   r~   rt   )r   ry   items      r   rt   _TextsAccumulator._any_traverse   s{     %
kkl	E4	 	   ''	E4	 	 38954  &599l :s   2Br   )r   N)__name__
__module____qualname____firstlineno____doc__r   r   r   r   r   r,   r%   r#   rA   r3   rJ   rO   rS   rZ   rW   r5   r`   rK   rh   rc   r   r   rC   rt   __static_attributes__ r   r   r   r   '   sM   & #  8EMM#:  t   4 >0U-?-? 0D 05:: %** Xejj1 d 4 ()?)? @44	<$55	<	<("'";";(  ((+u|| + +Zd38n c3h   r   r   tokenri   r   c                     U[         R                  R                  R                  R                  :X  a  [        U 5      R                  SSS9$ U R                  SS5      R                  S5      $ )Nr   big)length	byteorderu   ▁ utf-8)	r   
ModelProtoSentencePieceTypeBYTEr   to_bytesreplaceencode)r   ri   s     r   r   r      s\     
$//==BBGGG5!**!u*EE==$++G44r   c                 4   [        U 5      S:w  a  [        SU  35      eU R                  S5      (       a  U R                  S5      (       d  [        SU  35      e [	        U SS S5      nUS
:  a  [        SU  35      eU$ ! [         a    [        S	U  35      ef = f)zParses a hex byte string of the form '<0xXX>' and returns the integer value.

Raises ValueError if the input is malformed or the byte value is invalid.
   zInvalid byte length: z<0x>zInvalid byte format:          zInvalid hex value:    zByte value out of range: )lenr0   
startswithendswithint)r   r   s     r   r   r      s     	Z1_
,UG4
55			%	 	 s(;(;
,UG4
554
eAaj"
C 	CZ
08
99	* 
 4
*5'2
334s   A> >Bc                   P   \ rS rSrSrS\4S jr\R                  " S5      SS.S\	\
R                  \
R                  4   S	\\
R                     S
\
R                  4S jj5       r\R                  " S5      S\	\
R                  \
R                  4   S
\
R"                  4S j5       rSrg)r   i  a  [Experimental] Text Only Local Tokenizer.

This class provides a local tokenizer for text only token counting.

LIMITATIONS:
- Only supports text based tokenization and no multimodal tokenization.
- Forward compatibility depends on the open-source tokenizer models for future
Gemini versions.
- For token counting of tools and response schemas, the `LocalTokenizer` only
supports `types.Tool` and `types.Schema` objects. Python functions or Pydantic
models cannot be passed directly.

model_namec                 d   [         R                  " U5      U l        S U l        U R                  [         R                  ;   a&  [         R
                  " U R                  5      U l        g [         R                  " U R                  5      U l        [         R                  " U R                  5      U l        g r   )	loaderget_tokenizer_name_tokenizer_name_model_protoGEMMA_TOKENIZER_TO_MODEL_NAMESget_huggingface_tokenizer
_tokenizerload_model_protoget_sentencepiece)r   r   s     r   r   LocalTokenizer.__init__$  sz    !44Z@DDvDDD889M9MNdo 11$2F2FGd001E1EFdor   zThe SDK's local tokenizer implementation is experimental and may change in the future. It only supports text based tokenization.N)configr!   r   r   c                   [         R                  " U5      n[        5       n[        R                  R                  U=(       d    0 5      nUR                  U5        UR                  (       a  UR                  UR                  5        UR                  (       a@  UR                  R                  (       a%  UR                  UR                  R                  5        UR                  (       a0  UR                  [         R                  " UR                  /5      5        U R                  R                  [        UR!                  5       5      5      n[        R"                  " [%        S U 5       5      S9$ )a  Counts the number of tokens in a given text.

Args:
  contents: The contents to tokenize.
  config: The configuration for counting tokens.

Returns:
  A `CountTokensResult` containing the total number of tokens.

Usage:

.. code-block:: python

  from google.genai import local_tokenizer
  tokenizer = local_tokenizer.LocalTokenizer(model_name='gemini-2.5-flash')
  result = tokenizer.count_tokens("What is your name?")
  print(result)
  # total_tokens=5
c              3   8   #    U  H  n[        U5      v   M     g 7fr   )r   ).0tokenss     r   	<genexpr>.LocalTokenizer.count_tokens.<locals>.<genexpr>V  s     ?;V;s   )total_tokens)t
t_contentsr   r   CountTokensConfigmodel_validater%   rQ   rS   generation_configresponse_schemarc   system_instructionr   r   r~   r   CountTokensResultsum)r   r!   r   processed_contentstext_accumulatortokens_lists         r   count_tokensLocalTokenizer.count_tokens-  s    : h/(*$$33FLbAF!!"45||  .F$<$<$L$L!!&":":"J"JK  ##ALL&2K2K1L$MN//((.>.H.H.J)KLK""?;?? r   c                    [         R                  " U5      n/ n[        5       nU HU  nUR                  U5        UR                  (       d  M'  UR                   H  nUR                  UR                  5        M      MW     / nU R                  [        R                  ;   a  U R                  R                  [        UR                  5       5      5      n[        X5       H  u  pUR                  [        R                   " U	U R                  R#                  U	5       Vs/ s H4  nUR%                  SS5      R                  S5      R%                  SS5      PM6     snU
S95        M     [        R&                  " US9$ U R                  R)                  UR                  5       5      n[        X5       H  u  pUR                  [        R                   " UR*                   Vs/ s H  oR,                  PM     snUR*                   Vs/ s HD  n[/        UR0                  U R2                  R*                  UR,                     R4                  5      PMF     snU
S95        M     [        R&                  " US9$ s  snf s  snf s  snf )a  Computes the tokens ids and string pieces in the input.

Args:
  contents: The contents to tokenize.

Returns:
  A `ComputeTokensResult` containing the token information.

Usage:

.. code-block:: python

  from google.genai import local_tokenizer
  tokenizer = local_tokenizer.LocalTokenizer(model_name='gemini-2.5-flash')
  result = tokenizer.compute_tokens("What is your name?")
  print(result)
  # tokens_info=[TokensInfo(token_ids=[279, 329, 1313, 2508, 13], tokens=[b' What', b' is', b' your', b' name', b'?'], role='user')]
_r   r   s   ▁    )	token_idsr   r)   )tokens_info)r   r   r   r#   r(   r7   r)   r   r   r   r   r   r~   r   zipr   
TokensInfoconvert_ids_to_tokensr   ComputeTokensResultEncodeAsImmutableProtopiecesidr   piecer   ri   )r   r!   r   rolesr   r$   r   token_infosr   token_idr)   r   tokens_protostokens_protor   s                  r   compute_tokensLocalTokenizer.compute_tokensY  s#   4 h/E(*%""7+	A
,,w||
$  & KvDDD //((.>.H.H.J)KLi	1.("
 "&!F!Fx!P	 "Q MM#s+VG_W_d34 "Q	 		
 2 &&;??OO::""$M "-7


/;/B/BC/Be/BC
  ,22	  3e &kk4#4#4#;#;EHH#E#J#J  3	 	 8 $$==9$ Ds   ;I*I/=AI4)r   r   r   )r   r   r   r   r   r   r   r	   experimental_warningr   r   ContentListUnionContentListUnionDictr   CountTokensConfigOrDictr   r   r   r   r   r   r   r   r   r     s    G G B 9=	&e,,e.H.HHI& u445	&
 &	&P BE>e,,e.H.HHIE>   E>	E>r   r   )r   loggingtypingr   r   r   r   sentencepiecer    r	   r
   r   r   r   r   	getLoggerr9   __all__r   r   r   r   r   bytesr   r   r   r   r   r   r   <module>r      s     0    " 1  /   			9	:M M`55-88FFKK5
53 3 ,L> L>r   