o
    \hp                     @   s  zd dl Z W n ey   edw 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mZ d dlmZ d dlmZ d dlmZm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 m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z( d dl)m*Z* e+dZ,eG dd dZ-eG dd de-Z.ee-e.f Z/e	ee/f Z0G dd deZ1dd Z2dede	e3ef fddZ4eG dd dZ5dee#e6f de5fdd Z7d!e!de5fd"d#Z8d$e9de:fd%d&Z;d'ee	e3ef  d(edee3 fd)d*Z<d+e9de3fd,d-Z=dS ).    NzEPlease install LangChain to use this feature: 'pip install langchain')	dataclass)AnyDictListOptionalSequenceUnioncast)UUID)BaseCallbackHandler)AgentActionAgentFinish)Document)	AIMessageBaseMessageFunctionMessageHumanMessageSystemMessageToolMessage)ChatGeneration	LLMResult)	BaseModel)default_client)get_model_paramswith_privacy_mode)Clientposthogc                   @   sP   e Zd ZU eed< 	 eed< 	 ee ed< 	 ee ed< 	 edefddZ	dS )	SpanMetadataname
start_timeend_timeinputreturnc                 C   s   | j sdS | j | j S )Nr   )r    r   )self r$   a/home/air/segue/gemini/backup/venv/lib/python3.10/site-packages/posthog/ai/langchain/callbacks.pylatency6   s   zSpanMetadata.latencyN)
__name__
__module____qualname__str__annotations__floatr   r   propertyr&   r$   r$   r$   r%   r   +   s   
 r   c                   @   sz   e Zd ZU dZee ed< 	 dZee ed< 	 dZee	ee
f  ed< 	 dZee ed< 	 dZeee	ee
f   ed< dS )GenerationMetadataNprovidermodelmodel_paramsbase_urltools)r'   r(   r)   r/   r   r*   r+   r0   r1   r   r   r2   r3   r   r$   r$   r$   r%   r.   =   s   
 r.   c                   @   s  e Zd ZU dZeed< 	 eeee	e
ef  ed< 	 eeee	e
ef  ed< 	 ee ed< 	 ee ed< 	 eeeef  ed< 	 eed< 	 eeef ed	< 	 	
djd
d
d
dd
ddee deeee	e
ef  deeee	e
ef  deeeef  dedeeeef  fddZd
d
ddeeef deeef dedee deeeef  f
ddZd
ddeeef dedee defd d!Zd
dd"ededee defd#d$Zd
ddeeef d%eee  dedee fd&d'Zd
ddeeef d(ee dedee def
d)d*Zd
dd+ededee ded,ef
d-d.Zd
dd/ededee defd0d1Zd
dd"ededee defd2d3Zd
d
ddeeeef  d4ededee deeeef  ded,efd5d6Zd
dd7ededee ded,ef
d8d9Zd
d
d:d"ededee d;eee  ded,efd<d=Z d
d
ddeeeef  d>ededee deeeef  ded,efd?d@Z!d
ddAe"e# dedee defdBdCZ$d
d
d:d"ededee d;eee  ded,efdDdEZ%d
ddFe&dedee ded,ef
dGdHZ'd
ddIe(dedee ded,ef
dJdKZ)djdedee fdLdMZ*defdNdOZ+ded,efdPdQZ,	
djdeeeef  dRededee fdSdTZ-	
	
dkdeeef ded%eeeeef  ee f deeeef  dUeeeef  f
dVdWZ.ded,ee/ fdXdYZ0defdZd[Z1dededee fd\d]Z2dedee defd^d_Z3deded`e4dedee f
dadbZ5dedee d/eeef fdcddZ6	
djdeded`e7d7eeef dee f
dedfZ8	
djdgededee fdhdiZ9d
S )lCallbackHandlerzG
    The PostHog LLM observability callback handler for LangChain.
    _client_distinct_id	_trace_id_trace_input_trace_name_properties_runs_parent_treeNF)distinct_idtrace_id
propertiesprivacy_modegroupsclientr=   r>   r?   r@   rA   c                C   sT   |pt }|du rtd|| _|| _|| _|pi | _|| _|p i | _i | _i | _	dS )a  
        Args:
            client: PostHog client instance.
            distinct_id: Optional distinct ID of the user to associate the trace with.
            trace_id: Optional trace ID to use for the event.
            properties: Optional additional metadata to use for the trace.
            privacy_mode: Whether to redact the input and output of the trace.
            groups: Optional additional PostHog groups to use for the trace.
        NzPostHog client is required)
r   
ValueErrorr5   r6   r7   r:   _privacy_mode_groupsr;   r<   )r#   rB   r=   r>   r?   r@   rA   posthog_clientr$   r$   r%   __init__o   s   


zCallbackHandler.__init__)parent_run_idmetadata
serializedinputsrun_idrH   rI   c                K   :   | j d|||d | || | j||||fi | d S )Non_chain_start)rK   _log_debug_event_set_parent_of_run_set_trace_or_span_metadata)r#   rJ   rK   rL   rH   rI   kwargsr$   r$   r%   rN         

zCallbackHandler.on_chain_start)rH   outputsrS   c                K   $   | j d|||d | ||| d S )Non_chain_end)rU   rP   "_pop_run_and_capture_trace_or_span)r#   rU   rL   rH   rS   r$   r$   r%   rW         zCallbackHandler.on_chain_enderrorc                K   rV   )Non_chain_errorr[   rX   r#   r[   rL   rH   rS   r$   r$   r%   r\      rZ   zCallbackHandler.on_chain_errormessagesc                K   sF   | j d|||d | || dd |D }| j|||fi | d S )Non_chat_model_start)r_   c                 S   s   g | ]}|D ]}t |qqS r$   )_convert_message_to_dict).0rowmessager$   r$   r%   
<listcomp>   s
    z7CallbackHandler.on_chat_model_start.<locals>.<listcomp>rP   rQ   _set_llm_metadata)r#   rJ   r_   rL   rH   rS   r!   r$   r$   r%   r`      s   	z#CallbackHandler.on_chat_model_startpromptsc                K   s8   | j d|||d | || | j|||fi | d S )Non_llm_start)rh   rf   )r#   rJ   rh   rL   rH   rS   r$   r$   r%   ri      s   	zCallbackHandler.on_llm_starttokenr"   c                K   s   | j d|||d dS )z?Run on new LLM token. Only available when streaming is enabled.on_llm_new_token)rj   N)rP   )r#   rj   rL   rH   rS   r$   r$   r%   rk      s   	z CallbackHandler.on_llm_new_tokenresponsec                K   s&   | j d||||d | ||| dS )z
        The callback works for both streaming and non-streaming runs. For streaming runs, the chain must set `stream_usage=True` in the LLM.
        
on_llm_end)rl   rS   NrP   _pop_run_and_capture_generation)r#   rl   rL   rH   rS   r$   r$   r%   rm      s   
zCallbackHandler.on_llm_endc                K   rV   )Non_llm_errorr]   rn   r^   r$   r$   r%   rp      rZ   zCallbackHandler.on_llm_error	input_strc                K   rM   )Non_tool_start)rq   rO   )r#   rJ   rq   rL   rH   rI   rS   r$   r$   r%   rr      s   

zCallbackHandler.on_tool_startoutputc                K   rV   )Non_tool_end)rs   rX   )r#   rs   rL   rH   rS   r$   r$   r%   rt     rZ   zCallbackHandler.on_tool_end)rH   tagsru   c                K   rV   )Non_tool_errorr]   rX   r#   r[   rL   rH   ru   rS   r$   r$   r%   rv     s   	zCallbackHandler.on_tool_errorqueryc                K   rM   )Non_retriever_start)rx   rO   )r#   rJ   rx   rL   rH   rI   rS   r$   r$   r%   ry   "  rT   z"CallbackHandler.on_retriever_start	documentsc                K   rV   )Non_retriever_end)rz   rX   )r#   rz   rL   rH   rS   r$   r$   r%   r{   2  s   z CallbackHandler.on_retriever_endc                K   s$   | j d|||d | ||| dS )zRun when Retriever errors.on_retriever_errorr]   NrX   rw   r$   r$   r%   r|   ?  s   
z"CallbackHandler.on_retriever_erroractionc                K   s:   | j d|||d | || | jd|||fi | dS )zRun on agent action.on_agent_action)r}   NrO   )r#   r}   rL   rH   rS   r$   r$   r%   r~   L  s   	zCallbackHandler.on_agent_actionfinishc                K   rV   )Non_agent_finish)r   rX   )r#   r   rL   rH   rS   r$   r$   r%   r   Y  rZ   zCallbackHandler.on_agent_finishc                 C   s   |dur|| j |< dS dS )zd
        Set the parent run ID for a chain run. If there is no parent, the run is the root.
        Nr<   )r#   rL   rH   r$   r$   r%   rQ   d  s   z"CallbackHandler._set_parent_of_runc                 C   s(   z	| j | W dS  ty   Y dS w )z;
        Remove the parent run ID for a chain run.
        N)r<   popKeyError)r#   rL   r$   r$   r%   _pop_parent_of_runk  s
   z"CallbackHandler._pop_parent_of_runc                 C   s&   |}|| j v r| j | }|| j v s|S )z3
        Finds the root ID of a chain run.
        r   )r#   rL   idr$   r$   r%   _find_root_runt  s
   


zCallbackHandler._find_root_runr!   c                 K   sB   |d u rdnd}t |fi |p|}t||t d d| j|< d S )Ntracespanr   r!   r   r    )_get_langchain_run_namer   timer;   )r#   rJ   r!   rL   rH   rS   default_namerun_namer$   r$   r%   rR   }  s
   z+CallbackHandler._set_trace_or_span_metadatainvocation_paramsc                 K   s   t |fi |p	d}t||t d d}t|tr(t||_|d }	r(|	|_t|trA|d }
r7|
|_	|d }rA||_
z|d d }|d urO||_W n	 tyY   Y nw || j|< d S )N
generationr   r3   ls_model_namels_providerrS   openai_api_base)r   r.   r   
isinstancedictr   r1   getr3   r0   r/   r2   r   r;   )r#   rJ   rL   r_   rI   r   rS   r   r   r3   r0   r/   r2   r$   r$   r%   rg     s,   	


z!CallbackHandler._set_llm_metadatac                 C   sH   t   }z| j|}W n ty   td|  Y d S w ||_|S )NzNo run metadata found for run )r   r;   r   r   logwarningr    )r#   rL   r    runr$   r$   r%   _pop_run_metadata  s   z!CallbackHandler._pop_run_metadatac                 C   s   | j p| |}|s|S |S N)r7   r   )r#   rL   r>   r$   r$   r%   _get_trace_id  s   zCallbackHandler._get_trace_idc                 C   s   |dur|| j vr|S |S )zr
        Replace the parent run ID with the trace ID for second level runs when a custom trace ID is set.
        Nr   )r#   r>   rL   rH   r$   r$   r%   _get_parent_run_id  s   z"CallbackHandler._get_parent_run_idc                 C   sf   |  |}| | | |}|sd S t|tr#td| d d S | ||||| ||| d S )NRun zB is a generation, but attempted to be captured as a trace or span.)	r   r   r   r   r.   r   r   _capture_trace_or_spanr   )r#   rL   rH   rU   r>   r   r$   r$   r%   rY     s"   




z2CallbackHandler._pop_run_and_capture_trace_or_spanr   c                 C   s   |d u rdnd}|t | j| j|j|j|j|d}|d ur!||d< | jr*|| j t|t	r:t
||d< d|d< n|d urHt | j| j||d< | jd u rQd	|d
< | jj| jpX|||| jd d S )Nz	$ai_tracez$ai_span)$ai_trace_idz$ai_input_state$ai_latency$ai_span_name$ai_span_id$ai_parent_id	$ai_errorT$ai_is_errorz$ai_output_stateF$process_person_profiler=   eventr?   rA   )r   r5   rD   r!   r&   r   r:   updater   BaseException_stringify_exceptionr6   capturerE   )r#   r>   rL   r   rU   rH   
event_nameevent_propertiesr$   r$   r%   r     s8   	




z&CallbackHandler._capture_trace_or_spanc                 C   sf   |  |}| | | |}|sd S t|ts#td| d d S | ||||| ||| d S )Nr   zC is not a generation, but attempted to be captured as a generation.)	r   r   r   r   r.   r   r   _capture_generationr   )r#   rL   rH   rl   r>   r   r$   r$   r%   ro     s"   




z/CallbackHandler._pop_run_and_capture_generationc           
      C   sF  |||j ||j|j|jt| j| j|jd|j|j	d}|j
r)t| j| j|j
|d< t|tr?t||d< t||d< d|d< nBt|}|j|d< |j|d	< |j|d
< |j|d< |j|d< |jd }t|d trpdd |D }	ndd |D }	t| j| j|	|d< | jr|| j | jd u rd|d< | jj| jp|d|| jd d S )N   )r   r   r   r   z$ai_providerz	$ai_modelz$ai_model_parametersz	$ai_input$ai_http_statusr   z$ai_base_urlz	$ai_toolsr   r   Tr   z$ai_input_tokensz$ai_output_tokensz$ai_cache_creation_input_tokensz$ai_cache_read_input_tokensz$ai_reasoning_tokensc                 S   s   g | ]
}t tt|jqS r$   )ra   r	   r   rd   rb   r   r$   r$   r%   re   G  s    z7CallbackHandler._capture_generation.<locals>.<listcomp>c                 S   s   g | ]}t |qS r$   )_extract_raw_esponser   r$   r$   r%   re   L  s    z$ai_output_choicesFr   z$ai_generationr   )r   r/   r0   r1   r   r5   rD   r!   r&   r2   r3   r   r   _get_http_statusr   _parse_usageinput_tokensoutput_tokenscache_write_tokenscache_read_tokensreasoning_tokensgenerationsr   r:   r   r6   r   rE   )
r#   r>   rL   r   rs   rH   r   usagegeneration_resultcompletionsr$   r$   r%   r     sd   	









z#CallbackHandler._capture_generationr   c              
   K   s>   t d| dt|d d  dt|d d  d|  d S )NzEvent: z
, run_id:    z, parent_run_id: z
, kwargs: )r   debugr*   )r#   r   rL   rH   rS   r$   r$   r%   rP   `  s   2z CallbackHandler._log_debug_eventr   )NN):r'   r(   r)   __doc__r   r+   r   r   r*   intr,   r
   r   r   RunMetadataStorageboolrG   rN   rW   r   r\   r   r   r`   ri   rk   r   rm   rp   rr   rt   listrv   ry   r   r   r{   r|   r   r~   r   r   rQ   r   r   rR   rg   RunMetadatar   r   r   rY   r   r   ro   r.   r   rP   r$   r$   r$   r%   r4   O   sv  
 
%













	



	





	







)



Kr4   c                 C   s8   | j dur| j  dkr| j  S t| dr| jjS dS )z<Extract the response from the last response of the LLM call.N rd   )textstriphasattrrd   additional_kwargs)last_responser$   r$   r%   r   l  s
   

r   rd   r"   c                 C   s   t | trd| jd}n9t | trd| jd}n-t | tr$d| jd}n!t | tr0d| jd}nt | tr<d| jd}n	| jt| jd}| j	rN|
| j	 |S )Nuser)rolecontent	assistantsystemtoolfunction)r   r   r   r   r   r   r   typer*   r   r   )rd   message_dictr$   r$   r%   ra   y  s   




ra   c                   @   sJ   e Zd ZU ee ed< ee ed< ee ed< ee ed< ee ed< dS )
ModelUsager   r   r   r   r   N)r'   r(   r)   r   r   r+   r$   r$   r$   r%   r     s   
 r   r   c                    s   t | tr| j} g d}i  |D ]\}}|| v r+| | }t |tr%t|n|}| |< qd| v rIt | d trI| d d d< | d d d< d| v r]t | d tr]| d d d< dd	d
ddd}tdi  fdd| D S )N))r   r!   )r   rs   cache_creation_input_tokenscache_writecache_read_input_tokens
cache_read)prompt_token_countr!   )candidates_token_countrs   )cached_content_token_countr   )thoughts_token_count	reasoning)inputTokenCountr!   )outputTokenCountrs   )cacheCreationInputTokenCountr   )cacheReadInputTokenCountr   )prompt_tokensr!   )completion_tokensrs   r   r   )input_token_countr!   )generated_token_countrs   input_token_detailscache_creationr   r   output_token_detailsr   r   r   r   r   r   )r!   rs   r   r   r   c                    s    i | ]\}}|  |pd qS )r   )r   )rb   
mapped_keydataclass_keyparsed_usager$   r%   
<dictcomp>  s    z&_parse_usage_model.<locals>.<dictcomp>r$   )	r   r   __dict__r   sumr   r   r   items)r   conversion_list	model_keytype_keycaptured_countfinal_countfield_mappingr$   r   r%   _parse_usage_model  sB   




r   rl   c                 C   s   ddg}t d d d d d d}| jd ur&|D ]}| j|r%t| j| } nqt| dr| jD ]_}d|v r=t|d } |S |D ]M}|jrRd|jv rRt|jd } n;t|di }t|di }t|t	ri|dd nd }t|t	rv|dd nd }	t|dd }
|p|	p|
}|rt|} nq?q.|S )	Ntoken_usager   )r   r   r   r   r   r   usage_metadatard   response_metadataz amazon-bedrock-invocationMetrics)
r   
llm_outputr   r   r   r   generation_infogetattrr   r   )rl   llm_usage_keys	llm_usagekeyr   generation_chunkmessage_chunkr   bedrock_anthropic_usagebedrock_titan_usageollama_usagechunk_usager$   r$   r%   r     sd   


%
	
r   r[   c                 C   s   t | dt | dd}|S )Nstatus_codecoder   )r  )r[   r  r$   r$   r%   r     s   r   rJ   rS   c              	   K   sr   d|v r|d dur|d S | du rdS z| d W S  t tfy$   Y nw z| d d W S  t tfy8   Y dS w )aw  Retrieve the name of a serialized LangChain runnable.

    The prioritization for the determination of the run name is as follows:
    - The value assigned to the "name" key in `kwargs`.
    - The value assigned to the "name" key in `serialized`.
    - The last entry of the value assigned to the "id" key in `serialized`.
    - "<unknown>".

    Args:
        serialized (Optional[Dict[str, Any]]): A dictionary containing the runnable's serialized data.
        **kwargs (Any): Additional keyword arguments, potentially including the 'name' override.

    Returns:
        str: The determined name of the Langchain runnable.
    r   Nr   r   )r   	TypeError)rJ   rS   r$   r$   r%   r   $  s   
r   	exceptionc                 C   s&   t | }|r| jj d| S | jjS )Nz: )r*   	__class__r'   )r  descriptionr$   r$   r%   r   E  s   r   )>	langchainImportErrorModuleNotFoundErrorloggingr   dataclassesr   typingr   r   r   r   r   r   r	   uuidr
   langchain.callbacks.baser   langchain.schema.agentr   r   langchain_core.documentsr   langchain_core.messagesr   r   r   r   r   r   langchain_core.outputsr   r   pydanticr   r   r   posthog.ai.utilsr   r   posthog.clientr   	getLoggerr   r   r.   r   r   r4   r   r*   ra   r   r   r   r   r   r   r   r   r   r$   r$   r$   r%   <module>   sh    $	 
    !

H=
!