
     jh                        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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 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, d dl-m.Z.  ede	def                   Z/ ed          Z0 ed          Z1 G d d          Z2 e2            Z3e3j4        Z4 G d d          Z5 G d d          Z6dS )    N)wraps)AnyAsyncGeneratorCallableDict	GeneratorIterableListOptionalTupleTypeVarUnioncastoverload)_AgnosticContextManager)	ParamSpec)ObservationTypeLiteralNoEventget_observation_types_list)-LANGFUSE_OBSERVE_DECORATOR_IO_CAPTURE_ENABLED)_set_current_public_key
get_client)	LangfuseAgentLangfuseChainLangfuseEmbeddingLangfuseEvaluatorLangfuseGenerationLangfuseGuardrailLangfuseRetrieverLangfuseSpanLangfuseTool)langfuse_logger)TraceContextF.)boundPRc                      e Zd ZdZededefd            Ze	 ddddddddddee         dee	         d	ee
         d
ee
         deeegef                  deegef         fd            Z	 ddddddddee         dee         dee	         d	ee
         d
ee
         deeegef                  deeeegef         f         fdZdddedee         dee	         d	e
d
e
deeegef                  defdZdddedee         dee	         d	e
d
e
deeegef                  defdZedede
fd            Zddi dde
dededefdZ	 ddeeeeeeeeeef	         ded
e
deeegef                  def
dZ 	 ddeeeeeeeeeef	         de!d
e
deeegef                  def
dZ"dddeeeeeeeeeef	         ded
e
deeegef                  dee
ef         f
dZ#dS ) LangfuseDecoratora  Implementation of the @observe decorator for seamless Langfuse tracing integration.

    This class provides the core functionality for the @observe decorator, which enables
    automatic tracing of functions and methods in your application with Langfuse.
    It handles both synchronous and asynchronous functions, maintains proper trace context,
    and intelligently routes to the correct Langfuse client instance.

    The implementation follows a singleton pattern where a single decorator instance
    handles all @observe decorations throughout the application codebase.

    Features:
    - Automatic span creation and management for both sync and async functions
    - Proper trace context propagation between decorated functions
    - Specialized handling for LLM-related spans with the 'as_type="generation"' parameter
    - Type-safe decoration that preserves function signatures and type hints
    - Support for explicit trace and parent span ID specification
    - Thread-safe client resolution when multiple Langfuse projects are used
    funcreturnc                     d S N )selfr)   s     b/lsinfo/ai/hellotax_ai/base_platform/venv/lib/python3.11/site-packages/langfuse/_client/observe.pyobservezLangfuseDecorator.observeH   s    %(S    Nnameas_typecapture_inputcapture_outputtransform_to_stringr3   r4   r5   r6   r7   c                    d S r,   r-   )r.   r)   r3   r4   r5   r6   r7   s          r/   r0   zLangfuseDecorator.observeK   s	     3r1   c          
         
 t          t          t                              }A|vr=t          j        d dd                    t          |                     d           dt          j        	                    t          d                                          dv}||n|
||n|d	t          d
t          f 
fd}		 ||	S  |	|          S )a  Wrap a function to create and manage Langfuse tracing around its execution, supporting both synchronous and asynchronous functions.

        This decorator provides seamless integration of Langfuse observability into your codebase. It automatically creates
        spans or generations around function execution, capturing timing, inputs/outputs, and error states. The decorator
        intelligently handles both synchronous and asynchronous functions, preserving function signatures and type hints.

        Using OpenTelemetry's distributed tracing system, it maintains proper trace context propagation throughout your application,
        enabling you to see hierarchical traces of function calls with detailed performance metrics and function-specific details.

        Args:
            func (Optional[Callable]): The function to decorate. When used with parentheses @observe(), this will be None.
            name (Optional[str]): Custom name for the created trace or span. If not provided, the function name is used.
            as_type (Optional[Literal]): Set the observation type. Supported values:
                    "generation", "span", "agent", "tool", "chain", "retriever", "embedding", "evaluator", "guardrail".
                    Observation types are highlighted in the Langfuse UI for filtering and visualization.
                    The types "generation" and "embedding" create a span on which additional attributes such as model metrics
                    can be set.

        Returns:
            Callable: A wrapped version of the original function that automatically creates and manages Langfuse spans.

        Example:
            For general function tracing with automatic naming:
            ```python
            @observe()
            def process_user_request(user_id, query):
                # Function is automatically traced with name "process_user_request"
                return get_response(query)
            ```

            For language model generation tracking:
            ```python
            @observe(name="answer-generation", as_type="generation")
            async def generate_answer(query):
                # Creates a generation-type span with extended LLM metrics
                response = await openai.chat.completions.create(
                    model="gpt-4",
                    messages=[{"role": "user", "content": query}]
                )
                return response.choices[0].message.content
            ```

            For trace context propagation between functions:
            ```python
            @observe()
            def main_process():
                # Parent span is created
                return sub_process()  # Child span automatically connected to parent

            @observe()
            def sub_process():
                # Automatically becomes a child span of main_process
                return "result"
            ```

        Raises:
            Exception: Propagates any exceptions from the wrapped function after logging them in the trace.

        Notes:
            - The decorator preserves the original function's signature, docstring, and return type.
            - Proper parent-child relationships between spans are automatically maintained.
            - Special keyword arguments can be passed to control tracing:
              - langfuse_trace_id: Explicitly set the trace ID for this function call
              - langfuse_parent_observation_id: Explicitly set the parent span ID
              - langfuse_public_key: Use a specific Langfuse project (when multiple clients exist)
            - For async functions, the decorator returns an async function wrapper.
            - For sync functions, the decorator returns a synchronous wrapper.
        NzInvalid as_type 'z'. Valid types are: z, z. Defaulting to 'span'.spanTrue)false0r)   r*   c                     t          j        |           r                    |           n                    |           S )Nr2   )asyncioiscoroutinefunction_async_observe_sync_observe)r)   r4   r3   r.   should_capture_inputshould_capture_outputr7   s    r/   	decoratorz,LangfuseDecorator.observe.<locals>.decorator   sw     .t44###"6#8(; $    ''#"6#8(; (  r1   )setr   r   loggerwarningjoinsortedosenvirongetr   lowerr#   )r.   r)   r3   r4   r5   r6   r7   valid_typesfunction_io_capture_enabledrE   rC   rD   s   ` ``  `   @@r/   r0   zLangfuseDecorator.observeW   s3   \ 45RSSTT7+#=#=NxGxx6R]K^K^A_A_xxx   G&(jnn96'
 '

%'''(#
 +6MM<W 	 ) N, 		A 	! 	 	 	 	 	 	 	 	 	 	 	*		 <9T??"r1   )r7   c          	           t                    dt          t                   dt          t          t          f         dt          f fd            }t          t          |          S )Nargskwargsr*   c            	      ,  K   t          t          |                    dd                     }t          t          |                    dd                     }|r||dnd }pj        }r+                                                  | |          nd }t          t          |                    dd                     }t          |          5  t          |          }|r|                    |pd||d	          nd }	|	 | i | d {V cd d d            S |	5 }
d}	  | i | d {V }	                    |
|
          \  }}||s|

                                 cd d d            cd d d            S # t          t          j        f$ r?}|
                    dt          |          pt          |          j                   |d }~ww xY w# |s|

                                 w w xY w# 1 swxY w Y   	 d d d            d S # 1 swxY w Y   d S Nlangfuse_trace_idlangfuse_parent_observation_id)trace_idparent_span_id	is_method	func_argsfunc_kwargslangfuse_public_key)
public_keyr:   F)r3   r4   trace_contextinputend_on_exit)r6   r7   ERRORlevelstatus_message)r   strpop__name___get_input_from_func_args
_is_methodr   r   start_as_current_observation_handle_observe_resultend	Exceptionr?   CancelledErrorupdatetyperR   rS   rX   parent_observation_idr`   
final_namera   r_   langfuse_clientcontext_managerlangfuse_span_or_generationis_return_type_generatorresulter4   r5   r6   r)   r3   r.   r7   s                 r/   async_wrapperz7LangfuseDecorator._async_observe.<locals>.async_wrapper   s     C,?!F!FGGH$(VZZ @$GG% %! 	 (&;  
   .J !.."ood33" & /      c6::.CT#J#JKKJ )44 4> 4>",
"C"C"C* 'O@@' ' 16&3#$) A    +  0 #*!%t!6v!6!666666674> 4> 4> 4> 4> 4> 4> 4>: % >(C/4,>'+tT'<V'<'<!<!<!<!<!<!< !777"+90C	 8  4"  &  8 >7;;===/> > > > > > >;4> 4> 4> 4> 4> 4> 4> 4>X &w'=>      3::")#a&&:TDGGDT ;        8 >7;;====>-> > > > > > > > >;4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4>sm   A H	H	G0"+E<G0#H	<G:GGGG--G00G4	4H	7G4	8H		HH)r   r   r   r   rg   r   r#   )r.   r)   r3   r4   r5   r6   r7   r|   s   ``````` r/   rA   z LangfuseDecorator._async_observe   s     
tN	>uSz N	>T#s(^ N	>PS N	> N	> N	> N	> N	> N	> N	> N	> N	> N	> N	> 
N	>` A}%%%r1   c          	           t                    dt          dt          dt          f fd            }t          t          |          S )NrR   rS   r*   c            	         |                     dd           }|                     dd           }|r||dnd }pj        }r+                                                  | |          nd }|                     dd           }t	          |          5  t          |          }|r|                    |pd||d	          nd }	|	 | i |cd d d            S |	5 }
d}	  | i |}                    |
|
          \  }}||s|
                                 cd d d            cd d d            S # t          t          j        f$ r?}|
                    dt          |          pt          |          j                   |d }~ww xY w# |s|
                                 w w xY w# 1 swxY w Y   	 d d d            d S # 1 swxY w Y   d S rU   )rh   ri   rj   rk   r   r   rl   rm   rn   ro   r?   rp   rq   rg   rr   rs   s                 r/   sync_wrapperz5LangfuseDecorator._sync_observe.<locals>.sync_wrapperE  sR   zz"5t<<H$*JJ/OQU$V$V! 	 (&;  
   .J !.."ood33" & /       $94@@J )44 4> 4>",
"C"C"C* 'O@@' ' 16&3#$) A    +  0 #*400074> 4> 4> 4> 4> 4> 4> 4>: % >(C/4,>!%t!6v!6!6 !777"+90C	 8  4"  &  8 >7;;===/> > > > > > >;4> 4> 4> 4> 4> 4> 4> 4>X &w'=>      3::")#a&&:TDGGDT ;        8 >7;;====>-> > > > > > > > >;4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4> 4>sl   :GGF)!%D5F)G5F
:FF

FF&&F))F-	-G0F-	1GG	G)r   r   r   r#   )r.   r)   r3   r4   r5   r6   r7   r   s   ``````` r/   rB   zLangfuseDecorator._sync_observe;  s     
tL	> L	>s L	>s L	> L	> L	> L	> L	> L	> L	> L	> L	> L	> L	> 
L	>\ A|$$$r1   c                 n    dt          j        |           j        v pdt          j        |           j        v S )Nr.   cls)inspect	signature
parameters)r)   s    r/   rk   zLangfuseDecorator._is_method  s:     g'--88 ;)$//::	
r1   Fr-   rZ   r[   r\   r]   c                (    |r
|dd          n|}||dS )N   )rR   rS   r-   )r.   r[   r\   r]   logged_argss        r/   rj   z+LangfuseDecorator._get_input_from_func_args  s1     (1?immi  !
 
 	
r1   rx   	generatorc                 N    t          j                    }t          |||||          S r,   )contextvarscopy_context%_ContextPreservedSyncGeneratorWrapperr.   rx   r   r6   r7   preserved_contexts         r/   _wrap_sync_generator_resultz-LangfuseDecorator._wrap_sync_generator_result  s4    " (4664'
 
 	
r1   c                 N    t          j                    }t          |||||          S r,   )r   r   &_ContextPreservedAsyncGeneratorWrapperr   s         r/   _wrap_async_generator_resultz.LangfuseDecorator._wrap_async_generator_result  s4    " (4665'
 
 	
r1   rz   c                   t          j        |          rd|                     ||||          fS t          j        |          rd|                     ||||          fS t          |          j        dk    r6t          |d          r&|                     ||j        ||          |_        d|fS |du r|	                    |           d|fS )NTStreamingResponsebody_iteratoroutputF)
r   isgeneratorr   
isasyncgenr   rr   ri   hasattrr   rq   )r.   rx   rz   r6   r7   s        r/   rm   z(LangfuseDecorator._handle_observe_result  s   $ v&& 	99+#	    f%% 	::+#	    << $777GO=
 =
7 $(#D#D+$#	$ $F  <T!!'..f.===f}r1   r,   )$ri   
__module____qualname____doc__r   r#   r0   r   rg   r   boolr   r	   r   rA   rB   staticmethodrk   r   r   rj   r   r   r   r    r   r   r   r   r   r   r   r   r   r   rm   r-   r1   r/   r(   r(   4   s        & (A(!((( X( 	 #;?(,)-CG	 	 		 sm		
 78	  ~	 !	 &hz3&?@	 
1#q&		 	 	 X	 !E# #;?(,)-CGE# E# E#qkE# sm	E#
 78E#  ~E# !E# &hz3&?@E# 
q(A36""	#E# E# E# E#^ DH[& [& [&[& sm	[&
 78[& [& [& &hz3&?@[& 
[& [& [& [&J DHY% Y% Y%Y% sm	Y%
 78Y% Y% Y% &hz3&?@Y% 
Y% Y% Y% Y%v 
 
d 
 
 
 \
  
 
 
 
 	

 
 

 
 
 
< DH
 
%*
&

 
 
 &hz3&?@
  
!
 
 
 
T DH
 
%*
&

 "
 
 &hz3&?@
  
!
 
 
 
V DH!1 1 1%*
&
1 1 1  &hz3&?@!1" 
tSy	#1 1 1 1 1 1r1   r(   c                       e Zd ZdZdedej        deee	e
eeeeeef	         dedeeegef                  ddfd	Zdd
ZddZdeddfdZddZddZdefdZdS )r   zMSync generator wrapper that ensures each iteration runs in preserved context.r   contextr:   r6   transform_fnr*   Nc                 h    || _         || _        g | _        || _        || _        || _        d| _        d S NFr   r   itemsr:   r6   r   _span_endedr.   r   r   r:   r6   r   s         r/   __init__z._ContextPreservedSyncGeneratorWrapper.__init__  >    $ # "
	,( r1   c                     | S r,   r-   r.   s    r/   __iter__z._ContextPreservedSyncGeneratorWrapper.__iter__8      r1   c                 ^   | j         rd S | j        r|| j        }| j        |                     | j                  }n8t	          d | j        D                       rd                    | j                  }| j                            |           | j                                         d| _         d S )Nc              3   @   K   | ]}t          |t                    V  d S r,   
isinstancerg   .0items     r/   	<genexpr>zB_ContextPreservedSyncGeneratorWrapper._finalize.<locals>.<genexpr>E  ,      BBtZc**BBBBBBr1    r   T	r   r6   r   r   allrI   r:   rq   rn   r.   r   s     r/   	_finalizez/_ContextPreservedSyncGeneratorWrapper._finalize;       	F 		,*F ,**4:66BBtzBBBBB -,,IF+++	r1   errorc                     | j         rd S | j                            dt          |          pt	          |          j                                                   d| _         d S Nrc   rd   Tr   r:   rq   rg   rr   ri   rn   r.   r   s     r/   _finalize_with_errorz:_ContextPreservedSyncGeneratorWrapper._finalize_with_errorM  ^     	F	#e***LU8L 	 	
 	

#%%%r1   c                     | j         rd S 	 | j                            | j        j                   |                                  d S # t          t          j        f$ r}| 	                    |            d }~ww xY wr,   )
r   r   runr   closer   ro   r?   rp   r   r   s     r/   r   z+_ContextPreservedSyncGeneratorWrapper.closeV  s     	F	LT^1222
 NN	 712 	 	 	%%e,,,	s   $A A6A11A6c                 R    	 |                                   d S # t          $ r Y d S w xY wr,   )r   BaseExceptionr   s    r/   __del__z-_ContextPreservedSyncGeneratorWrapper.__del__b  s:    	JJLLLLL 	 	 	DD	s    
&&c                 8   	 | j                             t          | j                  }| j        r| j                            |           |S # t          $ r |                                   t          t          j        f$ r}|                     |            d }~ww xY wr,   )r   r   nextr   r6   r   appendStopIterationr   ro   r?   rp   r   r.   r   r{   s      r/   __next__z._ContextPreservedSyncGeneratorWrapper.__next__h  s    	<##D$.99D" (
!!$'''K 	 	 	NN712 	 	 	%%a(((	s   AA
 
4B>BB)r*   r   r*   N)ri   r   r   r   r   r   Contextr   r   r   r   r    r   r   r   r   r   r   r   r   r	   rg   r   r   r   r   r   r   r   r   r   r-   r1   r/   r   r     s-       WW!! $! 

	! !  x
C89!!" 
#! ! ! !4          $ -  D        
 
 
 
   #      r1   r   c                       e Zd ZdZdedej        deee	e
eeeeeef	         dedeeegef                  ddfd	Zdd
ZddZdeddfdZddZddZddZdefdZdS )r   zNAsync generator wrapper that ensures each iteration runs in preserved context.r   r   r:   r6   r   r*   Nc                 h    || _         || _        g | _        || _        || _        || _        d| _        d S r   r   r   s         r/   r   z/_ContextPreservedAsyncGeneratorWrapper.__init__}  r   r1   c                     | S r,   r-   r   s    r/   	__aiter__z0_ContextPreservedAsyncGeneratorWrapper.__aiter__  r   r1   c                 ^   | j         rd S | j        r|| j        }| j        |                     | j                  }n8t	          d | j        D                       rd                    | j                  }| j                            |           | j                                         d| _         d S )Nc              3   @   K   | ]}t          |t                    V  d S r,   r   r   s     r/   r   zC_ContextPreservedAsyncGeneratorWrapper._finalize.<locals>.<genexpr>  r   r1   r   r   Tr   r   s     r/   r   z0_ContextPreservedAsyncGeneratorWrapper._finalize  r   r1   r   c                     | j         rd S | j                            dt          |          pt	          |          j                                                   d| _         d S r   r   r   s     r/   r   z;_ContextPreservedAsyncGeneratorWrapper._finalize_with_error  r   r1   c                   K   | j         rd S 	 	 t          j        | j                                        | j                   d {V  nR# t          $ rE | j                            t          j        | j                                                   d {V  Y nw xY w|                                  d S # t          t          j
        f$ r}|                     |            d }~ww xY wN)r   )r   r?   create_taskr   acloser   	TypeErrorr   r   ro   rp   r   r   s     r/   r   z-_ContextPreservedAsyncGeneratorWrapper.aclose  s.      	F	U)N))++ L            U U Ul&&w':DN<Q<Q<S<STTTTTTTTTTTU NN	 712 	 	 	%%e,,,	s6   8A B/ ABB/ BB/ /C CC c                 >   K   |                                   d {V  d S r,   )r   r   s    r/   r   z,_ContextPreservedAsyncGeneratorWrapper.close  s,      kkmmr1   c                 .    |                                   d S r,   )r   r   s    r/   r   z._ContextPreservedAsyncGeneratorWrapper.__del__  s    r1   c                 
  K   	 	 t          j        | j                                        | j                   d {V }nR# t
          $ rE | j                            t           j        | j                                                   d {V }Y nw xY w| j        r| j        	                    |           |S # t          $ r |                                   t          t           j        f$ r}|                     |            d }~ww xY wr   )r?   r   r   	__anext__r   r   r   r6   r   r   StopAsyncIterationr   ro   rp   r   r   s      r/   r   z0_ContextPreservedAsyncGeneratorWrapper.__anext__  sU     	$0N,,.. L            !\--'N,,..        " (
!!$'''K! 	 	 	NN712 	 	 	%%a(((	s3   8> B3 AB
B3 B%B3 34D'C==D)r*   r   r   ) ri   r   r   r   r   r   r   r   r   r   r   r    r   r   r   r   r   r   r   r   r	   rg   r   r   r   r   r   r   r   r   r   r   r-   r1   r/   r   r   z  sA       XX!!! $! 

	! !  x
C89!!" 
#! ! ! !4          $ -  D           $            r1   r   )7r?   r   r   rK   	functoolsr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r   opentelemetry.util._decoratorr   typing_extensionsr   langfuse._client.constantsr   r   &langfuse._client.environment_variablesr   langfuse._client.get_clientr   r   langfuse._client.spanr   r   r   r   r   r   r   r   r    langfuse.loggerr!   rG   langfuse.typesr"   r#   r%   r&   r(   
_decoratorr0   r   r   r-   r1   r/   <module>r      s         				                                     B A A A A A ' ' ' ' ' '             L K K K K K K K
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 6 5 5 5 5 5 ' ' ' ' ' 'GCxS)***IcNNGCLL_ _ _ _ _ _ _ _D   


\ \ \ \ \ \ \ \~m m m m m m m m m mr1   