
    hj:                        d Z ddlZddlmZmZ ddlmZmZ ddlmZ ddl	m
Z
 ddl	mZ dd	l	mZ dd
l	mZ  ej        d          Zg dZ G d d          Zdedej        j        j        defdZdedefdZ G d d          ZdS )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                      e Zd ZdZddZdee         fdZdeej	                 ddfdZ
dej	        ddfd	Zd
ej        ddfdZdej        dej        fdZdeej                 ddfdZdeej                 ddfdZdej        ddfdZdej        dej        fdZdej        dej        fdZdeeef         deeef         fdZdedefdZdS )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                     g | _         d S N_textsselfs    `/var/www/app.qaans.com/backend/venv/lib/python3.11/site-packages/google/genai/local_tokenizer.py__init__z_TextsAccumulator.__init__;   s    DKKK    c                     | j         S r   r   r   s    r   	get_textsz_TextsAccumulator.get_texts>   s
    ;r   contentsc                 :    |D ]}|                      |           d S r   )add_content)r   r   contents      r   add_contentsz_TextsAccumulator.add_contentsA   s2        
w   r   r!   c                    t          j        g |j                  }|j        r|j        D ]}|j        J t          j                    }|j        |j        t          d          |j        |j        |_        |j	        &| 
                    |j	                   |j	        |_	        |j        &|                     |j                   |j        |_        |j        +|j        |_        | j                            |j                   |j                            |           |                    d          |                    d          k    r#t"                              d| d| d           d S d S )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    z_TextsAccumulator.add_contentE   s   m"7<@@@O} 3- 3 3$$000z||>%)9)EF   *(,(;,
%)

 
 !3
4
4
4'+'9,
$!-

$
$T%;
<
<
<+/+A,
(9 "i,

+

TY
'
'
'$$\2222t,,0J0J 1K 1 1   nn7$7 7,37 7 7     r   r.   c                     |j         r| j                            |j                    t          j        |j                   }|j        r#|                     |j                  }||_        dS dS )zProcesses a function call and adds relevant text to the accumulator.

    Args:
        function_call: The function call to process.
    )nameN)r;   r   r3   r   FunctionCallargs_dict_traverse)r   r.   counted_function_callcounted_argss       r   r/   z#_TextsAccumulator.add_function_calld   sy      -
k+,,,!.M4FGGG 0(();<<l#/   0 0r   toolc                     t          j        g           }|j        rG|j        D ]?}|                     |          }|j        g |_        |j                            |           @|S )N)function_declarations)r   ToolrC   _function_declaration_traverser3   )r   rA   counted_toolfunction_declarationcounted_function_declarations        r   add_toolz_TextsAccumulator.add_toolq   s    :B777L! P"&"< P P
'+'J'J (
 (
$ -5/1,
,*112NOOOOr   toolsc                 :    |D ]}|                      |           d S r   )rI   )r   rJ   rA   s      r   	add_toolsz_TextsAccumulator.add_tools~   s0      
mmD r   function_responsesc                 :    |D ]}|                      |           d S r   )r1   )r   rM   r0   s      r   add_function_responsesz(_TextsAccumulator.add_function_responses   s6     0 4 4
  !233334 4r   r0   c                     t          j                    }|j        r+| j                            |j                   |j        |_        |j        r#|                     |j                  }||_        d S d S r   )r   FunctionResponser;   r   r3   responser>   )r   r0   counted_function_responsecounted_responses       r   r1   z'_TextsAccumulator.add_function_response   s     !& 6 8 8 >
k*/000'8'=$! <,,->-GHH+;(((< <r   rG   c                    t          j                    }|j        r+| j                            |j                   |j        |_        |j        r+| j                            |j                   |j        |_        |j        r!|                     |j                  }||_        |j        r!|                     |j                  }||_        |S r   )	r   FunctionDeclarationr;   r   r3   description
parameters
add_schemarR   )r   rG   rH   counted_parametersrT   s        r   rE   z0_TextsAccumulator._function_declaration_traverse   s     $)#<#>#>   D
k-2333*>*C"'' 
k-9:::

* #. & C??+?+JKK0B"-$ ?)=)FGG.>"+''r   schemac                    t          j                    }|j        r|j        |_        |j        r|j        |_        |j        |j        |_        |j        r+| j                            |j                   |j        |_        |j        r+| j                            |j                   |j        |_        |j	        r+| j        
                    |j	                   |j	        |_	        |j        r+| j        
                    |j                   |j        |_        |j        r|j        |_        |j        r!|                     |j                  }||_        |j        r\i }|j                                        D ]9\  }}| j                            |           |                     |          }|||<   :||_        |j        r!|                     |j                  }||_        |S )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   r3   rW   enumextendrequiredproperty_orderingitemsrY   
propertiesexample_any_traverse)	r   r[   counted_schemacounted_schema_itemsdkeyvaluecounted_valuecounted_schema_examples	            r   rY   z_TextsAccumulator.add_schema   s    \^^N{ ("Kn| *#\n~!%~n} ,
k'''$mn 6
k+,,,#)#5n { (
k%%%"Kn 0
k))) &n B)/)An&| 2!__V\::1n $
a)//11  *#u3..#"#n~ 6#11&.AA5nr   rl   c                     i }| j                             t          |                                                     |                                D ]\  }}|                     |          ||<   |S )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   rc   listkeysrf   ri   )r   rl   counted_dictrm   vals        r   r>   z _TextsAccumulator._dict_traverse   si     LKtAFFHH~~&&&GGII 2 2S,,S11l3r   rn   c                     t          |t                    r j                            |           |S t          |t                    r                     |          S t          |t                    r fd|D             S |S )zProcesses a value and adds relevant text to the accumulator.

    Args:
        value: The value to process.

    Returns:
        The new value with only countable fields.
    c                 :    g | ]}                     |          S  )ri   ).0itemr   s     r   
<listcomp>z3_TextsAccumulator._any_traverse.<locals>.<listcomp>   s'    9994d  &&999r   )
isinstancestrr   r3   dictr>   rr   )r   rn   s   ` r   ri   z_TextsAccumulator._any_traverse   s     % 
kl	E4	 	    '''	E4	 	  999959999lr   )r   N)__name__
__module____qualname____doc__r   r   r}   r   r   r(   r"   r    r<   r/   rD   rI   rL   rQ   rO   r1   rV   rE   r]   rY   r~   r   r>   ri   rx   r   r   r   r   '   s
        &       #     8EM#:  t         4    >0U-? 0D 0 0 0 05: %*    Xej1 d    4 ()? @44 4 4 4	<$5	<	< 	< 	< 	<("'";( ( ( ( ((+u| + + + + +Zd38n c3h           r   r   tokenr^   r   c                     |t           j        j        j        j        k    r$t          |                               dd          S |                     dd                              d          S )Nr   big)length	byteorderu   ▁ utf-8)	r   
ModelProtoSentencePieceTypeBYTEr   to_bytesreplaceencode)r   r^   s     r   r   r      s_     
$/=BGGG5!!**!u*EEE==$$++G444r   c                 l   t          |           dk    rt          d|            |                     d          r|                     d          st          d|            	 t	          | dd         d          }n # t          $ r t          d	|            w xY w|d
k    rt          d|            |S )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: )lenr,   
startswithendswithint)r   ru   s     r   r   r      s     	ZZ1__
4U44
5
55			%	 	  6s(;(; 6
4U44
5
554
eAaCj"

CC	 4 4 4
2522
3
334 	CZZ
888
9
99	*s   #A< <Bc                      e Zd ZdZdefdZ ej        d          dddee	j
        e	j        f         dee	j                 d	e	j        fd
            Z ej        d          dee	j
        e	j        f         d	e	j        fd            ZdS )r   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                 $   t          j        |          | _        d | _        | j        t           j        v r t          j        | j                  | _        d S t          j        | j                  | _        t          j        | j                  | _        d S 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   zLocalTokenizer.__init__$  sv    !4Z@@DDvDDD89MNNdooo 1$2FGGd01EFFdooor   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                   t          j        |          }t                      }t          j                            |pi           }|                    |           |j        r|                    |j                   |j	        r+|j	        j
        r|                    |j	        j
                   |j        r-|                    t          j        |j        g                     | j                            t          |                                                    }t          j        t%          d |D                                 S )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   4   K   | ]}t          |          V  d S r   )r   )ry   tokenss     r   	<genexpr>z.LocalTokenizer.count_tokens.<locals>.<genexpr>V  s(      ??V??????r   )total_tokens)t
t_contentsr   r   CountTokensConfigmodel_validater"   rJ   rL   generation_configresponse_schemarY   system_instructionr   r   rr   r   CountTokensResultsum)r   r   r   processed_contentstext_accumulatortokens_lists         r   count_tokenszLocalTokenizer.count_tokens-  s1   : h//(**$33FLbAAF!!"4555| /  ... LF$<$L L!!&":"JKKK  O##AL&2K1L$M$MNNN/((.>.H.H.J.J)K)KLLK"??;?????   r   c           
          t          j        |          }g }t                      }|D ]B}|                    |           |j        r$|j        D ]}|                    |j                   Cg } j        t          j	        v r j
                            t          |                                                    }t          ||          D ]Q\  }	}
|                    t          j        |	d  j
                            |	          D             |
                     Rt          j        |          S  j
                            |                                          }t          ||          D ]O\  }}
|                    t          j        d |j        D              fd|j        D             |
                     Pt          j        |          S )aB  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')]
    c                     g | ]?}|                     d d                              d                               dd          @S )_r   r   s   ▁    )r   r   )ry   r   s     r   r{   z1LocalTokenizer.compute_tokens.<locals>.<listcomp>  sR         MM#s++VG__W_d33  r   )	token_idsr   r%   )tokens_infoc                     g | ]	}|j         
S rx   )id)ry   pieces     r   r{   z1LocalTokenizer.compute_tokens.<locals>.<listcomp>  s    CCCeCCCr   c                 n    g | ]1}t          |j        j        j        |j                 j                  2S rx   )r   r   r   piecesr   r^   )ry   r   r   s     r   r{   z1LocalTokenizer.compute_tokens.<locals>.<listcomp>  sL         &k4#4#;EH#E#J   r   )r   r   r   r    r$   r3   r%   r   r   r   r   r   rr   r   zipr   
TokensInfoconvert_ids_to_tokensComputeTokensResultEncodeAsImmutableProtor   )r   r   r   rolesr   r!   r   token_infosr   token_idr%   tokens_protostokens_protos   `            r   compute_tokenszLocalTokenizer.compute_tokensY  s+   4 h//E(**% % %""7+++	 % 	% 	%A
,,w|
$
$
$
$KvDDD /((.>.H.H.J.J)K)KLLi	511 
 
.(D"  "&!F!Fx!P!P	   	 	 		
 	
 	
 	
 &;????O::""$$ M "-77  d

CC|/BCCC     ,2	   	 	 	    $====r   )r   r   r   r   r}   r   r	   experimental_warningr   r   ContentListUnionContentListUnionDictr   CountTokensConfigOrDictr   r   r   r   rx   r   r   r   r     s"        G G G G G  7B  9=	& & &e,e.HHI& u45	&
 & & &	 &P  7B E>e,e.HHIE>  E> E> E>	 E> E> E>r   r   )r   loggingtypingr   r   r   r   sentencepiecer    r	   r
   r   r   r   r   	getLoggerr5   __all__r   r}   r   r   r   bytesr   r   r   r   rx   r   r   <module>r      s    0 /                  " " " " " " " " 1 1 1 1 1 1       / / / / / /                  		9	:	:  M M M M M M M M`55-8FK5
5 5 5 53 3    ,L> L> L> L> L> L> L> L> L> L>r   