
    hiy                    P   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	 ddl
mZmZmZmZ ddlZddlZddlmZmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZmZ ddl m!Z!m"Z"m#Z#m$Z$ ddl%m&Z&  ejN                  e(      Z)	 	 	 	 	 	 	 	 ddZ*	 	 	 	 ddZ+ G d de      Z, G d de,      Z-y)zQBase classes for OpenAI large language models. Chat models are in `chat_models/`.    )annotationsN)AsyncIterator
CollectionIteratorMapping)AnyLiteralOptionalUnion)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseLLM)
GenerationGenerationChunk	LLMResult)get_pydantic_field_names)_build_model_kwargsfrom_envsecret_from_env)
ConfigDictField	SecretStrmodel_validator)Selfc                    | j                  |d         }|D ]%  }||vr|d   |   ||<   ||xx   |d   |   z  cc<   ' y)zUpdate token usage.usageN)intersection)keysresponsetoken_usage_keys_to_use_keys        Y/var/www/html/aiagenthome/venv/lib/python3.12/site-packages/langchain_openai/llms/base.py_update_token_usager$      sY     $$Xg%67L{" ( 1$ 7K'!24!88	     c                    | d   st        d      S t        | d   d   d   xs d| d   d   j                  dd      | d   d   j                  dd      d	
      S )z0Convert a stream response to a generation chunk.choices )textr   r)   finish_reasonNlogprobsr*   r+   r)   generation_info)r   get)stream_responses    r#   $_stream_response_to_generation_chunkr1   &   su     9%B''Y'*628b,Y7:>>PTU'	21599*dK
 r%   c                  d    e Zd ZU dZ edd      Zded<    edd      Zded<    edd	
      Zded<   	 dZ	ded<   	 dZ
ded<   	 dZded<   	 dZded<   	 dZded<   	 dZded<   	 dZded<   	  ee      Zded<   	  ed edd             Zd!ed"<   	  ed# ed$d             Zd%ed&<   	  ed' ed(d)gd             Zd%ed*<   	  e ed+d            Zd%ed,<   d-Zded.<   	  edd/
      Zd0ed1<   	 dZd2ed3<   	 d4Zded5<   	 dZd6ed7<   	 dZd6ed8<   	 d9Zd:ed;<   	  e       Z d<ed=<   	 d>Z!d?ed@<   	 dZ"d%edA<   	 dZ#dBedC<   dZ$dDedE<   dZ%dFedG<   	 dZ&dFedH<   	 dZ'dIedJ<   	  e(dK      Z) e*dLM      e+d`dN              Z, e*dOM      dadP       Z-e.dbdQ       Z/	 	 dc	 	 	 	 	 	 	 	 	 dddRZ0	 	 dc	 	 	 	 	 	 	 	 	 dedSZ1	 	 dc	 	 	 	 	 	 	 	 	 dfdTZ2	 	 dc	 	 	 	 	 	 	 	 	 dgdUZ3	 dh	 	 	 	 	 	 	 didVZ4ddW	 	 	 	 	 	 	 	 	 	 	 djdXZ5e.dbdY       Z6e.dkdZ       Z7e.dld[       Z8dm fd\Z9e:dnd]       Z;e.dod^       Z<dpd_Z= xZ>S )q
BaseOpenAIu  Base OpenAI large language model class.

    Setup:
        Install ``langchain-openai`` and set environment variable ``OPENAI_API_KEY``.

        .. code-block:: bash

            pip install -U langchain-openai
            export OPENAI_API_KEY="your-api-key"

    Key init args — completion params:
        model_name: str
            Name of OpenAI model to use.
        temperature: float
            Sampling temperature.
        max_tokens: int
            Max number of tokens to generate.
        top_p: float
            Total probability mass of tokens to consider at each step.
        frequency_penalty: float
            Penalizes repeated tokens according to frequency.
        presence_penalty: float
            Penalizes repeated tokens.
        n: int
            How many completions to generate for each prompt.
        best_of: int
            Generates best_of completions server-side and returns the "best".
        logit_bias: Optional[dict[str, float]]
            Adjust the probability of specific tokens being generated.
        seed: Optional[int]
            Seed for generation.
        logprobs: Optional[int]
            Include the log probabilities on the logprobs most likely output tokens.
        streaming: bool
            Whether to stream the results or not.

    Key init args — client params:
        openai_api_key: Optional[SecretStr]
            OpenAI API key. If not passed in will be read from env var
            ``OPENAI_API_KEY``.
        openai_api_base: Optional[str]
            Base URL path for API requests, leave blank if not using a proxy or
            service emulator.
        openai_organization: Optional[str]
            OpenAI organization ID. If not passed in will be read from env
            var ``OPENAI_ORG_ID``.
        request_timeout: Union[float, tuple[float, float], Any, None]
            Timeout for requests to OpenAI completion API.
        max_retries: int
            Maximum number of retries to make when generating.
        batch_size: int
            Batch size to use when passing multiple documents to generate.

    See full list of supported init args and their descriptions in the params section.

    Instantiate:
        .. code-block:: python

            from langchain_openai.llms.base import BaseOpenAI

            llm = BaseOpenAI(
                model_name="gpt-3.5-turbo-instruct",
                temperature=0.7,
                max_tokens=256,
                top_p=1,
                frequency_penalty=0,
                presence_penalty=0,
                # openai_api_key="...",
                # openai_api_base="...",
                # openai_organization="...",
                # other params...
            )

    Invoke:
        .. code-block:: python

            input_text = "The meaning of life is "
            response = llm.invoke(input_text)
            print(response)

        .. code-block::

            "a philosophical question that has been debated by thinkers and
            scholars for centuries."

    Stream:
        .. code-block:: python

            for chunk in llm.stream(input_text):
                print(chunk, end="")

        .. code-block::

            a philosophical question that has been debated by thinkers and
            scholars for centuries.

    Async:
        .. code-block:: python

            response = await llm.ainvoke(input_text)

            # stream:
            # async for chunk in llm.astream(input_text):
            #     print(chunk, end="")

            # batch:
            # await llm.abatch([input_text])

        .. code-block::

            "a philosophical question that has been debated by thinkers and
            scholars for centuries."

    NT)defaultexcluder   clientasync_clientgpt-3.5-turbo-instructmodel)r4   aliasstr
model_namegffffff?floattemperature   int
max_tokens   top_pr   frequency_penaltypresence_penaltynbest_of)default_factorydict[str, Any]model_kwargsapi_keyOPENAI_API_KEY)r4   )r:   rH   zOptional[SecretStr]openai_api_keybase_urlOPENAI_API_BASEOptional[str]openai_api_baseorganizationOPENAI_ORG_IDOPENAI_ORGANIZATIONopenai_organizationOPENAI_PROXYopenai_proxy   
batch_sizetimeoutz,Union[float, tuple[float, float], Any, None]request_timeoutzOptional[dict[str, float]]
logit_bias   max_retrieszOptional[int]seedr+   Fbool	streamingzUnion[Literal['all'], set[str]]allowed_specialallz&Union[Literal['all'], Collection[str]]disallowed_specialtiktoken_model_namezUnion[Mapping[str, str], None]default_headersz!Union[Mapping[str, object], None]default_queryzUnion[Any, None]http_clienthttp_async_clientzOptional[Mapping[str, Any]]
extra_body)populate_by_namebefore)modec                0    t        |       }t        ||      S )z>Build extra kwargs from additional params that were passed in.)r   r   )clsvaluesall_required_field_namess      r#   build_extrazBaseOpenAI.build_extra  s     $<C#@ "6+CDDr%   afterc                   | j                   dk  rd}t        |      | j                  r| j                   dkD  rd}t        |      | j                  r| j                  dkD  rd}t        |      | j                  r| j                  j                         nd| j                  | j                  | j                  | j                  | j                  | j                  d}| j                  s4d| j                  i}t        j                  di ||j                   | _        | j"                  s4d| j$                  i}t        j&                  di ||j                   | _        | S )	z?Validate that api key and python package exists in environment.rB   zn must be at least 1.z!Cannot stream results when n > 1.z'Cannot stream results when best_of > 1.N)rK   rR   rN   rZ   r^   rf   rg   rh    )rF   
ValueErrorra   rG   rM   get_secret_valuerU   rQ   r[   r^   rf   rg   r6   rh   openaiOpenAIcompletionsr7   ri   AsyncOpenAI)selfmsgclient_paramssync_specificasync_specifics        r#   validate_environmentzBaseOpenAI.validate_environment  s?    66A:)CS/!>>dffqj5CS/!>>dllQ.;CS/! ;?:M:M##446SW 44,,++++#33!//

 {{*D,<,<=M --I-I=IUUDK  +T-C-CDN & 2 2 !! ! k 
 r%   c                   | j                   | j                  | j                  | j                  | j                  | j
                  | j                  d}| j                  | j                  |d<   | j                  | j                  |d<   | j                  | j                  |d<   | j                  dkD  r| j                  |d<   i || j                  S )z2Get the default parameters for calling OpenAI API.)r>   rC   rD   rE   rF   r_   r+   r\   rA   rj   rB   rG   )r>   rC   rD   rE   rF   r_   r+   r\   rA   rj   rG   rJ   )r|   normal_paramss     r#   _default_paramszBaseOpenAI._default_params0  s      ++ZZ!%!7!7 $ 5 5II)
 ??&*.//M,'??&*.//M,'??&*.//M,' <<!'+||M)$5-54#4#455r%   c              +    K   i | j                   |ddi}| j                  ||g|        | j                  j                  dd|i|D ]w  }t	        |t
              s|j                         }t        |      }|rD|j                  |j                  || j                  |j                  r|j                  d   nd        | y y wNstreamTpromptr+   )chunkverboser+   ru   )_invocation_paramsget_sub_promptsr6   create
isinstancedict
model_dumpr1   on_llm_new_tokenr)   r   r.   r|   r   stoprun_managerkwargsparamsstream_respr   s           r#   _streamzBaseOpenAI._streamM  s      GD++FvFxFVfXt4-4;;--FVFvFKk40)4468EE,,JJ LL !00 --j9! - 	 K! Gs   CCc                 K   i | j                   |ddi}| j                  ||g|        | j                  j                  dd|i| d {   2 3 d {   }t	        |t
              s|j                         }t        |      }|rL|j                  |j                  || j                  |j                  r|j                  d   nd        d {    | 7 7 7 6 y wr   )r   r   r7   r   r   r   r   r1   r   r)   r   r.   r   s           r#   _astreamzBaseOpenAI._astreamh  s     GD++FvFxFVfXt4'?t'8'8'?'? (
(
#(
 "
 "
 	+ k40)4468EE!22JJ LL !00 --j9! 3 	 	 	 K%"
 		"
sI   A
C!CC!CCCA5C!CC!CC!C!c                v   | j                   }i ||}| j                  |||      }g }i }h d}	d}
|D ]o  }| j                  rt        |      dkD  rd}t	        |      d} | j
                  |d   ||fi |D ]  }||}||z  } |d}t	        |      |j                  |j                  |j                  r|j                  j                  d      nd|j                  r|j                  j                  d      ndd	        | j                  j                  dd
|i|}t        |t              s|j                         }|j                  d      rt	        |j                  d            |j                  |d          t!        |	||       |
r_|j                  d      }
r | j#                  |||||
      S )a  Call out to OpenAI's endpoint with k unique prompts.

        Args:
            prompts: The prompts to pass into the model.
            stop: Optional list of stop words to use when generating.
            run_manager: Optional callback manager to use for the call.

        Returns:
            The full LLM output.

        Example:
            .. code-block:: python

                response = openai.generate(["Tell me a joke."])

        >   total_tokensprompt_tokenscompletion_tokensNrB   ,Cannot stream results with multiple prompts.r   $Generation is empty after streaming.r*   r+   r)   r*   r+   r   errorr'   system_fingerprintr   ru   )r   r   ra   lenrv   r   appendr)   r.   r/   r6   r   r   r   r   extendr$   create_llm_resultr|   promptsr   r   r   r   sub_promptsr'   r    _keysr   _promptsr}   
generationr   r   s                   r#   	_generatezBaseOpenAI._generate  s   0 ((%F%f%**67DA&( G,0#H~~x=1$HC$S/)8<
)T\\(1+t[SFSE!)%*
"e+
	 T
 %@C$S/) *  *99 '66::?K!%  *99 '66:::F!%  .4;;--HXHH!(D1  (224H <<($X\\'%:;;x	23#E8[A))16J)K&_ $` %%WfkFX & 
 	
r%   c                   K   | j                   }i ||}| j                  |||      }g }i }h d}	d}
|D ]  }| j                  rIt        |      dkD  rd}t	        |      d} | j
                  |d   ||fi |2 3 d{   }||}||z  } | j                  j                  dd
|i| d{   }t        |t              s|j                         }|j                  |d          t!        |	||        | j#                  |||||
      S 7 6 |d}t	        |      |j                  |j                  |j                  r|j                  j                  d      nd|j                  r|j                  j                  d      ndd	       X7 ޭw)z:Call out to OpenAI's endpoint async with k unique prompts.>   r   r   r   NrB   r   r   r   r*   r+   r   r   r'   r   ru   )r   r   ra   r   rv   r   r   r)   r.   r/   r7   r   r   r   r   r   r$   r   r   s                   r#   
_ageneratezBaseOpenAI._agenerate  s     ((%F%f%**67DA&( G,0#H~~x=1$HC$S/)8<
#04==QK{$6<$ ,% ")%*
"e+
( ":!2!2!9!9!T!TV!TT!(D1'224Hx	23#E8[AK $L %%WfkFX & 
 	
?, $ %@C$S/) *  *99 '66::?K!%  *99 '66:::F!%  Us8   A6F8D<D=D -F-F.AFDB Fc                
   |||d<   |d   dk(  r2t        |      dk7  rd}t        |      | j                  |d         |d<   t        dt        |      | j                        D cg c]  }|||| j                  z     c}S c c}w )z!Get the sub prompts for llm call.r   rA   rB   z7max_tokens set to -1 not supported for multiple inputs.r   )r   rv   max_tokens_for_promptrangerY   )r|   r   r   r   r}   is         r#   r   zBaseOpenAI.get_sub_prompts  s     !F6N,2%7|q O o%#'#=#=gaj#IF<  1c'lDOO<
< ADOO+,<
 	
 
s   $B r   c               l   g }|j                  d| j                        }t        |      D ]a  \  }}	|||z  |dz   |z   }
|j                  |
D cg c]3  }t	        |d   |j                  d      |j                  d      d      5 c}       c || j
                  d}|r||d	<   t        ||
      S c c}w )z2Create the LLMResult from the choices and prompts.rF   rB   r)   r*   r+   r,   r-   )r    r<   r   )generations
llm_output)r/   rF   	enumerater   r   r<   r   )r|   r'   r   r   r    r   r   rF   r   _sub_choiceschoicer   s                r#   r   zBaseOpenAI.create_llm_result(  s     JJsDFF#g&DAq!!a%1q5A+6K #.	 #. #F^-3ZZ-H(.

:(>) #.	 ' &1P
/AJ+,[ZHH	s   8B1
c                    | j                   S )z,Get the parameters used to invoke the model.)r   r|   s    r#   r   zBaseOpenAI._invocation_paramsG  s     ###r%   c                6    d| j                   i| j                  S )zGet the identifying parameters.r<   )r<   r   r   s    r#   _identifying_paramszBaseOpenAI._identifying_paramsL  s     dooF1E1EFFr%   c                     y)zReturn type of llm.rx   ru   r   s    r#   	_llm_typezBaseOpenAI._llm_typeQ  s     r%   c                   | j                   | j                  |      S t        j                  d   dk  rt        |   |      S | j
                  xs | j                  }	 t        j                  |      }|j                  || j                  | j                        S # t        $ r t        j                  d      }Y Hw xY w)z-Get the token IDs using the tiktoken package.rB      cl100k_base)rb   rd   )custom_get_token_idssysversion_infosuperget_num_tokensre   r<   tiktokenencoding_for_modelKeyErrorget_encodingencoderb   rd   )r|   r)   r<   enc	__class__s       r#   get_token_idszBaseOpenAI.get_token_idsV  s    $$0,,T22A"7)$//--@
	7--j9C zz 00#66  
 	
  	7''6C	7s   B B=<B=c                @   i ddddddddddddd	d
dd
dd
dddddddddddddddddddddddddddd}d| v r| j                  d      d   } |j                  |       }|/t        d |  d!d"j                  |j	                               z         |S )#ap  Calculate the maximum number of tokens possible to generate for a model.

        Args:
            modelname: The modelname we want to know the context size for.

        Returns:
            The maximum context size

        Example:
            .. code-block:: python

                max_tokens = openai.modelname_to_contextsize("gpt-3.5-turbo-instruct")

        zgpt-4o-minii  zgpt-4ozgpt-4o-2024-05-13zgpt-4i    z
gpt-4-0314z
gpt-4-0613z	gpt-4-32ki   zgpt-4-32k-0314zgpt-4-32k-0613zgpt-3.5-turboi   zgpt-3.5-turbo-0301zgpt-3.5-turbo-0613zgpt-3.5-turbo-16ki@  zgpt-3.5-turbo-16k-0613r8   ztext-ada-001i  adai  i  iA  i   )ztext-babbage-001babbageztext-curie-001curiedavinciztext-davinci-003ztext-davinci-002zcode-davinci-002zcode-davinci-001zcode-cushman-002zcode-cushman-001zft-:r   zUnknown model: z=. Please provide a valid OpenAI model name.Known models are: z, )splitr/   rv   joinr   )	modelnamemodel_token_mappingcontext_sizes      r#   modelname_to_contextsizez#BaseOpenAI.modelname_to_contextsizej  sp    
7
g
  
 T	

 $
 $
 
 e
 e
 T
 !$
 !$
  
 %e
 %d
  D!
" 4#
$ !%" $ $ $ $ $ $9
@ I!,Q/I*..y9!) -% %'+yy1D1I1I1K'LM 
 r%   c                8    | j                  | j                        S )z$Get max context size for this model.)r   r<   r   s    r#   max_context_sizezBaseOpenAI.max_context_size  s     ,,T__==r%   c                B    | j                  |      }| j                  |z
  S )aq  Calculate the maximum number of tokens possible to generate for a prompt.

        Args:
            prompt: The prompt to pass into the model.

        Returns:
            The maximum number of tokens to generate for a prompt.

        Example:
            .. code-block:: python

                max_tokens = openai.max_tokens_for_prompt("Tell me a joke.")

        )r   r   )r|   r   
num_tokenss      r#   r   z BaseOpenAI.max_tokens_for_prompt  s%     ((0
$$z11r%   )rp   rI   returnr   )r   r   r   rI   )NN)
r   r;   r   Optional[list[str]]r   "Optional[CallbackManagerForLLMRun]r   r   r   zIterator[GenerationChunk])
r   r;   r   r   r   'Optional[AsyncCallbackManagerForLLMRun]r   r   r   zAsyncIterator[GenerationChunk])
r   	list[str]r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )N)r   rI   r   r   r   r   r   zlist[list[str]])r'   r   r   r   r   rI   r    zdict[str, int]r   rP   r   r   )r   zMapping[str, Any])r   r;   )r)   r;   r   z	list[int])r   r;   r   r@   )r   r@   )r   r;   r   r@   )?__name__
__module____qualname____doc__r   r6   __annotations__r7   r<   r>   rA   rC   rD   rE   rF   rG   r   rJ   r   rM   r   rQ   rU   rW   rY   r[   r\   r^   r_   r+   ra   setrb   rd   re   rf   rg   rh   ri   rj   r   model_configr   classmethodrr   r   propertyr   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   __classcell__r   s   @r#   r3   r3   5   sz   qf d3FC3dD9L#9$<GLJLK+J( E5D u ;e$AsJ;GSK#(#>L.>V*/9ISW)X+N'  R%*(3Dd*S&O] ). 34d
*  Q"' >#L-  JHDIIEOA -1J*1DK<D-"Hm"#It/7:uO4<3AF>F7)--J 7;O3:7;M4; %)K!( +/'.W.2J+2@ t4L(#E  $E
 '"! #!F 6 6> %):>	 " 8	
  
#< %)?C	 " =	
  
(@ %):>	S
S
 "S
 8	S

 S
 
S
p %)?C	9
9
 "9
 =	9

 9
 
9
~ %)	

 
 "	

 

4 -1II I 	I
 $I *I 
I> $ $ G G  
( : :x > >2r%   r3   c                  v     e Zd ZdZedd       Zedd       Zed	 fd       Zed
d       Z	ed	d       Z
 xZS )ry   u  OpenAI completion model integration.

    Setup:
        Install ``langchain-openai`` and set environment variable ``OPENAI_API_KEY``.

        .. code-block:: bash

            pip install -U langchain-openai
            export OPENAI_API_KEY="your-api-key"

    Key init args — completion params:
        model: str
            Name of OpenAI model to use.
        temperature: float
            Sampling temperature.
        max_tokens: Optional[int]
            Max number of tokens to generate.
        logprobs: Optional[bool]
            Whether to return logprobs.
        stream_options: Dict
            Configure streaming outputs, like whether to return token usage when
            streaming (``{"include_usage": True}``).

    Key init args — client params:
        timeout: Union[float, Tuple[float, float], Any, None]
            Timeout for requests.
        max_retries: int
            Max number of retries.
        api_key: Optional[str]
            OpenAI API key. If not passed in will be read from env var ``OPENAI_API_KEY``.
        base_url: Optional[str]
            Base URL for API requests. Only specify if using a proxy or service
            emulator.
        organization: Optional[str]
            OpenAI organization ID. If not passed in will be read from env
            var ``OPENAI_ORG_ID``.

    See full list of supported init args and their descriptions in the params section.

    Instantiate:
        .. code-block:: python

            from langchain_openai import OpenAI

            llm = OpenAI(
                model="gpt-3.5-turbo-instruct",
                temperature=0,
                max_retries=2,
                # api_key="...",
                # base_url="...",
                # organization="...",
                # other params...
            )

    Invoke:
        .. code-block:: python

            input_text = "The meaning of life is "
            llm.invoke(input_text)

        .. code-block::

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    Stream:
        .. code-block:: python

            for chunk in llm.stream(input_text):
                print(chunk, end="|")

        .. code-block::

            a| philosophical| question| that| has| been| debated| by| thinkers| and| scholars| for| centuries|.

        .. code-block:: python

            "".join(llm.stream(input_text))

        .. code-block::

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    Async:
        .. code-block:: python

            await llm.ainvoke(input_text)

            # stream:
            # async for chunk in (await llm.astream(input_text)):
            #    print(chunk)

            # batch:
            # await llm.abatch([input_text])

        .. code-block::

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    c                
    g dS )z*Get the namespace of the langchain object.)	langchainllmsrx   ru   ro   s    r#   get_lc_namespacezOpenAI.get_lc_namespace$  s
     /.r%   c                     y)z9Return whether this model can be serialized by LangChain.Tru   r   s    r#   is_lc_serializablezOpenAI.is_lc_serializable)  s     r%   c                4    d| j                   it        |   S )Nr9   )r<   r   r   )r|   r   s    r#   r   zOpenAI._invocation_params.  s    GEG,FGGr%   c                
    ddiS )z0Mapping of secret keys to environment variables.rM   rL   ru   r   s    r#   
lc_secretszOpenAI.lc_secrets2  s     !"233r%   c                    i }| j                   r| j                   |d<   | j                  r| j                  |d<   | j                  r| j                  |d<   |S )z$LangChain attributes for this class.rQ   rU   rW   )rQ   rU   rW   )r|   
attributess     r#   lc_attributeszOpenAI.lc_attributes7  s\     &(
,0,@,@J()##040H0HJ,-)-):):J~&r%   )r   r   )r   r`   r   )r   zdict[str, str])r   r   r   r   r   r   r   r   r   r   r  r   r   s   @r#   ry   ry     sp    bH / /   H H 4 4  r%   ry   )r   zset[str]r   rI   r    rI   r   None)r0   rI   r   r   ).r   
__future__r   loggingr   collections.abcr   r   r   r   typingr   r	   r
   r   rx   r   langchain_core.callbacksr   r   #langchain_core.language_models.llmsr   langchain_core.outputsr   r   r   langchain_core.utilsr   langchain_core.utils.utilsr   r   r   pydanticr   r   r   r   typing_extensionsr   	getLoggerr   loggerr$   r1   r3   ry   ru   r%   r#   <module>r     s    W "  
 H H 0 0   8 I I 9 U U B B "			8	$	9
	9,	9;I	9		9#G
2 G
2TEZ Er%   