from argparse import ArgumentParser, Namespace
from typing import Any, List, Optional

from ..pipelines import Pipeline, get_supported_tasks, pipeline
from ..utils import logging
from . import BaseTransformersCLICommand


try:
       from fastapi import Body, FastAPI, HTTPException
       from fastapi.routing import APIRoute
       from pydantic import BaseModel
       from starlette.responses import JSONResponse
       from uvicorn import run

       a_							=      True
except (ImportError, AttributeError):
       a_							=      object




       def       __lowerCAmelCase      (						*A_   : int						,	**A_   : Optional[int]					)    ->  Any:
         pass





       a_							=      False


a_							=      logging.get_logger("""transformers-cli/serving""")




def       __lowerCAmelCase      (						A_   : Namespace					)    ->  Any:
  __UpperCAmelCase						    =       pipeline(
      task=args.task						,	model=args.model if args.model else None						,	config=args.config						,	tokenizer=args.tokenizer						,	device=args.device						,	)
  return ServeCommand(A_						,	args.host						,	args.port						,	args.workers					)


class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  lowerCAmelCase__		:	dict






class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  lowerCAmelCase__		:	List[str]
  lowerCAmelCase__		:	Optional[List[int]]






class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  lowerCAmelCase__		:	str






class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  lowerCAmelCase__		:	Any






class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  @staticmethod
  def 	_UpperCAmelCase				(				__lowerCAmelCase:			ArgumentParser   ) -> Tuple:




    '''simple docstring'''




    __UpperCAmelCase						    =       parser.add_parser(
        "serve"				,				help="CLI tool to run inference requests through REST and GraphQL endpoints."   )
    serve_parser.add_argument(
        "--task"				,				type=__lowerCAmelCase				,				choices=get_supported_tasks()				,				help="The task to run the pipeline on"				,				)
    serve_parser.add_argument("--host"				,				type=__lowerCAmelCase				,				default="localhost"				,				help="Interface the server will listen on."   )
    serve_parser.add_argument("--port"				,				type=__lowerCAmelCase				,				default=8_888				,				help="Port the serving will listen to."   )
    serve_parser.add_argument("--workers"				,				type=__lowerCAmelCase				,				default=1				,				help="Number of http workers"   )
    serve_parser.add_argument("--model"				,				type=__lowerCAmelCase				,				help="Model's name or path to stored model."   )
    serve_parser.add_argument("--config"				,				type=__lowerCAmelCase				,				help="Model's config name or path to stored model."   )
    serve_parser.add_argument("--tokenizer"				,				type=__lowerCAmelCase				,				help="Tokenizer name to use."   )
    serve_parser.add_argument(
        "--device"				,				type=__lowerCAmelCase				,				default=-1				,				help="Indicate the device to run onto, -1 indicates CPU, >= 0 indicates GPU (default: -1)"				,				)
    serve_parser.set_defaults(func=__lowerCAmelCase   )






  def __init__(				self:			int				,				__lowerCAmelCase:			Pipeline				,				__lowerCAmelCase:			str				,				__lowerCAmelCase:			int				,				__lowerCAmelCase:			int   ) -> Optional[int]:




    '''simple docstring'''




    __UpperCAmelCase						    =       pipeline

    __UpperCAmelCase						    =       host
    __UpperCAmelCase						    =       port
    __UpperCAmelCase						    =       workers

    if not _serve_dependencies_installed:
      raise RuntimeError(
          "Using serve command requires FastAPI and uvicorn. "
          "Please install transformers with [serving]: pip install \"transformers[serving]\"."
          "Or install FastAPI and uvicorn separately."   )
    else:
      logger.info(F'''Serving model over {host}:{port}'''   )
      __UpperCAmelCase						    =       FastAPI(
          routes=[
              APIRoute(
                  "/"				,				self.model_info				,				response_model=__lowerCAmelCase				,				response_class=__lowerCAmelCase				,				methods=["GET"]				,				),
              APIRoute(
                  "/tokenize"				,				self.tokenize				,				response_model=__lowerCAmelCase				,				response_class=__lowerCAmelCase				,				methods=["POST"]				,				),
              APIRoute(
                  "/detokenize"				,				self.detokenize				,				response_model=__lowerCAmelCase				,				response_class=__lowerCAmelCase				,				methods=["POST"]				,				),
              APIRoute(
                  "/forward"				,				self.forward				,				response_model=__lowerCAmelCase				,				response_class=__lowerCAmelCase				,				methods=["POST"]				,				),
          ]				,				timeout=600				,				)






  def 	_UpperCAmelCase				(				self:			Dict   ) -> Dict:




    '''simple docstring'''




    run(self._app				,				host=self.host				,				port=self.port				,				workers=self.workers   )






  def 	_UpperCAmelCase				(				self:			str   ) -> int:




    '''simple docstring'''




    return ServeModelInfoResult(infos=vars(self._pipeline.model.config   )   )






  def 	_UpperCAmelCase				(				self:			int				,				__lowerCAmelCase:			str = Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )				,				__lowerCAmelCase:			bool = Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )   ) -> str:




    '''simple docstring'''




    try:
      __UpperCAmelCase						    =       self._pipeline.tokenizer.tokenize(__lowerCAmelCase   )

      if return_ids:
        __UpperCAmelCase						    =       self._pipeline.tokenizer.convert_tokens_to_ids(__lowerCAmelCase   )
        return ServeTokenizeResult(tokens=__lowerCAmelCase				,				tokens_ids=__lowerCAmelCase   )
      else:
        return ServeTokenizeResult(tokens=__lowerCAmelCase   )

    except Exception as e:
      raise HTTPException(status_code=500				,				detail={"model": "", "error": str(__lowerCAmelCase   )}   )






  def 	_UpperCAmelCase				(				self:			int				,				__lowerCAmelCase:			List[int] = Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )				,				__lowerCAmelCase:			bool = Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )				,				__lowerCAmelCase:			bool = Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )				,				) -> int:




    '''simple docstring'''




    try:
      __UpperCAmelCase						    =       self._pipeline.tokenizer.decode(__lowerCAmelCase				,				__lowerCAmelCase				,				__lowerCAmelCase   )
      return ServeDeTokenizeResult(model=""				,				text=__lowerCAmelCase   )
    except Exception as e:
      raise HTTPException(status_code=500				,				detail={"model": "", "error": str(__lowerCAmelCase   )}   )






  async def 	_UpperCAmelCase				(				self:			str				,				__lowerCAmelCase:			List[Any]=Body(__lowerCAmelCase				,				embed=__lowerCAmelCase   )   ) -> int:




    '''simple docstring'''




    if len(__lowerCAmelCase   ) == 0:
      return ServeForwardResult(output=[]				,				attention=[]   )

    try:
      # Forward through the model
      __UpperCAmelCase						    =       self._pipeline(__lowerCAmelCase   )
      return ServeForwardResult(output=__lowerCAmelCase   )
    except Exception as e:
      raise HTTPException(500				,				{"error": str(__lowerCAmelCase   )}   )




from sklearn.metrics import fa_score

import datasets


a_							=      """
The F1 score is the harmonic mean of the precision and recall. It can be computed with the equation:
F1 = 2 * (precision * recall) / (precision + recall)
"""


a_							=      """
Args:
    predictions (`list` of `int`): Predicted labels.
    references (`list` of `int`): Ground truth labels.
    labels (`list` of `int`): The set of labels to include when `average` is not set to `'binary'`, and the order of the labels if `average` is `None`. Labels present in the data can be excluded, for example to calculate a multiclass average ignoring a majority negative class. Labels not present in the data will result in 0 components in a macro average. For multilabel targets, labels are column indices. By default, all labels in `predictions` and `references` are used in sorted order. Defaults to None.
    pos_label (`int`): The class to be considered the positive class, in the case where `average` is set to `binary`. Defaults to 1.
    average (`string`): This parameter is required for multiclass/multilabel targets. If set to `None`, the scores for each class are returned. Otherwise, this determines the type of averaging performed on the data. Defaults to `'binary'`.

        - 'binary': Only report results for the class specified by `pos_label`. This is applicable only if the classes found in `predictions` and `references` are binary.
        - 'micro': Calculate metrics globally by counting the total true positives, false negatives and false positives.
        - 'macro': Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account.
        - 'weighted': Calculate metrics for each label, and find their average weighted by support (the number of true instances for each label). This alters `'macro'` to account for label imbalance. This option can result in an F-score that is not between precision and recall.
        - 'samples': Calculate metrics for each instance, and find their average (only meaningful for multilabel classification).
    sample_weight (`list` of `float`): Sample weights Defaults to None.

Returns:
    f1 (`float` or `array` of `float`): F1 score or list of f1 scores, depending on the value passed to `average`. Minimum possible value is 0. Maximum possible value is 1. Higher f1 scores are better.

Examples:

    Example 1-A simple binary example
        >>> f1_metric = datasets.load_metric(\"f1\")
        >>> results = f1_metric.compute(references=[0, 1, 0, 1, 0], predictions=[0, 0, 1, 1, 0])
        >>> print(results)
        {'f1': 0.5}

    Example 2-The same simple binary example as in Example 1, but with `pos_label` set to `0`.
        >>> f1_metric = datasets.load_metric(\"f1\")
        >>> results = f1_metric.compute(references=[0, 1, 0, 1, 0], predictions=[0, 0, 1, 1, 0], pos_label=0)
        >>> print(round(results['f1'], 2))
        0.67

    Example 3-The same simple binary example as in Example 1, but with `sample_weight` included.
        >>> f1_metric = datasets.load_metric(\"f1\")
        >>> results = f1_metric.compute(references=[0, 1, 0, 1, 0], predictions=[0, 0, 1, 1, 0], sample_weight=[0.9, 0.5, 3.9, 1.2, 0.3])
        >>> print(round(results['f1'], 2))
        0.35

    Example 4-A multiclass example, with different values for the `average` input.
        >>> predictions = [0, 2, 1, 0, 0, 1]
        >>> references = [0, 1, 2, 0, 1, 2]
        >>> results = f1_metric.compute(predictions=predictions, references=references, average=\"macro\")
        >>> print(round(results['f1'], 2))
        0.27
        >>> results = f1_metric.compute(predictions=predictions, references=references, average=\"micro\")
        >>> print(round(results['f1'], 2))
        0.33
        >>> results = f1_metric.compute(predictions=predictions, references=references, average=\"weighted\")
        >>> print(round(results['f1'], 2))
        0.27
        >>> results = f1_metric.compute(predictions=predictions, references=references, average=None)
        >>> print(results)
        {'f1': array([0.8, 0. , 0. ])}
"""


a_							=      """
@article{scikit-learn,
    title={Scikit-learn: Machine Learning in {P}ython},
    author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.
           and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P.
           and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and
           Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.},
    journal={Journal of Machine Learning Research},
    volume={12},
    pages={2825--2830},
    year={2011}
}
"""


@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION		,	_KWARGS_DESCRIPTION					)
class 			UpperCAmelCase__    (		datasets.Metric					):



  """simple docstring"""






  def 	_UpperCAmelCase				(				self:			int   ) -> Dict:




    '''simple docstring'''




    return datasets.MetricInfo(
        description=_DESCRIPTION				,				citation=_CITATION				,				inputs_description=_KWARGS_DESCRIPTION				,				features=datasets.Features(
            {
                "predictions": datasets.Sequence(datasets.Value("int32"   )   ),
                "references": datasets.Sequence(datasets.Value("int32"   )   ),
            }
            if self.config_name == "multilabel"
            else {
                "predictions": datasets.Value("int32"   ),
                "references": datasets.Value("int32"   ),
            }   )				,				reference_urls=["https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html"]				,				)






  def 	_UpperCAmelCase				(				self:			Any				,				__lowerCAmelCase:			Tuple				,				__lowerCAmelCase:			Any				,				__lowerCAmelCase:			List[Any]=None				,				__lowerCAmelCase:			Optional[Any]=1				,				__lowerCAmelCase:			List[Any]="binary"				,				__lowerCAmelCase:			List[Any]=None   ) -> Optional[int]:




    '''simple docstring'''




    __UpperCAmelCase						    =       fa_score(
        __lowerCAmelCase				,				__lowerCAmelCase				,				labels=__lowerCAmelCase				,				pos_label=__lowerCAmelCase				,				average=__lowerCAmelCase				,				sample_weight=__lowerCAmelCase   )
    return {"f1": float(__lowerCAmelCase   ) if score.size == 1 else score}



