
    =Ki	j                       S SK Jr  S SKrS SKrS SKrS SKrS SKJr  S SKJ	r	J
r
JrJr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JrJr  \	(       a  S S
KJr  \" S\S\
4   S9r\R<                  " \5      r SS jr!SS jr"SS jr#      S S jr$S!S jr%S"S jr&S#S jr'  S$           S%S jjr( " S S\SS9r)\SSS.       S&S jj5       r*g)'    )annotationsN)Mapping)TYPE_CHECKINGAnyCallableOptionalTypeVarUnion)	TypedDict)client)run_helpers)	warn_beta)InputTokenDetailsOutputTokenDetailsUsageMetadata)genaiCzgenai.Client)boundc                b    U R                  5        VVs0 s H  u  pUc  M
  X_M     snn$ s  snnf )z%Remove `None` values from dictionary.)items)dkvs      \/var/www/html/dynamic-report/venv/lib/python3.13/site-packages/langsmith/wrappers/_gemini.py_strip_noner      s(    WWY8YTQ!DADY888s   	++c                f    SU ;   a+  [        U S   [        5      (       d  [        U S   5      U S'   ggg)zFConvert `GenerateContentConfig` to `dict` for LangSmith compatibility.configN)
isinstancedictvars)kwargss    r   _convert_config_for_tracingr"   $   s8    6*VH-=t"D"Dx 01x #E    c                   U R                  S5      nU(       d  U $ [        U[        5      (       aE  SUS./U R                  S5      S.U R                  5        VVs0 s H  u  p#US;  d  M  X#_M     snnE$ [        U[        5      (       Ga^  [        S U 5       5      (       aU  U Vs/ s H  nSUS.PM
     snU R                  S5      S.U R                  5        VVs0 s H  u  p#US;  d  M  X#_M     snnE$ / nU GH  n[        U[        5      (       d  M  UR                  SS5      nUR                  S	/ 5      n/ n	/ n
U GH  n[        U[        5      (       Ga  S
U;   a7  US
   (       a-  U	R                  US
   5        U
R                  S
US
   S.5        MW  SU;   a  US   nUR                  SS5      nUR                  SS5      n[        U[        5      (       a&  [        R                  " U5      R                  S5      nOUnU
R                  SSU SU 3SS.S.5        M  SU;   a>  US   nU
R                  SUR                  S5      UR                  S0 5      S.S.5        GM&  SU;   d  SU;   a  UR                  S5      =(       d    UR                  S5      nUbn  [        U[        5      (       d  UR                  5       nU
R                  SUR                  S 5      UR                  S5      UR                  S!0 5      S".S#.5        GM  GM  GM  [        U[        5      (       d  GM  U	R                  U5        U
R                  S
US.5        GM     U
(       a)  [        S$ U
 5       5      (       a  S%R                  U	5      nOU
(       a  U
OS&nUR                  UUS.5        GM     UU R                  S5      S.U R                  5        VVs0 s H  u  p#US;  d  M  X#_M     snnE$ U $ s  snnf s  snf s  snnf s  snnf )'u  Process Gemini inputs to normalize them for LangSmith tracing.

Example:
    ```txt
    {"contents": "Hello", "model": "gemini-pro"}
    → {"messages": [{"role": "user", "content": "Hello"}], "model": "gemini-pro"}
    {"contents": [{"role": "user", "parts": [{"text": "What is AI?"}]}], "model": "gemini-pro"}
    → {"messages": [{"role": "user", "content": "What is AI?"}], "model": "gemini-pro"}
    ```
contentsuser)rolecontentmodel)messagesr)   )r%   r)   c              3  B   #    U  H  n[        U[        5      v   M     g 7f)N)r   str).0items     r   	<genexpr>)_process_gemini_inputs.<locals>.<genexpr>E   s     :z$$$s   r'   partstexttyper2   inline_data	mime_type
image/jpegdatar#   utf-8	image_urldata:;base64,highurldetailr4   r:   functionResponsefunction_responsenameresponse)rD   rE   )r4   rC   function_callfunctionCallidargsrH   rD   	argumentsr4   rF   c              3  H   #    U  H  oR                  S 5      S:H  v   M     g7f)r4   r2   N)get)r-   ps     r   r/   r0      s      )5BEE&MV+]s    "
 )rN   r   r,   r   listallr   appendbytesbase64	b64encodedecodeto_dictjoin)inputsr%   r   r   r.   r*   r(   r'   r1   
text_partscontent_partspartr5   r6   r8   data_b64rC   rF   message_contents                      r   _process_gemini_inputsra   *   s    zz*%H (C  "(X>?ZZ(
 "(R1<Q3QR
 	
 (D!!:::: LTT84f>8TG, &,\\^V^TQq@U7UDAD^V  G'4(({{662GR0  
 "!D!$--!T>d6l&--d6l;)00&$v,1WX*d2*.}*=K(3\(RI#.??63#?D  *$66+1+;+;D+A+H+H+Q+/)00,716yk(/T282&!" 047045G0H-)00,?0A0E0Ef0M4E4I4I,65*:&!"
 -4$8N,0HH_,E - .JM  -8'1-'F'F4A4I4I4KM - 4 40?2?2C2CD2I4A4E4Ef4M9F9J9J6SU9V:*%&	!"  9 9O( $D#.."))$/%,,fd-KLC "H !S )5B) & & IM		"IO 8Em"O/ JKm  p !ZZ(
 "(R1<Q3QR
 	
 M[ S UV| Ss*   O+*O+&O1O6,O6O<O<c                D   [        U5      nUR                  S0 5      n[        US5      (       a'  UR                  n[	        USS5      n[	        USS5      nO3UR                  S5      nUR                  S5      nUR                  S5      nSSUR                  S5      UUUU S	.$ )
z*Extract invocation parameters for tracing.r   temperaturemax_output_tokensNstop_sequencesgooglechatr)   )ls_providerls_model_typels_model_namels_temperaturels_max_tokensls_stopls_invocation_params)r   rN   hasattrrc   getattr)prepopulated_invocation_paramsr!   strippedr   rc   
max_tokensstops          r   _infer_invocation_paramsru      s     6"H\\(B'F v}%%((V%8$?
v/6jj/ZZ 34
zz*+  !g.%# > r#   c                   U R                  S5      =(       d    SnU R                  S5      =(       d    SnU R                  S5      =(       d    SnU R                  S5      =(       d    SnU R                  S5      =(       d    X-   n0 nU(       a(  X6S'   [        SUS-
  5      US	'   [        SUS-
  5      US
'   0 nU(       a  XGS'   U(       a  [        SUS-
  5      US
'   [        UUU[        S0 UR	                  5        VV	s0 s H  u  pU	c  M
  X_M     sn	nD6[        S0 UR	                  5        VV	s0 s H  u  pU	c  M
  X_M     sn	nD6S9$ s  sn	nf s  sn	nf )z2Convert Gemini usage metadata to LangSmith format.prompt_token_countr   candidates_token_countcached_content_token_countthoughts_token_counttotal_token_count
cache_readi@ cache_read_over_200k	over_200k	reasoning)input_tokensoutput_tokenstotal_tokensinput_token_detailsoutput_token_details )rN   maxr   r   r   r   )
gemini_usage_metadatarw   rx   ry   rz   r{   r   r   r   r   s
             r   _create_usage_metadatar      s   .223GHMA2667OPUTU!!">?D1  1445KLQPQ!!"56 	76 
 !#!,FL)69)F27
23 ,/q2Dv2M+NK(!#,@[),/3IF3R,S[)',&- 
 3 9 9 ;M ;qtqt ;M
 0 
 4 : : <N <tqt <N

 

 N Os   >	EE0	E=Ec                    [        U S5      (       a  U R                  5       nO:[        U S5      (       a  U R                  5       nOS[        U S[	        U 5      5      0nSn/ nSnSU;   Ga  US   (       Ga  US   S   nSU;   Ga  US   nS	U;   Ga  US	   (       Gaw  US	    GHm  nSU;   a*  US   (       a   X'S   -  nUR                  SUS   S
.5        M4  SU;   a  US   b  US   nUR                  SS5      n	UR                  SS5      n
[        U
[        5      (       a&  [        R                  " U
5      R                  S5      nOU
nUR                  SSU	 SU 3SS.S.5        M  SU;   d  SU;   d  M  UR                  S5      =(       d    UR                  S5      nUc  GM  [        U[        5      (       d  UR                  5       nUR                  SUR                  S5      UR                  S5      UR                  S0 5      S.S.5        GMp     SU;   a  US   (       a  US   nOSU;   a  US   nUR                  SUS
.5        U Vs/ s H  oR                  S5      S:X  d  M  UPM     nnU(       av  U=(       d    SS U[        U5       VVs/ s HN  u  nnUS   R                  S5      =(       d    S!U 3S"UUS   S   [        R                  " US   S#   5      S$.S%.PMP     snnS&.nO/[!        U5      S':  d  U(       a  US   S   S:w  a  US US(.nOUS US(.nUR                  S)5      n[#        SSSS*9nU(       a  [%        U5      nUR                  S+5      (       a  US   S UUS+   US,.$ [        US   [        5      (       a
  US   S UUS-.$ US   S UUS-.$ s  snf s  snnf ! [&         a&  n[(        R+                  S.U 35        S/U 0s SnA$ SnAff = f)0z$Process Gemini response for tracing.rY   
model_dumpr2   rQ   N
candidatesr   r(   r1   r3   r5   r6   r7   r8   r#   r9   r:   r;   r<   r=   r>   rA   rF   rG   rH   rD   rI   rJ   rL   finish_reasonr4   	assistantcall_functionrK   )rD   rK   )rH   r4   indexr   )r(   r'   r   
tool_calls   )r(   r'   r   usage_metadatar   r   r   r   )r(   r'   r   r   r   )r(   r'   r   r   z"Error processing Gemini response: output)ro   rY   r   rp   r,   rT   rN   r   rU   rV   rW   rX   r   	enumeratejsondumpslenr   r   	Exceptionloggerdebug)rE   rdictcontent_resultr]   r   	candidater(   r^   r5   r6   r8   r_   rF   rO   r   itcresultr   
usage_dictes                        r   "_process_generate_content_responser      sO   R$8Y''$$&EX|,,'')EWXvs8}EFE '+5 U<%8%8l+A.II%#I.g%''*:*: ' 0!T>d6l*6l:N)00&$v,1WX*d2tM7J7V*.}*=K(3\(RI#.??63#?D  *$66+1+;+;D+A+H+H+Q+/)00,716yk(/T282&!" -4$8N,0HH_,E - .JM  -8'1-'F'F4A4I4I4KM - 4 40?2?2C2CD2I4A4E4Ef4M9F9J9J6SU9V:*%&	!"K !1^ #i/Io4N$-o$>Mu_"6]N  &.!IJ "/SA%%-?2Ra
S *1T#!. "+:!6 "72 !155d;Jqc{ *!"$&$7$?)-B4G4T)U%	 "7	F" !#mA.v6&@ )#!.F *#!.F #34$1!!%

 /?J ::l## "),#!.$\2",  &+S11%i0'%2&0	   &i0'%2&0	 E TB  $9!=>(##$s]   E.N% 4*N% #B)N% N(N.#N% AN&BN% .!N% 	N% N% %
O/O
OOc           	        U (       d  S[        SSSS9S.$ SnSnU  H6  n [        US5      (       a  UR                  (       a  XR                  -  nUnM8     [        SSSS9nU(       Ga   [        US5      (       a  UR                  (       a  [        UR                  S	5      (       a  UR                  R                  5       nO[        UR                  S
5      (       a  UR                  R                  5       nOq[        UR                  SS5      [        UR                  SS5      [        UR                  SS5      [        UR                  SS5      [        UR                  SS5      S.n[        U5      nUUS.$ ! [         a$  n[        R                  SU 35         SnAGM  SnAff = f! [         a"  n[        R                  SU 35         SnAN]SnAff = f)z/Reduce streaming chunks into a single response.rQ   r   r   )r(   r   Nr2   zError processing chunk: r   rY   r   rw   rx   ry   rz   r{   )rw   rx   ry   rz   r{   z+Error extracting metadata from last chunk: )r   ro   r2   r   r   r   r   rY   r   rp   r   )
all_chunks	full_text
last_chunkchunkr   r   r   s          r   _reduce_generate_content_chunksr     s   +aa
 	
 IJ	9uf%%%**ZZ'	J	  %2aa%N 	Lz#3449R9R:44i@@!+!:!:!B!B!DJZ66EE!+!:!:!E!E!GJ /6&557KQ/ 3:&557OQR3 7>&557SUV7 18&557Mq1 .5&557JA."J$ "8
!C ( O  	9LL3A3788	9F  	LLLFqcJKK	Ls0   2E9*D
F* 9
F'F""F'*
G4GGFc                   ^ ^^^^ U=(       d    0 m[         R                  " T 5      UUU UU4S j5       n[         R                  " T 5      UUU UU4S j5       n[        R                  " T 5      (       a  U$ U$ )z9Create a wrapper for Gemini's `generate_content` methods.c                    > [        U5        [        R                  " STST(       a  [        OS [        T(       d  [
        OS [        R                  " [        T5      S.TD6nU" T5      " U 0 UD6$ Nllm)rD   run_type	reduce_fnprocess_inputsprocess_outputs_invocation_params_fnr   	r"   r   	traceabler   ra   r   	functoolspartialru   rI   r!   	decoratoris_streamingrD   original_generaterq   textras      r   generate_get_wrapper.<locals>.generate  sq     	$F+)) 
9E541:F2D"+"3"3(*H#
 
	 *+T<V<<r#   c                    >#    [        U5        [        R                  " STST(       a  [        OS [        T(       d  [
        OS [        R                  " [        T5      S.TD6nU" T5      " U 0 UD6I S h  vN $  N7fr   r   r   s      r   	agenerate_get_wrapper.<locals>.agenerate  sz      	$F+)) 
9E541:F2D"+"3"3(*H#
 
	 014B6BBBBs   A1A;4A95A;)r   wrapsr   is_async)r   rD   rq   tracing_extrar   r   r   r   s   ``` `  @r   _get_wrapperr     st      bF__&'= = (=( __&'C C (C( $,,->??9MXMr#   c                  4    \ rS rSr% S\S'   S\S'   S\S'   Srg	)
TracingExtrai  zOptional[Mapping[str, Any]]metadatazOptional[list[str]]tagszOptional[ls_client.Client]r   r   N)__name__
__module____qualname____firstlineno____annotations____static_attributes__r   r#   r   r   r     s    ))
&&r#   r   )totalChatGoogleGenerativeAI)r   	chat_namec               |   U=(       d    0 n[        UR                  S5      =(       d    0 5      nUR                  S0 5      nUR                  5        VVs0 s H  u  pVUS:w  d  M  XV_M     nnnU(       a  X7S'   [	        U S5      (       aK  [	        U R
                  S5      (       a0  [	        U R
                  R                  S5      (       a  [        S5      e[	        U S5      (       aK  [	        U R
                  S5      (       a0  [        U R
                  R                  UUUSS9U R
                  l        [	        U S5      (       aK  [	        U R
                  S	5      (       a0  [        U R
                  R                  UUUS
S9U R
                  l	        [	        U S5      (       a  [	        U R                  S5      (       ai  [	        U R                  R
                  S5      (       aD  [        U R                  R
                  R                  UUUSS9U R                  R
                  l        [	        U S5      (       a  [	        U R                  S5      (       ai  [	        U R                  R
                  S	5      (       aD  [        U R                  R
                  R                  UUUS
S9U R                  R
                  l	        U $ s  snnf )a
  Patch the Google Gen AI client to make it traceable.

!!! warning

    **BETA**: This wrapper is in beta.

Supports:
    - `generate_content` and `generate_content_stream` methods
    - Sync and async clients
    - Streaming and non-streaming responses
    - Tool/function calling with proper UI rendering
    - Multimodal inputs (text + images)
    - Image generation with `inline_data` support
    - Token usage tracking including reasoning tokens

Args:
    client: The Google Gen AI client to patch.
    tracing_extra: Extra tracing information.
    chat_name: The run name for the chat endpoint.

Returns:
    The patched client.

Example:
    ```python
    from google import genai
    from google.genai import types
    from langsmith import wrappers

    # Use Google Gen AI client same as you normally would.
    client = wrappers.wrap_gemini(genai.Client(api_key="your-api-key"))

    # Basic text generation:
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents="Why is the sky blue?",
    )
    print(response.text)

    # Streaming:
    for chunk in client.models.generate_content_stream(
        model="gemini-2.5-flash",
        contents="Tell me a story",
    ):
        print(chunk.text, end="")

    # Tool/Function calling:
    schedule_meeting_function = {
        "name": "schedule_meeting",
        "description": "Schedules a meeting with specified attendees.",
        "parameters": {
            "type": "object",
            "properties": {
                "attendees": {"type": "array", "items": {"type": "string"}},
                "date": {"type": "string"},
                "time": {"type": "string"},
                "topic": {"type": "string"},
            },
            "required": ["attendees", "date", "time", "topic"],
        },
    }

    tools = types.Tool(function_declarations=[schedule_meeting_function])
    config = types.GenerateContentConfig(tools=[tools])

    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents="Schedule a meeting with Bob and Alice tomorrow at 2 PM.",
        config=config,
    )

    # Image generation:
    response = client.models.generate_content(
        model="gemini-2.5-flash-image",
        contents=["Create a picture of a futuristic city"],
    )

    # Save generated image
    from io import BytesIO
    from PIL import Image

    for part in response.candidates[0].content.parts:
        if part.inline_data is not None:
            image = Image.open(BytesIO(part.inline_data.data))
            image.save("generated_image.png")
    ```

!!! version-added "Added in `langsmith` 0.4.33"

    Initial beta release of Google Gemini wrapper.

r   rn   modelsgenerate_content__wrapped__zfThis Google Gen AI client has already been wrapped. Wrapping a client multiple times is not supported.F)r   r   generate_content_streamTaio)r   rN   popr   ro   r   r   
ValueErrorr   r   r   )r   r   r   r   rq   r   r   tracing_extra_rests           r   wrap_geminir     sF   F "'RM M%%j17R8H%-\\2H"%M" ',,.(.!z/.  ( )1:& 	!!FMM#566FMM22MBBA
 	
 vx  WV]]<N%O%O)5MM***,*
& vx  WV]]<U%V%V0<MM11*,1
- 	FJJ))FJJ%%'9::-9JJ..*,.


* 	FJJ))FJJ%%'@AA4@JJ55*,5


1 M(s   J8$J8)r   r   returnr   )r!   r   r   None)r[   r   r   r   )rq   r   r!   r   r   r   )r   r   r   r   )rE   r   r   r   )r   rR   r   r   )NF)r   r   rD   r,   rq   r   r   Optional[TracingExtra]r   boolr   r   )r   r   r   r   r   r,   r   r   )+
__future__r   rV   r   r   loggingcollections.abcr   typingr   r   r   r   r	   r
   typing_extensionsr   	langsmithr   	ls_clientr   #langsmith._internal._beta_decoratorr   langsmith.schemasr   r   r   rf   r   r   	getLoggerr   r   r   r"   ra   ru   r   r   r   r   r   r   r   r#   r   <module>r      sE   "     #  ( ) ! 9 R RCu^S012			8	$9
2BJ$(26	8&RT$n=H -14N4N
4N %)4N *	4N
 4N 4Nn'9E '  -1-	hh *h 	h
 h hr#   