
    yj8c                        d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZ d dl	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  ej        e          Z ed
          Zdddededee         de deg ee         f         de!defdZ"dedede de de#ded         de$dz  de!ddfdZ% G d de          Z& G d d          Z'ded ee          d!e d"ej(        dee)ee f                  f
d#Z* G d$ d%          Z+ e+            Z,dS )&    N)defaultdict)	AwaitableCallable)AnyLiteral
NamedTupleTypeVar)genai)types)AsyncOpenAI   )EmbeddingModelConfigresolve_embedding_model_configsettings_TT)is_final_attemptprovidermodeltextsinput_tokens_estimatefnr   returnc                   K   t          j                    }d}	  |             d{V 	 |d}nt          |t          j                  rd}nd}t          | |t          |          |t          j                    |z
  dz  |||           S # t          $ r}	|	} d}	~	ww xY w# |d}nt          |t          j                  rd}nd}t          | |t          |          |t          j                    |z
  dz  |||           w xY w)u  time a single embedding-provider call, emit
    `embedding.call.completed` on both success and exception, and return the
    call's result. Errors propagate unchanged — telemetry never bleeds into
    the caller's control flow.

    Caller-supplied `texts` is used only for `input_count`; we don't keep the
    list around for the event to avoid leaking content into telemetry.

    `is_final_attempt` defaults to True so one-shot callers (`embed`,
    `simple_batch_embed`) get correct semantics without changes. Retry-loop
    callers (`_process_batch`) pass the real attempt index so dashboards
    can distinguish exhausted retries from mid-retry failures.
    Nsuccess	cancellederrori  )r   r   input_countr   duration_msoutcomer   r   )timeperf_counter
isinstanceasyncioCancelledError_publish_embedding_eventlenBaseException)
r   r   r   r   r   r   startr   r   excs
             </DATA/AppData/hermes/projects/honcho/src/embedding_client.py_emit_embedding_callr+      s]     , E"&E
RTTzzzzzz
 =@IGGw566 	!GGG E

"7*,,u4<-		
 		
 		
 		
 		
     =@IGGw566 	!GGG E

"7*,,u4<-		
 		
 		
 		
 		
s$   B	 	
BBBB A!C?r   r   r   )r   r   r   r   c                    	 ddl m}m}	m}
 ddlm}m}m}m}  |            }d}|r8	  |	|          }n+# t          $ r t                              d|           Y nw xY w |
 | |            | |            | |||||||t          |          j        nd |                                 dS # t          $ r  t                              dd	           Y dS w xY w)
z<Build and emit the EmbeddingCallCompletedEvent. Best-effort.r   )EmbeddingCallCompletedEventEmbeddingCallPurposeemit)get_embedding_call_purposeget_embedding_parent_categoryget_embedding_run_idget_embedding_workspace_nameNz3Unknown embedding_call_purpose=%r; emitting without)workspace_namecall_purposeparent_categoryr   r   r   r   r   r   r   error_classrun_idz*Failed to emit EmbeddingCallCompletedEventT)exc_info)src.telemetry.eventsr-   r.   r/   src.utils.typesr0   r1   r2   r3   
ValueErrorloggerdebugtype__name__	Exception)r   r   r   r   r   r   r   r   r-   r.   r/   r0   r1   r2   r3   purpose_slugr5   s                    r*   r%   r%   E   s   ,R	
 	
 	
 	
 	
 	
 	
 	
 	
 	

	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 213348 	33LAA   I      	'';;==) = = ? ?!'&;'!1494EDKK004++--  	
 	
 	
 	
 	
   R R RADQQQQQQRs2   $B. 3 B. %AB. AAB. .&CCc                   <    e Zd ZU dZeed<   eed<   eed<   eed<   dS )	BatchItemz+A single item in a batch with its metadata.texttext_idchunk_indextoken_countN)r@   
__module____qualname____doc__str__annotations__int     r*   rD   rD      sB         55
IIILLLrP   rD   c                   j   e Zd ZdZdededededef
dZede	fd	            Z
d
ee         dee         fdZde	dee         fdZdee	         deee                  fdZdee	e	f         dee	eee                  f         fdZdee	e	f         dee	eee	ef                  f         fdZdee	eee	ef                  f         deee                  fdZ	 ddee         dedee	eeee         f         f         fdZdeee	eeee         f         f                  dee	eee                  f         fdZdS )_EmbeddingClientz[
    Embedding client supporting OpenAI and Gemini with chunking and batching support.
    configvector_dimensionsmax_input_tokensmax_tokens_per_requestsend_dimensionsc                |   |j         | _         |j        | _        || _        || _        | j         dk    rv|j        st          d          |j        rt          j        |j                  nd }t          j
        |j        |          | _        t          |d          | _        d| _        nD|j        st          d          t          |j        |j                  | _        || _        d| _        	 t!          j        | j                  | _        n)# t&          $ r t!          j        d	          | _        Y nw xY w|| _        d S )
NgeminizGemini API key is required)base_url)api_keyhttp_optionsi   d   zOpenAI API key is required)r[   rZ   cl100k_base)	transportr   rT   rW   r[   r<   rZ   genai_typesHttpOptionsr
   Clientclientminmax_embedding_tokensmax_batch_sizer   tiktokenencoding_for_modelencodingKeyErrorget_encoding max_embedding_tokens_per_request)selfrS   rT   rU   rV   rW   r\   s          r*   __init__z_EmbeddingClient.__init__   sb    %. ,
&7%4>X%%> ? !=>>> ?'AAAA 
 7<l)7 7 7DK
 .11A4-H-HD%'*D> ? !=>>>%  DK )9D%"&D	A/7/J4:/V/VDMM 	A 	A 	A$1-@@DMMM	A5K---s   -D #D21D2r   c                     | j         S N)r_   rm   s    r*   r   z_EmbeddingClient.provider   s
    ~rP   	embeddingc           	          t          |          | j        k    r<t          d| j         d| j         dd| j         dt          |           dz             |S )Nz!Embedding dimension mismatch for :z. z	Expected z, got .)r&   rT   r<   r_   r   )rm   rr   s     r*   _validate_embedding_dimensionsz/_EmbeddingClient._validate_embedding_dimensions   so    y>>T333SDNSSTZSSSMd4MMC	NNMMMN   rP   queryc                    K   t           j                                                }| j        k    rt	          d j         d| d          t           j        t          j                  rF j        dt          t                   f fd}t           j         j        g||           d {V S  j        dt          t                   f fd}t           j         j        g||           d {V S )Nz%Query exceeds maximum token limit of z tokens (got z tokens)r   c                  
  K   j         j                            j        dj        i           d {V } | j        r| j        d         j        st          d                              | j        d         j                  S )Noutput_dimensionalityr   contentsrS   r   z%No embedding returned from Gemini API)	aiomodelsembed_contentr   rT   
embeddingsvaluesr<   rv   )responsegemini_clientrw   rm   s    r*   _call_geminiz,_EmbeddingClient.embed.<locals>._call_gemini   s      !.!2!9!G!G*"3T5KL "H " "      
  * N(2Ea2H2O N$%LMMM::'*1  rP   r   r   r   r   r   c                     K   j         gd} j        r
j        | d<    j        j        di |  d {V }                    |j        d         j                  S )Nr   input
dimensionsr   rO   )r   rW   rT   r   createrv   datarr   )openai_kwargsr   openai_clientrw   rm   s     r*   _call_openaiz,_EmbeddingClient.embed.<locals>._call_openai   s|      6:jE7,S,SM# E.2.Dl+<]5<MM}MMMMMMMMH66x}Q7G7QRRRrP   )r&   ri   encodere   r<   r"   rc   r
   rb   listfloatr+   r_   r   )rm   rw   rH   r   r   r   r   s   ``   @@r*   embedz_EmbeddingClient.embed   s     $-..u5566222u8Quu`kuuu   dk5<00 	 KM
U 
 
 
 
 
 
 
 
 .jg&1          	SDK 	S 	S 	S 	S 	S 	S 	S 	S *^*'"-
 
 
 
 
 
 
 
 
 	
rP   r   c                 6   K   g }t          dt          |           j                  D ]}||| j        z            }|fdt          t                   dt          t          t
                            f fd}	 t           fd|D                       }t           j         j	        |||           d{V }|
                    |           # t          $ rB}dt	          |                                          v rt          d	 j         d
          | d}~ww xY w|S )a#  
        Simple batch embedding for a list of text strings.

        Args:
            texts: List of text strings to embed

        Returns:
            List of embedding vectors corresponding to input texts

        Raises:
            ValueError: If any text exceeds token limits
        r   batchr   c                   K   g }t          j        t          j                  rj        j        j                            j        | dj        i           d{V }|j	        r>|j	        D ]6}|j
        r-|                                        |j
                             7n^| j        d}j        r
j        |d<    j        j	        j        di | d{V }|                    fd|j        D                        |S )zOne provider call for one batch. Lifted into a closure so
                _emit_embedding_call can time + emit + propagate errors.rz   r{   N)r   r   r   c                 D    g | ]}                     |j                  S rO   )rv   rr   ).0r   rm   s     r*   
<listcomp>zM_EmbeddingClient.simple_batch_embed.<locals>._embed_batch.<locals>.<listcomp>'  s9        $ !??OO  rP   rO   )r"   rc   r
   rb   r}   r~   r   r   rT   r   r   appendrv   rW   r   extendr   )r   batch_embeddingsr   embr   rm   s        r*   _embed_batchz9_EmbeddingClient.simple_batch_embed.<locals>._embed_batch  sv      79 dk5<88 %)[_%;%I%I"j!& 79OP &J & &            H
  * "#+#6 " "C"z " 0 7 7$($G$G
$S$S!" !" !"
 "'!%5 5M + M6:6Ll3%BT[%;%B%S%S]%S%SSSSSSSH$++   (0     ('rP   c              3   f   K   | ]+}t          j                            |                    V  ,d S rp   )r&   ri   r   )r   trm   s     r*   	<genexpr>z6_EmbeddingClient.simple_batch_embed.<locals>.<genexpr>1  s;      %R%Rqc$-*>*>q*A*A&B&B%R%R%R%R%R%RrP   r   Ntokenz,Text content exceeds maximum token limit of ru   )ranger&   rf   r   rL   r   sumr+   r_   r   r   rA   lowerr<   re   )	rm   r   r   ir   r   tokens_estimater   es	   `        r*   simple_batch_embedz#_EmbeddingClient.simple_batch_embed   s      )+
q#e**d&9:: 6	 6	A!a$"5556E6; ( ($s) (T%[@Q ( ( ( ( ( (B #&%R%R%R%RE%R%R%R"R"R)=!^**9#* * * $ $ $ $ $ $  !!"23333   c!ffllnn,,$ctG`ccc   s   5AC


D=DDid_resource_dictc                     K   |si S                       |          }                     |          }t          j         fd|D               d{V }                     |          S )z
        Embed multiple texts, chunking long ones and batching API calls.

        Args:
            id_resource_dict: Maps text IDs to text content

        Returns:
            Maps text IDs to lists of embedding vectors (one per chunk)
        c                 :    g | ]}                     |          S rO   )_process_batch)r   r   rm   s     r*   r   z0_EmbeddingClient.batch_embed.<locals>.<listcomp>[  s'    >>>Ud!!%((>>>rP   N)_prepare_chunks_create_batchesr#   gather_accumulate_embeddings)rm   r   text_chunksbatchesbatch_resultss   `    r*   batch_embedz_EmbeddingClient.batch_embedD  s         	I **+;<< &&{33 &n>>>>g>>>
 
 
 
 
 
 

 **=999rP   c                    i }|                                 D ]l\  }}| j                            |          }t          |          | j        k    r t          ||| j        | j                  ||<   W|t          |          fg||<   m|S )a}  
        Chunk texts that exceed token limits.

        Args:
            id_resource_dict: Maps text IDs to text content. We tokenize with
                the embedding client's own encoding so token IDs match the
                decoder vocabulary used by the target embedding API.

        Returns:
            Maps text IDs to lists of (chunk_text, token_count) tuples
        )itemsri   r   r&   re   _chunk_text_with_tokens)rm   r   outrF   rE   tokenss         r*   r   z _EmbeddingClient._prepare_chunksa  s     13-3355 	5 	5MGT]))$//F6{{T6666&$";T]   G "&s6{{ 34G
rP   r   c           
         g }g }d}|                                 D ]\  }}t          |          D ]w\  }\  }}	||	z   | j        k    }
t          |          | j        k    }|r|
s|r|                    |           g }d}|                    t          ||||	                     ||	z  }x|r|                    |           |S )z
        Group chunks into batches that fit API limits.

        Args:
            text_chunks: Maps text IDs to lists of (chunk_text, token_count) tuples

        Returns:
            List of batches, each containing BatchItem objects
        r   )r   	enumeraterl   r&   rf   r   rD   )rm   r   r   current_batchcurrent_tokensrF   chunks	chunk_idx
chunk_textchunk_tokenswould_exceed_tokenswould_exceed_counts               r*   r   z _EmbeddingClient._create_batchesz  s    *,)+*0022 	/ 	/OGV9B69J9J / /5	5J #\1;< $ &)%7%74;N%N"  '&9 '=O 'NN=111$&M%&N$$j'9lKK   ,.!/$  	*NN=)))rP      r   max_retriesc                    K   d}dt           t          t           t          t          t                   f         f         f fd}t          d D                       }d D             }t          |          D ]}	 t           j         j	        |||||dz
  k               d{V }t          |          c S # t          $ r|}	|	}||dz
  k     rMd|z  }
t                              d	|dz    d
| dd|
 d|	 z              t          j        |
           d{V  nt                              d           Y d}	~	d}	~	ww xY w|pt!          d          )a=  
        Process a single batch through the embeddings API with retry logic.

        Args:
            batch: List of BatchItem objects to embed
            max_retries: Maximum number of retry attempts (default: 3)

        Returns:
            Maps text IDs to {chunk_index: embedding_vector} dictionaries
        Nr   c                    K   t          t                    } t          j        t          j                  rj        j        j                            j	        d D             dj
        i           d{V }|j        rQt          |j        d          D ]9\  }}|j        r-                    |j                  | |j                 |j        <   :nj	        d D             d}j        r
j
        |d	<    j        j        j        d
i | d{V }t          |j        d          D ]2\  }}                    |j                  | |j                 |j        <   3| S )u   One provider call. Lifted out of the retry loop so
            _emit_embedding_call emits a separate event per attempt — each
            attempt is a distinct provider hit and shows up as its own line
            item in analytics.c                     g | ]	}|j         
S rO   rE   r   items     r*   r   zK_EmbeddingClient._process_batch.<locals>._call_provider.<locals>.<listcomp>      :::Ddi:::rP   rz   r{   NT)strictc                     g | ]	}|j         
S rO   r   r   s     r*   r   zK_EmbeddingClient._process_batch.<locals>._call_provider.<locals>.<listcomp>  r   rP   r   r   rO   )r   dictr"   rc   r
   rb   r}   r~   r   r   rT   r   zipr   rv   rF   rG   rW   r   r   rr   )resultr   r   rr   r   embedding_datar   rm   s         r*   _call_providerz7_EmbeddingClient._process_batch.<locals>._call_provider  s     
 9DD8I8IF$+u|44 !%!7!E!E*::E:::3T5KL "F " "      
 & +.uh6IRV+W+W+W  i$+  $ C CIDT U U #4<01AB
 "Z::E:::1 1 ' I262HM,/!>!7!>!O!O!O!OOOOOOO,/x}T,R,R,R  (D.;;N<TUU 4<()9:: MrP   c              3   $   K   | ]}|j         V  d S rp   )rH   r   s     r*   r   z2_EmbeddingClient._process_batch.<locals>.<genexpr>  s%      #G#GD$4#G#G#G#G#G#GrP   c                     g | ]	}|j         
S rO   r   r   s     r*   r   z3_EmbeddingClient._process_batch.<locals>.<listcomp>  s    333Tty333rP   r   )r   r   r   r   r   r      z Embedding batch failed (attempt /z), zretrying in zs: z(Error processing batch after all retrieszBatch processing failed)r   rL   rN   r   r   r   r   r+   r_   r   rA   r=   warningr#   sleep	exceptionRuntimeError)rm   r   r   last_exceptionr   batch_tokens_estimatebatch_textsattemptr   r   	wait_times   ``         r*   r   z_EmbeddingClient._process_batch  s      ,0	d3S$u+5E0F+F&G 	 	 	 	 	 	 	D !$#G#G#G#G#G G G33U333[)) 	Q 	QGQ3!^*%*?%&-q&@            F||### Q Q Q!"[1_,, !7
INNY7Q;YYYYY:::q::;   "-	2222222222$$%OPPPQ G-F G GGs   ;:B88
D>A2D99D>r   c                     t          t                    }|D ]7}|                                D ] \  }}||                             |           !8d |                                D             S )z
        Combine batch results into final output, preserving chunk order.

        Args:
            batch_results: List of batch results from _process_batch

        Returns:
            Maps text IDs to ordered lists of embedding vectors
        c                 r    i | ]3\  }|fd t                                                    D             4S )c                      g | ]
}|         S rO   rO   )r   r   
chunk_dicts     r*   r   zF_EmbeddingClient._accumulate_embeddings.<locals>.<dictcomp>.<listcomp>  s    GGGjmGGGrP   )sortedkeys)r   rF   r   s     @r*   
<dictcomp>z;_EmbeddingClient._accumulate_embeddings.<locals>.<dictcomp>  sV     
 
 
# GGGGVJOO4E4E-F-FGGG
 
 
rP   )r   r   r   update)rm   r   all_embeddingsbatch_resultrF   r   s         r*   r   z'_EmbeddingClient._accumulate_embeddings  s     =H<M<M * 	; 	;L'3'9'9';'; ; ;#w'..z::::;
 
'5';';'='=
 
 
 	
rP   N)r   )r@   rI   rJ   rK   r   rN   boolrn   propertyrL   r   r   r   rv   r   r   r   r   tupler   rD   r   r   r   rO   rP   r*   rR   rR      s        ,L$,L 	,L
 ,L !$,L ,L ,L ,L ,L\ #    XU U    1
 1
e 1
 1
 1
 1
fGd3i GDe<M G G G GR: $S#X:	c4U$$	%: : : :: $S#X	c4c3h((	)   2&T%S/%: :;&	d9o	& & & &R :;MH MH)_MH36MH	c4T%[())	*MH MH MH MH^
!$sDd5k1A,B'B"CD
	c4U$$	%
 
 
 
 
 
rP   rR   rE   encoded_tokens
max_tokensri   c                     t                    k    r| t                    fgS t          dz            }|z
  }fdt          dt                    |          D             S )aN  
    Split text into chunks that fit within token limits, with 20% overlap.

    Args:
        text: Original text to chunk
        encoded_tokens: Pre-encoded tokens for the text
        max_tokens: Maximum tokens per chunk
        encoding: Tiktoken encoding model

    Returns:
        List of (chunk_text, token_count) tuples
    g?c           	          g | ]U}|t                    k                         ||z                      t          t                    |z
            fVS rO   )r&   decoderd   )r   r   r   ri   r   s     r*   r   z+_chunk_text_with_tokens.<locals>.<listcomp>$  ss       
 s>""""	 OON1q:~+=>??
C//!344	

 #""rP   r   )r&   rN   r   )rE   r   r   ri   overlap_tokens	step_sizes    ```  r*   r   r     s    $ >j((s>**+,, c)**N^+I     
 q#n--y99   rP   c                       e Zd ZU dZdZded<   dZeedf         dz  ed<    e	j
                    Ze	j
        ed<   dZded	<    fd
ZdefdZdefdZdeedf         fdZdedee         fdZdee         deee                  fdZdeeef         deeeee                  f         fdZedefd            Zedefd            Zedefd            Zedefd            Zedefd            Z ede!j"        fd            Z# xZ$S )EmbeddingClientz
    Singleton wrapper for the embedding client with deferred loading.

    The actual client is only initialized on first use, improving startup time
    and allowing the application to start even if API keys are not yet configured.
    Nz_EmbeddingClient | None	_instance._instance_signature_lockzEmbeddingClient | None_wrapper_instancec                 l    | j         &t                                          |           | _         | j         S )z3Ensure only one instance of EmbeddingClient exists.)r   super__new__)cls	__class__s    r*   r   zEmbeddingClient.__new__;  s/      ($)GGOOC$8$8C!$$rP   r   c           	         |                                  }| j        | j        |k    r| j        5  | j        | j        |k    r|                                 }t          |t          j        j        t          j        j	        t          j        j
        t          j                                                  | _        || _        t                              d|j        |j                   ddd           n# 1 swxY w Y   | j        S )z
        Get or create the underlying embedding client instance.

        Uses double-checked locking for thread-safe lazy initialization.
        N)rT   rU   rV   rW   z9Initialized embedding client with transport: %s model: %s)_get_settings_signaturer   r   r   _resolve_runtime_configrR   r   	EMBEDDINGVECTOR_DIMENSIONSMAX_INPUT_TOKENSMAX_TOKENS_PER_REQUESTresolve_send_dimensionsr=   r>   r_   r   )rm   	signatureruntime_configs      r*   _get_clientzEmbeddingClient._get_clientB  s,    0022	>!T%=%J%J  >)T-E-R-R%)%A%A%C%CN%5&*2*<*N)1);)L/7/A/X(0(:(R(R(T(T& & &DN 09D,LLS&0&,                " ~s   B6C00C47C4c                 >    t          t          j        j                  S rp   )r   r   r  MODEL_CONFIGrq   s    r*   r  z'EmbeddingClient._resolve_runtime_config]  s    -h.@.MNNNrP   c           	          |                                  }|j        |j        |j        |j        t
          j        j        t
          j        j        t
          j        j	        t
          j        
                                fS rp   )r  r_   r   r[   rZ   r   r  r  r  r  r  )rm   r	  s     r*   r  z'EmbeddingClient._get_settings_signature`  sb    5577$ "#0/56688	
 		
rP   rw   c                 `   K   |                                                      |           d{V S )zEmbed a single query string.N)r
  r   )rm   rw   s     r*   r   zEmbeddingClient.embedm  s8      %%''--e444444444rP   r   c                 `   K   |                                                      |           d{V S )z2Simple batch embedding for a list of text strings.N)r
  r   )rm   r   s     r*   r   z"EmbeddingClient.simple_batch_embedq  s8      %%''::5AAAAAAAAArP   r   c                 `   K   |                                                      |           d{V S )z@Embed multiple texts, chunking long ones and batching API calls.N)r
  r   )rm   r   s     r*   r   zEmbeddingClient.batch_embedu  s;       %%''334DEEEEEEEEErP   c                 4    |                                  j        S )zGet the provider name.)r
  r   rq   s    r*   r   zEmbeddingClient.provider{       !!**rP   c                 4    |                                  j        S )zGet the model name.)r
  r   rq   s    r*   r   zEmbeddingClient.model  s     !!''rP   c                 4    |                                  j        S )zGet the transport name.)r
  r_   rq   s    r*   r_   zEmbeddingClient.transport  s     !!++rP   c                 4    |                                  j        S )z!Get the maximum embedding tokens.)r
  re   rq   s    r*   re   z$EmbeddingClient.max_embedding_tokens  s     !!66rP   c                 4    |                                  j        S )z(Get the configured embedding dimensions.)r
  rT   rq   s    r*   rT   z!EmbeddingClient.vector_dimensions  s     !!33rP   c                 4    |                                  j        S )zGet the tiktoken encoding.)r
  ri   rq   s    r*   ri   zEmbeddingClient.encoding  r  rP   )%r@   rI   rJ   rK   r   rM   r   r   object	threadingLockr   r   r   rR   r
  r   r  r  rL   r   r   r   r   r   r   r   r   r   r_   rN   re   rT   rg   Encodingri   __classcell__)r   s   @r*   r   r   .  s          ,0I(///59vs{+d2999*IN,,E9>,,,26/666% % % % %-    6O)= O O O O
vs{); 
 
 
 
5 5e 5 5 5 5Bd3i BDe<M B B B BF $S#XF	c4U$$	%F F F F +# + + + X+ (s ( ( ( X( ,3 , , , X, 7c 7 7 7 X7 43 4 4 4 X4 +(+ + + + X+ + + + +rP   r   )-r#   loggingr  r    collectionsr   collections.abcr   r   typingr   r   r   r	   rg   googler
   google.genair   r`   openair   rS   r   r   r   	getLoggerr@   r=   r   rL   r   rN   r   r+   r   r'   r%   rD   rR   r  r   r   r   embedding_clientrO   rP   r*   <module>r&     s          # # # # # # / / / / / / / / 4 4 4 4 4 4 4 4 4 4 4 4        - - - - - -       R R R R R R R R R R		8	$	$WT]] "-
 -
 -
-
 -
 9	-

 -
 	Yr]"#-
 -
 -
 -
 -
 -
`8R8R 8R 	8R
 8R 8R 458R 48R 8R 
8R 8R 8R 8Rv    
   
 
 
 
 
 
 
 
D 
 I    	 
 
%S/       Fi+ i+ i+ i+ i+ i+ i+ i+Z #?$$   rP   