
    Cj#]                         S SK r S SKrS SKrS SKrS SKrS SKJrJr  S SKJrJ	r	J
r
Jr  S SKrS SKJr  S SKrS SKJr  S SKJr  S SKJr  S SKJrJr  S S	KJr  S S
KJrJr  S SK7  S SKJ r J!r!  S r" " S S\5      r#g)    N)datetimetimezone)AnyDictListOptional)	BaseModel)verbose_logger)uuid)CustomBatchLogger)create_mock_langsmith_clientshould_use_langsmith_mock)redact_user_api_key_info)get_async_httpx_clienthttpxSpecialProvider)*)StandardCallbackDynamicParamsStandardLoggingPayloadc                     [         R                  [         R                  [         R                  [        4n[        X5      (       + $ N)typesCoroutineTypeFunctionTypeGeneratorTyper	   
isinstance)valuenon_serializable_typess     p/home/rurouni/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/litellm/integrations/langsmith.pyis_serializabler      s8    	 %888    c                     ^  \ rS rSr     S)S\\   S\\   S\\   S\\   S\\   4
U 4S jjjrS\\R                  \
      4S	 jrS*S
 jr     S+S\\   S\\   S\\   S\\   S\S\4S jjrS\S\4S jrS\4S jrS\S\\\
4   4S jrS\S\\   4S jrS\4S jrS rS rS rS r S,S\S\S\S\4S jjrS\S\\   4S  jrS\\ \!4   4S! jr"S"\\\
4   S\4S# jr#S"\\\
4   S\4S$ jr$S% r%S& r&S\4S' jr'S(r(U =r)$ )-LangsmithLogger)   langsmith_api_keylangsmith_projectlangsmith_base_urllangsmith_sampling_ratelangsmith_tenant_idc                 P  > [         R                  " 5       U l        [        TU ]  " S
0 UDSU R                  0D6  [        5       U l        U R                  (       a   [        5         [        R                  " S5        U R                  UUUUS9U l        [        R                  " S5      b_  [        R                  " S5      R                  5       R                  5       (       a(  U=(       d    [!        [        R                  " S5      5      OSU l        [        R                  " SS5      U l        ['        [(        R*                  S9U l        [        R                  " S	S 5      =(       d    [.        R0                  nU(       a  [3        U5      U l        / U l        U R9                  5       U l        g )N
flush_lockz:[LANGSMITH MOCK] LangSmith logger initialized in mock mode)r$   r%   r&   r(   LANGSMITH_SAMPLING_RATEg      ?LANGSMITH_DEFAULT_RUN_NAMELLMRun)llm_providerLANGSMITH_BATCH_SIZE )asyncioLockr*   super__init__r   is_mock_moder   r
   debugget_credentials_from_envdefault_credentialsosgetenvstripisdigitfloatsampling_ratelangsmith_default_run_namer   r   LoggingCallbackasync_httpx_clientlitellmlangsmith_batch_sizeint
batch_size	log_queue_start_periodic_flush_task_flush_task)	selfr$   r%   r&   r'   r(   kwargs_batch_size	__class__s	           r   r4   LangsmithLogger.__init__*   sX    ",,.>6>doo>57(*  L $(#@#@//1 3	 $A $
  yy23?		34::<DDFF $ ;RYY89:  	 +-))((+
' #9-==#
 II,d3Sw7S7S 	 !+.DO57++- 	r    returnc                      [         R                  " 5       nUR                  U R                  5       5      $ ! [         a    [        R                  " S5         gf = f)zIStart the periodic flush task only when an event loop is already running.zRLangsmith logger init: no running event loop, skipping periodic flush task startupN)r1   get_running_loopRuntimeErrorr
   r6   create_taskperiodic_flushrI   loops     r   rG   *LangsmithLogger._start_periodic_flush_task[   sX    	++-D  3 3 566  	  d 		s   6  AAc                     U R                   b  U R                   R                  5       (       a  U R                  5       U l         g g r   )rH   donerG   )rI   s    r   _ensure_periodic_flush_task+LangsmithLogger._ensure_periodic_flush_taskg   s:     #t'7'7'<'<'>'>#>>@D (?r    allow_env_credentialsc                 j   USL a  Ub  UnU=(       d    SnUnUn	OU=(       d    [         R                  " S5      nU=(       d    [         R                  " S5      =(       d    SnU=(       d    [         R                  " S5      =(       d    SnU=(       d    [         R                  " S5      n	[        UUUU	S9$ )	NFzlitellm-completionLANGSMITH_API_KEYLANGSMITH_PROJECTLANGSMITH_BASE_URLzhttps://api.smith.langchain.comLANGSMITH_TENANT_ID)r]   r_   r^   r`   )r9   r:   LangsmithCredentialsObject)
rI   r$   r%   r&   r(   r[   _credentials_api_key_credentials_project_credentials_base_url_credentials_tenant_ids
             r   r7   (LangsmithLogger.get_credentials_from_envn   s     !E).@.L#4 #4#L8L $6!%8"#4#V		BU8V ! (9901(' ! # 5991254 "
 &9 &BII%=" *242 6	
 	
r    metadatacredentialsc           
      0   UR                  SUS   5      UR                  SU R                  5      UR                  SUR                  SS 5      5      UR                  SS 5      UR                  SS 5      UR                  SS 5      UR                  S	S 5      S
.$ )Nproject_namer^   run_nameidrun_idparent_run_idtrace_id
session_iddotted_order)rj   rk   rm   rn   ro   rp   rq   )getr?   )rI   rg   rh   s      r   _extract_metadata_fields(LangsmithLogger._extract_metadata_fields   s     %LL,? @ !Z1P1PQll4h)EF%\\/4@ Z6",,|T:$LL>

 
	
r    c                 &   [        U5      nUR                  S5      nU(       a2  [        U[         5      (       a  S H  nXC;   d  M
  XB;  d  M  X4   X$'   M     [        US9nUR                  S5      n[        U[         5      (       a  [        US9US'   U$ )Nrequester_metadata)rp   	thread_idconversation_id)rg   )dictrr   r   r   )rI   rg   extra_metadatarv   keynesteds         r   _build_extra_metadata%LangsmithLogger._build_extra_metadata   s    h+//0DE*-?"F"FE,1J*<*AN' F 2>J##$89fd##3K4N/0 r    payloadc                     US   n[        U[        5      (       a  0 UEnOSU0nUR                  SS5      UR                  SS5      UR                  SS5      UR                  SS5      S.US	'   U$ )
Nresponseoutputprompt_tokensr   completion_tokenstotal_tokensresponse_cost)input_tokensoutput_tokensr   
total_costusage_metadata)r   ry   rr   )rI   r   r   outputss       r   _build_outputs_with_usage)LangsmithLogger._build_outputs_with_usage   s{     :&h%%"lG*G#KK;$[[)<a@#KK:!++oq9	%
 ! r    datarm   c                 "   SU;  d  US   c"  [        [        R                  " 5       5      nX!S'   SU;  d  US   c  Ub  [        U[         5      (       a  X!S'   SU;  d  US   c-  Ub)  [        U[         5      (       a  U R	                  US9US'   g g g g )Nrl   ro   rq   )rm   )strr   uuid4r   make_dot_order)rI   r   rm   s      r   _ensure_required_ids$LangsmithLogger._ensure_required_ids   s    ttDz1&FJT!T*%5%=!j&=&=#)Z %n)=)E!j&=&='+':':&':'I^$ '>! *Fr    c           
          UR                  S0 5      =(       d    0 nUR                  S0 5      =(       d    0 nU R                  Xu5      n[        R                  " SUS    SUS    35        UR                  SS 5      n	U	c  [	        S5      eU	S   nU R                  [        U5      5      n
U R                  U	5      nUS   S	U	UUS   U	S
   U	S   U	S   U
S.	nU	S   b  U	S   S:X  a  U	S   US'   S H  nUS:X  a  SOUnX   (       d  M  X   X'   M      U R                  XS   5        [        R                  " SU5        U$ ! [         a    e f = f)Nlitellm_paramsrg   z"Langsmith Logging - project_name: rj   z, run_name rk   standard_logging_objectz,Error logging request payload. Payload=none.llm	startTimeendTimerequest_tags)	namerun_typeinputsr   session_name
start_timeend_timetagsextra	error_strstatusfailureerror)rl   rn   ro   rp   rq   rl   rm   z'Langsmith Logging data on langsmith: %s)	rr   rs   r
   r6   	Exceptionr}   ry   r   r   )rI   rJ   response_objr   r   rh   _litellm_paramsrg   fieldsr   rz   r   r   r{   	field_keys                  r   _prepare_log_data!LangsmithLogger._prepare_log_data   s   1	$jj)92>D"O&**:r:@bH228IF  4VN5K4LKX^_iXjWkl 9?

)49G  NOOz*H!77XGN44W=G z*!!" &~ 6%k2#I./'
D {#/GH4E4R ' 4W ),tH	$$ & 1DI %%d8,<=  !JDQK 		s   DD> 6D> >E
c                 Z    U R                  US9n[        R                  " 5       nXe:  a&  [        R                  " SR	                  XV5      5        g [        R
                  " SUU5        U R                  US9nU R                  UUUUUS9nU R                  R                  [        UUS95        [        R
                  " SU R                   S35        [        U R                  5      U R                  :  a  U R                  5         g g ! [         a    [        R                   " S5         g f = f)	NrJ   >Skipping Langsmith logging. Sampling rate={}, random_sample={}z;Langsmith Sync Layer Logging - kwargs: %s, response_obj: %srJ   r   r   r   rh   r   rh   z/Langsmith, event added to queue. Will flush in z seconds...z/Langsmith Layer Error - log_success_event error)%_get_sampling_rate_to_use_for_requestrandomr
   infoformatr6   #_get_credentials_to_use_for_requestr   rF   appendLangsmithQueueObjectflush_intervallenrE   _send_batchr   	exception	rI   rJ   r   r   r   r>   random_samplerh   r   s	            r   log_success_event!LangsmithLogger.log_success_event  s0   &	X FFfFUM"MMOM,##T[[%
   M BB&BQK)))%!' * D NN!!$ +   A$BUBUAVVab 4>>"doo5  " 6  	X$$%VW	Xs   AD B4D  D*)D*c                   #     U R                  5         U R                  US9n[        R                  " 5       nXe:  a&  [        R                  " SR                  XV5      5        g [        R                  " SUU5        U R                  US9nU R                  UUUUUS9nU R                  R                  [        UUS95        [        R                  " S[        U R                  5      U R                  5        [        U R                  5      U R                  :  a  U R                  5       I S h  vN   g g  N! [         a    [        R                   " S5         g f = f7f)Nr   r   z<Langsmith Async Layer Logging - kwargs: %s, response_obj: %sr   r   1Langsmith logging: queue length %s, batch size %sz:Langsmith Layer Error - error logging async success event.)rY   r   r   r
   r   r   r6   r   r   rF   r   r   r   rE   flush_queuer   r   r   s	            r   async_log_success_event'LangsmithLogger.async_log_success_event5  sF    (	,,. FFfFUM"MMOM,##T[[%
   N
 BB&BQK)))%!' * D NN!!$ +   CDNN#
 4>>"doo5&&((( 6( 	$$L	sH   EAD4 "E#CD4 +D2,D4 0E2D4 4 EEEEc                   #     U R                  5         U R                  US9n[        R                  " 5       nXe:  a&  [        R                  " SR                  XV5      5        g [        R                  " S5        U R                  US9nU R                  UUUUUS9nU R                  R                  [        UUS95        [        R                  " S[        U R                  5      U R                  5        [        U R                  5      U R                  :  a  U R                  5       I S h  vN   g g  N! [         a    [        R                   " S5         g f = f7f)Nr   r   z Langsmith Failure Event Logging!r   r   r   z:Langsmith Layer Error - error logging async failure event.)rY   r   r   r
   r   r   r   r   rF   r   r   r6   r   rE   r   r   r   r   s	            r   async_log_failure_event'LangsmithLogger.async_log_failure_event`  s<    $	,,. FFfFUM"MMOM,##T[[%
  BCBB&BQK)))%!' * D NN!!$ +   CDNN#
 4>>"doo5&&((( 6( 	$$L	sH   EAD2 "E#CD2 )D0*D2 .E0D2 2 EEEEc                    #    U R                   (       d  gU R                  5       nUR                  5        H/  nU R                  UR                  UR
                  S9I Sh  vN   M1     g N	7f)a  
Handles sending batches of runs to Langsmith

self.log_queue contains LangsmithQueueObjects
    Each LangsmithQueueObject has the following:
        - "credentials" - credentials to use for the request (langsmith_api_key, langsmith_project, langsmith_base_url)
        - "data" - data to log on to langsmith for the request


This function
 - groups the queue objects by credentials
 - loops through each unique credentials and sends batches to Langsmith


This was added to support key/team based logging on langsmith
Nrh   queue_objects)rF   _group_batches_by_credentialsvalues_log_batch_on_langsmithrh   r   )rI   batch_groupsbatch_groups      r   async_send_batch LangsmithLogger.async_send_batch  sf     " ~~99;'..0K..'33)77 /    1s   AA+A) 
A+urlendpointapi_versionc                 |    X1;  a  UR                  S5       U 3nUR                  S5      (       a  U U 3$ U SU 3$ )N/)rstripendswith)rI   r   r   r   s       r   _add_endpoint_to_url$LangsmithLogger._add_endpoint_to_url  sP     !ZZ_%k]3C<<U8*%%az""r    r   c                 2  #    US   nUS   nUR                  S5      nU R                  US5      nSU0nU(       a  XWS'   U Vs/ s H  oS   PM	     n	n [        R                  " S[	        U	5      5        U R
                  (       a  [        R                  " S	5        U R                  R                  US
U	0US9I Sh  vN n
U
R                  5         U
R                  S:  a1  [        R                  " SU
R                   SU
R                   35        gU R
                  (       a$  [        R                  " S[	        U	5       S35        g[        R                  " S[	        U R                  5       S35        gs  snf  N! [        R                   aN  n[        R                  " SUR                   R                   SUR                   R                   35         SnAgSnAf["         a/    [        R                  " S[$        R&                  " 5        35         gf = f7f)a  
Logs a batch of runs to Langsmith
sends runs to /batch endpoint for the given credentials

Args:
    credentials: LangsmithCredentialsObject
    queue_objects: List[LangsmithQueueObject]

Returns: None

Raises: Does not raise an exception, will only verbose_logger.exception()
r_   r]   r`   z
runs/batch	x-api-keyx-tenant-idr   z%Sending batch of %s runs to LangsmithzB[LANGSMITH MOCK] Mock mode enabled - API calls will be interceptedpost)r   jsonheadersNi,  zLangsmith Error: z - z[LANGSMITH MOCK] Batch of z runs successfully mockedz	Batch of z runs successfully createdzLangsmith HTTP Error: zLangsmith Layer Error - )rr   r   r
   r6   r   r5   rA   r   raise_for_statusstatus_coder   textrF   httpxHTTPStatusErrorr   r   r   	traceback
format_exc)rI   rh   r   langsmith_api_baser$   r(   r   r   queue_objectelements_to_logr   es               r   r   'LangsmithLogger._log_batch_on_langsmith  s    " ))=>'(;<)oo.CD''(:LI 12%8M"DQRML/MR#	  7_9M   $$X "4499o. :  H
 %%'##s*$$'(<(<'=SP $$"((4S5I4JJcd #((#C$7#88RS7 S( $$ 	$$()?)?(@AJJOOCTU   	$$*9+?+?+A*BC	su   AHE4HA'E; ;E9<AE; H4E; H-E; 3H9E; ;HAGH9HHHHc           	      6   0 nU R                    H  nUS   nUS   b  US   c   [        R                  " SUS   US   5        M4  [        US   US   US   UR	                  S5      S9nXA;  a  [        U/ S9X'   X   R                  R                  U5        M     U$ )	z@Groups queue objects by credentials using a proper key structurerh   r]   r^   zBLangsmith Logging - credentials missing - api_key: %s, project: %sr_   r`   )api_keyprojectbase_url	tenant_idr   )rF   r
   warningCredentialsKeyrr   
BatchGroupr   r   )rI   log_queue_by_credentialsr   rh   r{   s        r   r   -LangsmithLogger._group_batches_by_credentials  s    EG  NNL&}5K /0823;&&X 34 34
  #$78#$78$%9:%//*?@	C 20: +21(- %)77>>|L3 +6 ('r    rJ   c                     UR                  SS 5      nU R                  nUb  UR                  S5      nUb  [        U5      nU$ )N standard_callback_dynamic_paramsr'   )rr   r>   r=   )rI   rJ   r   r>   _sampling_rates        r   r   5LangsmithLogger._get_sampling_rate_to_use_for_request  sT    JJ94@ 	)  $11+7=AA)N ) %n 5r    c           
         UR                  SS5      nUbg  U R                  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L S9nU$ U R                  nU$ )z
Handles key/team based logging

If standard_callback_dynamic_params are provided, use those credentials.

Otherwise, use the default credentials.
r   Nr$   r%   r&   r(   )r$   r%   r&   r(   r[   )rr   r7   r8   )rI   rJ   r   rh   s       r   r   3LangsmithLogger._get_credentials_to_use_for_request  s     JJ94@ 	) ,777"B"F"F'# #C"F"F'# $D#G#G($$ %E$H$H)4% 'G&J&J($' ' 8 K(  22Kr    c                 n   U R                   (       d  g [        R                  " 5       nUR                  5       (       a%  [        R                  " U R                  5       5        gUR                  U R                  5       5        g! [         a'    [        R                  " U R                  5       5         gf = f)z'Calls async_send_batch in an event loopN)	rF   r1   get_event_loop
is_runningrR   r   run_until_completerQ   runrT   s     r   r   LangsmithLogger._send_batch=  s    ~~	1))+D  ##D$9$9$;< ''(=(=(?@ 	1KK--/0	1s   AB #B .B43B4c                     U R                   S   nU R                   S   nU R                   R                  S5      nU SU 3nSU0nU(       a  XFS'   [        R                  R                  UUS9nUR	                  5       $ )Nr]   r_   r`   z/runs/r   r   )r   r   )r8   rr   rB   module_level_clientr   )rI   rm   r$   r   r(   r   r   r   s           r   get_run_by_idLangsmithLogger.get_run_by_idO  s     445HI!556JK"66::;PQ#$F6(3 12%8M"..22 3 

 }}r    c                     [         R                  " [        R                  5      nUnUR	                  S5      [        U5      -   $ )Nz%Y%m%dT%H%M%S%fZ)r   nowr   utcstrftimer   )rI   rm   stid_s       r   r   LangsmithLogger.make_dot_order_  s2    \\(,,'{{-.S99r    )	rH   rA   rE   r8   r*   r5   r?   rF   r>   )NNNNN)rN   N)NNNNT)z/api/v1)*__name__
__module____qualname____firstlineno__r   r   r=   r4   r1   Taskr   rG   rY   boolra   r7   ry   rs   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   __static_attributes____classcell__)rL   s   @r   r"   r"   )   s    ,0+/,037-1/
#C=/
 $C=/
 %SM	/

 "*%/
 &c]/
 /
b
7HW\\#5F,G 
7A ,0+/,0-1&*"
#C="
 $C="
 %SM	"

 &c]"
  $"
 
$"
H

+E
d $-	c3h"J Jx} J9 09v'XR)V%N8 ;D##"%#47#	#=/= 01=~(tNJ4N/O (BDcN u "38n"	#"H1$ :S : :r    r"   )$r1   r9   r   r   r   r   r   typingr   r   r   r   r   pydanticr	   rB   litellm._loggingr
   litellm._uuidr   (litellm.integrations.custom_batch_loggerr   *litellm.integrations.langsmith_mock_clientr   r   *litellm.litellm_core_utils.redact_messagesr   &litellm.llms.custom_httpx.http_handlerr   r   $litellm.types.integrations.langsmithlitellm.types.utilsr   r   r   r"   r0   r    r   <module>r#     s]     	    ' , ,    +  F P 3 U9y:' y:r    