
    bi,;                        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y)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y)_NULL_SENTRYzA sentinel singleton class used to distinguish omitted keyword arguments
    from those passed in with the value None (which may have different behavior).
    c                     y)NF selfs    [/home/obispo/Crisostomo_bridge/mision_env/lib/python3.12/site-packages/langsmith/_expect.py__bool__z_NULL_SENTRY.__bool__Q   s        c                     y)N	NOT_GIVENr   r   s    r   __repr__z_NULL_SENTRY.__repr__T   s    r   N)returnzLiteral[False])r   str)__name__
__module____qualname____doc__r   r   r   r   r   r   r   L   s    r   r   c                      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ddZddZddZy)_Matcherz4A class for making assertions on expectation values.Nc                    || _         || _        || _        |xs t        j                  d      | _        t        j                         | _        | j                  r| j                  j                  | _
        y || _
        y )N   max_workers)_clientkeyvaluels_utilsContextThreadPoolExecutor	_executorrhget_current_run_tree_rttrace_id_run_id)r   r   r+   r,   r/   run_ids         r   __init__z_Matcher.__init__^   s^     
"Wh&H&HUV&W**,,0HHtxx((&r   c           	        t        j                         s| j                  st        j                         | _        | j
                  j                  | j                  j                  | j                  d||| j                  r| j                  j                  nd | j                  r| j                  j                  nd        y y )Nexpectation)r5   r+   scorecomment
session_id
start_time)r-   test_tracking_is_disabledr*   rtget_cached_clientr/   submitcreate_feedbackr4   r2   r;   r<   )r   r9   messages      r   _submit_feedbackz_Matcher._submit_feedbackm   s    113<<!335NN!!,,||!26((488..26((488.. "  4r   c                    	 |sJ |       | j                  dd| j                   d|        y # t        $ r#}| j                  dt        |             |d d }~ww xY w)N   z	Success: .)rB   r   )rC   r+   AssertionErrorrepr)r   	conditionrB   method_namees        r   _assertz_Matcher._assert{   sd    	%g%9!!!y
!K=-Q!R 	!!!T!W-	s   ,/ 	AAAc           	     ~    | j                  | j                  |k  d| j                   d| d| j                   d       y)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rL   r,   r+   r   r,   s     r   rP   z_Matcher.to_be_less_than   s>     	JJz!25'DJJ<P	
r   c           	     ~    | j                  | j                  |kD  d| j                   d| d| j                   d       y)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.
        rN   z to be greater than rO   to_be_greater_thanNrQ   rR   s     r   rT   z_Matcher.to_be_greater_than   s>     	JJz!5eWJtzzlS 	
r   c                    | j                  || j                  cxk  xr |k  nc d| j                   d| d| d| j                   d       y)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.
        rN   z to be between z and rO   to_be_betweenNrQ   )r   	min_value	max_values      r   rV   z_Matcher.to_be_between   sO     	

.Y.z5 L

|%		
r   c           	         | j                  t        | j                  |      t        ||      k(  d| j                   d| d| j                   d       y)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.
        rN   z to be approximately rO   to_be_approximatelyN)rL   roundr,   r+   )r   r,   	precisions      r   rZ   z_Matcher.to_be_approximately   sL     	$**i(E%,CCz!6ugZ

|T!	
r   c           	     ~    | j                  | j                  |k(  d| j                   d| d| j                   d       y)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.
        rN   z to be equal to rO   to_equalNrQ   rR   s     r   r^   z_Matcher.to_equal   s>     	JJ%z!1%
4::,O	
r   c                v    | j                  | j                  du d| j                   d| j                   d       y)zAssert that the expectation value is `None`.

        Raises:
            AssertionError: If the expectation value is not `None`.
        NrN   z to be None, but got 
to_be_nonerQ   r   s    r   r`   z_Matcher.to_be_none   s8     	JJ$z!6tzzlC	
r   c                d    | j                  || j                  v d| j                   d| dd       y)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.
        rN   z to contain z, but it does not
to_containNrQ   rR   s     r   rb   z_Matcher.to_contain   s6     	TZZzeW4EF	
r   c                   t        j                  |      }| j                   || j                        d| d| j                   d       y)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	signaturerL   r,   r+   )r   funcfunc_signatures      r   rd   z_Matcher.against   sD     !**40(TXXJ?	
r   )NN)
r   Optional[ls_client.Client]r+   r   r,   r   r/   z,Optional[ls_utils.ContextThreadPoolExecutor]r5   Optional[str]N)r9   intrB   rj   r   None)rI   boolrB   r   rJ   r   r   rm   )r,   floatr   rm   )rW   ro   rX   ro   r   rm   )   )r,   ro   r\   rl   r   rm   )r   rm   )r,   r   r   rm   )rg   r   r   rm   )r    r!   r"   r#   r6   rC   rL   rP   rT   rV   rZ   r^   r`   rb   rd   r   r   r   r%   r%   [   s}    > CG $A*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y)_Expectz1A class for setting expectations on test results.Nr   c                   || _         t        j                  d      | _        t	        j
                  | j                  j                  d       y )Nr'   r(   T)wait)r*   r-   r.   executoratexitregistershutdownr   r   s     r   r6   z_Expect.__init__  s3     ::qI..T:r   configc          	     ,   ddl m} |xs i }|j                  d      rdnd} ||      }|j                  ||      }||j                  d}| j                  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openairz   
prediction	reference)r~   metricembedding_distanceUsing z
, Metric: r9   source_infor:   r/   )	'langsmith._internal._embedding_distancer}   getevaluatedistancerC   r%   r*   ru   )	r   r   r   r{   r}   encoder_func	evaluatorr9   src_infos	            r   r   z_Expect.embedding_distance	  s    T 	N2#)::i#8xh%V4	""jI"N+y7I7IJ '#L>I<N<N;OP	
 LL.
 	
r   c          	     (   ddl m} |xs i }|j                  d      xs d}|j                  dd      } ||      }|j                  ||      }||d	}	| j	                  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_scoreTrz   r   )r   	normalizeedit_distancer   z, Normalize: r   r   )"langsmith._internal._edit_distancer   r   r   rC   r%   r*   ru   )
r   r   r   r{   r   r   r   r   r9   r   s
             r   r   z_Expect.edit_distanceF  s    F 	D2H%>)>JJ0$7	 /	""jI"N$9='#F8=D	
 LLmm	
 	
r   c                H    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%   r*   ru   rR   s     r   r,   z_Expect.value  s     guNNr   r9   )r+   source_run_idr:   c               z    | j                  ||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)r9   r   r   r:   r   )rC   r%   r*   ru   )r   r9   r+   r   r:   s        r   r9   z_Expect.score  sF    , 	 (.9!."		
 c5DMMJJr   c                    y rk   r   rR   s     r   __call__z_Expect.__call__  s    36r   c                   y rk   r   ry   s     r   r   z_Expect.__call__  s    CFr   c               P    t        |      }|t        ur|j                  |      S |S )Nr   )rr   r   r,   )r   r,   r   expecteds       r   r   z_Expect.__call__  s*     &)	!>>%((r   c                (   t        j                         }|r|j                  nd }t        j                         sZ| j
                  st        j                         | _         | j                  j                  | j
                  j                  f||d| y y )N)r5   r+   )r0   r1   r3   r-   r=   r*   r>   r?   ru   r@   rA   )r   r+   resultscurrent_runr5   s        r   rC   z_Expect._submit_feedback  sz    --/)4%%$113<<!335 DMM  ,,5;HO 4r   )r   ri   )r   r   r   r   r{   zOptional[EmbeddingConfig]r   r%   )r   r   r   r   r{   zOptional[EditDistanceConfig]r   r%   )r,   r   r   r%   )
r9   zUnion[float, int, bool]r+   r   r   zOptional[ls_client.ID_TYPE]r:   rj   r   r%   )r   zls_client.Clientr   rr   )r   ri   r,   zOptional[Any]r   zUnion[_Expect, _Matcher])r+   r   r   dict)r    r!   r"   r#   r6   r   r   r,   r9   r
   r   r   rC   r   r   r   rr   rr     s   ;?C ; -1;
;
 ;

 *;
 
;
D 048
8
 8

 -8
 
8
tO( 59!%K&K 	K
 3K K 
KF 6 6F F  )-1		 +			
 
"	r   rr   expect) r#   
__future__r   rv   re   typingr   r   r   r   r   r	   r
   	langsmithr   	ls_clientr   r0   r   r>   r   r-   r   r   r   r   r   r   r%   rr   r   __all__r   r   r   <module>r      sy   0d #     * ' % 'EG	 	 N	c
 c
LK K\ 
*r   