U
    9%eu                     @   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mZm	Z	m
Z
mZmZ d dlmZmZmZmZ d dlmZmZmZ ddl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"m#Z#m$Z$ d
dl%m&Z&m'Z' e$(e)Z*e" rd dl+Z+e! rd dl,m-Z- dZ.d2ddZ/dZ0G dd dZ1G dd de1Z2G dd de1Z3e1dddZ4dd Z5ddddd d!d"d#d$d%d&
Z6d'd( Z7d)d* Z8d3d,d-Z9d.d/ Z:G d0d1 d1Z;dS )4    N)AnyDictListOptionalUnion)create_repohf_hub_downloadmetadata_updateupload_folder)RepositoryNotFoundErrorbuild_hf_headersget_session   )custom_object_saveget_class_from_dynamic_moduleget_imports)is_pil_image)AutoProcessor)CONFIG_NAMEcached_fileis_accelerate_availableis_torch_availableis_vision_availablelogging   )handle_agent_inputshandle_agent_outputs)send_to_devicetool_config.jsonc                 K   s   |d k	r|S zt | tfddi| W dS  tk
r   zt | tfddi| W Y dS  tk
rz   td|  dY n tk
r   Y Y dS X Y n tk
r   Y dS X d S )N	repo_typespacemodel`z9` does not seem to be a valid repo identifier on the Hub.)r   TOOL_CONFIG_FILEr   EnvironmentError	Exception)repo_idr   
hub_kwargs r(   V/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/transformers/tools/base.pyget_repo_type7   s    r*   zufrom transformers import launch_gradio_demo
from {module_name} import {class_name}

launch_gradio_demo({class_name})
c                   @   s   e Zd ZU dZdZeed< dZeed< ee ed< ee ed< dd	 Z	d
d Z
dd Zdd Zedeee ee edddZdeeee eeeef  eedddZedd ZdS )Toola  
    A base class for the functions used by the agent. Subclass this and implement the `__call__` method as well as the
    following class attributes:

    - **description** (`str`) -- A short description of what your tool does, the inputs it expects and the output(s) it
      will return. For instance 'This is a tool that downloads a file from a `url`. It takes the `url` as input, and
      returns the text contained in the file'.
    - **name** (`str`) -- A performative name that will be used for your tool in the prompt to the agent. For instance
      `"text-classifier"` or `"image_generator"`.
    - **inputs** (`List[str]`) -- The list of modalities expected for the inputs (in the same order as in the call).
      Modalitiies should be `"text"`, `"image"` or `"audio"`. This is only used by `launch_gradio_demo` or to make a
      nice space from your tool.
    - **outputs** (`List[str]`) -- The list of modalities returned but the tool (in the same order as the return of the
      call method). Modalitiies should be `"text"`, `"image"` or `"audio"`. This is only used by `launch_gradio_demo`
      or to make a nice space from your tool.

    You can also override the method [`~Tool.setup`] if your tool as an expensive operation to perform before being
    usable (such as loading a model). [`~Tool.setup`] will be called the first time you use your tool, but not at
    instantiation.
    zThis is a tool that ...description nameinputsoutputsc                 O   s
   d| _ d S )NFis_initializedselfargskwargsr(   r(   r)   __init__m   s    zTool.__init__c                 O   s   t dS )Nz-Write this method in your subclass of `Tool`.)NotImplementedr3   r(   r(   r)   __call__p   s    zTool.__call__c                 C   s
   d| _ dS )z
        Overwrite this method here for any operation that is expensive and needs to be executed before you start using
        your tool. Such as loading a big model.
        TNr1   r4   r(   r(   r)   setups   s    z
Tool.setupc              	   C   s  t j|dd | jdkr.td|  d| dt| |}| jj}|dd }| d| jj }t j	|d	}t j
|rt|d
dd}t|}W 5 Q R X ni }|| j| jd}t|ddd }|tj|dddd  W 5 Q R X t j	|d}	t|	ddd}|tj|| jjd W 5 Q R X t j	|d}
g }|D ]}|t| q>tt|}t|
ddd}|d	|d  W 5 Q R X dS )a  
        Saves the relevant code files for your tool so it can be pushed to the Hub. This will copy the code of your
        tool in `output_dir` as well as autogenerate:

        - a config file named `tool_config.json`
        - an `app.py` file so that your tool can be converted to a space
        - a `requirements.txt` containing the names of the module used by your tool (as detected when inspecting its
          code)

        You should only use this method to save tools that are defined in a separate module (not `__main__`).

        Args:
            output_dir (`str`): The folder in which you want to save your tool.
        T)exist_ok__main__z We can't save the code defining z in z{ as it's been defined in __main__. You have to put this code in a separate module so we can include it in the saved folder..r   rutf-8encoding)
tool_classr,   r.   wr   )indent	sort_keys
zapp.py)module_name
class_namezrequirements.txtN)osmakedirs
__module__
ValueErrorr   	__class__split__name__pathjoinisfileopenjsonloadr,   r.   writedumpsAPP_FILE_TEMPLATEformatextendr   listset)r4   
output_dirZmodule_filesrI   Zlast_moduleZ	full_nameconfig_filefZtool_configZapp_fileZrequirements_fileZimportsmoduler(   r(   r)   savez   s6    

$"z	Tool.saveNF)r&   model_repo_idtokenremotec              	      s  |r2|dkr2t  }||kr*td| d|| }dddddd	d
dg  fdd| D }t|f||d	< t|tfd|i|ddd}|dk	}	|dkrt|tfd|i|ddd}|dkrt| dt|dd}
t	
|
}W 5 Q R X |	sd|krt| d|d }n|}|d }t||fd|i|}t|jdkrT|d |_|j|d krt|j d |d |_t|jdkr|d |_|j|d krt|j d |d |_|rt|||dS ||fd|i|S )aw  
        Loads a tool defined on the Hub.

        Args:
            repo_id (`str`):
                The name of the repo on the Hub where your tool is defined.
            model_repo_id (`str`, *optional*):
                If your tool uses a model and you want to use a different model than the default, you can pass a second
                repo ID or an endpoint url to this argument.
            token (`str`, *optional*):
                The token to identify you on hf.co. If unset, will use the token generated when running
                `huggingface-cli login` (stored in `~/.huggingface`).
            remote (`bool`, *optional*, defaults to `False`):
                Whether to use your tool by downloading the model or (if it is available) with an inference endpoint.
            kwargs (additional keyword arguments, *optional*):
                Additional keyword arguments that will be split in two: all arguments relevant to the Hub (such as
                `cache_dir`, `revision`, `subfolder`) will be used when downloading the files for your tool, and the
                others will be passed along to its init.
        N'Could not infer a default endpoint for :, you need to pass one using the `model_repo_id` argument.	cache_dirZforce_downloadZresume_downloadproxiesrevisionr   Z	subfolderZlocal_files_onlyc                    s   i | ]\}}| kr||qS r(   r(   ).0kvZhub_kwargs_namesr(   r)   
<dictcomp>   s       z!Tool.from_hub.<locals>.<dictcomp>Zuse_auth_tokenF)Z%_raise_exceptions_for_missing_entriesZ'_raise_exceptions_for_connection_errorszY does not appear to provide a valid configuration in `tool_config.json` or `config.json`.rA   rB   custom_toolzO does not provide a mapping to custom tools in its configuration `config.json`.rD   r   r.   z_ implements a different name in its configuration and class. Using the tool configuration name.r,   zm implements a different description in its configuration and class. Using the tool configuration description.re   rD   re   )get_default_endpointsrN   itemsr*   r   r#   r   r$   rU   rV   rW   r   lenr.   loggerwarningrQ   r,   
RemoteTool)clsr&   rd   re   rf   r6   	endpointsr'   Zresolved_config_fileZis_tool_configreaderconfigrq   rD   r(   ro   r)   from_hub   s    











zTool.from_hubUpload tool)r&   commit_messageprivatere   	create_prreturnc                 C   s   t |||dddd}|j}t|ddgidd t N}| | td| d	d
t	
|  t|||||ddW  5 Q R  S Q R X dS )a  
        Upload the tool to the Hub.

        Parameters:
            repo_id (`str`):
                The name of the repository you want to push your tool to. It should contain your organization name when
                pushing to a given organization.
            commit_message (`str`, *optional*, defaults to `"Upload tool"`):
                Message to commit while pushing.
            private (`bool`, *optional*):
                Whether or not the repository created should be private.
            token (`bool` or `str`, *optional*):
                The token to use as HTTP bearer authorization for remote files. If unset, will use the token generated
                when running `huggingface-cli login` (stored in `~/.huggingface`).
            create_pr (`bool`, *optional*, defaults to `False`):
                Whether or not to create a PR with the uploaded files or directly commit.
        Tr    gradio)r&   re   r   r<   r   Z	space_sdktagstoolr   z!Uploading the following files to z: ,)r&   r   Zfolder_pathre   r   r   N)r   r&   r	   tempfileTemporaryDirectoryrc   rv   inforS   rK   listdirr
   )r4   r&   r   r   re   r   repo_urlZwork_dirr(   r(   r)   push_to_hub  s*         

"zTool.push_to_hubc                 C   s    G dd dt }| j|_|| S )z8
        Creates a [`Tool`] from a gradio tool.
        c                       s   e Zd Z fddZ  ZS )z+Tool.from_gradio.<locals>.GradioToolWrapperc                    s   t    |j| _|j| _d S N)superr7   r.   r,   )r4   Z_gradio_toolrO   r(   r)   r7   Q  s    
z4Tool.from_gradio.<locals>.GradioToolWrapper.__init__)rQ   rM   __qualname__r7   __classcell__r(   r(   r   r)   GradioToolWrapperP  s   r   )r+   runr9   )Zgradio_toolr   r(   r(   r)   from_gradioJ  s    zTool.from_gradio)NNF)r~   NNF)rQ   rM   r   __doc__r,   str__annotations__r.   r   r7   r9   r;   rc   classmethodr   boolr}   r   r   staticmethodr   r(   r(   r(   r)   r+   Q   sB   
6   p    ,r+   c                   @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )rx   ah  
    A [`Tool`] that will make requests to an inference endpoint.

    Args:
        endpoint_url (`str`):
            The url of the endpoint to use.
        token (`str`, *optional*):
            The token to use as HTTP bearer authorization for remote files. If unset, will use the token generated when
            running `huggingface-cli login` (stored in `~/.huggingface`).
        tool_class (`type`, *optional*):
            The corresponding `tool_class` if this is a remote version of an existing tool. Will help determine when
            the output should be converted to another type (like images).
    Nc                 C   s   || _ t||d| _|| _d S )Nre   )endpoint_urlEndpointClientclientrD   )r4   r   re   rD   r(   r(   r)   r7   i  s    zRemoteTool.__init__c                 O   sN  |  }t|dkr| jdk	rt| jtr6| jj}n| jj}t|j	}dd |
 D }|d dkrt|dd }t|t|krt| j dt| dt| d	t||D ]\}}|||< qnRt|dkrtd
n<t|dkrt|d rd| j|d iS d|d iS |
 D ]$\}	}
t|
r | j|
||	< q d|iS )aP  
        Prepare the inputs received for the HTTP client sending data to the endpoint. Positional arguments will be
        matched with the signature of the `tool_class` if it was provided at instantation. Images will be encoded into
        bytes.

        You can override this method in your custom class of [`RemoteTool`].
        r   Nc                 S   s*   g | ]"\}}|j tjjtjjfkr|qS r(   )kindinspect_ParameterKindVAR_POSITIONALVAR_KEYWORD)rl   rm   pr(   r(   r)   
<listcomp>  s   z-RemoteTool.prepare_inputs.<locals>.<listcomp>r4   r   z only accepts z arguments but z were given.z4A `RemoteTool` can only accept one positional input.r/   )copyru   rD   
issubclassPipelineToolencoder9   r   	signature
parametersrt   rN   zipr   r   encode_image)r4   r5   r6   r/   Zcall_methodr   r   argr.   keyvaluer(   r(   r)   prepare_inputsn  s8    



zRemoteTool.prepare_inputsc                 C   s   |S )z
        You can override this method in your custom class of [`RemoteTool`] to apply some custom post-processing of the
        outputs of the endpoint.
        r(   r4   r0   r(   r(   r)   extract_outputs  s    zRemoteTool.extract_outputsc                 O   s   t ||\}}| jd k	o$| jjdgk}| j||}t|trR| jf |d|i}n| j||d}t|trt|dkrt|d tr|d }t	|| jd k	r| jjnd }| 
|S )Nimageoutput_image)r   r   r   )r   rD   r0   r   
isinstancedictr   r]   ru   r   r   )r4   r5   r6   r   r/   r0   r(   r(   r)   r9     s    
$zRemoteTool.__call__)NNN)rQ   rM   r   r   r7   r   r   r9   r(   r(   r(   r)   rx   Z  s
   
+rx   c                       s^   e Zd ZdZeZdZeZdZd fdd	Z	 fddZ
dd Zd	d
 Zdd Zdd Z  ZS )r   a0	  
    A [`Tool`] tailored towards Transformer models. On top of the class attributes of the base class [`Tool`], you will
    need to specify:

    - **model_class** (`type`) -- The class to use to load the model in this tool.
    - **default_checkpoint** (`str`) -- The default checkpoint that should be used when the user doesn't specify one.
    - **pre_processor_class** (`type`, *optional*, defaults to [`AutoProcessor`]) -- The class to use to load the
      pre-processor
    - **post_processor_class** (`type`, *optional*, defaults to [`AutoProcessor`]) -- The class to use to load the
      post-processor (when different from the pre-processor).

    Args:
        model (`str` or [`PreTrainedModel`], *optional*):
            The name of the checkpoint to use for the model, or the instantiated model. If unset, will default to the
            value of the class attribute `default_checkpoint`.
        pre_processor (`str` or `Any`, *optional*):
            The name of the checkpoint to use for the pre-processor, or the instantiated pre-processor (can be a
            tokenizer, an image processor, a feature extractor or a processor). Will default to the value of `model` if
            unset.
        post_processor (`str` or `Any`, *optional*):
            The name of the checkpoint to use for the post-processor, or the instantiated pre-processor (can be a
            tokenizer, an image processor, a feature extractor or a processor). Will default to the `pre_processor` if
            unset.
        device (`int`, `str` or `torch.device`, *optional*):
            The device on which to execute the model. Will default to any accelerator available (GPU, MPS etc...), the
            CPU otherwise.
        device_map (`str` or `dict`, *optional*):
            If passed along, will be used to instantiate the model.
        model_kwargs (`dict`, *optional*):
            Any keyword argument to send to the model instantiation.
        token (`str`, *optional*):
            The token to use as HTTP bearer authorization for remote files. If unset, will use the token generated when
            running `huggingface-cli login` (stored in `~/.huggingface`).
        hub_kwargs (additional keyword arguments, *optional*):
            Any additional keyword argument to send to the methods that will load the data from the Hub.
    Nc           	         s   t  stdt std|d kr<| jd kr6td| j}|d krH|}|| _|| _|| _|| _|| _	|d krri n|| _
|d k	r|| j
d< || _|| jd< t   d S )N/Please install torch in order to use this tool.z4Please install accelerate in order to use this tool.zHThis tool does not implement a default checkpoint, you need to pass one.
device_mapre   )r   ImportErrorr   default_checkpointrN   r!   pre_processorpost_processordevicer   model_kwargsr'   r   r7   )	r4   r!   r   r   r   r   r   re   r'   r   r(   r)   r7     s*    


zPipelineTool.__init__c                    s   t | jtr"| jj| jf| j| _t | jtrJ| jj| jf| j| j| _| j	dkr^| j| _	n"t | j	tr| j
j| j	f| j| _	| jdkr| jdk	rt| jj d | _nt | _| jdkr| j| j t   dS )z^
        Instantiates the `pre_processor`, `model` and `post_processor` if necessary.
        Nr   )r   r   r   pre_processor_classZfrom_pretrainedr'   r!   model_classr   r   post_processor_classr   r   r]   Zhf_device_mapvaluesget_default_devicetor   r;   r:   r   r(   r)   r;     s    




zPipelineTool.setupc                 C   s
   |  |S )zQ
        Uses the `pre_processor` to prepare the inputs for the `model`.
        )r   )r4   Z
raw_inputsr(   r(   r)   r     s    zPipelineTool.encodec              
   C   s,   t   | jf |W  5 Q R  S Q R X dS )z7
        Sends the inputs through the `model`.
        N)torchZno_gradr!   )r4   r/   r(   r(   r)   forward!  s    
zPipelineTool.forwardc                 C   s
   |  |S )zG
        Uses the `post_processor` to decode the model output.
        )r   r   r(   r(   r)   decode(  s    zPipelineTool.decodec                 O   s^   t ||\}}| js|   | j||}t|| j}| |}t|d}| |}t|| j	S )Ncpu)
r   r2   r;   r   r   r   r   r   r   r0   )r4   r5   r6   Zencoded_inputsr0   Zdecoded_outputsr(   r(   r)   r9   .  s    


zPipelineTool.__call__)NNNNNNN)rQ   rM   r   r   r   r   r   r   r   r7   r;   r   r   r   r9   r   r(   r(   r   r)   r     s$   %       %r   )rD   c                    s`   zddl }W n tk
r(   tdY nX |    fdd}|j|| j| j| j jd  dS )z
    Launches a gradio demo for a tool. The corresponding tool class needs to properly implement the class attributes
    `inputs` and `outputs`.

    Args:
        tool_class (`type`): The class of the tool for which to launch the demo.
    r   Nz<Gradio should be installed in order to launch a gradio demo.c                     s
    | |S r   r(   )r5   r6   r   r(   r)   fnL  s    zlaunch_gradio_demo.<locals>.fn)r   r/   r0   titleZarticle)r   r   Z	Interfacer/   r0   rQ   r,   Zlaunch)rD   grr   r(   r   r)   launch_gradio_demo=  s    r   c                   C   sR   t  stdtjj r0tjj r0tdS tj rDtdS tdS d S )Nr   mpscudar   )	r   r   r   backendsr   Zis_availableZis_builtr   r   r(   r(   r(   r)   r   Y  s    


r   ZDocumentQuestionAnsweringToolZImageCaptioningToolZImageQuestionAnsweringToolZImageSegmentationToolZSpeechToTextToolZTextSummarizationToolZTextClassificationToolZTextQuestionAnsweringToolZTextToSpeechToolZTranslationTool)
zdocument-question-answeringzimage-captioningzimage-question-answeringzimage-segmentationzspeech-to-textZsummarizationztext-classificationztext-question-answeringztext-to-speechtranslationc               	   C   s6   t dddd} t| ddd}t|}W 5 Q R X |S )Nz#huggingface-tools/default-endpointszdefault_endpoints.jsonZdatasetr   r@   rA   rB   )r   rU   rV   rW   )Zendpoints_filera   rz   r(   r(   r)   rs   s  s    rs   c                 C   s   t  }| |kS r   )rs   )task_or_repo_idrz   r(   r(   r)   supports_remotez  s    r   Fc           
      K   s   | t krt |  }td}|j}t||}|rj|dkr\t }	| |	krTtd|  d|	|  }t|||dS ||fd|i|S ntj	| f|||d|S dS )a  
    Main function to quickly load a tool, be it on the Hub or in the Transformers library.

    Args:
        task_or_repo_id (`str`):
            The task for which to load the tool or a repo ID of a tool on the Hub. Tasks implemented in Transformers
            are:

            - `"document-question-answering"`
            - `"image-captioning"`
            - `"image-question-answering"`
            - `"image-segmentation"`
            - `"speech-to-text"`
            - `"summarization"`
            - `"text-classification"`
            - `"text-question-answering"`
            - `"text-to-speech"`
            - `"translation"`

        model_repo_id (`str`, *optional*):
            Use this argument to use a different model than the default one for the tool you selected.
        remote (`bool`, *optional*, defaults to `False`):
            Whether to use your tool by downloading the model or (if it is available) with an inference endpoint.
        token (`str`, *optional*):
            The token to identify you on hf.co. If unset, will use the token generated when running `huggingface-cli
            login` (stored in `~/.huggingface`).
        kwargs (additional keyword arguments, *optional*):
            Additional keyword arguments that will be split in two: all arguments relevant to the Hub (such as
            `cache_dir`, `revision`, `subfolder`) will be used when downloading the files for your tool, and the others
            will be passed along to its init.
    ZtransformersNrg   rh   rr   re   )rd   re   rf   )
TASK_MAPPING	importlibimport_moduleZtoolsgetattrrs   rN   rx   r+   r}   )
r   rd   rf   re   r6   Ztool_class_nameZmain_moduleZtools_modulerD   rz   r(   r(   r)   	load_tool  s      


r   c                    s    fdd}|S )z<
    A decorator that adds a description to a function.
    c                    s    | _ | j| _| S r   )r,   rQ   r.   )funcr,   r(   r)   inner  s    zadd_description.<locals>.innerr(   )r,   r   r(   r   r)   add_description  s    r   c                	   @   sv   e Zd Zdeee dddZedd Zedd Zdee	ee
ee eee  f  ee
 ee eed
ddZdS )r   N)r   re   c                 C   s   t |dddi| _|| _d S )Nr   zContent-Typezapplication/json)r   headersr   )r4   r   re   r(   r(   r)   r7     s    zEndpointClient.__init__c                 C   s.   t  }| j|dd t| }|dS )NZPNG)r[   rA   )ioBytesIOrc   base64	b64encodegetvaluer   )r   _bytesb64r(   r(   r)   r     s    zEndpointClient.encode_imagec                 C   s8   t  stdddlm} t| }t|}||S )NzbThis tool returned an image but Pillow is not installed. Please install it (`pip install Pillow`).r   )Image)	r   r   ZPILr   r   	b64decoder   r   rU   )Z	raw_imager   r   r   r(   r(   r)   decode_image  s    

zEndpointClient.decode_imageF)r/   paramsdatar   r   c                 C   sP   i }|r||d< |r||d< t  j| j| j||d}|rD| |jS | S d S )Nr/   r   )r   rV   r   )r   postr   r   r   contentrV   )r4   r/   r   r   r   payloadresponser(   r(   r)   r9     s    zEndpointClient.__call__)N)NNNF)rQ   rM   r   r   r   r7   r   r   r   r   r   r   bytesr   r   r9   r(   r(   r(   r)   r     s    

    r   )N)NFN)<r   r   r   r   rV   rK   r   typingr   r   r   r   r   Zhuggingface_hubr   r   r	   r
   Zhuggingface_hub.utilsr   r   r   Zdynamic_module_utilsr   r   r   Zimage_utilsr   Zmodels.autor   utilsr   r   r   r   r   r   Zagent_typesr   r   Z
get_loggerrQ   rv   r   Zaccelerate.utilsr   r#   r*   rZ   r+   rx   r   r   r   r   rs   r   r   r   r   r(   r(   r(   r)   <module>   s\    

  W 
6