o
    wiʁ                     @   s  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	m
Z
 d dlmZmZ d dlmZ d dlmZ d dlZd dlmZ d dlmZmZmZmZmZ d dlmZmZ d	d
lmZ e  dkrld dl!Z!e rd dl"m#Z# d dl$m%Z% d dl&m'Z' e rd dl(Z(d dlm)Z)m*Z*m+Z+ e,ej-ej. Z/e,ej-ej0 ej. d Z1ddiddiddiddiddiddiddidZ2dZ3dd4e25  dZ6g dZ7G dd  d Z8eG d!d" d"Z9d#e
fd$d%Z:G d&d' d'eZ;dS )(    N)ArgumentParser	Namespace)	dataclassfield)Thread)Optional)disable_progress_bars)AutoTokenizerGenerationConfigPreTrainedTokenizerTextIteratorStreamerlogging)is_rich_availableis_torch_available   )BaseTransformersCLICommandWindows)Console)Live)Markdown)AutoModelForCausalLMBitsAndBytesConfigPreTrainedModelz .!\"#$%&'()*+,\-/:<=>?@[]^_`{|}~textz5There is a Llama in my lawn, how can I get rid of it?zyWrite a Python function that integrates any Python function f(x) numerically over an arbitrary interval [x_start, x_end].z4How many helicopters can a human eat in one sitting?z4Count to 10 but skip every number ending with an 'e'zWhy aren't birds real?z2Why is it important to eat socks after meditating?z$Which number is larger, 9.9 or 9.11?)llamacode
helicopternumbersbirdssocksnumbers2a  

**TRANSFORMERS CHAT INTERFACE**

Chat interface to try out a model. Besides chatting with the model, here are some basic commands:
- **!help**: shows all available commands (set generation settings, save chat, etc.)
- **!status**: shows the current status of the model and generation settings
- **!clear**: clears the current conversation and starts a new one
- **!exit**: closes the interface
am  

**TRANSFORMERS CHAT INTERFACE HELP**

Full command list:
- **!help**: shows this help message
- **!clear**: clears the current conversation and starts a new one
- **!status**: shows the current status of the model and generation settings
- **!example {NAME}**: loads example named `{NAME}` from the config and uses it as the user input.
Available example names: `z`, `a%  `
- **!set {ARG_1}={VALUE_1} {ARG_2}={VALUE_2}** ...: changes the system prompt or generation settings (multiple
settings are separated by a space). Accepts the same flags and format as the `generate_flags` CLI argument.
If you're a new user, check this basic flag guide: https://huggingface.co/docs/transformers/llm_tutorial#common-options
- **!save {SAVE_NAME} (optional)**: saves the current chat and settings to file by default to
`./chat_history/{MODEL_NAME}/chat_{DATETIME}.yaml` or `{SAVE_NAME}` if provided
- **!exit**: closes the interface
)	)max_new_tokens   r!   )	do_sampleTr#   )	num_beamsr   r$   )temperature      ?r%   )top_k2   r'   )top_pr&   r)   )repetition_penaltyr&   r*   )
eos_tokensNeos_token_id)eos_token_idsNr,   c                   @   s   e Zd Zddee dee fddZdedefdd	Zdefd
dZdd Z	defddZ
dedefddZddefddZdededefddZdS )RichInterfaceN
model_name	user_namec                 C   s:   t  | _|d u rd| _n|| _|d u rd| _d S || _d S )N	assistantuser)r   _consoler/   r0   )selfr/   r0    r5   W/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/transformers/commands/chat.py__init__}   s   

zRichInterface.__init__output_streamreturnc           	      C   s   d}| j d| j d t| j ddQ}t|D ]D\}}|r#|dkr$qtdd|}||7 }g }| D ]}|| |	d	rG|d
 q5|d q5t
d| dd}|| qW d   n1 shw   Y  | j   |S )zRStream output from a role, and return the generated text after it's done steaming. z[bold blue]<z>:   )consolerefresh_per_secondr   z<(/*)(\w*)>z\<\1\2\>z```
z  
zgithub-dark)
code_themeN)r3   printr/   r   	enumerateresub
splitlinesappend
startswithr   joinstripupdate)	r4   r8   r   liveioutputslineslinemarkdownr5   r5   r6   stream_output   s(   


 zRichInterface.stream_outputc                 C   s$   | j d| j d}| j   |S )z!Gets user input from the console.[bold red]<z>:
)r3   inputr0   r@   )r4   rR   r5   r5   r6   rR      s   
zRichInterface.inputc                 C   s   | j   dS )zClears the console.N)r3   clear)r4   r5   r5   r6   rS      s   zRichInterface.clearr   c                 C   s(   | j d| j d|  | j   dS )z%Prints a user message to the console.rQ   z>:[/ bold red]
N)r3   r@   r0   )r4   r   r5   r5   r6   print_user_message   s   z RichInterface.print_user_messagecolorc                 C   s&   | j d| d|  | j   dS )z,Prints text in a given color to the console.z[bold ]Nr3   r@   )r4   r   rU   r5   r5   r6   print_color      zRichInterface.print_colorFminimalc                 C   s&   | j t|rtnt | j   dS )z'Prints the help message to the console.N)r3   r@   r   HELP_STRING_MINIMALHELP_STRING)r4   rZ   r5   r5   r6   
print_help   rY   zRichInterface.print_helpgeneration_configmodel_kwargsc                 C   sJ   | j d| d |r| j d|  | j d|  | j   dS )zFPrints the status of the model and generation settings to the console.z[bold blue]Model: r>   z[bold blue]Model kwargs: z[bold blue]NrW   )r4   r/   r^   r_   r5   r5   r6   print_status   s
   zRichInterface.print_status)NN)F)__name__
__module____qualname__r   strr7   r   rP   rR   rS   rT   rX   boolr]   r
   dictr`   r5   r5   r5   r6   r.   |   s    *r.   c                   @   s  e Zd ZU dZedddidZee ed< edddidZ	ee ed< eddd	idZ
ee ed
< edddidZeed< edddidZee ed< edddidZeed< edddidZee ed< edddidZeed< edddidZeed< edddidZeed< edddidZeed < ed!dd"idZeed#< eddd$idZeed%< eddd&idZeed'< eddd(idZee ed)< eddd*idZee ed+< ed,dd-idZeed.< ed/dd0idZeed1< ed2d3g d4d5dZee ed6< eddd7idZeed8< eddd9idZee ed:< eddd;idZ eed<< eddd=idZ!eed>< ed?d@dAd?gd5dZ"eedB< edddCidZ#eedD< dS )EChatArgumentsz
    Arguments for the chat CLI.

    See the metadata arg for each argument's description -- the medatata will be printed with
    `transformers chat --help`
    Nhelpz_Name of the pre-trained model. The positional argument will take precedence if both are passed.)defaultmetadatamodel_name_or_pathzKUsername to display in chat interface. Defaults to the current user's name.r2   zSystem prompt.system_promptz./chat_history/zFolder to save chat history.save_folderz"Path to a yaml file with examples.examples_pathFz7Whether to show runtime warnings in the chat interface.verbosezPath to a local generation config file or to a HuggingFace repo containing a `generation_config.json` file. Other generation settings passed as CLI arguments will be applied on top of this generation config.r^   r"   z%Maximum number of tokens to generate.r!   Tz,Whether to sample outputs during generation.r#   r   z Number of beams for beam search.r$   r&   z%Temperature parameter for generation.r%   r(   zValue of k for top-k sampling.r'   z Value of p for nucleus sampling.r)   zRepetition penalty.r*   z\EOS tokens (text format) to stop the generation. If multiple they should be comma separated.r+   zQEOS token IDs to stop the generation. If multiple they should be comma separated.r-   mainzLSpecific model version to use (can be a branch name, tag name or commit id).model_revisioncpuzDevice to use for inference.deviceautozOverride the default `torch.dtype` and load the model under this dtype. If `'auto'` is passed, the dtype will be automatically derived from the model's weights.)rt   bfloat16float16float32)rh   choicestorch_dtypez2Whether to trust remote code when loading a model.trust_remote_codezWhich attention implementation to use; you can run --attn_implementation=flash_attention_2, in which case you must install this manually by running `pip install flash-attn --no-build-isolation`.attn_implementationzIWhether to use 8 bit precision for the base model - works only with LoRA.load_in_8bitzIWhether to use 4 bit precision for the base model - works only with LoRA.load_in_4bitnf4zQuantization type.fp4bnb_4bit_quant_typez#Whether to use nested quantization.use_bnb_nested_quant)$ra   rb   rc   __doc__r   rk   r   rd   __annotations__r2   rl   rm   rn   ro   re   r^   r!   intr#   r$   r%   floatr'   r)   r*   r+   r-   rq   rs   ry   rz   r{   r|   r}   r   r   r5   r5   r5   r6   rg      s   
 rg   argsc                 C   s   t | S )z;
    Factory function used to chat with a local model.
    )ChatCommand)r   r5   r5   r6   chat_command_factory0  s   r   c                   @   s  e Zd ZedefddZdd Zdedefdd	Zede	fd
dZ
ed/dedee	 de	fddZed/dee	 dee fddZdee	 defddZdedededeeef fddZedededee	 dee	 deeee f f
ddZededed  fd!d"Zdeded#ef fd$d%Zd&e	ded'ed(ee	ee	e	f f ded)ed*ee deee eef fd+d,Zd-d. ZdS )0r   parserc                 C   sT   t f}| jd|d}|d}|jdtddd |jdtdd	d
d |jtd dS )z
        Register this command to argparse so it's available for the transformer-cli

        Args:
            parser: Root parser to register command-specific arguments
        chat)dataclass_typeszPositional argumentsmodel_name_or_path_positionalNzName of the pre-trained model.)typeri   rh   generate_flagsa  Flags to pass to `generate`, using a space as a separator between flags. Accepts booleans, numbers, and lists of integers, more advanced parameterization should be set through --generation-config. Example: `transformers chat <model_repo> max_new_tokens=100 do_sample=False eos_token_id=[1,2]`. If you're a new user, check this basic flag guide: https://huggingface.co/docs/transformers/llm_tutorial#common-options*)r   ri   rh   nargs)func)rg   
add_parseradd_argument_groupadd_argumentrd   set_defaultsr   )r   r   chat_parsergroupr5   r5   r6   register_subcommand8  s   
zChatCommand.register_subcommandc                 C   s   |  |}|| _d S N)_handle_deprecated_argsr   )r4   r   r5   r5   r6   r7   U  s   

zChatCommand.__init__r   r9   c              
   C   s   d}|j p|j|_ |j du rtd|jdurd}tdt tD ] \}}}t||}||krAd}td| d| d| d	t q!|rKtd
 t	  |S )z
        Handles deprecated arguments and their deprecation cycle. To be removed after we fully migrated to the new
        args.
        FNzOne of the following must be provided:
- The positional argument containing the model repo, e.g. `transformers chat <model_repo>`
- the optional --model_name_or_path argument, containing the model repo (deprecated)TzThe --model_name_or_path argument is deprecated will be removed in v4.54.0. Use the positional argument instead, e.g. `transformers chat <model_repo>`.zThe --a.   argument is deprecated will be removed in v4.54.0. There are two alternative solutions to specify this generation option: 
1. Pass `--generation-config <path_to_file/Hub repo>` to specify a generation config.
2. Pass `generate` flags through positional arguments, e.g. `transformers chat <model_repo> =`z
(Press enter to continue))
r   rk   
ValueErrorwarningswarnFutureWarning_DEPRECATION_MAPgetattrr@   rR   )r4   r   has_warningsdeprecated_argdefault_valuenew_argvaluer5   r5   r6   r   Y  s:   


	z#ChatCommand._handle_deprecated_argsc                   C   s$   t  dkr
t S tt jS )z)Returns the username of the current user.r   )platformsystemosgetloginpwdgetpwuidgetuidpw_namer5   r5   r5   r6   get_username  s   zChatCommand.get_usernameNfilenamec                 C   s   i }t ||d< | |d< |j}|du r(td}|j d| d}tj||}tjtj	|dd t
|d	}tj||d
d W d   n1 sKw   Y  tj|S )z!Saves the chat history to a file.settingschat_historyNz%Y-%m-%d_%H-%M-%Sz/chat_.jsonT)exist_okwr;   )indent)varsrm   timestrftimer   r   pathrG   makedirsdirnameopenjsondumpabspath)r   r   r   output_dictfoldertime_strfr5   r5   r6   	save_chat  s   
zChatCommand.save_chatrl   c                 C   s    | du rg }|S d| dg}|S )zClears the chat history.Nr   rolecontentr5   )rl   r   r5   r5   r6   clear_chat_history  s
   zChatCommand.clear_chat_historyr   c                    s   t |dkri S dd |D }dd | D }dd | D }dtdtfdd	  fd
d| D }ddd | D }d| d }|dd}|dd}|dd}|dd}|dd}|dd}zt|}W |S  tjy   t	dw )zUParses the generate flags from the user input into a dictionary of `generate` kwargs.r   c                 S   s.   i | ]}d | dd  d  | dd qS )"r   r   r   )split).0flagr5   r5   r6   
<dictcomp>  s   . z4ChatCommand.parse_generate_flags.<locals>.<dictcomp>c                 S   s*   i | ]\}}||  d v r|  n|qS ))truefalse)lowerr   kvr5   r5   r6   r     s    c                 S   s"   i | ]\}}||d krdn|qS )Nonenullr5   r   r5   r5   r6   r     s   " sr9   c                 S   s(   |  dr| dd  } | ddd S )N-r   .r:   )rF   replaceisdigit)r   r5   r5   r6   	is_number  s   
z3ChatCommand.parse_generate_flags.<locals>.is_numberc                    s*   i | ]\}}| |sd | d n|qS )r   r5   r   r   r5   r6   r     s   * z, c                 S   s   g | ]\}}| d | qS )z: r5   r   r5   r5   r6   
<listcomp>  s    z4ChatCommand.parse_generate_flags.<locals>.<listcomp>{}z"null"r   z"true"r   z"false"r   z"[[z]"rV   r   :zFailed to convert `generate_flags` into a valid JSON object.
`generate_flags` = {generate_flags}
Converted JSON string = {generate_flags_string})
lenitemsrd   re   rG   r   r   loadsJSONDecodeErrorr   )r4   r   generate_flags_as_dictgenerate_flags_stringprocessed_generate_flagsr5   r   r6   parse_generate_flags  s2   z ChatCommand.parse_generate_flags	tokenizermodelc              
   C   s   |j du r3t|j }| |||j|j\}}|j|j|j|j	|j
|j|j||d	}|jdi | n d|j v rMtj|j }tj|j }	t||	}nt|j }| |j}
|jdi |
}||fS )zj
        Returns a GenerationConfig object holding the generation parameters for the CLI command.
        N)	r!   r#   r$   r%   r'   r)   r*   pad_token_idr,   r   r5   )r^   copydeepcopyparse_eos_tokensr+   r-   r!   r#   r$   r%   r'   r)   r*   rI   r   r   r   basenamer
   from_pretrainedr   r   )r4   r   r   r   r^   r   r-   deprecated_kwargsr   r   parsed_generate_flagsr_   r5   r5   r6   get_generation_parameterization  s0   

z+ChatCommand.get_generation_parameterizationr^   r+   r-   c                 C   s|   |j du r	|j}n|j }g }|dur|| |d |dur.|dd |dD  t|dkr:||j ||fS )z:Retrieves the pad token ID and all possible EOS token IDs.N,c                 S   s   g | ]}t |qS r5   )r   )r   token_idr5   r5   r6   r     s    z0ChatCommand.parse_eos_tokens.<locals>.<listcomp>r   )r   r,   extendconvert_tokens_to_idsr   r   rE   )r   r^   r+   r-   r   all_eos_token_idsr5   r5   r6   r   
  s   
zChatCommand.parse_eos_tokens
model_argsr   c                 C   s@   | j rtd| j| j| j| jd}|S | jrtdd}|S d }|S )NT)r}   bnb_4bit_compute_dtyper   bnb_4bit_use_double_quantbnb_4bit_quant_storage)r|   )r}   r   ry   r   r   r|   )r   quantization_configr5   r5   r6   get_quantization_config&  s    z#ChatCommand.get_quantization_configr   c                 C   s   t j|j|j|jd}|jdv r|jntt|j}| |}|j|j	|d|d}t
j|jfd|ji|}t|dd d u rC||j}||fS )N)revisionrz   )rt   Nrt   )r  r{   ry   
device_mapr   rz   hf_device_map)r	   r   r   rq   rz   ry   r   torchr  r{   r   tors   )r4   r   r   ry   r   r_   r   r5   r5   r6   load_model_and_tokenizer:  s.   
z$ChatCommand.load_model_and_tokenizer
user_input	interfaceexamplesr_   r   c                 C   s  d}|dkr|  |j}|  n|dkr|  n|drKt| dk rK| }	t|	dkr6|	d }
nd}
| |||
}
|jd|
 d	d
d n|dr|dd 	 }| }|D ]}d|vrq|jd| ddd  nq^| 
|}|jdi |}|jdi | ng|drt| dkr| d }||v r|  g }||| d  |d|| d d n4d| dt|  d}|j|dd n|dkr|j|j||d nd}|jd| ddd |  ||||fS )z
        Handles all user commands except for `!exit`. May update the chat history (e.g. reset it) or the
        generation config (e.g. set a new flag).
        Tz!clearz!helpz!save   r   NzChat saved in !green)r   rU   z!setr;   r   z(Invalid flag format, missing `=` after `z;`. Please use the format `arg_1=value_1 arg_2=value_2 ...`.red!exampler   r2   r   zExample z* not found in list of available examples: r   z!status)r/   r^   r_   F'z/' is not a valid command. Showing help message.r5   )r   rl   rS   r]   rF   r   r   r   rX   rH   r   rI   rT   rE   listkeysr`   r   )r4   r  r   r	  r
  r^   r_   r   valid_commandsplit_inputr   new_generate_flagsr   parsed_new_generate_flagsnew_model_kwargsexample_nameexample_errorr5   r5   r6   handle_non_exit_user_commandsU  s`   





z)ChatCommand.handle_non_exit_user_commandsc              	   C   s  t  stdt std| j}|jd u rt}nt|j}t|}W d    n1 s.w   Y  |j	d u r=| 
 }n|j	}| |\}}t|ddd}| |||\}}	|jsat  t  t|j|d}
|
  | |j}|
jdd 	 zj|
 }|dr|dkrW d S | j|||
|||	|d	\}}}}	|r|d
sW qxn|d|d |j|ddd|j}t |}||||d|	}t!|j"|d}|#  |
$|}|%  |d|d W n
 t&y   Y d S w qy)NzHYou need to install rich to use the chat interface. (`pip install rich`)zJYou need to install torch to use the chat interface. (`pip install torch`)T)skip_special_tokensskip_prompt)r/   r0   )rZ   r  z!exit)r  r   r	  r
  r^   r_   r   r  r2   r   pt)return_tensorsadd_generation_prompt)inputsattention_maskstreamerr^   )targetkwargsr1   )'r   ImportErrorr   r   rn   DEFAULT_EXAMPLESr   yaml	safe_loadr2   r   r  r   r   ro   r   set_verbosity_errorr   r.   r   rS   r   rl   r]   rR   rF   r  rE   apply_chat_templater  rs   r  	ones_liker   generatestartrP   rG   KeyboardInterrupt)r4   r   r
  r   r2   r   r   generation_streamerr^   r_   r	  r   r  r  r   r!  generation_kwargsthreadmodel_outputr5   r5   r6   run  s|   






zChatCommand.runr   )ra   rb   rc   staticmethodr   r   r7   rg   r   rd   r   r   r   r  rf   r   r   r	   r   tupler
   r   r   r   r   r  r  r.   r  r3  r5   r5   r5   r6   r   7  sl    +
6

*	
Tr   )<r   r   r   r   rB   stringr   r   argparser   r   dataclassesr   r   	threadingr   typingr   r'  huggingface_hub.utilsr   transformersr	   r
   r   r   r   transformers.utilsr   r   r:   r   r   r   rich.consoler   	rich.liver   rich.markdownr   r  r   r   r   setascii_letters
whitespaceALLOWED_KEY_CHARSdigitsALLOWED_VALUE_CHARSr&  r[   rG   r  r\   r   r.   rg   r   r   r5   r5   r5   r6   <module>   sd   	X[