
    bi	j                       d dl mZ d dlZd dlZd dlZd dlZd dlmZ d dlm	Z	m
Z
mZmZ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mZmZ e	rd d
lmZ  edede
f         Z ej<                  e      Z ddZ!ddZ"ddZ#	 	 	 	 	 	 d dZ$d!dZ%d"dZ&d#dZ'	 	 d$	 	 	 	 	 	 	 	 	 	 	 d%dZ( G d ded      Z)eddd	 	 	 	 	 	 	 d&d       Z*y)'    )annotationsN)Mapping)TYPE_CHECKINGAnyCallableOptionalTypeVarUnion)	TypedDict)client)run_helpers)	warn_beta)InputTokenDetailsOutputTokenDetailsUsageMetadata)genaiCzgenai.Client)boundc                \    | j                         D ci c]  \  }}|	|| c}}S c c}}w )z%Remove `None` values from dictionary.)items)dkvs      d/home/obispo/Crisostomo_bridge/mision_env/lib/python3.12/site-packages/langsmith/wrappers/_gemini.py_strip_noner      s(    WWY8TQ!-AqD888s   
((c                X    d| v r&t        | d   t              st        | d         | d<   yyy)zFConvert `GenerateContentConfig` to `dict` for LangSmith compatibility.configN)
isinstancedictvars)kwargss    r   _convert_config_for_tracingr"   $   s5    6*VH-=t"Dx 01x #E    c                *   | j                  d      }|s| S t        |t              rAd|dg| j                  d      d| j                         D ci c]  \  }}|dvs|| c}}S t        |t              rt        d |D              rN|D cg c]  }d|d	 c}| j                  d      d| j                         D ci c]  \  }}|dvs|| c}}S g }|D ]_  }t        |t              s|j                  dd      }|j                  d	g       }g }	g }
|D ]  }t        |t              rd
|v r1|d
   r,|	j                  |d
          |
j                  d
|d
   d       Jd|v r~|d   }|j                  dd      }|j                  dd      }t        |t              r%t        j                  |      j                  d      }n|}|
j                  dd| d| ddd       d|v r=|d   }|
j                  d|j                  d      |j                  di       dd       d|v sd|v s|j                  d      xs |j                  d      }|?t        |t              s|j                         }|
j                  d|j                  d       |j                  d      |j                  d!i       d"d#       t        |t              s|	j                  |       |
j                  d
|d        |
r$t        d$ |
D              rd%j                  |	      }n|
r|
nd&}|j                  ||d       b || j                  d      d| j                         D ci c]  \  }}|dvs|| c}}S | S c c}}w c c}w c c}}w c c}}w )'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  <   K   | ]  }t        |t                y w)N)r   str).0items     r   	<genexpr>z)_process_gemini_inputs.<locals>.<genexpr>E   s     :z$$:s   r'   partstexttyper1   inline_data	mime_type
image/jpegdatar#   utf-8	image_urldata:;base64,highurldetailr3   r9   functionResponsefunction_responsenameresponse)rC   rD   )r3   rB   function_callfunctionCallidargsrG   rC   	argumentsr3   rE   c              3  D   K   | ]  }|j                  d       dk(    yw)r3   r1   N)get)r-   ps     r   r/   z)_process_gemini_inputs.<locals>.<genexpr>   s"      )01AEE&MV+)s    
 )rM   r   r,   r   listallr   appendbytesbase64	b64encodedecodeto_dictjoin)inputsr%   r   r   r.   r*   r(   r'   r0   
text_partscontent_partspartr4   r5   r7   data_b64rB   rE   message_contents                      r   _process_gemini_inputsr`   *   s    zz*%H (C "(X>?ZZ(
 "(RA1<Q3Q1R
 	
 (D!::: LTT4f>TG, &,\\^VTQq@U7UAqDV   V	LG'4({{662GR0  
 "! AMD!$-!T>d6l&--d6l;)00&$v,1WX*d2*.}*=K(3\(RI#.??63#?D  *$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-'F4A4I4I4KM - 4 40?2?2C2CD2I4A4E4Ef4M9F9J9J6SU9V:*%&	!" $D#."))$/%,,fd-KLCAMH !S )5B) & IM		"IO 8Em"O/ JKmV	Lp !ZZ(
 "(RA1<Q3Q1R
 	
 M[ S UV| Ss*   M>M>NN	N	%N2Nc                :   t        |      }|j                  di       }t        |d      r'|j                  }t	        |dd      }t	        |dd      }n3|j                  d      }|j                  d      }|j                  d      }dd|j                  d      |||| d	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   rM   hasattrrb   getattr)prepopulated_invocation_paramsr!   strippedr   rb   
max_tokensstops          r   _infer_invocation_paramsrt      s     6"H\\(B'F v}%((V%8$?
v/6jj/ZZ 34
zz*+  !g.%# > r#   c                ^   | j                  d      xs d}| j                  d      xs d}| j                  d      xs d}| j                  d      xs d}| j                  d      xs ||z   }i }|r)||d<   t        d|dz
        |d	<   t        d|dz
        |d
<   i }|r||d<   |rt        d|dz
        |d
<   t        |||t        di |j	                         D 	ci c]  \  }}	|		||	 c}	}t        di |j	                         D 	ci c]  \  }}	|		||	 c}	}      S c c}	}w c c}	}w )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 )rM   maxr   r   r   r   )
gemini_usage_metadatarv   rw   rx   ry   rz   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6 
 !#!,FL)69)F27
23 ,/q2Dv2M+NK(!#,@[),/3IF3R,S[)',&- 
 3 9 9 ;M1q}q!tM
 0 
 4 : : <N1q!tN

 

 N Os   
D#$D#
D)D)c                   	 t        | d      r| j                         }n5t        | d      r| j                         }ndt        | dt	        |             i}d}g }d}d|v r|d   r~|d   d   }d|v r|d   }d	|v rX|d	   rR|d	   D ]I  }d|v r%|d   r ||d   z  }|j                  d|d   d
       -d|v r|d   ~|d   }|j                  dd      }	|j                  dd      }
t        |
t              r%t        j                  |
      j                  d      }n|
}|j                  dd|	 d| ddd       d|v sd|v s|j                  d      xs |j                  d      }|t        |t              s|j                         }|j                  d|j                  d      |j                  d      |j                  di       dd       L d|v r(|d   r#|d   }nd|v r|d   }|j                  d|d
       |D cg c]  }|j                  d      dk(  s| }}|rh|xs dd |t        |      D cg c]G  \  }}|d   j                  d      xs d!| d"||d   d   t        j                  |d   d#         d$d%I c}}d&}n(t!        |      d'kD  s|r|d   d   dk7  r|d |d(}n|d |d(}|j                  d)      }t#        ddd*      }|rt%        |      }|j                  d+      r|d   d ||d+   |d,S t        |d   t              r
|d   d ||d-S |d   d ||d-S c c}w c c}}w # t&        $ r&}t(        j+                  d.|        d/| icY d}~S d}~ww xY w)0z$Process Gemini response for tracing.rX   
model_dumpr1   rP   N
candidatesr   r(   r0   r2   r4   r5   r6   r7   r#   r8   r9   r:   r;   r<   r=   r@   rE   rF   rG   rC   rH   rI   rK   finish_reasonr3   	assistantcall_functionrJ   )rC   rJ   )rG   r3   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)rn   rX   r   ro   r,   rS   rM   r   rT   rU   rV   rW   r   	enumeratejsondumpslenr   r   	Exceptionloggerdebug)rD   rdictcontent_resultr\   r   	candidater(   r]   r4   r5   r7   r^   rE   rN   r   itcresultr   
usage_dictes                        r   "_process_generate_content_responser      s7   R$8Y'$$&EX|,'')EWXvs8}EFE '+5 U<%8l+A.II%#I.g%''*: ' 0 ."!T>d6l*d6l:N)00&$v,1WX*d2tM7J7V*.}*=K(3\(RI#.??63#?D  *$6+1+;+;D+A+H+H+Q+/)00,716yk(/T282&!" -4$8N,0HH_,E - .JM  -8'1-'F4A4I4I4KM - 4 40?2?2C2CD2I4A4E4Ef4M9F9J9J6SU9V:*%&	!"K."^ #i/Io4N$-o$>Mu_"6]N  &.!IJ "/SA!%%-?2RaS
S *1T#!. "+:!6 2 !155d;Jqc{ *!"$&$7$?)-B4G4T)U%		F" !#mA.v6&@ )#!.F *#!.F #34$1!!%

 /?J ::l# "),#!.$\2",  &+S1%i0'%2&0	   &i0'%2&0	 E TB  $9!=>(##$s]   EL3 &L3 +BL3 L(L("L3 ;AL-A9L3 L3 	L3 (L3 3	M"<MM"M"c           	     d   | sdt        ddd      dS d}d}| D ],  }	 t        |d      r|j                  r||j                  z  }|}. t        ddd      }|r	 t        |d      r|j                  rt        |j                  d	      r|j                  j                         }nt        |j                  d
      r|j                  j                         }nqt        |j                  dd      t        |j                  dd      t        |j                  dd      t        |j                  dd      t        |j                  dd      d}t        |      }||dS # t        $ r#}t        j                  d|        Y d}~bd}~ww xY w# t        $ r"}t        j                  d|        Y d}~Zd}~ww xY w)z/Reduce streaming chunks into a single response.rP   r   r   )r(   r   Nr1   zError processing chunk: r   rX   r   rv   rw   rx   ry   rz   )rv   rw   rx   ry   rz   z+Error extracting metadata from last chunk: )r   rn   r1   r   r   r   r   rX   r   ro   r   )
all_chunks	full_text
last_chunkchunkr   r   r   s          r   _reduce_generate_content_chunksr     s   +aa
 	
 IJ 9	9uf%%**UZZ'	J	9 %2aa%N 	Lz#349R9R:44i@!+!:!:!B!B!DJZ66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   )EC6F 	FE<<F	F/F**F/Fc                     |xs i t        j                          fd       }t        j                          fd       }t        j                         r|S |S )z9Create a wrapper for Gemini's `generate_content` methods.c                     t        |       t        j                  ddrt        nd t        st
        nd t        j                  t              d}  |      | i |S Nllm)rC   run_type	reduce_fnprocess_inputsprocess_outputs_invocation_params_fnr   	r"   r   	traceabler   r`   r   	functoolspartialrt   rH   r!   	decoratoris_streamingrC   original_generaterp   textras      r   generatez_get_wrapper.<locals>.generate  ss     	$F+)) 
9E541:F2D"+"3"3(*H#
 
	 ,y*+T<V<<r#   c                    K   t        |       t        j                  ddrt        nd t        st
        nd t        j                  t              d}  |      | i | d {   S 7 wr   r   r   s      r   	ageneratez_get_wrapper.<locals>.agenerate  s}      	$F+)) 
9E541:F2D"+"3"3(*H#
 
	 2Y014B6BBBBs   A%A/(A-)A/)r   wrapsr   is_async)r   rC   rp   tracing_extrar   r   r   r   s   ``` `  @r   _get_wrapperr     sf      bF__&'= (=( __&'C (C( $,,->?9MXMr#   c                  ,    e Zd ZU ded<   ded<   ded<   y)TracingExtrazOptional[Mapping[str, Any]]metadatazOptional[list[str]]tagszOptional[ls_client.Client]r   N)__name__
__module____qualname____annotations__r   r#   r   r   r     s    ))
&&r#   r   )totalChatGoogleGenerativeAI)r   	chat_namec                  |xs i }t        |j                  d      xs i       }|j                  di       }|j                         D ci c]  \  }}|dk7  s|| }}}|r||d<   t	        | d      rAt	        | j
                  d      r+t	        | j
                  j                  d      rt        d      t	        | d      rIt	        | j
                  d      r3t        | j
                  j                  |||d      | j
                  _        t	        | d      rIt	        | j
                  d	      r3t        | j
                  j                  |||d
      | j
                  _	        t	        | d      r}t	        | j                  d      rgt	        | j                  j
                  d      rGt        | j                  j
                  j                  |||d      | j                  j
                  _        t	        | d      r}t	        | j                  d      rgt	        | j                  j
                  d	      rGt        | j                  j
                  j                  |||d
      | j                  j
                  _	        | S c c}}w )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   rm   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   rM   popr   rn   r   r   
ValueErrorr   r   r   )r   r   r   r   rp   r   r   tracing_extra_rests           r   wrap_geminir     s"   F "'RM M%%j17R8H%-\\2H"%M" ',,.(A!z/1( ( )1:& 	!FMM#56FMM22MBA
 	
 vx WV]]<N%O)5MM***,*
& vx WV]]<U%V0<MM11*,1
- 	FJJ)FJJ%%'9:-9JJ..*,.


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

1 M(s   
I2I2)r   r   returnr   )r!   r   r   None)rZ   r   r   r   )rp   r   r!   r   r   r   )r   r   r   r   )rD   r   r   r   )r   rQ   r   r   )NF)r   r   rC   r,   rp   r   r   Optional[TracingExtra]r   boolr   r   )r   r   r   r   r   r,   r   r   )+
__future__r   rU   r   r   loggingcollections.abcr   typingr   r   r   r   r	   r
   typing_extensionsr   	langsmithr   	ls_clientr   #langsmith._internal._beta_decoratorr   langsmith.schemasr   r   r   re   r   r   	getLoggerr   r   r   r"   r`   rt   r   r   r   r   r   r   r   r#   r   <module>r      sG   "     #  ( ) ! 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#   