
    NgB\                       U d dl mZ d dlZd dlZd dlZd dlZ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 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 d d
lmZ  d dlm!Z" d dlm#Z$ d dl%m&Z& 	 d dl'Z'e'j(        j)        Z*n# e+$ r  G d de)          Z*Y nw xY w ej,        e-          Z. ed          Z/ ed          Z0edLd            Z1eddddddMd             Z1dNd$Z1dOd&Z2dPd'Z3dQd*Z4dRd-Z5 ed.           a6d/e7d0<   dSd5Z8dTd7Z9 ed8ee:         9          Z;dUd;Z< G d< d6          Z= G d= d>ed?@          Z>dVdCZ?dWdFZ@dXdJZAdXdKZBe1ZCdS )Y    )annotationsN)defaultdict)Path)AnyCallableOptionalSequenceTupleTypeVaroverload)	TypedDict)client)env)run_helpers)	run_trees)schemas)utils)_orjsonc                      e Zd ZdS )SkipExceptionN)__name__
__module____qualname__     N/var/www/html/ai-engine/env/lib/python3.11/site-packages/langsmith/_testing.pyr   r      s        r   r   TUfuncr   returnc                    d S Nr   )r   s    r   testr#   *   s	     sr   idoutput_keysr   test_suite_namer%   Optional[uuid.UUID]r&   Optional[Sequence[str]]r   Optional[ls_client.Client]r'   Optional[str]Callable[[Callable], Callable]c                    d S r"   r   r$   s       r   r#   r#   0   s	     &)Sr   argsr   kwargsc                 $   t          |                    dd          |                    dd          |                    dd          |                    dd          t          j        |                    dd                              |r)t	          j        d|                                            t          j                    rt	          j        d	           dfd}| r&t          | d                   r || d                   S |S )a[  Create a test case in LangSmith.

    This decorator is used to mark a function as a test case for LangSmith. It ensures
    that the necessary example data is created and associated with the test function.
    The decorated function will be executed as a test case, and the results will be
    recorded and reported by LangSmith.

    Args:
        - id (Optional[uuid.UUID]): A unique identifier for the test case. If not
            provided, an ID will be generated based on the test function's module
            and name.
        - output_keys (Optional[Sequence[str]]): A list of keys to be considered as
            the output keys for the test case. These keys will be extracted from the
            test function's inputs and stored as the expected outputs.
        - client (Optional[ls_client.Client]): An instance of the LangSmith client
            to be used for communication with the LangSmith service. If not provided,
            a default client will be used.
        - test_suite_name (Optional[str]): The name of the test suite to which the
            test case belongs. If not provided, the test suite name will be determined
            based on the environment or the package name.

    Returns:
        Callable: The decorated test function.

    Environment:
        - LANGSMITH_TEST_CACHE: If set, API calls will be cached to disk to
            save time and costs during testing. Recommended to commit the
            cache files to your repository for faster CI/CD runs.
            Requires the 'langsmith[vcr]' package to be installed.
        - LANGSMITH_TEST_TRACKING: Set this variable to the path of a directory
            to enable caching of test results. This is useful for re-running tests
             without re-executing the code. Requires the 'langsmith[vcr]' package.

    Example:
        For basic usage, simply decorate a test function with `@test`:

        >>> @test
        ... def test_addition():
        ...     assert 3 + 4 == 7


        Any code that is traced (such as those traced using `@traceable`
        or `wrap_*` functions) will be traced within the test case for
        improved visibility and debugging.

        >>> from langsmith import traceable
        >>> @traceable
        ... def generate_numbers():
        ...     return 3, 4

        >>> @test
        ... def test_nested():
        ...     # Traced code will be included in the test case
        ...     a, b = generate_numbers()
        ...     assert a + b == 7

        LLM calls are expensive! Cache requests by setting
        `LANGSMITH_TEST_CACHE=path/to/cache`. Check in these files to speed up
        CI/CD pipelines, so your results only change when your prompt or requested
        model changes.

        Note that this will require that you install langsmith with the `vcr` extra:

        `pip install -U "langsmith[vcr]"`

        Caching is faster if you install libyaml. See
        https://vcrpy.readthedocs.io/en/latest/installation.html#speed for more details.

        >>> # os.environ["LANGSMITH_TEST_CACHE"] = "tests/cassettes"
        >>> import openai
        >>> from langsmith.wrappers import wrap_openai
        >>> oai_client = wrap_openai(openai.Client())
        >>> @test
        ... def test_openai_says_hello():
        ...     # Traced code will be included in the test case
        ...     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!"},
        ...         ],
        ...     )
        ...     assert "hello" in response.choices[0].message.content.lower()

        LLMs are stochastic. Naive assertions are flakey. You can use langsmith's
        `expect` to score and make approximate assertions on your results.

        >>> from langsmith import expect
        >>> @test
        ... 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!"},
        ...         ],
        ...     )
        ...     # The embedding_distance call logs the embedding distance to LangSmith
        ...     expect.embedding_distance(
        ...         prediction=response.choices[0].message.content,
        ...         reference="Hello!",
        ...         # The following optional assertion logs a
        ...         # pass/fail score to LangSmith
        ...         # and raises an AssertionError if the assertion fails.
        ...     ).to_be_less_than(1.0)
        ...     # Compute damerau_levenshtein distance
        ...     expect.edit_distance(
        ...         prediction=response.choices[0].message.content,
        ...         reference="Hello!",
        ...         # And then log a pass/fail score to LangSmith
        ...     ).to_be_less_than(1.0)

        The `@test` decorator works natively with pytest fixtures.
        The values will populate the "inputs" of the corresponding example in LangSmith.

        >>> import pytest
        >>> @pytest.fixture
        ... def some_input():
        ...     return "Some input"
        >>>
        >>> @test
        ... def test_with_fixture(some_input: str):
        ...     assert "input" in some_input
        >>>

        You can still use pytest.parametrize() as usual to run multiple test cases
        using the same test function.

        >>> @test(output_keys=["expected"])
        ... @pytest.mark.parametrize(
        ...     "a, b, expected",
        ...     [
        ...         (1, 2, 3),
        ...         (3, 4, 7),
        ...     ],
        ... )
        ... def test_addition_with_multiple_inputs(a: int, b: int, expected: int):
        ...     assert a + b == expected

        By default, each test case will be assigned a consistent, unique identifier
        based on the function name and module. You can also provide a custom identifier
        using the `id` argument:
        >>> @test(id="1a77e4b5-1d38-4081-b829-b0442cf3f145")
        ... def test_multiplication():
        ...     assert 3 * 4 == 12

        By default, all test test inputs are saved as "inputs" to a dataset.
        You can specify the `output_keys` argument to persist those keys
        within the dataset's "outputs" fields.

        >>> @pytest.fixture
        ... def expected_output():
        ...     return "input"
        >>> @test(output_keys=["expected_output"])
        ... def test_with_expected_output(some_input: str, expected_output: str):
        ...     assert expected_output in some_input


        To run these tests, use the pytest CLI. Or directly run the test functions.
        >>> test_output_semantically_close()
        >>> test_addition()
        >>> test_nested()
        >>> test_with_fixture("Some input")
        >>> test_with_expected_output("Some input", "Some")
        >>> test_multiplication()
        >>> test_openai_says_hello()
        >>> test_addition_with_multiple_inputs(1, 2, 3)
    r%   Nr&   r   r'   cache)r%   r&   r   r'   r1   zUnexpected keyword arguments: zLLANGSMITH_TEST_TRACKING is set to 'false'. Skipping LangSmith test tracking.r   r   r    c                     t          j                   r$t          j                   d fd            }|S t          j                   d fd            }|S )N	test_argsr   test_kwargsc                 `   K   r | i | d {V S t          g| R i |di d {V  d S Nlangtest_extra)
_arun_testr3   r4   disable_trackingr   r7   s     r   async_wrapperz.test.<locals>.decorator.<locals>.async_wrapper   s      # A!%y!@K!@!@@@@@@@@ $  (3 DR           r   c                 D    r | i |S t          g| R i |di d S r6   )	_run_testr9   s     r   wrapperz(test.<locals>.decorator.<locals>.wrapper   sO     7tY6+666dUYUUU+UUnUUUUUUr   )r3   r   r4   r   )inspectiscoroutinefunction	functoolswraps)r   r;   r>   r:   r7   s   `  r   	decoratorztest.<locals>.decorator   s    &t,, 
	!_T""       #" ! 				V 	V 	V 	V 	V 	V 	V 
		V
 r   r   r   r   r    r   )	_UTExtrapopls_utilsget_cache_dirwarningswarnkeystest_tracking_is_disabledcallable)r.   r/   rC   r:   r7   s      @@r   r#   r#   :   s2   R ::dD!!JJ}d33zz(D))

#4d;;$VZZ%>%>??  N  HFv{{}}FFGGG9;; 
1	
 	
 	

      *  "a!! "ya!!!r   strc                 |    t          j        d          pd} |  dt          j                    j        d d          }|S )NFTestSuiteResult:   )rG   get_tracer_projectuuiduuid4hex)prefixnames     r   _get_experiment_namerY     sB    (//D3DF--tz||'+--DKr   c                   t          j        d          }|r|S t          j                    d         }	 t	          j        |           }|r| d|j         S n*# t          $ r t          	                    d           Y nw xY wt          d          )N
TEST_SUITE	repo_name.z3Could not determine test suite name from file path.z9Please set the LANGSMITH_TEST_SUITE environment variable.)rG   get_env_varls_envget_git_infor?   	getmoduler   BaseExceptionloggerdebug
ValueError)r   r'   r\   mods       r   _get_test_suite_namerg     s    *<88O #%%k2IL%% 	100#,000	1 L L LJKKKKKL P
Q
QQs   !A $A=<A=ls_client.Clientls_schemas.Datasetc                    |                      |          r|                     |          S t          j                                        d          pd}d}|r|d| z  }|                     ||          S )N)dataset_name
remote_url z
Test suitez for )rk   description)has_datasetread_datasetr_   r`   getcreate_dataset)r   r'   reporn   s       r   _get_test_suitert   '  s     77 	
"""@@@"$$((66<"" 	*>4>>)K$$(k % 
 
 	
r   
test_suitels_schemas.TracerSessionc           	         t                      }	 |                     ||j        ddt          j                                        d          i          S # t          j        $ r |                     |          cY S w xY w)NzTest Suite Results.revision_id)reference_dataset_idrn   metadata)project_name)	rY   create_projectr%   r_   get_langchain_env_var_metadatarq   rG   LangSmithConflictErrorread_project)r   ru   experiment_names      r   _start_experimentr   6  s     +,,OA$$!+-vDFFJJ!   	 % 	
 	
 		
 * A A A"""@@@@@As   AA %A<;A<c                 *    t          t                    S r"   )r   intr   r   r   <lambda>r   M  s    C(8(8 r   dict_param_dictinputssuite_id	uuid.UUIDTuple[uuid.UUID, str]c                   	 t          t          t          j        |                                         t          j                                        }n# t          $ r
 | j        }Y nw xY w| | d| j         }t          t          |                                                    }g }|D ]G}t          |         |xx         dz  cc<   |                    | t          |         |                     H|r|dd                    |           dz  }t          j        t          j        |          |t%          t          |                    d          fS )Nz::   [-])rN   r   r?   getfilerelative_tocwdre   r   r   tuplesortedrK   r   appendjoinrT   uuid5NAMESPACE_DNSlen)r   r   r   	file_path
identifier
input_keysarg_indiceskeys           r   _get_idr   P  s[   $W_T2233??

KKLL		 $ $ $O			$ :i::4=::Jvfkkmm,,--JK C CJ$$$)$$$cA;z#:3#?AABBBB 32#((;//2222
:d(*55z#c(mmBTBTBVBV7WWWs   AA A)(A)_LangSmithTestSuitec           	     n   t          j                    pi }| j                            | j        t
          j                            t
          j        j                  i || 	                                t          j
                                        d          d           |                                  d S )Nrx   )dataset_versionrx   )end_timerz   )r_   r`   r   update_projectexperiment_iddatetimenowtimezoneutcget_versionr}   rq   wait)ru   git_infos     r   
_end_testsr   b  s     "$$*H$$ "&&x'8'<==

)5577!@BBFF}UU
 
 
 %    OOr   VT)boundvaluesc                Z    | | S t          j        |           }t          j        |          S r"   )	ls_client_dumps_jsonr   loads)r   btss     r   _serde_example_valuesr   u  s,    ~


'
'C=r   c                      e Zd ZU dZded<    ej                    Zd+d
Ze	d             Z
e	d             Ze	d             Ze	 d,d-d            Ze	d             Zd.dZd/dZ	 d0d1d!Z	 d0d1d"Zd2d(Zd2d)Zd* ZdS )3r   NzOptional[dict]
_instancesr   r*   
experimentrv   datasetri   c                    |pt          j                    | _        || _        || _        d | _        t          j        d          | _        t          j
        t          |            d S )Nr   )max_workers)rtget_cached_clientr   _experiment_dataset_versionrG   ContextThreadPoolExecutor	_executoratexitregisterr   )selfr   r   r   s       r   __init__z_LangSmithTestSuite.__init__  s\     6 4 6 6%59!;JJJ
D)))))r   c                    | j         j        S r"   )r   r%   r   s    r   r%   z_LangSmithTestSuite.id  s    }r   c                    | j         j        S r"   )r   r%   r   s    r   r   z!_LangSmithTestSuite.experiment_id  s    ""r   c                    | j         S r"   )r   r   s    r   r   z_LangSmithTestSuite.experiment  s    r   r   r   r'   r+   r    c                >   |pt          j                    }|pt          |          }| j        5  | j        si | _        || j        vr5t          ||          }t          ||          } | |||          | j        |<   d d d            n# 1 swxY w Y   | j        |         S r"   )r   r   rg   _lockr   rt   r   )clsr   r   r'   ru   r   s         r   	from_testz_LangSmithTestSuite.from_test  s     12/11)G-A$-G-GY 	V 	V> $!#cn44,V_EE
.vzBB
25#fj*2U2U/	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V ~o..s   ABBBc                    | j         j        S r"   )r   rX   r   s    r   rX   z_LangSmithTestSuite.name  s    $$r   versiondatetime.datetimeNonec                x    | j         5  | j        || j        k    r|| _        d d d            d S # 1 swxY w Y   d S r"   r   r   )r   r   s     r   update_versionz"_LangSmithTestSuite.update_version  s    Z 	( 	(}$$-(?(? '	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	(s   /33Optional[datetime.datetime]c                R    | j         5  | j        cd d d            S # 1 swxY w Y   d S r"   r   r   s    r   r   z_LangSmithTestSuite.get_version  ss    Z 	! 	!=	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	!s     Frun_idr   errorskippedboolc                L    | j                             | j        |||           d S )N)r   )r   submit_submit_resultr   r   r   r   s       r   submit_resultz!_LangSmithTestSuite.submit_result  s,     	d165'RRRRRr   c           	        |rb|r0| j                             |dd dt          |                      d S | j                             |dddt          |                      d S | j                             |dd           d S )Npassz	Skipped: )r   scorecommentr   zError: r   )r   r   )r   create_feedbackreprr   s       r   r   z"_LangSmithTestSuite._submit_result  s      	 ++5U55 ,      ++a9P4;;9P9P ,      K'' (     r   
example_idr   r   outputsrz   c                p    | j                             | j        ||||                                           d S r"   )r   r   _sync_examplecopy)r   r   r   r   rz   s        r   sync_examplez _LangSmithTestSuite.sync_example  s>     	
FGX]]__	
 	
 	
 	
 	
r   c           	        t          |          }t          |          }	 | j                            |          }||j        k    s5||j        k    s*t          |j                  t          | j                  k    r)| j                            |j        |||| j                   nD# t          j
        $ r2 | j                            |||| j        || j        j                  }Y nw xY w|j        r|                     |j                   d S d S )N)r   )r   r   r   rz   
dataset_id)r   r   r   r   rz   
created_at)r   r   read_exampler   r   rN   r   r%   update_examplerG   LangSmithNotFoundErrorcreate_exampler   
start_timemodified_atr   )r   r   r   r   rz   inputs_outputs_examples           r   r   z!_LangSmithTestSuite._sync_example  s4    (//(11	k..*.EEG7>))w..w)**c$'ll::**&z"$%#w +    . 	 	 	k00% 7!+6 1  GGG	  	5 344444	5 	5s   BB% %>C&%C&c                <    | j                             d           d S )NT)r   )r   shutdownr   s    r   r   z_LangSmithTestSuite.wait  s!    T*****r   )r   r*   r   rv   r   ri   r"   )r   r*   r   r   r'   r+   r    r   )r   r   r    r   )r    r   )NF)r   r   r   r+   r   r   r    r   )
r   r   r   r   r   r   rz   r   r    r   )r   r   r   r   __annotations__	threadingRLockr   r   propertyr%   r   r   classmethodr   rX   r   r   r   r   r   r   r   r   r   r   r   r   |  s        !%J%%%%IOE* * * *     X  # # X#     X  
 *.	/ / / / [/" % % X%( ( ( (
! ! ! !
 OTS S S S S OT    .
 
 
 
5 5 5 5>+ + + + +r   c                  B    e Zd ZU ded<   ded<   ded<   ded<   ded	<   d
S )rE   r*   r   r(   r%   r)   r&   r+   r'   r1   N)r   r   r   r   r   r   r   rE   rE     sN         &&&&((((""""r   rE   F)totalsiginspect.Signaturec                    t          | dd           pd}t          | dd           pd}|rd|                                 }| | | S )Nr   rm   __doc__z - )getattrstrip)r   r  rX   rn   s       r   _get_test_reprr	    se    4T**0bD$	4006BK 21K--//11&C&&&&r   r7   %Tuple[_LangSmithTestSuite, uuid.UUID]c          	        |d         pt          j                    }|d         }t          j        |           }t	          j        |g|R i |}i }|r|D ]}	|                    |	d           ||	<   t                              || |	                    d                    }
t          | ||
j                  \  }}|d         p|}|
                    |||t          | |          |d           |
|fS )Nr   r&   r'   r%   )	signaturerX   )rz   )r   r   r?   r  rh_get_inputs_saferF   r   r   rq   r   r%   r   r	  )r   r7   r.   r/   r   r&   r  r   r   kru   r   example_names                r   _ensure_exampler    s'    H%?)=)?)?F /K!$''I&yB4BBB6BBFG - 	- 	-AAt,,GAJJ$..n(():;; J  'tVZ]CCJ%3J-dI>>UU	     z!!r   r3   r4   r   c               *   	
 t           gR i d|i\  
t          j                    	 	
fd}|d         r t          |d                   
j         dz  nd }t          j                    }i |d         pi 
j        j        t                    d}t          j
        di i |d|i5  t          j        |
j        j        g          5   |             d d d            n# 1 swxY w Y   d d d            d S # 1 swxY w Y   d S )	Nr7   c                 (   t          j        t          j                  gR i } t          j        t          dd          | 	j        t          f          5 }	  i }|                    |t          |t                    r|nd|i           n# t          $ rQ}	                    t          |          d           |                    dt          |          i           |d }~wt          $ r+}	                    t          |          	           |d }~ww xY w	 	                    d 	           n7# t          $ r*}t                              d
 d|            Y d }~nd }~ww xY wd d d            d S # 1 swxY w Y   d S Nr   Test)rX   r   reference_example_idr   r{   exceptions_to_handleoutput)r   T)r   r   skipped_reason)r   z%Failed to create feedback for run_id z: r  r  r?   r  tracer  rX   r   end
isinstancer   r   r   rb   rc   warning
func_inputsrun_treeresulter   r   r   r3   r4   ru   s
       r   _testz_run_test.<locals>._test/  sq   )d##
&/
 
 
3>
 
 Xz622!+#"/!1
 
 
 	V y8K88 ">Z-E-E> &/	      !   ((tAww(MMM-tAww7         ((tAww(???V((t(<<<<  V V VTvTTQRTTUUUUUUUUV9	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	Vsm   F9BF
D'#AC//D'<&D""D''F+EF
E7 E2-F2E77FFFr1   .yamlrz   r   r  ignore_hostsr   r  rT   rU   r   r%   r  get_tracing_contextr   rX   rN   tracing_contextrG   with_optional_cacher   api_urlr   r7   r3   r4   r$  
cache_pathcurrent_contextrz   r   r   ru   s   ` ``    @@@r   r=   r=   '  s9    -  ' 8F  J
 Z\\F!V !V !V !V !V !V !V !V !V !VJ '"	^G$%%:=(?(?(??? 
 ,..O:&," %/4$'
OO
 
H 
	 
 

3_
3j(
3
3
 
  #*"3";!<   
 	                                s6   7"DC0$D0C4	4D7C4	8DDDc               :   	
K   t           gR i d|i\  
t          j                    	 	
fd}|d         r t          |d                   
j         dz  nd }t          j                    }i |d         pi 
j        j        t                    d}t          j
        di i |d|i5  t          j        |
j        j        g          5   |             d {V  d d d            n# 1 swxY w Y   d d d            d S # 1 swxY w Y   d S )	Nr7   c                 8  K   t          j        t          j                  gR i } t          j        t          dd          | 	j        t          f          5 }	  i  d {V }|                    |t          |t                    r|nd|i           n# t          $ rQ}	                    t          |          d           |                    dt          |          i           |d }~wt          $ r+}	                    t          |          	           |d }~ww xY w	 	                    d 	           n7# t          $ r*}t                              d
 d|            Y d }~nd }~ww xY wd d d            d S # 1 swxY w Y   d S r  r  r  s
       r   r$  z_arun_test.<locals>._testo  s     )d##
&/
 
 
3>
 
 Xz622!+#"/!1
 
 
 	V #tY>+>>>>>>>> ">Z-E-E> &/	      !   ((tAww(MMM-tAww7         ((tAww(???V((t(<<<<  V V VTvTTQRTTUUUUUUUUV9	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	Vsm   F!?B! F!
D/+AC77D/&D**D//F3E
F
E? E:5F:E??FFFr1   r%  rz   r&  r'  r   r)  r.  s   ` ``    @@@r   r8   r8   g  sI      -  ' 8F  J
 Z\\F!V !V !V !V !V !V !V !V !V !VJ '"	^G$%%:=(?(?(??? 
 ,..O:&," %/4$'
OO
 
H 
	 
 

3_
3j(
3
3
 
  #*"3";!<   
 egg                                s6   9"DC8,D8C<	<D?C<	 DDDrD   )
r%   r(   r&   r)   r   r*   r'   r+   r    r,   )r.   r   r/   r   r    r   )r    rN   )r   r   r    rN   )r   rh   r'   rN   r    ri   )r   rh   ru   ri   r    rv   )r   r   r   r   r   r   r    r   )ru   r   )r   r   r    r   )r   r   r  r  r    rN   )
r   r   r.   r   r7   rE   r/   r   r    r
  )
r   r   r3   r   r7   rE   r4   r   r    r   )D
__future__r   r   r   rA   r?   loggingr   rT   rI   collectionsr   pathlibr   typingr   r   r   r	   r
   r   r   typing_extensionsr   	langsmithr   r   r   r_   r   r  r   r   r   
ls_schemasr   rG   langsmith._internalr   pytestskip	Exceptionr   ImportError	getLoggerr   rc   r   r   r#   rY   rg   rt   r   r   r   r   r   r   r   r   r   rE   r	  r  r=   r8   unitr   r   r   <module>rB     s   " " " " " " "               # # # # # #       N N N N N N N N N N N N N N N N N N ' ' ' ' ' ' ) ) ) ) ) ) # # # # # # ' ' ' ' ' ' % % % % % % + + + + + + ' ' ' ' ' ' ' ' ' ' ' 'MMMK)MM       	      
	8	$	$ GCLLGCLL 
   

 
 #+/)-%)) ) ) ) ) 
)Q Q Q Qn   R R R R
 
 
 
A A A A.  K 8 899 9 9 9 9X X X X$     WT$(((   + + + + + + + +D    y    ' ' ' '" " " "2= = = =@= = = =B s   7B BB