
    h                        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mZ d dlmZm	Z	m
Z
mZ d dlZd dlmZmZmZmZmZmZ d dlZd dlm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'm(Z(m)Z)m*Z*  e       Z+e+jY                  ddg ee#      g      defd       Z-e+jY                  ddg ee#      g       ee#       ej\                  d      fde dee	d   e/f   fd       Z0de1fdZ2d Z3	 dOde/de4de4de5de
e/   d e
e/   fd!Z6	 dOd"Z7e+jY                  d#dg ee#      g       ee#       ej\                  dd$       ej\                  dd%      fde d&e
e/   d e
e/   fd'       Z8e+jY                  d(dg ee#      g       ee#       ej\                  dd)       ej\                  dd*       ej\                  d+d,d-d./       ej\                  d d0d 1      fde d&e
e/   d2e
e/   d3e9d4e9f
d5       Z:e+jY                  d6dg ee#      g       ee#      fde fd7       Z;d8 ejx                         d9a=d: Z>e+jY                  d;dg ee#      g      e+jY                  d<dg ee#      g      d=               Z?d> Z@e+jY                  d?dg ee#      g      d@        ZAe+jY                  dAdgB      e+jY                  dCdgB      dD               ZBe+j                  d?dg ee#      g      dE        ZDe+j                  dAdgB      e+j                  dCdgB      dF               ZEe+j                  dGdg ee#      g       ej                  dHdI       ej                  ddJ       ee#      fdedKe
e	dL      dMede fdN       ZHy)P    N)datetime	timedelta)DictLiteralOptionalUnion)	APIRouterDependsHTTPExceptionRequestResponsestatus)verbose_proxy_logger)HEALTH_CHECK_TIMEOUT_SECONDS)AsyncHTTPHandler)	AlertTypeCallInfoLitellm_EntityTypeProxyErrorTypesProxyExceptionUserAPIKeyAuthWebhookEvent)user_api_key_auth)PrismaDBExceptionHandler)_clean_endpoint_data'_update_litellm_params_for_health_checkperform_health_checkrun_with_timeoutz/testhealth)tagsdependenciesrequestc                 :   K   d| j                   j                  iS w)a  
    [DEPRECATED] use `/health/liveliness` instead.

    A test endpoint that pings the proxy server to check if it's healthy.

    Parameters:
        request (Request): The incoming request.

    Returns:
        dict: A dictionary containing the route of the request URL.
    route)urlpath)r"   s    l/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/health_endpoints/_health_endpoints.pytest_endpointr(   '   s     $ W[[%%&&s   z/health/serviceszSpecify the service being hit.)descriptionuser_api_key_dictservice)	slack_budget_alertslangfuseslack	openmeterwebhookemail
braintrustdatadoggeneric_apic                 
  K   	 ddl m}m}m} |t	        dddi      |dvrt	        ddd	| d
dg i      |dk(  s!|dk(  s|dk(  s|t
        j                  v r>|dk7  r9t        j                  ddddgdd       d{   }ddj                  |      dS |dk(  r<ddl	m
}  |       }|j                          d{   }|d   |d   dk(  r|d   dS ddS |dk(  rIdd lm}	  |	       }
|
j                  j                          t        j                   ddddgdd      }dd!dS |d"k(  rgt#        | j$                  xs d#d$d| j&                  | j(                  | j*                  t,        j.                  %      }|j1                  d&|'       d{    |d(k(  s|dk(  rd(|j3                  d)g       v r|j4                  j6                  	 |j4                  j6                  D ]  }|j4                  j8                  	 ||j4                  j8                  vr3d*}|t:        j<                  k(  rd+}n|t:        j>                  k(  rd,}np|t:        j@                  k(  rd-}nZ|t:        j0                  k(  rd.}nD|t:        jB                  k(  rd/}n.|t:        jD                  k(  rd0}n|t:        jF                  k(  rd1}nd.}|jI                  |d2|3       d{     n*|jI                  d4d2t:        j0                  3       d{    |ZtK        jL                  |j4                  jO                                tK        jL                  |j4                  jQ                                |j4                  j8                  xs g }tS        |      }d|d5d6S t	        d7dd8j                  |      i      |d9k(  rtU        d:t,        j.                  d;| j$                  xs d#d<dd| j&                  tW        jX                  d=      | j*                  >
      }|j4                  j[                  |?       d{    dd@dS y7 7 m7 7 g7 =7 # t\        $ r}t_        j`                  dAj                  tc        |                   t_        jd                  tg        jh                                tk        |t              rYtm        to        |dBdCtc        |       dD      tp        jr                  to        |dEdF      to        |dGtt        jv                        H      tk        |tl              r|tm        dItc        |      z   tp        jr                  to        |dEdF      tt        jv                  H      d}~ww xY ww)Jz
    Use this admin-only endpoint to check if the service is healthy.

    Example:
    ```
    curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog'     -H 'Authorization: Bearer sk-1234'
    ```
    r   )general_settingsprisma_clientproxy_logging_objNi  errorzService must be specified.status_codedetail)r,   r1   r-   r.   r/   r0   r2   otelcustom_callback_api	langsmithr3   r4   z!Service must be in list. Service=z. List=r,   r/   r2   r4   r-   z"openai/litellm-mock-response-modeluserzHey, how's it going?)rolecontentzlitellm:/health/serviceszThis is a mock response)modelmessagesr@   mock_responsesuccessz!Mock LLM request made - check {}.)r   messager3   )DataDogLoggerr   	unhealthyerror_messagezDatadog is healthy)LangFuseLoggerz'Mock LLM request made - check langfuse.r0       )tokenspend
max_budgetuser_id	key_aliasteam_idevent_groupuser_budget)type	user_infor.   alertingzdefault test messagezLLM Exception test alertzLLM Too Slow test alertzLLM Requests Hanging test alertzBudget Alert test alertzDB Exception test alertz!Outage Alert Exception test alertzDaily Reports test alertLow)rG   level
alert_typez"This is a test slack alert messagezBMock Slack Alert sent, verify Slack Alert Received on your channel)r   alert_typesrG   i  z@"{}" not in proxy config: general_settings. Unable to test this.r1   key_createdzTest Email AlertzNEmail Test key (This is only a test alert key. DO NOT USE THIS IN PRODUCTION.)TEST_EMAIL_ADDRESS)
eventrT   event_messagerN   rR   rO   rP   rQ   
user_emailrS   )webhook_eventz2Mock Email Alert sent, verify Email Alert ReceivedzMlitellm.proxy.proxy_server.health_services_endpoint(): Exception occured - {}r<   zAuthentication Error()paramNoner;   )rG   rV   rd   codezAuthentication Error, )<litellm.proxy.proxy_serverr6   r7   r8   r   litellmsuccess_callbackacompletionformat$litellm.integrations.datadog.datadogrH   async_health_check&litellm.integrations.langfuse.langfuserK   Langfuse
auth_check
completionr   rN   rQ   rR   rS   r   KEYbudget_alertsgetslack_alerting_instancealert_to_webhook_urlr\   r   llm_exceptionsllm_too_slowllm_requests_hangingdb_exceptionsoutage_alertsdaily_reportsalerting_handlerasynciocreate_tasksend_monthly_spend_reportsend_weekly_spend_reportlistr   osgetenv&send_key_created_or_user_invited_email	Exceptionr   r9   strdebug	traceback
format_exc
isinstancer   getattrr   
auth_errorr   HTTP_500_INTERNAL_SERVER_ERROR)r*   r+   r6   r7   r8   _rH   datadog_loggerresponserK   langfuse_loggerrW   r[   test_messager\   rb   es                    r'   health_services_endpointr   <   s    >T
	
 	
 ?2N(O   
 
  @	RgQhPij  {",&-'7333:8M)):#)6LMN/7	 A $>EEgN  	!J*_N+>>@@H"8,  )[8 _- 
 .  
"M,.O$$//1"":#)6LMN/7	A $D 
 i '--3)11+55)11.22I $11"# 2   
 g,A!A*..z2>> &==RR 
 +BBWW # .EEQQ#'( *#4#L#L#X#X!Y %'=%)A)AA+EL'9+A+AA+DL'9+I+II+LL'9+B+BB+DL'9+B+BB+DL'9+B+BB+NL'9+B+BB+EL+DL/@@$0* A   9 X@ ,<< D##,#:#: =    !,'')AA[[] '')AAZZ\
 &==IIOR  #;/'#.c  $ #!c!j!j#"  g(#.220'--3j)1199%9:)11M $;;bb+ c   
 $O ' A AFV^  
""[bbA	

 	""9#7#7#9:a' 8/DSVHA-NO$//a&1Qv/T/TU	  >*G,s1v5 ++!Wf-66	
 	
!
s   UA;P8 ?P' P8 U%P8 =P*>P8 UP8 UAP8 &U'A'P8 P-D:P8 	P0
,P8 6P37B
P8 UBP8 P6P8 %U'P8 *P8 -P8 0P8 3P8 6P8 8
UDUUUreturnc                    | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  r| j                  j                         nd| j                  r| j                  j                         dS ddS )z9Convert health check database record to dictionary formatN)health_check_id
model_namemodel_idr   healthy_countunhealthy_countrJ   response_time_msdetails
checked_by
checked_at
created_at)r   r   r   r   r   r   rJ   r   r   r   r   	isoformatr   )checks    r'   _convert_health_check_to_dictr   2  s     !00&&NN,,,, 00,,!22==&&6;6F6Fe&&002D6;6F6Fe&&002  MQ     c                  P    ddl m}  | t        t        j                  ddi      | S )zIHelper to check if prisma_client is available and raise appropriate errorr   r7   r9   zDatabase not initializedr:   )rg   r7   r   r   r   r   s    r'   _check_prisma_clientr   D  s2    8==78
 	
 r   r   healthy_endpointsunhealthy_endpoints
start_timerQ   r   c                 l  K   	 |r(|d   j                  d      rt        |d   d         dd nd}| j                  |||rdndt        |      t        |      |t	        j                         |z
  dz  d|	       d{    y7 # t
        $ r%}t        j                  d	| d
|        Y d}~yd}~ww xY ww)z8Helper function to save health check results to databaser   r9   Ni  healthyrI     )	r   r   r   r   r   rJ   r   r   r   z2Failed to save health check to database for model : )rt   r   save_health_check_resultlentimer   r   warning)	r7   r   r   r   r   rQ   r   rJ   db_errors	            r'   _save_health_check_to_dbr   P  s     t #':1'='A'A''J #A&w/0#6 	 44! 19{/0 34'"iikJ6$> 5 

 
	
 
	
  t$$'YZdYeeghpgq%rsstsA   B4A7B ;B<B  B4B 	B1B,'B4,B11B4c                    K   t        | |||       d{   \  }}	|-||n|}
|
%t        j                  t        ||
||	|||             ||	t	        |      t	        |	      dS 7 Ow)zDHelper function to perform health check and save results to database)
model_list	cli_modelrC   r   Nr   )r   r   r   r   )r   r~   r   r   r   )r   target_modelr   r   r7   r   rQ   r   r   r   model_name_for_dbs              r'   _perform_health_check_and_saver   r  s      4H	4 .**  )2)>IL( 8!!#!!  /2./23	 -.s   A'A%AA'z/healthz!Specify the model name (optional)zSpecify the model ID (optional)rC   c           
        K   ddl m}m}m}m}m}m}m}	 ddl}
 |
j                         }|}|ri|sg|D	 |j                  |      }||j                  }n!t        t        j                  dd| di      n!t        t        j                  dd| di      	 |D|%t#        g d|||	|| j$                  d       d{   S t        t        j&                  ddi      t)        j*                  |      }t-        | j.                        dkD  rn	 |r|S t#        ||d||	|| j$                  |       d{   S # t        $ rA}t        j                   d	| d
|        t        t        j                  dd| di      d}~ww xY w7 7 S# t        $ r[}t        j                   dj1                  t3        |                   t        j4                  t7        j8                                |d}~ww xY ww)u  
    🚨 USE `/health/liveliness` to health check the proxy 🚨

    See more 👉 https://docs.litellm.ai/docs/proxy/health


    Check the health of all the endpoints in config.yaml

    To run health checks in the background, add this to config.yaml:
    ```
    general_settings:
        # ... other settings
        background_health_checks: True
    ```
    else, the health checks will be run on models when /health is called.
    r   )health_check_detailshealth_check_resultsllm_model_list
llm_routeruse_background_health_checks
user_modelr7   Nr   r9   zModel with ID z
 not foundr:   z&Error getting deployment for model_id r   )r   r   r   r   r7   r   rQ   r   zModel list not initializedzHlitellm.proxy.proxy_server.py::health_endpoint(): Exception occured - {})rg   r   r   r   r   r   r   r7   r   get_deploymentr   r   r   HTTP_404_NOT_FOUNDr   r   r9   r   rQ   r   copydeepcopyr   modelsrk   r   r   r   r   )r*   rC   r   r   r   r   r   r   r   r7   r   r   r   
deploymentr   _llm_model_lists                   r'   health_endpointr     s4    4   J L!'666I
)#-#8#8L'$*$=$= '>(:)NO  !  "55>(:!FG 
,!%;!!%(0"/)-55!	 	 	  "AA!=>  --7 ''(1,'''7*),+%)11!	 	 	O  $**-ST\S]]_`a_b+cd# & 9 9#~hZz%JK  	.	  ""V]]A	

 	""9#7#7#9:s   0G.AD6 5"G.$F <F=F  G.AF G. F 1F2F 5G.6	F ?<E;;F  G.F F 	G+AG&&G++G.z/health/historyzFilter by specific model namez$Filter by status (healthy/unhealthy)d   zNumber of records to returnrM   r   )r)   gelezNumber of records to skip)r)   r   status_filterlimitoffsetc           	      \  K   t               }	 |j                  ||||       d{   }|D cg c]  }t        |       }}|t        |      ||dS 7 ,c c}w # t        $ rF}	t        j                  d|	        t        t        j                  ddt        |	       i      d}	~	ww xY ww)zt
    Get health check history for models
    
    Returns historical health check data with optional filtering.
    )r   r   r   r   N)health_checkstotal_recordsr   r   z$Error getting health check history: r9   z)Failed to retrieve health check history: r:   )r   get_health_check_historyr   r   r   r   r9   r   r   r   r   )
r*   rC   r   r   r   r7   historyr   history_datar   s
             r'   health_check_history_endpointr     s     * )*M
%>>'	 ? 
 
 KRR5e<RR * .	
 	

 S  
""%I!#MN==HQQR
 	

sJ   B,A AA AA B,A A 	B)#AB$$B))B,z/health/latestc           	        K   t               }	 |j                          d{   }|D ci c]0  }|j                  r|j                  n|j                  t	        |      2 }}|t        |      dS 7 Mc c}w # t        $ rF}t        j                  d|        t        t        j                  ddt        |       i      d}~ww xY ww)z
    Get the latest health check status for all models
    
    Returns the most recent health check result for each model.
    N)latest_health_checkstotal_modelsz$Error getting latest health checks: r9   z)Failed to retrieve latest health checks: r:   )r   get_all_latest_health_checksr   r   r   r   r   r   r9   r   r   r   r   )r*   r7   latest_checksr   checks_datar   s         r'   latest_health_checks_endpointr   ;  s      )*M
+HHJJ
 '
  %~~U^^53C3CFcdiFjj
 
 %0,
 	
 K
  
""%I!#MN==HQQR
 	

sJ   CA6 A/A6 5A1A6 .C/A6 1A6 6	C?AC  CCunknownr   last_updatedc                    K   ddl m}  	 t        j                         t        d   z
  }t        d   dk7  r|t        d      k  rt        S | dt        j                         d	at        S | j                          d {    d
t        j                         d	at        S 7 !# t        $ r%}t        j                  |       t        cY d }~S d }~ww xY ww)Nr   r   r   r   r      )minutesdisconnectedr   	connected)
rg   r7   r   nowdb_health_cacher   health_checkr   r   handle_db_exception)r7   	time_diffr   s      r'   _db_health_readiness_checkr   ^  s     8
LLN_^%DD	8$	1i)TUBV6V"" )7XO""((***%0(,,.Q 	+   44Q7s^   C>B C	B 'C(B ;B< B CB 	C(CCCCCz	/settingsz/active/callbacksc                  r  K   ddl m} m} t        | j	                  d            }t
        j                  D cg c]  }t        |       }}t
        j                  D cg c]  }t        |       }}t
        j                  D cg c]  }t        |       }}t
        j                  D cg c]  }t        |       }}t
        j                  D cg c]  }t        |       }}t
        j                  D cg c]  }t        |       }	}t
        j                  D cg c]  }t        |       }
}||z   |z   |z   |z   |	z   |
z   }|j                  }d}|rt        |t              rt!        |      }|||||||	|
|t!        |      |t
        j"                  dS c c}w c c}w c c}w c c}w c c}w c c}w c c}w w)au  
    Returns a list of litellm level settings

    This is useful for debugging and ensuring the proxy server is configured correctly.

    Response schema:
    ```
    {
        "alerting": _alerting,
        "litellm.callbacks": litellm_callbacks,
        "litellm.input_callback": litellm_input_callbacks,
        "litellm.failure_callback": litellm_failure_callbacks,
        "litellm.success_callback": litellm_success_callbacks,
        "litellm._async_success_callback": litellm_async_success_callbacks,
        "litellm._async_failure_callback": litellm_async_failure_callbacks,
        "litellm._async_input_callback": litellm_async_input_callbacks,
        "all_litellm_callbacks": all_litellm_callbacks,
        "num_callbacks": len(all_litellm_callbacks),
        "num_alerting": _num_alerting,
        "litellm.request_timeout": litellm.request_timeout,
    }
    ```
    r   )r6   r8   rX   )rX   zlitellm.callbackszlitellm.input_callbackzlitellm.failure_callbackzlitellm.success_callbackzlitellm._async_success_callbackzlitellm._async_failure_callbackzlitellm._async_input_callbackall_litellm_callbacksnum_callbacksnum_alertingzlitellm.request_timeout)rg   r6   r8   r   rt   rh   	callbacksinput_callbackfailure_callbackri   _async_success_callback_async_failure_callback_async_input_callbackrX   r   r   r   request_timeout)r6   r8   	_alertingxlitellm_callbackslitellm_input_callbackslitellm_failure_callbackslitellm_success_callbackslitellm_async_success_callbackslitellm_async_failure_callbackslitellm_async_input_callbacksr   rX   _num_alertings                 r'   active_callbacksr  v  s    F O$((45I *1):):;AQ;;/6/E/EF!s1vFF181I1I JAQ J J181I1I JAQ J J7>7V7V&W!s1v&W#&W7>7V7V&W!s1v&W#&W5<5R5R$SSV$S!$S 	
!	"
#	$ $	$ *		*
 *	* (	(  !))HMJx.H ."9$=$=+J+J)F!623%#*#:#: / <F J J&W&W$SsY   5F7F	F7F/F7FF7)F#;F7F(!F75F-F7F2-B
F7c                     t        | t              r| S 	 | j                  S # t        $ r6 	 | j                  j                  cY S # t        $ r t        |       cY cY S w xY ww xY wN)r   r   __name__AttributeError	__class__)callbacks    r'   callback_namer
    sa    (C !    !	!%%... 	!x= 	!!s+     	AAAAAAAz/health/readinessc                    K   ddl m} m} 	 g }	 t        j                  D cg c]  }t        |       }}d}t        j                  zddlm	} t        j                  j                  }t        t        j                  j                  |      r6	 t        j                  j                  j                          d{   }||d}| /t                d{   }dd|||t!        j"                         d	|S dd
|||t!        j"                         d	S c c}w # t        $ r t        j                  }Y w xY w7 y# t        $ r}dt        |      z   }Y d}~d}~ww xY w7 # t        $ r}t%        ddt        |       d      d}~ww xY ww)zJ
    Unprotected endpoint for checking if worker can receive requests
    r   )r7   versionN)RedisSemanticCachezindex does not exist - error: )rV   
index_infor   r   )r   dbcachelitellm_versionsuccess_callbacksuse_aiohttp_transportzNot connectedi  zService Unhealthy (rc   r:   )rg   r7   r  rh   ri   r
  r  r  litellm.caching.cachingr  rV   r   _index_infor   r   r   r   _should_use_aiohttp_transportr   )	r7   r  success_callback_namesr   
cache_typer  r  r   db_health_statuss	            r'   health_readinessr    s     B4U!#	> +2*B*B&%&a &" & 
==$B ++J'----/ABK'.}}':':'F'F'H!HJ '1
K
 $%?%AA#!##*%;)9)W)W)Y #  $%##*%;)9)W)W)Y I&  	>%,%=%="	> "I  K!ACF!JJK  B&  U6I#a&QR4STTUs   	FE D DD AE +D3 7D18D3 <E E E 1F2E FD D.+E -D..E 1D3 3	E<E
E EE 	F"E<<FFz/health/liveliness)r    z/health/livenessc                     K   yw)z>
    Unprotected endpoint for checking if worker is alive
    z
I'm alive! r  r   r'   health_livelinessr    s      s   c                  0   K   dddd} t        | d      S w)z6
    Options endpoint for health/readiness check.
    GET, OPTIONS*AllowzAccess-Control-Allow-MethodszAccess-Control-Allow-Headers   headersr;   r   response_headerss    r'   health_readiness_optionsr)  #  s)       (6(+
 ,#>>   c                  0   K   dddd} t        | d      S w)z7
    Options endpoint for health/liveliness check.
    r  r   r!  r#  r$  r&  r'  s    r'   health_liveliness_optionsr,  4  s)       (6(+
 ,#>>r*  z/health/test_connectionchatzThe mode to test the model withzIParameters for litellm.completion, litellm.embedding for the health checkmode)	r-  rq   	embeddingaudio_speechaudio_transcriptionimage_generationbatchrerankrealtimelitellm_paramsc           	        K   	 t        i |      }|xs |j                  dd      }t        t        j                  ||ddg      t
               d{   }t        i ||d      }d|v rdnd	|d
S 7  # t        $ rv}t        j                  dt        |              t        j                  t        j                                t        t        j                   ddt        |       i      d}~ww xY ww)a  
    Test a direct connection to a specific model.
    
    This endpoint allows you to verify if your proxy can successfully connect to a specific model.
    It's useful for troubleshooting model connectivity issues without going through the full proxy routing.
    
    Example:
    ```bash
    curl -X POST 'http://localhost:4000/health/test_connection' \
      -H 'Authorization: Bearer sk-1234' \
      -H 'Content-Type: application/json' \
      -d '{
        "litellm_params": {
            "model": "gpt-4",
            "custom_llm_provider": "azure_ai",
            "litellm_credential_name": null,
            "api_key": "6xxxxxxx",
            "api_base": "https://litellm8397336933.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-10-21",
        },
        "mode": "chat"
      }'
    ```
    
    Returns:
        dict: A dictionary containing the health check result with either success information or error details.
    )
model_infor6  r.  Nztest from litellm)model_paramsr.  promptinputT)r   r9   rF   )r   resultzMlitellm.proxy.health_endpoints.test_model_connection(): Exception occurred - zFailed to test connection: r:   )r   popr   rh   ahealth_checkr   r   r   r   r9   r   r   r   r   r   r   r   )r"   r.  r6  r*   r<  cleaned_resultr   s          r'   test_model_connectionr@  H  s    h#
@)
 7~))&$7'!!+**+	 )
 
 .(~(($

 ")F!2g	$
 	

(  
""[\_`a\b[cd	
 	""9#7#7#9:==:3q6(CD
 	

s<   C7AA5 A3A5 2C73A5 5	C4>A1C//C44C7r  )Ir~   r   r   r   r   r   r   typingr   r   r   r   fastapir	   r
   r   r   r   r   rh   litellm._loggingr   litellm.constantsr   &litellm.llms.custom_httpx.http_handlerr   litellm.proxy._typesr   r   r   r   r   r   r   $litellm.proxy.auth.user_api_key_authr   "litellm.proxy.db.exception_handlerr   litellm.proxy.health_checkr   r   r   r   routerrt   r(   Queryr   r   dictr   r   r   floatr   r   r   intr   r   r   r   r   r  r
  r  r  optionsr)  r,  postBodyr@  r  r   r'   <module>rR     sN     	   ( 1 1  P P  1 : C   C G  
 
+,-  
' '
'  
+,-   )00A(B 	"BCn
%n

	
 		n

n
bD $	& #tt t 	t
 t c]t smtT &R IXJg>O6P5QR(/0A(B(7=== ,gmm;l%lC=l
 sml Sl^ XJgFW>X=YZ(/0A(B(7==9 $17==@$ 61  '--	2q,
%,
C=,

 C=,
 ,
 ,
 [,
^ H:WEV=W<XY(/0A(B
%
 Z
> 'G0 
+,-  
 
+,-  
BBJ
! 
+,-  
:U
:Uz 
   
  		 
+,-  
	?
	? 
   
  	?			? 
+,-  & 	V)JK'7<<_ )00A(B'R
R


	
R
 R
& &'R

R
r   