U
    h                     @   sv   d Z ddl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 G dd	 d	eeZd
S )zRWKV models.

Based on https://github.com/saharNooby/rwkv.cpp/blob/master/rwkv/chat_with_bot.py
         https://github.com/BlinkDL/ChatRWKV/blob/main/v2/chat.py
    )AnyDictListMappingOptionalSet)CallbackManagerForLLMRun)LLM)	BaseModel)pre_init)enforce_stop_tokensc                   @   s  e Zd ZU dZeed< eed< dZeed< dZeed< dZ	e
ed	< d
Ze
ed< dZe
ed< dZe
ed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< dZeed< G dd dZeeeef dddZeee dddZeeedd d!Zee eef dd"d#Z!eedd$d%Z"d0e#e eed'd(d)Z$eed*d+d,Z%d1ee&e#e  e&e' eed-d.d/Z(dS )2RWKVa  RWKV language models.

    To use, you should have the ``rwkv`` python package installed, the
    pre-trained model file, and the model's config information.

    Example:
        .. code-block:: python

            from langchain_community.llms import RWKV
            model = RWKV(model="./models/rwkv-3b-fp16.bin", strategy="cpu fp32")

            # Simplest invocation
            response = model.invoke("Once upon a time, ")
    modeltokens_pathzcpu fp32strategyTrwkv_verboseg      ?temperatureg      ?top_pg?penalty_alpha_frequencypenalty_alpha_presence   	CHUNK_LENmax_tokens_per_generationNclient	tokenizerpipelinemodel_tokensmodel_statec                   @   s   e Zd ZdZdS )zRWKV.ConfigZforbidN)__name__
__module____qualname__extra r"   r"   A/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/llms/rwkv.pyConfigM   s   r$   )returnc                 C   s"   | j | j| j| j| j| j| jdS )Get the identifying parameters.verboser   r   r   r   r   r   r'   selfr"   r"   r#   _default_paramsP   s    zRWKV._default_paramsc                   C   s   dhS )r&   r(   r"   r"   r"   r"   r#   _rwkv_param_names]   s    zRWKV._rwkv_param_names)valuesr%   c                    s   zddl }W n tk
r(   tdY nX zddlm} ddlm} |j|d |d< |    fdd	|	 D }|d
 |d< ||d fd|d i||d< ||d |d |d< W n tk
r   tdY nX |S )z;Validate that the python package exists in the environment.r   Nz\Could not import tokenizers python package. Please install it with `pip install tokenizers`.)r   )PIPELINEr   r   c                    s   i | ]\}}| kr||qS r"   r"   .0kvZ	rwkv_keysr"   r#   
<dictcomp>u   s       z-RWKV.validate_environment.<locals>.<dictcomp>r   r(   r   r   r   r   zPCould not import rwkv python package. Please install it with `pip install rwkv`.)

tokenizersImportErrorZ
rwkv.modelr   Z
rwkv.utilsr.   	Tokenizer	from_filer,   items)clsr-   r5   Z	RWKVMODELr.   Zmodel_kwargsr"   r3   r#   validate_environmentd   s4    


zRWKV.validate_environmentc                 C   s"   d| j i| jdd | j D S )r&   r   c                 S   s"   i | ]\}}|t  kr||qS r"   )r   r,   r/   r"   r"   r#   r4      s       z,RWKV._identifying_params.<locals>.<dictcomp>)r   r+   __dict__r9   r)   r"   r"   r#   _identifying_params   s     zRWKV._identifying_paramsc                 C   s   dS )zReturn the type of llm.Zrwkvr"   r)   r"   r"   r#   	_llm_type   s    zRWKV._llm_typer   )_tokensnewline_adjr%   c           
      C   s   g }d}|D ](}| j |}t|dks,t||7 }qdd |D }|  j|7  _d }t|dkr| j|d | j | j\}| _|| jd  }qVd}	||	  |7  < | jd |krd|| jd < |S )	Nu   ，：？！   c                 S   s   g | ]}t |qS r"   )int)r0   xr"   r"   r#   
<listcomp>   s     z RWKV.run_rnn.<locals>.<listcomp>r      i6e)	r   encodelenAssertionErrorr   r   Zforwardr   r   )
r*   r?   r@   ZAVOID_REPEAT_TOKENSZAVOID_REPEATiddtokensoutZEND_OF_LINEr"   r"   r#   run_rnn   s(    
 
zRWKV.run_rnn)promptr%   c                 C   s  d | _ g | _| | j|j}t| j}|}i }d}t| jD ]}|D ]$}||  | j	|| | j
  8  < qH| jj|| j| jd}	d}
|	|
kr q|	|krd||	< n||	  d7  < | |	g}| j| j|d  }d|kr@||7 }|| d }|| jd kr@ qq@|S )N )r   r   r   rA   u   �d   )r   r   rN   r   rG   idsrH   ranger   r   r   r   Zsample_logitsr   r   decode)r*   rO   ZlogitsbeginZout_lastZ
occurrencedecodedrJ   ntokenZEND_OF_TEXTZxxxr"   r"   r#   rwkv_generate   sB    
  
zRWKV.rwkv_generate)rO   stoprun_managerkwargsr%   c                 K   s    |  |}|dk	rt||}|S )a  RWKV generation

        Args:
            prompt: The prompt to pass into the model.
            stop: A list of strings to stop generation when encountered.

        Returns:
            The string generated by the model.

        Example:
            .. code-block:: python

                prompt = "Once upon a time, "
                response = model.invoke(prompt, n_predict=55)
        N)rY   r   )r*   rO   rZ   r[   r\   textr"   r"   r#   _call   s    

z
RWKV._call)r   )NN))r   r   r    __doc__str__annotations__r   r   boolr   floatr   r   r   r   rB   r   r   r   r   r   r   r   r$   propertyr   r+   staticmethodr   r,   r   r;   r   r=   r>   r   rN   rY   r   r   r^   r"   r"   r"   r#   r      sL   
)  
r   N)r_   typingr   r   r   r   r   r   Zlangchain_core.callbacksr   Z#langchain_core.language_models.llmsr	   Zlangchain_core.pydantic_v1r
   Zlangchain_core.utilsr   Zlangchain_community.llms.utilsr   r   r"   r"   r"   r#   <module>   s    