





import os
from shutil import copyfile
from typing import TYPE_CHECKING, Optional, Tuple

from tokenizers import processors

from ...tokenization_utils_fast import PreTrainedTokenizerFast
from ...utils import is_sentencepiece_available, logging
from ...utils.versions import require_version


if TYPE_CHECKING:
			from transformers.pipelines.conversational import Conversation

require_version("""tokenizers>=0.13.3""")

if is_sentencepiece_available():
			from .tokenization_llama import LlamaTokenizer
else:
			__UpperCamelCase:  Any   =   None

__UpperCamelCase:  List[str]   =   logging.get_logger(__name__)
__UpperCamelCase:  Dict   =   {"""vocab_file""": """tokenizer.model""", """tokenizer_file""": """tokenizer.json"""}

__UpperCamelCase,  __UpperCamelCase:  Tuple   =   """[INST]""", """[/INST]"""
__UpperCamelCase,  __UpperCamelCase:  Optional[int]   =   """<<SYS>>\n""", """\n<</SYS>>\n\n"""

# fmt: off
__UpperCamelCase:  List[Any]   =   """You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your\
answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure\
that your responses are socially unbiased and positive in nature.

If a question does not make any sense, or is not factually coherent, explain why instead of answering something not\
correct. If you don't know the answer to a question, please don't share false information."""


class 			__lowerCAmelCase				(					_UpperCamelCase			):


	'''simple docstring'''





	_A       	=							VOCAB_FILES_NAMES
	_A       	=							LlamaTokenizer
	_A       	=							"left"
	_A       	=							["input_ids", "attention_mask"]

	def __init__(	self:	Any,				lowerCamelCase_:	List[Any]=None,				lowerCamelCase_:	Union[str, Any]=None,				lowerCamelCase_:	List[str]=False,				lowerCamelCase_:	List[str]="<unk>",				lowerCamelCase_:	Optional[int]="<s>",				lowerCamelCase_:	Dict="</s>",				lowerCamelCase_:	str=True,				lowerCamelCase_:	Dict=False,				**lowerCamelCase_:	Union[str, Any],				):
			super().__init__(
			    vocab_file=lowerCamelCase_,				tokenizer_file=lowerCamelCase_,				clean_up_tokenization_spaces=lowerCamelCase_,				unk_token=lowerCamelCase_,				bos_token=lowerCamelCase_,				eos_token=lowerCamelCase_,				**lowerCamelCase_,				)
			lowercase__				:			Tuple            =		add_bos_token
			lowercase__				:			Dict            =		add_eos_token
			self.update_post_processor()

			lowercase__				:			int            =		vocab_file
			lowercase__				:			Optional[int]            =		False if not self.vocab_file else True

	def       snake_case__(	self:	str ):
			lowercase__				:			str            =		self.bos_token
			lowercase__				:			List[str]            =		self.bos_token_id

			lowercase__				:			List[Any]            =		self.eos_token
			lowercase__				:			List[str]            =		self.eos_token_id

			lowercase__				:			Optional[Any]            =		F"""{(bos+":0 ") * self.add_bos_token}$A:0{(" "+eos+":0") * self.add_eos_token}"""
			lowercase__				:			Optional[Any]            =		F"""{single}{(" "+bos+":1") * self.add_bos_token} $B:1{(" "+eos+":1") * self.add_eos_token}"""

			lowercase__				:			Tuple            =		[]
			if self.add_bos_token:
					special_tokens.append((bos, bos_token_id) )
			if self.add_eos_token:
					special_tokens.append((eos, eos_token_id) )
			lowercase__				:			int            =		processors.TemplateProcessing(
			    single=lowerCamelCase_,				pair=lowerCamelCase_,				special_tokens=lowerCamelCase_ )

	@property
	def       snake_case__(	self:	List[Any] ):
			return self._add_eos_token

	@property
	def       snake_case__(	self:	str ):
			return self._add_bos_token

	@add_eos_token.setter
	def       snake_case__(	self:	Union[str, Any],				lowerCamelCase_:	List[Any] ):
			lowercase__				:			Union[str, Any]            =		value
			self.update_post_processor()

	@add_bos_token.setter
	def       snake_case__(	self:	int,				lowerCamelCase_:	List[str] ):
			lowercase__				:			Union[str, Any]            =		value
			self.update_post_processor()

	def       snake_case__(	self:	List[Any],				lowerCamelCase_:	str,				lowerCamelCase_:	Optional[str] = None ):
			if not self.can_save_slow_tokenizer:
					raise ValueError(
					    'Your fast tokenizer does not have the necessary information to save the vocabulary for a slow '
					    'tokenizer.' )

			if not os.path.isdir(lowerCamelCase_ ):
					logger.error(F"""Vocabulary path ({save_directory}) should be a directory""" )
					return
			lowercase__				:			List[str]            =		os.path.join(
			    lowerCamelCase_,				(filename_prefix + '-' if filename_prefix else '') + VOCAB_FILES_NAMES['vocab_file'] )

			if os.path.abspath(self.vocab_file ) != os.path.abspath(lowerCamelCase_ ):
					copyfile(self.vocab_file,				lowerCamelCase_ )

			return (out_vocab_file,)





	def       snake_case__(	self:	int,				lowerCamelCase_:	"Conversation" ):
			lowercase__				:			str            =		list(conversation.iter_texts() )
			if not all([is_user for is_user, msg in dialogue[::2]] ) or not all(
			    [not is_user for is_user, msg in dialogue[1::2]] ):
					raise ValueError(
					    'The model only supports \'user\' and \'assistant\' roles, starting with user and alternating (u/a/u/a/u...)' )

			lowercase__				:			Optional[Any]            =		[]
			if len(conversation.past_user_inputs ) > 0:
					if not conversation.past_user_inputs[0].startswith(lowerCamelCase_ ) or E_SYS not in conversation.past_user_inputs[0]:
							lowercase__				:			str            =		(
							    B_SYS + DEFAULT_SYSTEM_PROMPT + E_SYS + conversation.past_user_inputs[0]
							)
			elif not dialogue[0][1].startswith(lowerCamelCase_ ) or E_SYS not in dialogue[0][1]:
					lowercase__				:			Any            =		(dialogue[0][0], B_SYS + DEFAULT_SYSTEM_PROMPT + E_SYS + dialogue[0][1])

			dialog_tokens += sum(
			    [
			        [self.bos_token_id]
			        + self.encode(
			            F"""{B_INST} {(prompt[1]).strip()} {E_INST} {(answer[1]).strip()} """,				add_special_tokens=lowerCamelCase_ )
			        + [self.eos_token_id]
			        for prompt, answer in zip(dialogue[::2],				dialogue[1::2] )
			    ],				[],				)
			if not (dialogue[-1][0]):
					raise ValueError(F"""Last message must be from user, got {dialogue[-1]["role"]}""" )
			dialog_tokens += [self.bos_token_id] + self.encode(
			    F"""{B_INST} {(dialogue[-1][1]).strip()} {E_INST}""",				add_special_tokens=lowerCamelCase_ )
			return dialog_tokens









import sacrebleu as scb
from packaging import version

import datasets


__UpperCamelCase:  Optional[Any]   =   """\
@inproceedings{post-2018-call,
    title = \"A Call for Clarity in Reporting {BLEU} Scores\",
    author = \"Post, Matt\",
    booktitle = \"Proceedings of the Third Conference on Machine Translation: Research Papers\",
    month = oct,
    year = \"2018\",
    address = \"Belgium, Brussels\",
    publisher = \"Association for Computational Linguistics\",
    url = \"https://www.aclweb.org/anthology/W18-6319\",
    pages = \"186--191\",
}
"""

__UpperCamelCase:  int   =   """\
SacreBLEU provides hassle-free computation of shareable, comparable, and reproducible BLEU scores.
Inspired by Rico Sennrich's `multi-bleu-detok.perl`, it produces the official WMT scores but works with plain text.
It also knows all the standard test sets and handles downloading, processing, and tokenization for you.

See the [README.md] file at https://github.com/mjpost/sacreBLEU for more information.
"""

__UpperCamelCase:  int   =   """
Produces BLEU scores along with its sufficient statistics
from a source against one or more references.

Args:
    predictions (`list` of `str`): list of translations to score. Each translation should be tokenized into a list of tokens.
    references (`list` of `list` of `str`): A list of lists of references. The contents of the first sub-list are the references for the first prediction, the contents of the second sub-list are for the second prediction, etc. Note that there must be the same number of references for each prediction (i.e. all sub-lists must be of the same length).
    smooth_method (`str`): The smoothing method to use, defaults to `'exp'`. Possible values are:
        - `'none'`: no smoothing
        - `'floor'`: increment zero counts
        - `'add-k'`: increment num/denom by k for n>1
        - `'exp'`: exponential decay
    smooth_value (`float`): The smoothing value. Only valid when `smooth_method='floor'` (in which case `smooth_value` defaults to `0.1`) or `smooth_method='add-k'` (in which case `smooth_value` defaults to `1`).
    tokenize (`str`): Tokenization method to use for BLEU. If not provided, defaults to `'zh'` for Chinese, `'ja-mecab'` for Japanese and `'13a'` (mteval) otherwise. Possible values are:
        - `'none'`: No tokenization.
        - `'zh'`: Chinese tokenization.
        - `'13a'`: mimics the `mteval-v13a` script from Moses.
        - `'intl'`: International tokenization, mimics the `mteval-v14` script from Moses
        - `'char'`: Language-agnostic character-level tokenization.
        - `'ja-mecab'`: Japanese tokenization. Uses the [MeCab tokenizer](https://pypi.org/project/mecab-python3).
    lowercase (`bool`): If `True`, lowercases the input, enabling case-insensitivity. Defaults to `False`.
    force (`bool`): If `True`, insists that your tokenized input is actually detokenized. Defaults to `False`.
    use_effective_order (`bool`): If `True`, stops including n-gram orders for which precision is 0. This should be `True`, if sentence-level BLEU will be computed. Defaults to `False`.

Returns:
    'score': BLEU score,
    'counts': Counts,
    'totals': Totals,
    'precisions': Precisions,
    'bp': Brevity penalty,
    'sys_len': predictions length,
    'ref_len': reference length,

Examples:

    Example 1:
        >>> predictions = [\"hello there general kenobi\", \"foo bar foobar\"]
        >>> references = [[\"hello there general kenobi\", \"hello there !\"], [\"foo bar foobar\", \"foo bar foobar\"]]
        >>> sacrebleu = datasets.load_metric(\"sacrebleu\")
        >>> results = sacrebleu.compute(predictions=predictions, references=references)
        >>> print(list(results.keys()))
        ['score', 'counts', 'totals', 'precisions', 'bp', 'sys_len', 'ref_len']
        >>> print(round(results[\"score\"], 1))
        100.0

    Example 2:
        >>> predictions = [\"hello there general kenobi\",
        ...                 \"on our way to ankh morpork\"]
        >>> references = [[\"hello there general kenobi\", \"hello there !\"],
        ...                 [\"goodbye ankh morpork\", \"ankh morpork\"]]
        >>> sacrebleu = datasets.load_metric(\"sacrebleu\")
        >>> results = sacrebleu.compute(predictions=predictions,
        ...                             references=references)
        >>> print(list(results.keys()))
        ['score', 'counts', 'totals', 'precisions', 'bp', 'sys_len', 'ref_len']
        >>> print(round(results[\"score\"], 1))
        39.8
"""


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


	'''simple docstring'''





	def       snake_case__(	self:	Optional[Any] ):
			if version.parse(scb.__version__ ) < version.parse('1.4.12' ):
					raise ImportWarning(
					    'To use `sacrebleu`, the module `sacrebleu>=1.4.12` is required, and the current version of `sacrebleu` doesn\'t match this condition.\n'
					    'You can install it with `pip install "sacrebleu>=1.4.12"`.' )
			return datasets.MetricInfo(
			    description=_DESCRIPTION,				citation=_CITATION,				homepage='https://github.com/mjpost/sacreBLEU',				inputs_description=_KWARGS_DESCRIPTION,				features=datasets.Features(
			        {
			            'predictions': datasets.Value('string',				id='sequence' ),
			            'references': datasets.Sequence(datasets.Value('string',				id='sequence' ),				id='references' ),
			        } ),				codebase_urls=['https://github.com/mjpost/sacreBLEU'],				reference_urls=[
			        'https://github.com/mjpost/sacreBLEU',
			        'https://en.wikipedia.org/wiki/BLEU',
			        'https://towardsdatascience.com/evaluating-text-output-in-nlp-bleu-at-your-own-risk-e8609665a213',
			    ],				)





	def       snake_case__(	self:	Optional[Any],				lowerCamelCase_:	Optional[int],				lowerCamelCase_:	List[str],				lowerCamelCase_:	Dict="exp",				lowerCamelCase_:	Optional[int]=None,				lowerCamelCase_:	Dict=False,				lowerCamelCase_:	int=False,				lowerCamelCase_:	Tuple=None,				lowerCamelCase_:	str=False,				):
			lowercase__				:			int            =		len(references[0] )
			if any(len(lowerCamelCase_ ) != references_per_prediction for refs in references ):
					raise ValueError('Sacrebleu requires the same number of references for each prediction' )
			lowercase__				:			Optional[Any]            =		[[refs[i] for refs in references] for i in range(lowerCamelCase_ )]
			lowercase__				:			List[str]            =		scb.corpus_bleu(
			    lowerCamelCase_,				lowerCamelCase_,				smooth_method=lowerCamelCase_,				smooth_value=lowerCamelCase_,				force=lowerCamelCase_,				lowercase=lowerCamelCase_,				use_effective_order=lowerCamelCase_,				**({'tokenize': tokenize} if tokenize else {}),				)
			lowercase__				:			Union[str, Any]            =		{
			    'score': output.score,
			    'counts': output.counts,
			    'totals': output.totals,
			    'precisions': output.precisions,
			    'bp': output.bp,
			    'sys_len': output.sys_len,
			    'ref_len': output.ref_len,
			}
			return output_dict


