
    AHjX                         d dl Z d dlZd dlZd dlZd dlZd dlmZmZ d dlmZm	Z	m
Z
mZ d dlZd dlmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZmZ d d	lmZmZ d d
l d dlmZmZ d Z  G d de      Z!y)    N)datetimetimezone)AnyDictListOptional)	BaseModel)verbose_logger)uuid)CustomBatchLogger)create_mock_langsmith_clientshould_use_langsmith_mock)get_async_httpx_clienthttpxSpecialProvider)*)StandardCallbackDynamicParamsStandardLoggingPayloadc                     t         j                  t         j                  t         j                  t        f}t        | |       S N)typesCoroutineTypeFunctionTypeGeneratorTyper	   
isinstance)valuenon_serializable_typess     V/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/integrations/langsmith.pyis_serializabler      s;    	 %!7888    c                       e Zd Z	 	 	 	 	 d&dee   dee   dee   dee   dee   f
 fdZdeej                  e	      fdZ
d'd	Z	 	 	 	 d(dee   dee   dee   dee   def
d
ZdedefdZdefdZdedeee	f   fdZdedee   fdZdefdZd Zd Zd Zd Z	 d)dedededefdZdedee   fdZdeeef   fdZ d eee	f   defd!Z!d eee	f   defd"Z"d# Z#d$ Z$defd%Z% xZ&S )*LangsmithLoggerlangsmith_api_keylangsmith_projectlangsmith_base_urllangsmith_sampling_ratelangsmith_tenant_idc                    t        j                         | _        t        |   d
i |d| j                  i t               | _        | j                  rt                t        j                  d       | j                  ||||      | _        t        j                  d      St        j                  d      j                         j                         r"|xs  t!        t        j                  d            nd| _        t        j                  dd      | _        t'        t(        j*                        | _        t        j                  d	d       xs t.        j0                  }|rt3        |      | _        g | _        | j9                         | _        y )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   r3   zLangsmithLogger.__init__)   sV    ",,.>6>doo>57(*  L $(#@#@//1 3	 $A $
  yy23?		34::<DDF $ ;RYY89:  	 +-))((+
' #9-==#
 II,d3Sw7S7S 	 !+.DO57 ++- 	r   returnc                     	 t        j                         }|j                  | j                               S # t        $ r t        j                  d       Y yw xY w)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)r0   get_running_loopRuntimeErrorr
   r5   create_taskperiodic_flushrH   loops     r   rF   z*LangsmithLogger._start_periodic_flush_taskZ   sX    	++-D  3 3 566  	  d 		s   5 AAc                 |    | j                   | j                   j                         r| j                         | _         y y r   )rG   donerF   )rH   s    r   _ensure_periodic_flush_taskz+LangsmithLogger._ensure_periodic_flush_taskf   s7     #t'7'7'<'<'>#>>@D (?r   c                     |xs t        j                  d      }|xs t        j                  d      xs d}|xs t        j                  d      xs d}|xs t        j                  d      }t        ||||      S )NLANGSMITH_API_KEYLANGSMITH_PROJECTzlitellm-completionLANGSMITH_BASE_URLzhttps://api.smith.langchain.comLANGSMITH_TENANT_ID)rX   rZ   rY   r[   )r8   r9   LangsmithCredentialsObject)	rH   r"   r#   r$   r&   _credentials_api_key_credentials_project_credentials_base_url_credentials_tenant_ids	            r   r6   z(LangsmithLogger.get_credentials_from_envm   s      1RBII>Q4RW+>!?WCW 	  1yy-.10 	
 "5!X		BW8X)242 6	
 	
r   metadatacredentialsc           
      0   |j                  d|d         |j                  d| j                        |j                  d|j                  dd             |j                  dd       |j                  dd       |j                  dd       |j                  d	d       d
S )Nproject_namerY   run_nameidrun_idparent_run_idtrace_id
session_iddotted_order)rd   re   rg   rh   ri   rj   rk   )getr>   )rH   ra   rb   s      r   _extract_metadata_fieldsz(LangsmithLogger._extract_metadata_fields   s     %LL,? @ !Z1P1PQll4h)EF%\\/4@ Z6",,|T:$LL>

 
	
r   c                     t        |      }|j                  d      }|r)t        |t               rdD ]  }||v s||vs||   ||<    |S )Nrequester_metadata)rj   	thread_idconversation_id)dictrl   r   )rH   ra   extra_metadataro   keys        r   _build_extra_metadataz%LangsmithLogger._build_extra_metadata   sb    h+//0DE*-?"FE B,,N1J*<S*AN3'B r   payloadc                     |d   }t        |t              ri |}nd|i}|j                  dd      |j                  dd      |j                  dd      |j                  dd      d|d	<   |S )
Nresponseoutputprompt_tokensr   completion_tokenstotal_tokensresponse_cost)input_tokensoutput_tokensr|   
total_costusage_metadata)r   rr   rl   )rH   rv   rx   outputss       r   _build_outputs_with_usagez)LangsmithLogger._build_outputs_with_usage   sx     :&h%"lG*G#KK;$[[)<a@#KK:!++oq9	%
 ! r   datarg   c                     d|vs|d   "t        t        j                               }||d<   d|vs|d   |t        |t               r||d<   d|vs|d   *|'t        |t               r| j	                  |      |d<   y y y y )Nrf   ri   rk   )rg   )strr   uuid4r   make_dot_order)rH   r   rg   s      r   _ensure_required_idsz$LangsmithLogger._ensure_required_ids   s    ttDz1&FDJT!T*%5%=!j&=#)Z %n)=)E!j&='+':':&':'I^$ '>! *Fr   c           
      r   	 |j                  di       xs i }|j                  di       xs i }| j                  ||      }t        j                  d|d    d|d           |j                  dd       }	|	t	        d      |	d   }| j                  t        |            }
| j                  |	      }|d   d	|	||d   |	d
   |	d   |	d   |
d	}|	d   |	d   dk(  r|	d   |d<   dD ]  }|dk(  rdn|}||   s||   ||<    | j                  ||d          t        j                  d|       |S # t        $ r  w xY w)Nlitellm_paramsra   z"Langsmith Logging - project_name: rd   z, run_name re   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)rf   rh   ri   rj   rk   rf   rg   z'Langsmith Logging data on langsmith: %s)	rl   rm   r
   r5   	Exceptionru   rr   r   r   )rH   rI   response_objr   r   rb   _litellm_paramsra   fieldsrv   rs   r   r   rt   	field_keys                  r   _prepare_log_dataz!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 	2 ),tH	)$ &y 1DI	2 %%dF8,<=  !JDQK 		s   C1D+ 46D+ +D6c                 f   	 | j                  |      }t        j                         }||kD  r&t        j                  dj	                  ||             y t        j
                  d||       | j                  |      }| j                  |||||      }| j                  j                  t        ||             t        j
                  d| j                   d       t        | j                        | j                  k\  r| j                          y y # t        $ r t        j                   d       Y y w xY w)	NrI   >Skipping Langsmith logging. Sampling rate={}, random_sample={}z;Langsmith Sync Layer Logging - kwargs: %s, response_obj: %srI   r   r   r   rb   r   rb   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formatr5   #_get_credentials_to_use_for_requestr   rE   appendLangsmithQueueObjectflush_intervallenrD   _send_batchr   	exception	rH   rI   r   r   r   r=   random_samplerb   r   s	            r   log_success_eventz!LangsmithLogger.log_success_event   s4   &	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 B:D D0/D0c                   K   	 | j                          | j                  |      }t        j                         }||kD  r&t        j                  dj                  ||             y t        j                  d||       | j                  |      }| j                  |||||      }| j                  j                  t        ||             t        j                  dt        | j                        | j                         t        | j                        | j                  k\  r| j                          d {    y y 7 # t        $ r t        j                   d       Y y w xY ww)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.)rV   r   r   r
   r   r   r5   r   r   rE   r   r   r   rD   flush_queuer   r   r   s	            r   async_log_success_eventz'LangsmithLogger.async_log_success_event   sK    (	,,. FFfFUM"MMOM},##T[[%}
   N
 BB&BQK)))%!' * D NN!!$ +   CDNN#
 4>>"doo5&&((( 6( 	$$L	sH   E A D< $E %CD< 3D:4D< 8E :D< <EE EE c                   K   	 | j                          | j                  |      }t        j                         }||kD  r&t        j                  dj                  ||             y t        j                  d       | j                  |      }| j                  |||||      }| j                  j                  t        ||             t        j                  dt        | j                        | j                         t        | j                        | j                  k\  r| j                          d {    y y 7 # t        $ r t        j                   d       Y y w xY ww)Nr   r   z Langsmith Failure Event Logging!r   r   r   z:Langsmith Layer Error - error logging async failure event.)rV   r   r   r
   r   r   r   r   rE   r   r   r5   r   rD   r   r   r   r   s	            r   async_log_failure_eventz'LangsmithLogger.async_log_failure_eventK  sA    $	,,. FFfFUM"MMOM},##T[[%}
  BCBB&BQK)))%!' * D NN!!$ +   CDNN#
 4>>"doo5&&((( 6( 	$$L	sH   EA D: $E%CD: 1D82D: 6E8D: :EEEEc                    K   | j                   sy| j                         }|j                         D ]1  }| j                  |j                  |j
                         d{    3 y7 w)aX  
        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rb   queue_objects)rE   _group_batches_by_credentialsvalues_log_batch_on_langsmithrb   r   )rH   batch_groupsbatch_groups      r   async_send_batchz LangsmithLogger.async_send_batchr  sl     " ~~99;'..0 	K..'33)77 /   	s   AA'A%A'urlendpointapi_versionc                 p    ||vr|j                  d       | }|j                  d      r| | S | d| S )N/)rstripendswith)rH   r   r   r   s       r   _add_endpoint_to_urlz$LangsmithLogger._add_endpoint_to_url  sO     c!ZZ_%k]3C<<U8*%%az""r   r   c                   K   |d   }|d   }|j                  d      }| j                  |d      }d|i}|r||d<   |D cg c]  }|d   	 }	}	 t        j                  dt	        |	             | j
                  rt        j                  d	       | j                  j                  |d
|	i|       d{   }
|
j                          |
j                  dk\  r0t        j                  d|
j                   d|
j                          y| j
                  r#t        j                  dt	        |	       d       yt        j                  dt	        | j                         d       yc c}w 7 # t        j                  $ rM}t        j                  d|j                   j                   d|j                   j                          Y d}~yd}~wt"        $ r- t        j                  dt%        j&                                 Y yw xY ww)aV  
        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()
        rZ   rX   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 - )rl   r   r
   r5   r   r4   r@   r   raise_for_statusstatus_coder   textrE   httpxHTTPStatusErrorr   rx   r   	traceback
format_exc)rH   rb   r   langsmith_api_baser"   r&   r   r   queue_objectelements_to_logrx   es               r   r   z'LangsmithLogger._log_batch_on_langsmith  s    " ))=>'(;<)oo.CD''(:LI 12%8GM"DQRL</R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	ss   =G?E!G?A#E( 1E&2AE( G?.E( 3G?4,E(  G?&E( (G<;AG>G?6G<9G?;G<<G?c           	      8   i }| j                   D ]  }|d   }|d   |d   t        j                  d|d   |d          0t        |d   |d   |d   |j	                  d            }||vrt        |g       ||<   ||   j                  j                  |        |S )	z@Groups queue objects by credentials using a proper key structurerb   rX   rY   zBLangsmith Logging - credentials missing - api_key: %s, project: %srZ   r[   )api_keyprojectbase_url	tenant_idr   )rE   r
   warningCredentialsKeyrl   
BatchGroupr   r   )rH   log_queue_by_credentialsr   rb   rt   s        r   r   z-LangsmithLogger._group_batches_by_credentials  s    EG  NN 	ML&}5K /0823;&&X 34 34
  #$78#$78$%9:%//*?@	C 220: +21(- %S)77>>|L3	M6 ('r   rI   c                     |j                  dd       }| j                  }||j                  d      }|t        |      }|S )N standard_callback_dynamic_paramsr%   )rl   r=   r<   )rH   rI   r   r=   _sampling_rates        r   r   z5LangsmithLogger._get_sampling_rate_to_use_for_request  sV     JJ94@ 	)  $11+7=AA)N ) %n 5r   c           	          |j                  dd      }|W| j                  |j                  dd      |j                  dd      |j                  dd      |j                  dd            }|S | j                  }|S )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)   )rl   r6   r7   )rH   rI   r   rb   s       r   r   z3LangsmithLogger._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% 8 K   22Kr   c                 R   | j                   sy	 t        j                         }|j                         r$t        j                  | j                                y|j                  | j                                y# t        $ r& t        j                  | j                                Y yw xY w)z'Calls async_send_batch in an event loopN)	rE   r0   get_event_loop
is_runningrP   r   run_until_completerO   runrR   s     r   r   zLangsmithLogger._send_batch$  s}    ~~	1))+D ##D$9$9$;< ''(=(=(?@ 	1KK--/0	1s   AA7 A7 7,B&%B&c                     | j                   d   }| j                   d   }| j                   j                  d      }| d| }d|i}|r||d<   t        j                  j                  ||      }|j	                         S )NrX   rZ   r[   z/runs/r   r   )r   r   )r7   rl   rA   module_level_clientr   )rH   rg   r"   r   r&   r   r   rx   s           r   get_run_by_idzLangsmithLogger.get_run_by_id6  s     445HI!556JK"66::;PQ#$F6(3 12%8GM"..22 3 

 }}r   c                     t        j                  t        j                        }|}|j	                  d      t        |      z   S )Nz%Y%m%dT%H%M%S%fZ)r   nowr   utcstrftimer   )rH   rg   stid_s       r   r   zLangsmithLogger.make_dot_orderF  s2    \\(,,'{{-.S99r   )NNNNN)rL   N)NNNN)z/api/v1)'__name__
__module____qualname__r   r   r<   r3   r0   Taskr   rF   rV   r\   r6   rr   rm   r   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)rK   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]
 
$
2

+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	#@1$ :S :r   r!   )"r0   r8   r   r   r   r   r   typingr   r   r   r   r   pydanticr	   rA   litellm._loggingr
   litellm._uuidr   (litellm.integrations.custom_batch_loggerr   *litellm.integrations.langsmith_mock_clientr   r   &litellm.llms.custom_httpx.http_handlerr   r   $litellm.types.integrations.langsmithlitellm.types.utilsr   r   r   r!   r/   r   r   <module>r     sW     	    ' , ,    +  F 3 U9a:' a:r   