U
    hU                     @  s  U d Z ddlm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mZmZmZmZmZ ddlmZmZ zddlmZmZ W n$ ek
r   ddlmZmZ Y nX ddlZddlZddlmZ dd	lm Z  dd
l!m"Z"m#Z#m$Z$m%Z%m&Z& e'e(Z)dZ*e+e* dZ,e,-dZ.e+e* dZ/e+e* dZ0e+e* dZ1da2de3d< e4 Z5dddddZ6G dd dej7Z8G dd dZ9ddddd Z:d!d"dd#d$d%Z;ddgZ<dS )&zSchemas for the LangSmith API.    )annotationsN)datetimetimezone)	AnyDictListMappingOptionalSequenceTupleUnioncast)UUIDuuid4)Fieldroot_validator)schemas)utils)ID_TYPE
RUN_TYPE_TClient_dumps_json_ensure_uuidz
langsmith-traceutf-8metadatatagsprojectOptional[Client]_CLIENTr   r   )init_kwargsreturnc                  K  s   t d krt d krtf | a t S N)r   r   )r     r#   7/tmp/pip-unpacked-wheel-cqvhoa9t/langsmith/run_trees.pyget_cached_client*   s    
r%   c                      s  e Zd ZU dZded< eedZded< eddZded	< ed
d dZ	ded< edddZ
ded< eeddhidZded< edd ddZded< edddZded< eedZd ed!< eedZd"ed#< eedZd$ed%< edddZd&ed'< ed(d)d*Zded+< ed(d,d*Zded-< G d.d/ d/Zedd0d1d1d2d3d4Zed5d0d1d1d2d6d7Zed8d9d:d;Zed<d9d=d>Z fd?d@ZdAdBdCdDdEZdFdBdGdHdIZdFdBdJdKdLZ dMdBdNdOdPZ!ddddddQdRdSdTdUdVdBdWdXdYZ"d~ddddddddddddZdd[d\dRdRdRdSddTdTd"dRd]d d^d_d`Z#dadb Z$ddcdBdddedfZ%dBd9dgdhZ&dBd9didjZ'dd9dkdlZ(e)ddmd dndodpZ*e)dqdmddrdsdtZ+e)dudmddvdwdxZ,dyd9dzd{Z-d|d} Z.  Z/S )RunTreez1Run Schema with back-references for posting runs.strname)default_factoryr   idchain)defaultrun_typec                   C  s   t tjS r"   )r   nowr   utcr#   r#   r#   r$   <lambda>8       zRunTree.<lambda>r   
start_timeNT)r,   excludezOptional[RunTree]
parent_run__all__parent_run_id)r)   r3   zList[RunTree]
child_runsc                   C  s   t  p
dS )Nr,   )r   Zget_tracer_projectr#   r#   r#   r$   r0   ?   r1   project_name)r)   aliassession_nameZ
project_id)r,   r9   Optional[UUID]
session_idr   extraOptional[List[str]]r   z
List[Dict]eventszOptional[Any]	ls_client z!The order of the run in the tree.)r,   descriptiondotted_orderzThe trace id of the run.trace_idc                   @  s   e Zd ZdZdZdZdZdS )zRunTree.ConfigzPydantic model configuration.TignoreN)__name__
__module____qualname____doc__Zarbitrary_types_allowedZallow_population_by_field_namer=   r#   r#   r#   r$   ConfigN   s   rJ   )predict)valuesr!   c                 C  s  | ddkrZ| ddk	rZd|d kr:|d d |d< n d|d krZ|d d d |d< | ddkrpd|d< d|kr|d|d< nd	|kr|d	|d< | dsd|d< | d
dk	r|d
 j|d< d|krt |d< d|krd
|kr|d
 j|d< n|d |d< tt|di  | ddkr8g |d< | ddkrPg |d< | ddkrhi |d< | ddkri |d< |S )zAssign name to the run.r(   N
serializedr*   ZUnnamedclientr@   _clientr4   r6   rD   r=   r?   r   outputsattachments)getpopr*   r   rD   r   rL   
setdefault)clsrM   r#   r#   r$   infer_defaultsU   s>    



zRunTree.infer_defaultsFc                 C  sX   | d}|r| r|S t|d |d }|d rL|d jd | |d< n||d< |S )z#Ensure the dotted order of the run.rC   r2   r*   r4   .)rT   strip_create_current_dotted_orderrC   )rW   rM   Zcurrent_dotted_orderr#   r#   r$   ensure_dotted_ordery   s    
 zRunTree.ensure_dotted_orderr   r!   c                 C  s   | j dkrt | _ | j S )zReturn the client.N)r@   r%   selfr#   r#   r$   rP      s    
zRunTree.clientr   c                 C  s   | j S r"   )r@   r^   r#   r#   r$   rQ      s    zRunTree._clientc                   s"   |dkr|| _ nt ||S dS )zSet the _client specially.rQ   N)r@   super__setattr__)r_   r(   value	__class__r#   r$   ra      s    zRunTree.__setattr__zUnion[Sequence[str], str]None)r   r!   c                 C  s0   t |tr|g}| jdkr g | _| j| dS )zAdd tags to the run.N)
isinstancer'   r   extend)r_   r   r#   r#   r$   add_tags   s
    

zRunTree.add_tagszDict[str, Any])r   r!   c                 C  s2   | j dkri | _ tt| j di }|| dS )zAdd metadata to the run.Nr   )r=   r   rL   rV   update)r_   r   	metadata_r#   r#   r$   add_metadata   s    
zRunTree.add_metadata)rR   r!   c                 C  s    | j dkri | _ | j | dS )zUpsert the given outputs into the run.

        Args:
            outputs (Dict[str, Any]): A dictionary containing the outputs to be added.

        Returns:
            None
        N)rR   ri   )r_   rR   r#   r#   r$   add_outputs   s    	
zRunTree.add_outputszTUnion[ls_schemas.RunEvent, Sequence[ls_schemas.RunEvent], Sequence[dict], dict, str])r?   r!   c                 C  sd   | j dkrg | _ t|tr(| j | n8t|trT| j dttj	 |d n| j 
| dS )a~  Add an event to the list of events.

        Args:
            events (Union[ls_schemas.RunEvent, Sequence[ls_schemas.RunEvent],
                    Sequence[dict], dict, str]):
                The event(s) to be added. It can be a single event, a sequence
                of events, a sequence of dictionaries, a dictionary, or a string.

        Returns:
            None
        Neventr(   timemessage)r?   rf   rL   appendr'   r   r.   r   r/   	isoformatrg   )r_   r?   r#   r#   r$   	add_event   s    


zRunTree.add_event)rR   errorend_timer?   r   zOptional[Dict]Optional[str]Optional[datetime]z'Optional[Sequence[ls_schemas.RunEvent]]zOptional[Dict[str, Any]])rR   rt   ru   r?   r   r!   c                C  sj   |pt tj| _|dk	r4| js(|| _n| j| |dk	rB|| _|dk	rT| | |dk	rf| 	| dS )z/Set the end time of the run and all child runs.N)
r   r.   r   r/   ru   rR   ri   rt   rs   rk   )r_   rR   rt   ru   r?   r   r#   r#   r$   end   s    

zRunTree.end)run_idrN   inputsrR   rt   reference_example_idr2   ru   r   r=   rS   r   zOptional[ID_TYPE]z Optional[ls_schemas.Attachments])r(   r-   ry   rN   rz   rR   rt   r{   r2   ru   r   r=   rS   r!   c                C  sh   |p
d|i}t |t|||pi |p$i ||||	p8ttj|
|p@i | | j| j||pRi d}| j	| |S )z Add a child run to the run tree.r(   )r(   r*   rN   rz   rR   rt   r-   r{   r2   ru   r=   r4   r8   r@   r   rS   )
r&   r   r   r.   r   r/   r:   r@   r7   rq   )r_   r(   r-   ry   rN   rz   rR   rt   r{   r2   ru   r   r=   rS   Zserialized_runr#   r#   r$   create_child   s*    zRunTree.create_childc                 C  sH   | j dddhdd}| jd k	r,| j |d< | jd k	rD| j |d< |S )Nr7   rz   rR   T)r3   Zexclude_none)rL   rz   copyrR   )r_   Z	self_dictr#   r#   r$   _get_dicts_safe  s     

zRunTree._get_dicts_safebool)exclude_child_runsr!   c                 C  sv   |   }| jjf | |d }rVdd |D }| jdttj	
 t|d |sr| jD ]}|jdd q`dS )	z,Post the run tree to the API asynchronously.rS   c                 S  s   g | ]}t |qS r#   )r'   ).0r(   r#   r#   r$   
<listcomp>1  s     z RunTree.post.<locals>.<listcomp>uploaded_attachmentrn   F)r   N)r   rP   Z
create_runrT   r?   rq   r   r.   r   r/   rr   setr7   post)r_   r   kwargsrS   keysZ	child_runr#   r#   r$   r   ,  s    
zRunTree.postc                   s   | j s|   | j}z8|rJtdd | jD d  rJ fdd| D }W n2 tk
r~ } ztd|  W 5 d}~X Y nX | j	j
| j| j| jr| j nd| j| j| j| j | j| j| j| j| j|d dS )z5Patch the run tree to the API in a background thread.c                 s  s    | ]}| d dkr|V  qdS )r(   r   N)rT   )r   Zevr#   r#   r$   	<genexpr>F  s   z RunTree.patch.<locals>.<genexpr>Nc                   s"   i | ]\}}| d  kr||qS )rp   r#   )r   avZuploadedr#   r$   
<dictcomp>N  s    z!RunTree.patch.<locals>.<dictcomp>z'Error filtering attachments to upload: )r(   ry   rR   rt   r6   r{   ru   rC   rD   r?   r   r=   rS   )ru   rx   rS   nextr?   items	ExceptionloggerwarningrP   Z
update_runr(   r*   rR   r~   rt   r6   r{   rC   rD   r   r=   )r_   rS   er#   r   r$   patch=  s@    

"zRunTree.patchc                 C  s   dS )z"Wait for all _futures to complete.Nr#   r^   r#   r#   r$   waite  s    zRunTree.waitc                 C  s   | j j| dS )zReturn the URL of the run.)r|   )rP   Zget_run_urlr^   r#   r#   r$   get_urli  s    zRunTree.get_urlr   )rC   r   r!   c                 K  s   t |i}tt| j|f|S )zwCreate a new 'child' span from the provided dotted order.

        Returns:
            RunTree: The new span.
        )LANGSMITH_DOTTED_ORDERr   r&   from_headers)rW   rC   r   headersr#   r#   r$   from_dotted_orderm  s     zRunTree.from_dotted_orderzOptional[dict])configr   r!   c              
     s  z0ddl m}m} ddlm}m} ddlm  W n, tk
r\ } ztd|W 5 d}~X Y nX |dkr|t	|t
r|t||nd}n
t||}|d }	rt	|	||fr|	jrt fdd	|	jD d }
r|
jt|	j }r|jr|j}|j|d
< |j|d< |j|d< |j|d< |j|d< tt|jpHg |dg  |d< |j|d< |di }|di }||j n0t|
dr|	j|
j kr|
j |	j d }ndS |
j!|d< |
j"|d< t#j$|f|S dS )zCreate a new 'child' span from the provided runnable config.

        Requires langchain to be installed.

        Returns:
            Optional[RunTree]: The new span or None if
                no parent span information is found.
        r   )AsyncCallbackManagerCallbackManager)RunnableConfigensure_configLangChainTracerz{RunTree.from_runnable_config requires langchain-core to be installed. You can install it with `pip install langchain-core`.N	callbacksc                 3  s   | ]}t | r|V  qd S r"   )rf   )r   tr   r#   r$   r     s     
 z/RunTree.from_runnable_config.<locals>.<genexpr>r-   rz   rR   r2   ru   r   r(   r=   r   	order_map   rP   r8   )%Z langchain_core.callbacks.managerr   r   Zlangchain_core.runnablesr   r   Z langchain_core.tracers.langchainr   ImportErrorrf   rL   r   rT   r6   r   handlersZrun_mapr'   rC   r-   rz   rR   r2   ru   sortedr   r   r(   rV   ri   r   hasattrr   rP   r8   r&   r   )rW   r   r   r   r   r   r   r   Zconfig_cbZtracerr|   rC   Zextra_rj   r#   r   r$   from_runnable_config}  sZ    
 




$


zRunTree.from_runnable_configz-Mapping[Union[str, bytes], Union[str, bytes]])r   r   r!   c                 K  sx  |  }ttt |t}|sFttt |t}|s<dS |d}|	 }t
|}|d d }||d< |d d |d< ||d< t|d	kr|d
 d |d< |dpttj|d< |dpd|d< |dpd|d< t|}	|	js|	jrn|di |d< |d di |d d< |	j|d d }
|
|d d< tt|	j|dg  }||d< |	jrn|	j|d< tf |S )a  Create a new 'parent' span from the provided headers.

        Extracts parent span information from the headers and creates a new span.
        Metadata and tags are extracted from the baggage header.
        The dotted order and trace id are extracted from the trace header.

        Returns:
            Optional[RunTree]: The new span or None if
                no parent span information is found.
        Nr   r   r   rD   rO   r*   rC      r6   r2   r-   r+   r(   parentr=   r   r   r8   )r~   r   r	   r'   rT   r   bytesLANGSMITH_DOTTED_ORDER_BYTESdecoderZ   _parse_dotted_orderlenr   r.   r   r/   _Baggager   r   r   rV   r   r   r8   r&   )rW   r   r   Z	init_argsZlangsmith_traceZlangsmith_trace_bytesZparent_dotted_orderZparsed_dotted_orderrD   baggager   r   r#   r#   r$   r     sJ     

 
zRunTree.from_headerszDict[str, str]c                 C  sB   i }| j r| j|t < t| jdi | j| jd}| |d< |S )z.Return the RunTree as a dictionary of headers.r   r   r   r8   r   )	rD   rC   r   r   r=   rT   r   r:   	to_header)r_   r   r   r#   r#   r$   
to_headers  s    zRunTree.to_headersc              	   C  s&   d| j  d| j d| j d| j d	S )z5Return a string representation of the RunTree object.zRunTree(id=z, name='z', run_type='z', dotted_order='z'))r*   r(   r-   rC   r^   r#   r#   r$   __repr__  s    $zRunTree.__repr__)r+   )T)0rF   rG   rH   rI   __annotations__r   r   r*   r-   r2   r4   listr7   r:   r<   rL   r=   r   r?   r@   rC   rD   rJ   r   rX   r\   propertyrP   rQ   ra   rh   rk   rl   rs   rx   r}   r   r   r   r   r   classmethodr   r   r   r   r   __classcell__r#   r#   rc   r$   r&   2   s   
 #' ,((@8r&   c                   @  sZ   e Zd ZdZdddddddZedd d	d
dZedd dddZddddZdS )r   zBaggage header information.NzOptional[Dict[str, str]]r>   rv   r   c                 C  s   |pi | _ |pg | _|| _dS )zInitialize the Baggage object.Nr   )r_   r   r   r8   r#   r#   r$   __init__  s    

z_Baggage.__init__)header_valuer!   c           	   
   C  s   |s
|  S i }g }d}zp| dD ]`}| dd\}}|tkrRttj|}q"|tkrntj| d}q"|tkr"tj|}q"W n2 t	k
r } zt
d|  W 5 d}~X Y nX | |||dS )z4Create a Baggage object from the given header value.N,=r   zError parsing baggage header: r   )splitLANGSMITH_METADATAjsonloadsurllibparseunquoteLANGSMITH_TAGSLANGSMITH_PROJECTr   r   r   )	rW   r   r   r   r8   itemkeyrb   r   r#   r#   r$   from_header  s"    "z_Baggage.from_headerzMapping[Union[str, bytes], Any])r   r!   c                 C  sF   d|kr|  |d S d|kr8|  tt|d dS |  d S d S )Nr   s   baggager   )r   r   r   r   )rW   r   r#   r#   r$   r   0  s
    z_Baggage.from_headersr'   r]   c                 C  s   g }| j r0t| j }|t dtj|  | jr^d| j}|t dtj|  | j	r|t dtj| j	  d|S )z,Return the Baggage object as a header value.z	metadata=r   ztags=zproject=)
r   r   rq   LANGSMITH_PREFIXr   r   quoter   joinr8   )r_   r   Zserialized_metadataZserialized_tagsr#   r#   r$   r   9  s     
z_Baggage.to_header)NNN)	rF   rG   rH   rI   r   r   r   r   r   r#   r#   r#   r$   r     s      r   r'   zList[Tuple[datetime, UUID]])rC   r!   c                 C  s   |  d}dd |D S )zParse the dotted order string.rY   c                 S  s0   g | ](}t |d d dt|dd  fqS )Ni%Y%m%dT%H%M%S%fZ)r   strptimer   )r   partr#   r#   r$   r   P  s   z'_parse_dotted_order.<locals>.<listcomp>)r   )rC   partsr#   r#   r$   r   M  s    
r   rw   r;   )r2   ry   r!   c                 C  s,   | pt tj}|pt }|dt| S )z Create the current dotted order.r   )r   r.   r   r/   r   strftimer'   )r2   ry   stZid_r#   r#   r$   r[   V  s    
r[   )=rI   
__future__r   r   loggingsysr   r   typingr   r   r   r   r	   r
   r   r   r   uuidr   r   Zpydantic.v1r   r   r   Zpydantic	threadingurllib.parser   Z	langsmithr   Z
ls_schemasr   Zlangsmith.clientr   r   r   r   r   	getLoggerrF   r   r   internr   encoder   r   r   r   r   r   LockZ_LOCKr%   ZRunBaser&   r   r   r[   r5   r#   r#   r#   r$   <module>   sD   ,

   ]A		