
    a
i,;                       d Z ddlmZ ddlZddl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 ddlmZ erdd	lmZ dd
lmZ  G d d          Z e            Z G d d          Z G d d          Z e            ZdgZdS )a<  Make approximate assertions as "expectations" on test results.

This module is designed to be used within test cases decorated with the
`@pytest.mark.decorator` decorator

It allows you to log scores about a test case and optionally make assertions that log as
"expectation" feedback to LangSmith.

Example:
    ```python
    import pytest
    from langsmith import expect


    @pytest.mark.langsmith
    def test_output_semantically_close():
        response = oai_client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": "You are a helpful assistant."},
                {"role": "user", "content": "Say hello!"},
            ],
        )
        response_txt = response.choices[0].message.content
        # Intended usage
        expect.embedding_distance(
            prediction=response_txt,
            reference="Hello!",
        ).to_be_less_than(0.9)

        # Score the test case
        matcher = expect.edit_distance(
            prediction=response_txt,
            reference="Hello!",
        )
        # Apply an assertion and log 'expectation' feedback to LangSmith
        matcher.to_be_less_than(1)

        # You can also directly make assertions on values directly
        expect.value(response_txt).to_contain("Hello!")
        # Or using a custom check
        expect.value(response_txt).against(lambda x: "Hello" in x)

        # You can even use this for basic metric logging within tests

        expect.score(0.8)
        expect.score(0.7, key="similarity").to_be_greater_than(0.7)
    ```
    )annotationsN)TYPE_CHECKINGAnyCallableLiteralOptionalUnionoverloadclient)run_helpers)	run_trees)utils)EditDistanceConfig)EmbeddingConfigc                  "    e Zd ZdZddZd	dZdS )
_NULL_SENTRYzA sentinel singleton class used to distinguish omitted keyword arguments
    from those passed in with the value None (which may have different behavior).
    returnLiteral[False]c                    dS )NF selfs    C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langsmith/_expect.py__bool__z_NULL_SENTRY.__bool__Q   s    u    strc                    dS )N	NOT_GIVENr   r   s    r   __repr__z_NULL_SENTRY.__repr__T   s    {r   N)r   r   )r   r   )__name__
__module____qualname____doc__r   r    r   r   r   r   r   L   sF                 r   r   c                  t    e Zd ZdZ	 	 d'd(dZd)d*dZd+dZd,dZd,dZd-dZ	d.d/d Z
d,d!Zd0d"Zd1d#Zd2d&ZdS )3_Matcherz4A class for making assertions on expectation values.Nr   Optional[ls_client.Client]keyr   valuer   	_executor,Optional[ls_utils.ContextThreadPoolExecutor]run_idOptional[str]c                    || _         || _        || _        |pt          j        d          | _        t          j                    | _        | j        r| j        j	        n|| _
        d S )N   max_workers)_clientr(   r)   ls_utilsContextThreadPoolExecutorr*   rhget_current_run_tree_rttrace_id_run_id)r   r   r(   r)   r*   r,   s         r   __init__z_Matcher.__init__^   s`     
"Wh&HUV&W&W&W*,,,0H@tx((&r   scoreintmessager   Nonec           	        t          j                    sw| j        st          j                    | _        | j                            | j        j        | j        d||| j	        r| j	        j
        nd | j	        r| j	        j        nd            d S d S )Nexpectation)r,   r(   r;   comment
session_id
start_time)r3   test_tracking_is_disabledr2   rtget_cached_clientr*   submitcreate_feedbackr9   r7   rB   rC   )r   r;   r=   s      r   _submit_feedbackz_Matcher._submit_feedbackm   s    133 	< 6!355N!!,|!26(D48..26(D48.. "     	 	r   	conditionboolmethod_namec                    	 |s
J |            |                      dd| j         d|            d S # t          $ r+}|                      dt          |                     |d d }~ww xY w)N   z	Success: .)r=   r   )rI   r(   AssertionErrorrepr)r   rJ   r=   rL   es        r   _assertz_Matcher._assert{   s    	%%g%%9!!!-Q-Q-QK-Q-Q!RRRRR 	 	 	!!!T!WW---	s   .2 
A'&A""A'floatc           	     l    |                      | j        |k     d| j         d| d| j         d           dS )zAssert that the expectation value is less than the given value.

        Args:
            value: The value to compare against.

        Raises:
            AssertionError: If the expectation value is not less than the given value.
        	Expected z to be less than 
, but got to_be_less_thanNrS   r)   r(   r   r)   s     r   rX   z_Matcher.to_be_less_than   sP     	JPPP5PPDJPP	
 	
 	
 	
 	
r   c           	     l    |                      | j        |k    d| j         d| d| j         d           dS )a  Assert that the expectation value is greater than the given value.

        Args:
            value: The value to compare against.

        Raises:
            AssertionError: If the expectation value is not
            greater than the given value.
        rV   z to be greater than rW   to_be_greater_thanNrY   rZ   s     r   r\   z_Matcher.to_be_greater_than   sP     	JSSSeSStzSS 	
 	
 	
 	
 	
r   	min_value	max_valuec                    |                      || j        cxk     o|k     nc d| j         d| d| d| j         d           dS )a4  Assert that the expectation value is between the given min and max values.

        Args:
            min_value: The minimum value (exclusive).
            max_value: The maximum value (exclusive).

        Raises:
            AssertionError: If the expectation value is not between the min and max.
        rV   z to be between z and rW   to_be_betweenNrY   )r   r]   r^   s      r   r`   z_Matcher.to_be_between   s     	
....Y....% % % % % % %
% %		
 	
 	
 	
 	
r      	precisionc           	         |                      t          | j        |          t          ||          k    d| j         d| d| j         d           dS )ak  Assert that the expectation value is approximately equal to the given value.

        Args:
            value: The value to compare against.
            precision: The number of decimal places to round to for comparison.

        Raises:
            AssertionError: If the rounded expectation value
                does not equal the rounded given value.
        rV   z to be approximately rW   to_be_approximatelyN)rS   roundr)   r(   )r   r)   rb   s      r   rd   z_Matcher.to_be_approximately   sd     	$*i((E%,C,CCTTTuTT
TT!	
 	
 	
 	
 	
r   c           	     l    |                      | j        |k    d| j         d| d| j         d           dS )a   Assert that the expectation value equals the given value.

        Args:
            value: The value to compare against.

        Raises:
            AssertionError: If the expectation value does
                not exactly equal the given value.
        rV   z to be equal to rW   to_equalNrY   rZ   s     r   rg   z_Matcher.to_equal   sP     	J%OOO%OO4:OO	
 	
 	
 	
 	
r   c                b    |                      | j        du d| j         d| j         d           dS )zAssert that the expectation value is `None`.

        Raises:
            AssertionError: If the expectation value is not `None`.
        NrV   z to be None, but got 
to_be_nonerY   r   s    r   ri   z_Matcher.to_be_none   sH     	J$CCCtzCC	
 	
 	
 	
 	
r   c                Z    |                      || j        v d| j         d| dd           dS )zAssert that the expectation value contains the given value.

        Args:
            value: The value to check for containment.

        Raises:
            AssertionError: If the expectation value does not contain the given value.
        rV   z to contain z, but it does not
to_containNrY   rZ   s     r   rk   z_Matcher.to_contain   sI     	TZFFFeFFF	
 	
 	
 	
 	
r   funcr   c                   t          j        |          }|                      || j                  d| d| j         d           dS )zAssert the expectation value against a custom function.

        Args:
            func: A custom function that takes the expectation value as input.

        Raises:
            AssertionError: If the custom function returns False.
        z
Assertion z failed for againstN)inspect	signaturerS   r)   r(   )r   rl   func_signatures      r   rn   z_Matcher.against   s[     !*400D???TX??	
 	
 	
 	
 	
r   )NN)
r   r'   r(   r   r)   r   r*   r+   r,   r-   N)r;   r<   r=   r-   r   r>   )rJ   rK   r=   r   rL   r   r   r>   )r)   rT   r   r>   )r]   rT   r^   rT   r   r>   )ra   )r)   rT   rb   r<   r   r>   )r   r>   )r)   r   r   r>   )rl   r   r   r>   )r!   r"   r#   r$   r:   rI   rS   rX   r\   r`   rd   rg   ri   rk   rn   r   r   r   r&   r&   [   s       >> CG $A A A A A       
 
 
 

 
 
 
 
 
 
 
"
 
 
 
 
"
 
 
 
 

 

 

 


 
 
 
 
 
 
 
 
 
r   r&   c                      e Zd ZdZddd'dZddd(dZddd)dZd*dZddddd+dZe	d*d            Z
e	d,d             Z
edfd-d#Z
d.d&ZdS )/_Expectz1A class for setting expectations on test results.Nr   r   r'   c                   || _         t          j        d          | _        t	          j        | j        j        d           d S )Nr/   r0   T)wait)r2   r3   r4   executoratexitregistershutdownr   r   s     r   r:   z_Expect.__init__  s>     :qIII.T::::::r   config
predictionr   	referencer}   Optional[EmbeddingConfig]r   r&   c          	     &   ddl m} |pi }|                    d          rdnd} ||          }|                    ||          }||j        d}|                     d	||d
| d|j         d           t          | j        d	|| j                  S )a  Compute the embedding distance between the prediction and reference.

        This logs the embedding distance to LangSmith and returns a `_Matcher` instance
        for making assertions on the distance value.

        By default, this uses the OpenAI API for computing embeddings.

        Args:
            prediction: The predicted string to compare.
            reference: The reference string to compare against.
            config: Optional configuration for the embedding distance evaluator.

                Supported options:

                - `encoder`: A custom encoder function to encode the list of input
                    strings to embeddings.

                    Defaults to the OpenAI API.
                - `metric`: The distance metric to use for comparison.

                    Supported values: `'cosine'`, `'euclidean'`, `'manhattan'`,
                    `'chebyshev'`, `'hamming'`.

        Returns:
            A `_Matcher` instance for the embedding distance value.


        Example:
            ```python
            expect.embedding_distance(
                prediction="hello",
                reference="hi",
            ).to_be_less_than(1.0)
            ```
        r   )EmbeddingDistanceencodercustomopenair|   r~   r   )r   metricembedding_distanceUsing z
, Metric: r;   source_inforA   r*   )	'langsmith._internal._embedding_distancer   getevaluatedistancerI   r&   r2   rw   )	r   r~   r   r}   r   encoder_func	evaluatorr;   src_infos	            r   r   z_Expect.embedding_distance	  s    T 	NMMMMM2#)::i#8#8Fxxh%%V444	""jI"NN+y7IJJ 'PLPPI<NPP 	
 	
 	
 L.
 
 
 	
r   Optional[EditDistanceConfig]c          	     :   ddl m} |pi }|                    d          pd}|                    dd          } ||          }|                    ||          }||d	}	|                     d
||	d| d| d           t          | j        d
|| j                  S )aB  Compute the string distance between the prediction and reference.

        This logs the string distance (Damerau-Levenshtein) to LangSmith and returns
        a `_Matcher` instance for making assertions on the distance value.

        This depends on the `rapidfuzz` package for string distance computation.

        Args:
            prediction: The predicted string to compare.
            reference: The reference string to compare against.
            config: Optional configuration for the string distance evaluator.

                Supported options:

                - `metric`: The distance metric to use for comparison.

                    Supported values: `'damerau_levenshtein'`, `'levenshtein'`,
                    `'jaro'`, `'jaro_winkler'`, `'hamming'`, `'indel'`.
                - `normalize_score`: Whether to normalize the score between `0` and `1`.

        Returns:
            A `_Matcher` instance for the string distance value.

        Examples:
            ```python
            expect.edit_distance("hello", "helo").to_be_less_than(1)
            ```
        r   )EditDistancer   damerau_levenshteinnormalize_scoreTr|   r   )r   	normalizeedit_distancer   z, Normalize: r   r   )"langsmith._internal._edit_distancer   r   r   rI   r&   r2   rw   )
r   r~   r   r}   r   r   r   r   r;   r   s
             r   r   z_Expect.edit_distanceF  s    F 	DCCCCC2H%%>)>JJ0$77	 L///	""jI"NN$9=='DFDDDD 	
 	
 	
 Lm	
 
 
 	
r   r)   r   c                <    t          | j        d|| j                  S )aD  Create a `_Matcher` instance for making assertions on the given value.

        Args:
            value: The value to make assertions on.

        Returns:
            A `_Matcher` instance for the given value.

        Example:
            ```python
            expect.value(10).to_be_less_than(20)
            ```
        r)   r   )r&   r2   rw   rZ   s     r   r)   z_Expect.value  s     guNNNNr   r;   )r(   source_run_idrA   Union[float, int, bool]r(   r   Optional[ls_client.ID_TYPE]rA   r-   c               v    |                      ||ddi||d           t          | j        ||| j                  S )a  Log a numeric score to LangSmith.

        Args:
            score: The score value to log.
            key: The key to use for logging the score. Defaults to `'score'`.

        Example:
            ```python
            expect.score(0.8)  # doctest: +ELLIPSIS
            <langsmith._expect._Matcher object at ...>

            expect.score(0.8, key="similarity").to_be_greater_than(0.7)
            ```
        methodzexpect.score)r;   r   r   rA   r   )rI   r&   r2   rw   )r   r;   r(   r   rA   s        r   r;   z_Expect.score  sW    , 	 (.9!."	 	
 	
 	
 c5DMJJJJr   c                   d S rr   r   rZ   s     r   __call__z_Expect.__call__  s    363r   ls_client.Clientc                  d S rr   r   r{   s     r   r   z_Expect.__call__  s    CF3r   Optional[Any]Union[_Expect, _Matcher]c               b    t          |          }|t          ur|                    |          S |S )Nr   )rt   r   r)   )r   r)   r   expecteds       r   r   z_Expect.__call__  s6     &)))	!!>>%(((r   resultsdictc                    t          j                    }|r|j        nd }t          j                    sA| j        st          j                    | _         | j        j	        | j        j
        f||d| d S d S )N)r,   r(   )r5   r6   r8   r3   rD   r2   rE   rF   rw   rG   rH   )r   r(   r   current_runr,   s        r   rI   z_Expect._submit_feedback  s    -//)4>%%$133 	< 6!355 DM ,5; HO    	 	r   )r   r'   )r~   r   r   r   r}   r   r   r&   )r~   r   r   r   r}   r   r   r&   )r)   r   r   r&   )
r;   r   r(   r   r   r   rA   r-   r   r&   )r   r   r   rt   )r   r'   r)   r   r   r   )r(   r   r   r   )r!   r"   r#   r$   r:   r   r   r)   r;   r
   r   r   rI   r   r   r   rt   rt     s.       ;;?C ; ; ; ; ; ; -1;
 ;
 ;
 ;
 ;
 ;
D 048
 8
 8
 8
 8
 8
tO O O O( 59!%K K K K K KF 666 X6FFF XF  )-1		 	 	 	 	     r   rt   expect) r$   
__future__r   rx   ro   typingr   r   r   r   r   r	   r
   	langsmithr   	ls_clientr   r5   r   rE   r   r3   r   r   r   r   r   r   r&   rt   r   __all__r   r   r   <module>r      s  0 0d # " " " " "                    * ) ) ) ) ) ' ' ' ' ' ' % % % % % % ' ' ' ' ' ' HEEEEEEGGGGGG	 	 	 	 	 	 	 	 LNN	c
 c
 c
 c
 c
 c
 c
 c
LK K K K K K K K\ 
*r   